From s.hauer at pengutronix.de  Mon Apr  2 23:54:36 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 3 Apr 2018 08:54:36 +0200
Subject: [PATCH 2/3] console: Add simplified 'serdev' framework from
 Linux kernel
In-Reply-To: <20180326130915.8726-3-andrew.smirnov@gmail.com>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-3-andrew.smirnov@gmail.com>
Message-ID: <20180403065436.p2vec7ntdja55hts@pengutronix.de>

Hi Andrey,

Some comments inside.


On Mon, Mar 26, 2018 at 06:09:14AM -0700, Andrey Smirnov wrote:
> Port 'serdev' UART-slave deivce framework found in recent Linux
> kernels (post 4.13) in order to be able to port 'serdev' slave drivers
> from Linux.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> @@ -323,6 +324,17 @@ int console_register(struct console_device *newcdev)
>  		dev->parent = newcdev->dev;
>  	platform_device_register(dev);
>  
> +	newcdev->open_count = 0;
> +
> +	/*
> +	 * If our console deive is a serdev, we skip the creation of

s/deive/device/

> +	 * corresponding entry in /dev as well as registration in
> +	 * console_list and just go straigh to populating child

s/straigh/straight/

> +	 * devices.
> +	 */
> +	if (serdev_node)
> +		return of_platform_populate(serdev_node, NULL, dev);

How is this going to be used? A serdev driver binds to the serdev_node
and then it probably needs to get a pointer to the console device,
right? How does the driver accomplish this?

> +/**
> + * struct serdev_device - Basic representation of an serdev device
> + *
> + * @dev:		Corresponding device
> + * @fifo:		Circular buffer used for console draining
> + * @buf:		Buffer used to pass Rx data to consumers
> + * @poller		Async poller used to poll this serdev
> + * @polling_interval:	Async poller periodicity
> + * @polling_window:	Duration of a single busy loop poll
> + * @receive_buf:	Function called with data received from device;
> + *			returns number of bytes accepted;
> + */
> +struct serdev_device {
> +	struct device_d *dev;
> +	struct kfifo *fifo;
> +	unsigned char *buf;
> +	struct poller_async poller;
> +	uint64_t polling_interval;
> +	uint64_t polling_window;
> +
> +	int (*receive_buf)(struct serdev_device *, const unsigned char *,
> +			   size_t);
> +};
> +
> +int serdev_device_open(struct serdev_device *);
> +unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
> +int serdev_device_write(struct serdev_device *, const unsigned char *,
> +			size_t, unsigned long);

So a serdev driver uses serdev_device_write() to send characters out. To
receive characters it has to implement serdev_device->receive_buf,
right? What kind of devices did you implement this for? For devices
which send data without request (GPS?) this seems the way to go. For
others a synchronous receive function might be good, no?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr  3 00:04:27 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 3 Apr 2018 09:04:27 +0200
Subject: [PATCH 3/3] serial: Check result of console_unregister()
In-Reply-To: <20180326130915.8726-4-andrew.smirnov@gmail.com>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-4-andrew.smirnov@gmail.com>
Message-ID: <20180403070427.terivivcpl2abuuf@pengutronix.de>

On Mon, Mar 26, 2018 at 06:09:15AM -0700, Andrey Smirnov wrote:
> In order to allow 'serdev' devices to prevent parent console device
> removal and correspondign memory deallocation add code to all serial
> driver to check result of console_unregister() and bail out early if
> it is unsuccessful.
> 
> One example of a use-case for this would be a reset handler relying on
> a serdev device for transport. Without this patch underlying console
> device would be removed and de-allocated before reset handler is even
> run thus leading to unpredictable behaviour and crashes.

Can't we make this sure at driver core level? So if a device decides not
to return -EBUSY in the remove callback then the parent devices won't be
removed?

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr  3 00:08:48 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 3 Apr 2018 09:08:48 +0200
Subject: [PATCH] aiodev: Constify 'unit' in 'struct aiodev'
In-Reply-To: <20180326131445.11229-1-andrew.smirnov@gmail.com>
References: <20180326131445.11229-1-andrew.smirnov@gmail.com>
Message-ID: <20180403070848.4cygxoaji652xa3k@pengutronix.de>

On Mon, Mar 26, 2018 at 06:14:45AM -0700, Andrey Smirnov wrote:
> The way it is currently used, there's no reason for 'uint' field to be
> mutable, so constify it in order to allow 'aiodev' drivers to pass
> sting literals in that field.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  include/aiodev.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/include/aiodev.h b/include/aiodev.h
> index 0d4f7a294..5e38b4fab 100644
> --- a/include/aiodev.h
> +++ b/include/aiodev.h
> @@ -23,7 +23,7 @@
>  struct aiodevice;
>  struct aiochannel {
>  	int index;
> -	char *unit;
> +	const char *unit;
>  	struct aiodevice *aiodev;
>  
>  	int value;
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr  3 00:08:36 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 3 Apr 2018 09:08:36 +0200
Subject: [PATCH] lib: Port CRC-CCITT functions from Linux kernel
In-Reply-To: <20180326131231.9268-1-andrew.smirnov@gmail.com>
References: <20180326131231.9268-1-andrew.smirnov@gmail.com>
Message-ID: <20180403070836.glay7l25x2wnpb6m@pengutronix.de>

On Mon, Mar 26, 2018 at 06:12:31AM -0700, Andrey Smirnov wrote:
> Port CRC-CCITT implemenation in order to support porting MFD driver
> for RAVE SP.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---

Applied, thanks

Sascha

>  include/linux/crc-ccitt.h |  23 +++++++++
>  lib/Kconfig               |   8 +++
>  lib/Makefile              |   1 +
>  lib/crc-ccitt.c           | 124 ++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 156 insertions(+)
>  create mode 100644 include/linux/crc-ccitt.h
>  create mode 100644 lib/crc-ccitt.c
> 
> diff --git a/include/linux/crc-ccitt.h b/include/linux/crc-ccitt.h
> new file mode 100644
> index 000000000..72c92c396
> --- /dev/null
> +++ b/include/linux/crc-ccitt.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_CRC_CCITT_H
> +#define _LINUX_CRC_CCITT_H
> +
> +#include <linux/types.h>
> +
> +extern u16 const crc_ccitt_table[256];
> +extern u16 const crc_ccitt_false_table[256];
> +
> +extern u16 crc_ccitt(u16 crc, const u8 *buffer, size_t len);
> +extern u16 crc_ccitt_false(u16 crc, const u8 *buffer, size_t len);
> +
> +static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
> +{
> +	return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
> +}
> +
> +static inline u16 crc_ccitt_false_byte(u16 crc, const u8 c)
> +{
> +    return (crc << 8) ^ crc_ccitt_false_table[(crc >> 8) ^ c];
> +}
> +
> +#endif /* _LINUX_CRC_CCITT_H */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 4e9213f3e..b4b10afa2 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -110,6 +110,14 @@ config ALLOW_PRNG_FALLBACK
>  	  available and this option is disabled, cmd_password will fail.
>  	  Enable it on your own risk.
>  
> +config CRC_CCITT
> +        bool "CRC-CCITT functions"
> +	help
> +	  This option is provided for the case where no in-kernel-tree
> +	  modules require CRC-CCITT functions, but a module built outside
> +	  the kernel tree does. Such modules that use library CRC-CCITT
> +	  functions require M here.
> +
>  source lib/gui/Kconfig
>  
>  source lib/fonts/Kconfig
> diff --git a/lib/Makefile b/lib/Makefile
> index e5cf32c16..a285f6d0c 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -63,3 +63,4 @@ obj-$(CONFIG_RATP)	+= ratp.o
>  obj-y			+= list_sort.o
>  obj-y			+= int_sqrt.o
>  obj-y			+= parseopt.o
> +obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
> diff --git a/lib/crc-ccitt.c b/lib/crc-ccitt.c
> new file mode 100644
> index 000000000..b5a916dd8
> --- /dev/null
> +++ b/lib/crc-ccitt.c
> @@ -0,0 +1,124 @@
> +/*
> + *	linux/lib/crc-ccitt.c
> + *
> + *	This source code is licensed under the GNU General Public License,
> + *	Version 2. See the file COPYING for more details.
> + */
> +#include <common.h>
> +#include <linux/types.h>
> +#include <linux/crc-ccitt.h>
> +
> +/*
> + * This mysterious table is just the CRC of each possible byte. It can be
> + * computed using the standard bit-at-a-time methods. The polynomial can
> + * be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12.
> + * Add the implicit x^16, and you have the standard CRC-CCITT.
> + */
> +u16 const crc_ccitt_table[256] = {
> +	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
> +	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
> +	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
> +	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
> +	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
> +	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
> +	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
> +	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
> +	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
> +	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
> +	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
> +	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
> +	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
> +	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
> +	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
> +	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
> +	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
> +	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
> +	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
> +	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
> +	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
> +	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
> +	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
> +	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
> +	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
> +	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
> +	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
> +	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
> +	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
> +	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
> +	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
> +	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
> +};
> +EXPORT_SYMBOL(crc_ccitt_table);
> +
> +/*
> + * Similar table to calculate CRC16 variant known as CRC-CCITT-FALSE
> + * Reflected bits order, does not augment final value.
> + */
> +u16 const crc_ccitt_false_table[256] = {
> +    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
> +    0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
> +    0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
> +    0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
> +    0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
> +    0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
> +    0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
> +    0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
> +    0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
> +    0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
> +    0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
> +    0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
> +    0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
> +    0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
> +    0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
> +    0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
> +    0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
> +    0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
> +    0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
> +    0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
> +    0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
> +    0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
> +    0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
> +    0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
> +    0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
> +    0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
> +    0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
> +    0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
> +    0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
> +    0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
> +    0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
> +    0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
> +};
> +EXPORT_SYMBOL(crc_ccitt_false_table);
> +
> +/**
> + *	crc_ccitt - recompute the CRC (CRC-CCITT variant) for the data
> + *	buffer
> + *	@crc: previous CRC value
> + *	@buffer: data pointer
> + *	@len: number of bytes in the buffer
> + */
> +u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
> +{
> +	while (len--)
> +		crc = crc_ccitt_byte(crc, *buffer++);
> +	return crc;
> +}
> +EXPORT_SYMBOL(crc_ccitt);
> +
> +/**
> + *	crc_ccitt_false - recompute the CRC (CRC-CCITT-FALSE variant)
> + *	for the data buffer
> + *	@crc: previous CRC value
> + *	@buffer: data pointer
> + *	@len: number of bytes in the buffer
> + */
> +u16 crc_ccitt_false(u16 crc, u8 const *buffer, size_t len)
> +{
> +	while (len--)
> +		crc = crc_ccitt_false_byte(crc, *buffer++);
> +	return crc;
> +}
> +EXPORT_SYMBOL(crc_ccitt_false);
> +
> +MODULE_DESCRIPTION("CRC-CCITT calculations");
> +MODULE_LICENSE("GPL");
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr  3 00:12:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 3 Apr 2018 09:12:44 +0200
Subject: [PATCH 0/3] APBH DMA fixes for i.MX7
In-Reply-To: <20180401011358.11621-1-andrew.smirnov@gmail.com>
References: <20180401011358.11621-1-andrew.smirnov@gmail.com>
Message-ID: <20180403071244.l2peshkb4gyyxbh7@pengutronix.de>

On Sat, Mar 31, 2018 at 06:13:54PM -0700, Andrey Smirnov wrote:
> Hi everyone:
> 
> The following two patches are to fix a case of broken boot I
> discovered when I built a mult-image build for i.MX6 and i.MX7 and
> tried to boot it on my i.MX7 SabreSD board.
> 
> Let me know if anything needs changing.

Looks fine, thanks. Applied.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr  3 00:48:43 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:43 +0200
Subject: [PATCH 11/19] loadenv: Do not depend on normalise_path()
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-12-s.hauer@pengutronix.de>

normalise_path() will go away, so do without it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 commands/loadenv.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/commands/loadenv.c b/commands/loadenv.c
index 44e96c3b60..6469affadb 100644
--- a/commands/loadenv.c
+++ b/commands/loadenv.c
@@ -62,20 +62,16 @@ static int do_loadenv(int argc, char *argv[])
 	if (argc - optind < 1) {
 		filename = default_environment_path_get();
 	} else {
-		char *str = normalise_path(argv[optind]);
-
 		/*
 		 * /dev/defaultenv use to contain the defaultenvironment.
 		 * we do not have this file anymore, but maintain compatibility
 		 * to the 'loadenv -s /dev/defaultenv' command to restore the
 		 * default environment for some time.
 		 */
-		if (!strcmp(str, "/dev/defaultenv"))
+		if (!strcmp(argv[optind], "/dev/defaultenv"))
 			defaultenv = 1;
 		else
 			filename = argv[optind];
-
-		free(str);
 	}
 
 	if (scrub) {
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:50 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:50 +0200
Subject: [PATCH 18/19] fs: tftp: Switch to dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-19-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/Kconfig |  1 -
 fs/tftp.c  | 96 +++++++++++++++++++++++++++++++++++---------------------------
 2 files changed, 55 insertions(+), 42 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index b2d4242e63..2be883e544 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -29,7 +29,6 @@ config FS_DEVFS
 
 config FS_TFTP
 	bool
-	depends on BROKEN
 	prompt "tftp support"
 	depends on NET
 
diff --git a/fs/tftp.c b/fs/tftp.c
index 847921aa56..753444c459 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -89,26 +89,6 @@ struct tftp_priv {
 	IPaddr_t server;
 };
 
-static int tftp_create(struct device_d *dev, const char *pathname, mode_t mode)
-{
-	return 0;
-}
-
-static int tftp_unlink(struct device_d *dev, const char *pathname)
-{
-	return -ENOSYS;
-}
-
-static int tftp_mkdir(struct device_d *dev, const char *pathname)
-{
-	return -ENOSYS;
-}
-
-static int tftp_rmdir(struct device_d *dev, const char *pathname)
-{
-	return -ENOSYS;
-}
-
 static int tftp_truncate(struct device_d *dev, FILE *f, ulong size)
 {
 	return 0;
@@ -466,6 +446,9 @@ out:
 static int tftp_open(struct device_d *dev, FILE *file, const char *filename)
 {
 	struct file_priv *priv;
+	struct fs_device_d *fsdev = dev_to_fs_device(dev);
+
+	filename = dpath(file->dentry, fsdev->vfsmount.mnt_root);
 
 	priv = tftp_do_open(dev, file->flags, filename);
 	if (IS_ERR(priv))
@@ -618,40 +601,77 @@ out_free:
 	return -ENOSYS;
 }
 
-static DIR* tftp_opendir(struct device_d *dev, const char *pathname)
+static const struct inode_operations tftp_file_inode_operations;
+static const struct inode_operations tftp_dir_inode_operations;
+static const struct file_operations tftp_file_operations;
+
+static struct inode *tftp_get_inode(struct super_block *sb, const struct inode *dir,
+                                     umode_t mode)
 {
-	/* not implemented in tftp protocol */
-	return NULL;
+	struct inode *inode = new_inode(sb);
+
+	if (!inode)
+		return NULL;
+
+	inode->i_ino = get_next_ino();
+	inode->i_mode = mode;
+
+	switch (mode & S_IFMT) {
+	default:
+		return NULL;
+	case S_IFREG:
+		inode->i_op = &tftp_file_inode_operations;
+		inode->i_fop = &tftp_file_operations;
+		break;
+	case S_IFDIR:
+		inode->i_op = &tftp_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+		inc_nlink(inode);
+		break;
+	}
+
+	return inode;
 }
 
-static int tftp_stat(struct device_d *dev, const char *filename, struct stat *s)
+static struct dentry *tftp_lookup(struct inode *dir, struct dentry *dentry,
+			    unsigned int flags)
 {
-	struct file_priv *priv;
+	struct inode *inode;
 
-	priv = tftp_do_open(dev, O_RDONLY, filename);
-	if (IS_ERR(priv))
-		return PTR_ERR(priv);
+	printf("Lookup: \"%s\"\n", dentry->name);
 
-	s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
-	if (priv->filesize)
-		s->st_size = priv->filesize;
-	else
-		s->st_size = FILESIZE_MAX;
+	inode = tftp_get_inode(dir->i_sb, dir, S_IFREG | S_IRWXUGO);
+	if (!inode)
+		return ERR_PTR(-ENOSPC);
 
-	tftp_do_close(priv);
+	d_add(dentry, inode);
 
-	return 0;
+	return NULL;
 }
 
+static const struct inode_operations tftp_dir_inode_operations =
+{
+	.lookup = tftp_lookup,
+};
+
+static const struct super_operations tftp_ops;
+
 static int tftp_probe(struct device_d *dev)
 {
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
 	struct tftp_priv *priv = xzalloc(sizeof(struct tftp_priv));
+	struct super_block *sb = &fsdev->sb;
+	struct inode *inode;
 
 	dev->priv = priv;
 
 	priv->server = resolv(fsdev->backingstore);
 
+	sb->s_op = &tftp_ops;
+
+	inode = tftp_get_inode(sb, NULL, S_IFDIR);
+	sb->s_root = d_make_root(inode);
+
 	return 0;
 }
 
@@ -667,12 +687,6 @@ static struct fs_driver_d tftp_driver = {
 	.close     = tftp_close,
 	.read      = tftp_read,
 	.lseek     = tftp_lseek,
-	.opendir   = tftp_opendir,
-	.stat      = tftp_stat,
-	.create    = tftp_create,
-	.unlink    = tftp_unlink,
-	.mkdir     = tftp_mkdir,
-	.rmdir     = tftp_rmdir,
 	.write     = tftp_write,
 	.truncate  = tftp_truncate,
 	.flags     = 0,
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:38 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:38 +0200
Subject: [PATCH 06/19] fs: Move mem_write/mem_read to devfs-core
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-7-s.hauer@pengutronix.de>

fs.c is already heavily filled with code. Move mem_write/mem_read
to devfs-core where it fits better.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/devfs-core.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/fs.c         | 66 -------------------------------------------------------
 2 files changed, 68 insertions(+), 66 deletions(-)

diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index d06a534b57..6b5e6da6a8 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -513,3 +513,71 @@ void cdev_remove_loop(struct cdev *cdev)
 	free(cdev->name);
 	free(cdev);
 }
+
+static void memcpy_sz(void *dst, const void *src, size_t count, int rwsize)
+{
+	/* no rwsize specification given. Do whatever memcpy likes best */
+	if (!rwsize) {
+		memcpy(dst, src, count);
+		return;
+	}
+
+	rwsize = rwsize >> O_RWSIZE_SHIFT;
+
+	count /= rwsize;
+
+	while (count-- > 0) {
+		switch (rwsize) {
+		case 1:
+			*((u8 *)dst) = *((u8 *)src);
+			break;
+		case 2:
+			*((u16 *)dst) = *((u16 *)src);
+			break;
+		case 4:
+			*((u32  *)dst) = *((u32  *)src);
+			break;
+		case 8:
+			*((u64  *)dst) = *((u64  *)src);
+			break;
+		}
+		dst += rwsize;
+		src += rwsize;
+	}
+}
+
+ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset,
+		 unsigned long flags)
+{
+	unsigned long size;
+	struct device_d *dev;
+
+	if (!cdev->dev || cdev->dev->num_resources < 1)
+		return -1;
+	dev = cdev->dev;
+
+	size = min((resource_size_t)count,
+			resource_size(&dev->resource[0]) -
+			(resource_size_t)offset);
+	memcpy_sz(buf, dev_get_mem_region(dev, 0) + offset, size, flags & O_RWSIZE_MASK);
+	return size;
+}
+EXPORT_SYMBOL(mem_read);
+
+ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset,
+		  unsigned long flags)
+{
+	unsigned long size;
+	struct device_d *dev;
+
+	if (!cdev->dev || cdev->dev->num_resources < 1)
+		return -1;
+	dev = cdev->dev;
+
+	size = min((resource_size_t)count,
+			resource_size(&dev->resource[0]) -
+			(resource_size_t)offset);
+	memcpy_sz(dev_get_mem_region(dev, 0) + offset, buf, size, flags & O_RWSIZE_MASK);
+	return size;
+}
+EXPORT_SYMBOL(mem_write);
diff --git a/fs/fs.c b/fs/fs.c
index 5135112c8b..ca4fe70e15 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -1739,72 +1739,6 @@ out:
 }
 EXPORT_SYMBOL(rmdir);
 
-static void memcpy_sz(void *dst, const void *src, size_t count, int rwsize)
-{
-	/* no rwsize specification given. Do whatever memcpy likes best */
-	if (!rwsize) {
-		memcpy(dst, src, count);
-		return;
-	}
-
-	rwsize = rwsize >> O_RWSIZE_SHIFT;
-
-	count /= rwsize;
-
-	while (count-- > 0) {
-		switch (rwsize) {
-		case 1:
-			*((u8 *)dst) = *((u8 *)src);
-			break;
-		case 2:
-			*((u16 *)dst) = *((u16 *)src);
-			break;
-		case 4:
-			*((u32  *)dst) = *((u32  *)src);
-			break;
-		case 8:
-			*((u64  *)dst) = *((u64  *)src);
-			break;
-		}
-		dst += rwsize;
-		src += rwsize;
-	}
-}
-
-ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags)
-{
-	ulong size;
-	struct device_d *dev;
-
-	if (!cdev->dev || cdev->dev->num_resources < 1)
-		return -1;
-	dev = cdev->dev;
-
-	size = min((resource_size_t)count,
-			resource_size(&dev->resource[0]) -
-			(resource_size_t)offset);
-	memcpy_sz(buf, dev_get_mem_region(dev, 0) + offset, size, flags & O_RWSIZE_MASK);
-	return size;
-}
-EXPORT_SYMBOL(mem_read);
-
-ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags)
-{
-	ulong size;
-	struct device_d *dev;
-
-	if (!cdev->dev || cdev->dev->num_resources < 1)
-		return -1;
-	dev = cdev->dev;
-
-	size = min((resource_size_t)count,
-			resource_size(&dev->resource[0]) -
-			(resource_size_t)offset);
-	memcpy_sz(dev_get_mem_region(dev, 0) + offset, buf, size, flags & O_RWSIZE_MASK);
-	return size;
-}
-EXPORT_SYMBOL(mem_write);
-
 /*
  * cdev_get_mount_path - return the path a cdev is mounted on
  *
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:36 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:36 +0200
Subject: [PATCH 04/19] ubifs: remove dead code
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-5-s.hauer@pengutronix.de>

Remove code that was added to UBIFS for U-Boot but that is not needed
for barebox.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ubifs/ubifs.c | 475 -------------------------------------------------------
 1 file changed, 475 deletions(-)

diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 0bb1c26d7d..a525b044b8 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -273,135 +273,6 @@ int __init ubifs_compressors_init(void)
  * ubifsls...
  */
 
-#ifndef __BAREBOX__
-static int filldir(struct ubifs_info *c, const char *name, int namlen,
-		   u64 ino, unsigned int d_type)
-{
-	struct inode *inode;
-	char filetime[32];
-
-	switch (d_type) {
-	case UBIFS_ITYPE_REG:
-		printf("\t");
-		break;
-	case UBIFS_ITYPE_DIR:
-		printf("<DIR>\t");
-		break;
-	case UBIFS_ITYPE_LNK:
-		printf("<LNK>\t");
-		break;
-	default:
-		printf("other\t");
-		break;
-	}
-
-	inode = ubifs_iget(c->vfs_sb, ino);
-	if (IS_ERR(inode)) {
-		printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
-		       __func__, ino, inode);
-		return -1;
-	}
-	ctime_r((time_t *)&inode->i_mtime, filetime);
-	printf("%9lld  %24.24s  ", inode->i_size, filetime);
-#ifndef __BAREBOX__
-	ubifs_iput(inode);
-#endif
-
-	printf("%s\n", name);
-
-	return 0;
-}
-
-static int ubifs_printdir(struct file *file, void *dirent)
-{
-	int err, over = 0;
-	struct qstr nm;
-	union ubifs_key key;
-	struct ubifs_dent_node *dent;
-	struct inode *dir = file->f_path.dentry->d_inode;
-	struct ubifs_info *c = dir->i_sb->s_fs_info;
-
-	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
-
-	if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
-		/*
-		 * The directory was seek'ed to a senseless position or there
-		 * are no more entries.
-		 */
-		return 0;
-
-	if (file->f_pos == 1) {
-		/* Find the first entry in TNC and save it */
-		lowest_dent_key(c, &key, dir->i_ino);
-		nm.name = NULL;
-		dent = ubifs_tnc_next_ent(c, &key, &nm);
-		if (IS_ERR(dent)) {
-			err = PTR_ERR(dent);
-			goto out;
-		}
-
-		file->f_pos = key_hash_flash(c, &dent->key);
-		file->private_data = dent;
-	}
-
-	dent = file->private_data;
-	if (!dent) {
-		/*
-		 * The directory was seek'ed to and is now readdir'ed.
-		 * Find the entry corresponding to @file->f_pos or the
-		 * closest one.
-		 */
-		dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
-		nm.name = NULL;
-		dent = ubifs_tnc_next_ent(c, &key, &nm);
-		if (IS_ERR(dent)) {
-			err = PTR_ERR(dent);
-			goto out;
-		}
-		file->f_pos = key_hash_flash(c, &dent->key);
-		file->private_data = dent;
-	}
-
-	while (1) {
-		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
-			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
-			key_hash_flash(c, &dent->key));
-		ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
-
-		nm.len = le16_to_cpu(dent->nlen);
-		over = filldir(c, (char *)dent->name, nm.len,
-			       le64_to_cpu(dent->inum), dent->type);
-		if (over)
-			return 0;
-
-		/* Switch to the next entry */
-		key_read(c, &dent->key, &key);
-		nm.name = (char *)dent->name;
-		dent = ubifs_tnc_next_ent(c, &key, &nm);
-		if (IS_ERR(dent)) {
-			err = PTR_ERR(dent);
-			goto out;
-		}
-
-		kfree(file->private_data);
-		file->f_pos = key_hash_flash(c, &dent->key);
-		file->private_data = dent;
-		cond_resched();
-	}
-
-out:
-	if (err != -ENOENT) {
-		ubifs_err(c, "cannot find next direntry, error %d", err);
-		return err;
-	}
-
-	kfree(file->private_data);
-	file->private_data = NULL;
-	file->f_pos = 2;
-	return 0;
-}
-#endif
-
 static int ubifs_finddir(struct super_block *sb, char *dirname,
 			 unsigned long root_inum, unsigned long *inum)
 {
@@ -549,117 +420,6 @@ static unsigned long ubifs_findfile(struct super_block *sb, const char *filename
 	return 0;
 }
 
-#ifndef __BAREBOX__
-int ubifs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info)
-{
-	if (rbdd) {
-		debug("UBIFS cannot be used with normal block devices\n");
-		return -1;
-	}
-
-	/*
-	 * Should never happen since get_device_and_partition() already checks
-	 * this, but better safe then sorry.
-	 */
-	if (!ubifs_is_mounted()) {
-		debug("UBIFS not mounted, use ubifsmount to mount volume first!\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-int ubifs_ls(const char *filename)
-{
-	struct ubifs_info *c = ubifs_sb->s_fs_info;
-	struct file *file;
-	struct dentry *dentry;
-	struct inode *dir;
-	void *dirent = NULL;
-	unsigned long inum;
-	int ret = 0;
-
-	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
-	inum = ubifs_findfile(ubifs_sb, (char *)filename);
-	if (!inum) {
-		ret = -1;
-		goto out;
-	}
-
-	file = kzalloc(sizeof(struct file), 0);
-	dentry = kzalloc(sizeof(struct dentry), 0);
-	dir = kzalloc(sizeof(struct inode), 0);
-	if (!file || !dentry || !dir) {
-		printf("%s: Error, no memory for malloc!\n", __func__);
-		ret = -ENOMEM;
-		goto out_mem;
-	}
-
-	dir->i_sb = ubifs_sb;
-	file->f_path.dentry = dentry;
-	file->f_path.dentry->d_parent = dentry;
-	file->f_path.dentry->d_inode = dir;
-	file->f_path.dentry->d_inode->i_ino = inum;
-	file->f_pos = 1;
-	file->private_data = NULL;
-	ubifs_printdir(file, dirent);
-
-out_mem:
-	if (file)
-		free(file);
-	if (dentry)
-		free(dentry);
-	if (dir)
-		free(dir);
-
-out:
-	ubi_close_volume(c->ubi);
-	return ret;
-}
-
-int ubifs_exists(const char *filename)
-{
-	struct ubifs_info *c = ubifs_sb->s_fs_info;
-	unsigned long inum;
-
-	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
-	inum = ubifs_findfile(ubifs_sb, (char *)filename);
-	ubi_close_volume(c->ubi);
-
-	return inum != 0;
-}
-
-int ubifs_size(const char *filename, loff_t *size)
-{
-	struct ubifs_info *c = ubifs_sb->s_fs_info;
-	unsigned long inum;
-	struct inode *inode;
-	int err = 0;
-
-	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
-
-	inum = ubifs_findfile(ubifs_sb, (char *)filename);
-	if (!inum) {
-		err = -1;
-		goto out;
-	}
-
-	inode = ubifs_iget(ubifs_sb, inum);
-	if (IS_ERR(inode)) {
-		printf("%s: Error reading inode %ld!\n", __func__, inum);
-		err = PTR_ERR(inode);
-		goto out;
-	}
-
-	*size = inode->i_size;
-
-	ubifs_iput(inode);
-out:
-	ubi_close_volume(c->ubi);
-	return err;
-}
-#endif
-
 /*
  * ubifsload...
  */
@@ -718,241 +478,6 @@ dump:
 	return -EINVAL;
 }
 
-#ifndef __BAREBOX__
-static int do_readpage(struct ubifs_info *c, struct inode *inode,
-		       struct page *page, int last_block_size)
-{
-	void *addr;
-	int err = 0, i;
-	unsigned int block, beyond;
-	struct ubifs_data_node *dn;
-	loff_t i_size = inode->i_size;
-
-	dbg_gen("ino %lu, pg %lu, i_size %lld",
-		inode->i_ino, page->index, i_size);
-
-	addr = kmap(page);
-
-	block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
-	beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
-	if (block >= beyond) {
-		/* Reading beyond inode */
-		memset(addr, 0, PAGE_CACHE_SIZE);
-		goto out;
-	}
-
-	dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
-	if (!dn)
-		return -ENOMEM;
-
-	i = 0;
-	while (1) {
-		int ret;
-
-		if (block >= beyond) {
-			/* Reading beyond inode */
-			err = -ENOENT;
-			memset(addr, 0, UBIFS_BLOCK_SIZE);
-		} else {
-			/*
-			 * Reading last block? Make sure to not write beyond
-			 * the requested size in the destination buffer.
-			 */
-			if (((block + 1) == beyond) || last_block_size) {
-				void *buff;
-				int dlen;
-
-				/*
-				 * We need to buffer the data locally for the
-				 * last block. This is to not pad the
-				 * destination area to a multiple of
-				 * UBIFS_BLOCK_SIZE.
-				 */
-				buff = kzalloc(UBIFS_BLOCK_SIZE, 0);
-				if (!buff) {
-					printf("%s: Error, malloc fails!\n",
-					       __func__);
-					err = -ENOMEM;
-					break;
-				}
-
-				/* Read block-size into temp buffer */
-				ret = read_block(inode, buff, block, dn);
-				if (ret) {
-					err = ret;
-					if (err != -ENOENT) {
-						free(buff);
-						break;
-					}
-				}
-
-				if (last_block_size)
-					dlen = last_block_size;
-				else
-					dlen = le32_to_cpu(dn->size);
-
-				/* Now copy required size back to dest */
-				memcpy(addr, buff, dlen);
-
-				free(buff);
-			} else {
-				ret = read_block(inode, addr, block, dn);
-				if (ret) {
-					err = ret;
-					if (err != -ENOENT)
-						break;
-				}
-			}
-		}
-		if (++i >= UBIFS_BLOCKS_PER_PAGE)
-			break;
-		block += 1;
-		addr += UBIFS_BLOCK_SIZE;
-	}
-	if (err) {
-		if (err == -ENOENT) {
-			/* Not found, so it must be a hole */
-			dbg_gen("hole");
-			goto out_free;
-		}
-		ubifs_err(c, "cannot read page %lu of inode %lu, error %d",
-			  page->index, inode->i_ino, err);
-		goto error;
-	}
-
-out_free:
-	kfree(dn);
-out:
-	return 0;
-
-error:
-	kfree(dn);
-	return err;
-}
-
-int ubifs_read(const char *filename, void *buf, loff_t offset,
-	       loff_t size, loff_t *actread)
-{
-	struct ubifs_info *c = ubifs_sb->s_fs_info;
-	unsigned long inum;
-	struct inode *inode;
-	struct page page;
-	int err = 0;
-	int i;
-	int count;
-	int last_block_size = 0;
-
-	*actread = 0;
-
-	if (offset & (PAGE_SIZE - 1)) {
-		printf("ubifs: Error offset must be a multple of %d\n",
-		       PAGE_SIZE);
-		return -1;
-	}
-
-	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
-	/* ubifs_findfile will resolve symlinks, so we know that we get
-	 * the real file here */
-	inum = ubifs_findfile(ubifs_sb, (char *)filename);
-	if (!inum) {
-		err = -1;
-		goto out;
-	}
-
-	/*
-	 * Read file inode
-	 */
-	inode = ubifs_iget(ubifs_sb, inum);
-	if (IS_ERR(inode)) {
-		printf("%s: Error reading inode %ld!\n", __func__, inum);
-		err = PTR_ERR(inode);
-		goto out;
-	}
-
-	if (offset > inode->i_size) {
-		printf("ubifs: Error offset (%lld) > file-size (%lld)\n",
-		       offset, size);
-		err = -1;
-		goto put_inode;
-	}
-
-	/*
-	 * If no size was specified or if size bigger than filesize
-	 * set size to filesize
-	 */
-	if ((size == 0) || (size > (inode->i_size - offset)))
-		size = inode->i_size - offset;
-
-	count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
-
-	page.addr = buf;
-	page.index = offset / PAGE_SIZE;
-	page.inode = inode;
-	for (i = 0; i < count; i++) {
-		/*
-		 * Make sure to not read beyond the requested size
-		 */
-		if (((i + 1) == count) && (size < inode->i_size))
-			last_block_size = size - (i * PAGE_SIZE);
-
-		err = do_readpage(c, inode, &page, last_block_size);
-		if (err)
-			break;
-
-		page.addr += PAGE_SIZE;
-		page.index++;
-	}
-
-	if (err) {
-		printf("Error reading file '%s'\n", filename);
-		*actread = i * PAGE_SIZE;
-	} else {
-		*actread = size;
-	}
-
-put_inode:
-	ubifs_iput(inode);
-
-out:
-	ubi_close_volume(c->ubi);
-	return err;
-}
-
-void ubifs_close(void)
-{
-}
-
-/* Compat wrappers for common/cmd_ubifs.c */
-int ubifs_load(char *filename, u32 addr, u32 size)
-{
-	loff_t actread;
-	int err;
-
-	printf("Loading file '%s' to addr 0x%08x...\n", filename, addr);
-
-	err = ubifs_read(filename, (void *)addr, 0, size, &actread);
-	if (err == 0) {
-		setenv_hex("filesize", actread);
-		printf("Done\n");
-	}
-
-	return err;
-}
-#endif
-
-void uboot_ubifs_umount(void)
-{
-	if (ubifs_sb) {
-		printf("Unmounting UBIFS volume %s!\n",
-		       ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name);
-		ubifs_umount(ubifs_sb->s_fs_info);
-		ubifs_sb = NULL;
-	}
-}
-
-
-
-
 struct ubifs_file {
 	struct inode *inode;
 	void *buf;
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:51 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:51 +0200
Subject: [PATCH 19/19] block: Adjust cache sizes
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-20-s.hauer@pengutronix.de>

Use four times more cache entries and divide the memory for each entry
by four. This lowers the linear read throughput somewhat but increases
the access speed for filesystems.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/block.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/block.c b/common/block.c
index 55d8d1637e..219b943afc 100644
--- a/common/block.c
+++ b/common/block.c
@@ -36,7 +36,7 @@ struct chunk {
 	struct list_head list;
 };
 
-#define BUFSIZE (PAGE_SIZE * 16)
+#define BUFSIZE (PAGE_SIZE * 4)
 
 /*
  * Write all dirty chunks back to the device
@@ -361,7 +361,7 @@ int blockdevice_register(struct block_device *blk)
 	debug("%s: rdbufsize: %d blockbits: %d blkmask: 0x%08x\n", __func__, blk->rdbufsize, blk->blockbits,
 			blk->blkmask);
 
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 32; i++) {
 		struct chunk *chunk = xzalloc(sizeof(*chunk));
 		chunk->data = dma_alloc(BUFSIZE);
 		chunk->num = i;
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:39 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:39 +0200
Subject: [PATCH 07/19] fs: Cleanup whitespace damage
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-8-s.hauer@pengutronix.de>

fs.c has some whitespaces where there should be tabs. Fix it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/fs.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index ca4fe70e15..92f336b821 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -99,13 +99,13 @@ char *normalise_path(const char *pathname)
 
 	slashes[0] = in = out = path;
 
-        while (*in) {
-                if(*in == '/') {
+	while (*in) {
+		if(*in == '/') {
 			slashes[sl++] = out;
-                        *out++ = *in++;
-                        while(*in == '/')
-                                in++;
-                } else {
+			*out++ = *in++;
+			while(*in == '/')
+				in++;
+		} else {
 			if (*in == '.' && (*(in + 1) == '/' || !*(in + 1))) {
 				sl--;
 				if (sl < 0)
@@ -123,16 +123,16 @@ char *normalise_path(const char *pathname)
 				continue;
 			}
                         *out++ = *in++;
-                }
-        }
+		}
+	}
 
 	*out-- = 0;
 
-        /*
-         * Remove trailing slash
-         */
-        if (*out == '/')
-                *out = 0;
+	/*
+	 * Remove trailing slash
+	 */
+	if (*out == '/')
+		*out = 0;
 
 	if (!*path) {
 		*path = '/';
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:42 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:42 +0200
Subject: [PATCH 10/19] ls: Do not depend on normalise_path()
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-11-s.hauer@pengutronix.de>

When we want to show a directory we want to show the path
ls is passed, not the normalised one.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 commands/ls.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/commands/ls.c b/commands/ls.c
index 771477b6e0..e54991862d 100644
--- a/commands/ls.c
+++ b/commands/ls.c
@@ -115,11 +115,8 @@ int ls(const char *path, ulong flags)
 			continue;
 		}
 
-		if (s.st_mode & S_IFDIR) {
-			char *norm = normalise_path(tmp);
-			ls(norm, flags);
-			free(norm);
-		}
+		if (s.st_mode & S_IFDIR)
+			ls(tmp, flags);
 	}
 
 out:
@@ -158,7 +155,7 @@ static int do_ls(int argc, char *argv[])
 		flags |= LS_SHOWARG;
 
 	if (optind == argc) {
-		ret = ls(getcwd(), flags);
+		ret = ls(".", flags);
 		return ret ? 1 : 0;
 	}
 
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:34 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:34 +0200
Subject: [PATCH 02/19] ubifs: remove dead code
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-3-s.hauer@pengutronix.de>

Remove stuff that was added to UBIFS for U-Boot which we do not need
because we already have it in the Linux header files.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ubifs/ubifs.h | 187 -------------------------------------------------------
 1 file changed, 187 deletions(-)

diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 5c5a82637e..5589f99401 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -96,193 +96,6 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp);
 /* uapi/linux/limits.h */
 #define XATTR_LIST_MAX 65536	/* size of extended attribute namelist (64k) */
 
-#ifndef __BAREBOX__
-/* linux/include/time.h */
-#define NSEC_PER_SEC	1000000000L
-#define get_seconds()	0
-#define CURRENT_TIME_SEC	((struct timespec) { get_seconds(), 0 })
-
-struct timespec {
-	time_t	tv_sec;		/* seconds */
-	long	tv_nsec;	/* nanoseconds */
-};
-
-static struct timespec current_fs_time(struct super_block *sb)
-{
-	struct timespec now;
-	now.tv_sec = 0;
-	now.tv_nsec = 0;
-	return now;
-};
-
-/* linux/include/dcache.h */
-
-/*
- * "quick string" -- eases parameter passing, but more importantly
- * saves "metadata" about the string (ie length and the hash).
- *
- * hash comes first so it snuggles against d_parent in the
- * dentry.
- */
-struct qstr {
-	unsigned int hash;
-	unsigned int len;
-#ifndef __BAREBOX__
-	const char *name;
-#else
-	char *name;
-#endif
-};
-
-/* include/linux/fs.h */
-
-/* Possible states of 'frozen' field */
-enum {
-	SB_UNFROZEN = 0,		/* FS is unfrozen */
-	SB_FREEZE_WRITE	= 1,		/* Writes, dir ops, ioctls frozen */
-	SB_FREEZE_PAGEFAULT = 2,	/* Page faults stopped as well */
-	SB_FREEZE_FS = 3,		/* For internal FS use (e.g. to stop
-					 * internal threads if needed) */
-	SB_FREEZE_COMPLETE = 4,		/* ->freeze_fs finished successfully */
-};
-
-#define SB_FREEZE_LEVELS (SB_FREEZE_COMPLETE - 1)
-
-struct sb_writers {
-#ifndef __BAREBOX__
-	/* Counters for counting writers at each level */
-	struct percpu_counter	counter[SB_FREEZE_LEVELS];
-#endif
-	wait_queue_head_t	wait;		/* queue for waiting for
-						   writers / faults to finish */
-	int			frozen;		/* Is sb frozen? */
-	wait_queue_head_t	wait_unfrozen;	/* queue for waiting for
-						   sb to be thawed */
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	lock_map[SB_FREEZE_LEVELS];
-#endif
-};
-
-struct address_space {
-	struct inode		*host;		/* owner: inode, block_device */
-#ifndef __BAREBOX__
-	struct radix_tree_root	page_tree;	/* radix tree of all pages */
-#endif
-	spinlock_t		tree_lock;	/* and lock protecting it */
-	unsigned int		i_mmap_writable;/* count VM_SHARED mappings */
-	struct rb_root		i_mmap;		/* tree of private and shared mappings */
-	struct list_head	i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
-	struct mutex		i_mmap_mutex;	/* protect tree, count, list */
-	/* Protected by tree_lock together with the radix tree */
-	unsigned long		nrpages;	/* number of total pages */
-	pgoff_t			writeback_index;/* writeback starts here */
-	const struct address_space_operations *a_ops;	/* methods */
-	unsigned long		flags;		/* error bits/gfp mask */
-#ifndef __BAREBOX__
-	struct backing_dev_info *backing_dev_info; /* device readahead, etc */
-#endif
-	spinlock_t		private_lock;	/* for use by the address_space */
-	struct list_head	private_list;	/* ditto */
-	void			*private_data;	/* ditto */
-} __attribute__((aligned(sizeof(long))));
-
-/*
- * Keep mostly read-only and often accessed (especially for
- * the RCU path lookup and 'stat' data) fields at the beginning
- * of the 'struct inode'
- */
-struct inode {
-	umode_t			i_mode;
-	unsigned short		i_opflags;
-	kuid_t			i_uid;
-	kgid_t			i_gid;
-	unsigned int		i_flags;
-
-#ifdef CONFIG_FS_POSIX_ACL
-	struct posix_acl	*i_acl;
-	struct posix_acl	*i_default_acl;
-#endif
-
-	const struct inode_operations	*i_op;
-	struct super_block	*i_sb;
-	struct address_space	*i_mapping;
-
-#ifdef CONFIG_SECURITY
-	void			*i_security;
-#endif
-
-	/* Stat data, not accessed from path walking */
-	unsigned long		i_ino;
-	/*
-	 * Filesystems may only read i_nlink directly.  They shall use the
-	 * following functions for modification:
-	 *
-	 *    (set|clear|inc|drop)_nlink
-	 *    inode_(inc|dec)_link_count
-	 */
-	union {
-		const unsigned int i_nlink;
-		unsigned int __i_nlink;
-	};
-	dev_t			i_rdev;
-	loff_t			i_size;
-	struct timespec		i_atime;
-	struct timespec		i_mtime;
-	struct timespec		i_ctime;
-	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
-	unsigned short          i_bytes;
-	unsigned int		i_blkbits;
-	blkcnt_t		i_blocks;
-
-#ifdef __NEED_I_SIZE_ORDERED
-	seqcount_t		i_size_seqcount;
-#endif
-
-	/* Misc */
-	unsigned long		i_state;
-	struct mutex		i_mutex;
-
-	unsigned long		dirtied_when;	/* jiffies of first dirtying */
-
-	struct hlist_node	i_hash;
-	struct list_head	i_wb_list;	/* backing dev IO list */
-	struct list_head	i_lru;		/* inode LRU list */
-	struct list_head	i_sb_list;
-	union {
-		struct hlist_head	i_dentry;
-		struct rcu_head		i_rcu;
-	};
-	u64			i_version;
-	atomic_t		i_count;
-	atomic_t		i_dio_count;
-	atomic_t		i_writecount;
-	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
-	struct file_lock	*i_flock;
-	struct address_space	i_data;
-#ifdef CONFIG_QUOTA
-	struct dquot		*i_dquot[MAXQUOTAS];
-#endif
-	struct list_head	i_devices;
-	union {
-		struct pipe_inode_info	*i_pipe;
-		struct block_device	*i_bdev;
-		struct cdev		*i_cdev;
-	};
-
-	__u32			i_generation;
-
-#ifdef CONFIG_FSNOTIFY
-	__u32			i_fsnotify_mask; /* all events this inode cares about */
-	struct hlist_head	i_fsnotify_marks;
-#endif
-
-#ifdef CONFIG_IMA
-	atomic_t		i_readcount; /* struct files open RO */
-#endif
-	void			*i_private; /* fs or device private pointer */
-};
-#endif
-
 struct super_operations {
    	struct inode *(*alloc_inode)(struct super_block *sb);
 	void (*destroy_inode)(struct inode *);
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:48 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:48 +0200
Subject: [PATCH 16/19] fs: ubifs: Switch to dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-17-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ubifs/Kconfig  |   1 -
 fs/ubifs/Makefile |   2 +-
 fs/ubifs/dir.c    | 410 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/super.c  | 153 ++------------------
 fs/ubifs/ubifs.c  | 341 +--------------------------------------------
 fs/ubifs/ubifs.h  |   7 +-
 6 files changed, 432 insertions(+), 482 deletions(-)
 create mode 100644 fs/ubifs/dir.c

diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index d013ea5780..889a2be97a 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -1,7 +1,6 @@
 menuconfig FS_UBIFS
 	bool
 	depends on MTD_UBI
-	depends on BROKEN
 	prompt "ubifs support"
 
 if FS_UBIFS
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index e39ae3b0fd..44ef1b561c 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -1,4 +1,4 @@
 obj-y += ubifs.o io.o super.o sb.o master.o lpt.o
-obj-y += lpt_commit.o scan.o lprops.o
+obj-y += lpt_commit.o scan.o lprops.o dir.o
 obj-y += tnc.o tnc_misc.o debug.o crc16.o budget.o
 obj-y += log.o orphan.o recovery.o replay.o gc.o
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
new file mode 100644
index 0000000000..e90bdb8348
--- /dev/null
+++ b/fs/ubifs/dir.c
@@ -0,0 +1,410 @@
+/* * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ * Copyright (C) 2006, 2007 University of Szeged, Hungary
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy (???????? ?????)
+ *          Adrian Hunter
+ *          Zoltan Sogor
+ */
+
+/*
+ * This file implements directory operations.
+ *
+ * All FS operations in this file allocate budget before writing anything to the
+ * media. If they fail to allocate it, the error is returned. The only
+ * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even
+ * if they unable to allocate the budget, because deletion %-ENOSPC failure is
+ * not what users are usually ready to get. UBIFS budgeting subsystem has some
+ * space reserved for these purposes.
+ *
+ * All operations in this file write all inodes which they change straight
+ * away, instead of marking them dirty. For example, 'ubifs_link()' changes
+ * @i_size of the parent inode and writes the parent inode together with the
+ * target inode. This was done to simplify file-system recovery which would
+ * otherwise be very difficult to do. The only exception is rename which marks
+ * the re-named inode dirty (because its @i_ctime is updated) but does not
+ * write it, but just marks it as dirty.
+ */
+
+#include "ubifs.h"
+
+/**
+ * inherit_flags - inherit flags of the parent inode.
+ * @dir: parent inode
+ * @mode: new inode mode flags
+ *
+ * This is a helper function for 'ubifs_new_inode()' which inherits flag of the
+ * parent directory inode @dir. UBIFS inodes inherit the following flags:
+ * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on
+ *   sub-directory basis;
+ * o %UBIFS_SYNC_FL - useful for the same reasons;
+ * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories.
+ *
+ * This function returns the inherited flags.
+ */
+static int inherit_flags(const struct inode *dir, umode_t mode)
+{
+	int flags;
+	const struct ubifs_inode *ui = ubifs_inode(dir);
+
+	if (!S_ISDIR(dir->i_mode))
+		/*
+		 * The parent is not a directory, which means that an extended
+		 * attribute inode is being created. No flags.
+		 */
+		return 0;
+
+	flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL);
+	if (!S_ISDIR(mode))
+		/* The "DIRSYNC" flag only applies to directories */
+		flags &= ~UBIFS_DIRSYNC_FL;
+	return flags;
+}
+
+/**
+ * ubifs_new_inode - allocate new UBIFS inode object.
+ * @c: UBIFS file-system description object
+ * @dir: parent directory inode
+ * @mode: inode mode flags
+ *
+ * This function finds an unused inode number, allocates new inode and
+ * initializes it. Returns new inode in case of success and an error code in
+ * case of failure.
+ */
+struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
+			      umode_t mode)
+{
+	struct inode *inode;
+	struct ubifs_inode *ui;
+
+	inode = new_inode(c->vfs_sb);
+	ui = ubifs_inode(inode);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and
+	 * marking them dirty in file write path (see 'file_update_time()').
+	 * UBIFS has to fully control "clean <-> dirty" transitions of inodes
+	 * to make budgeting work.
+	 */
+	inode->i_flags |= S_NOCMTIME;
+
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+		inode->i_op = &ubifs_file_inode_operations;
+		inode->i_fop = &ubifs_file_operations;
+		break;
+	case S_IFDIR:
+		inode->i_op  = &ubifs_dir_inode_operations;
+		inode->i_fop = &ubifs_dir_operations;
+		inode->i_size = ui->ui_size = UBIFS_INO_NODE_SZ;
+		break;
+	case S_IFLNK:
+		inode->i_op = &ubifs_symlink_inode_operations;
+		break;
+	case S_IFSOCK:
+	case S_IFIFO:
+	case S_IFBLK:
+	case S_IFCHR:
+		inode->i_op  = &ubifs_file_inode_operations;
+		break;
+	default:
+		BUG();
+	}
+
+	ui->flags = inherit_flags(dir, mode);
+	ubifs_set_inode_flags(inode);
+	if (S_ISREG(mode))
+		ui->compr_type = c->default_compr;
+	else
+		ui->compr_type = UBIFS_COMPR_NONE;
+	ui->synced_i_size = 0;
+
+	spin_lock(&c->cnt_lock);
+	/* Inode number overflow is currently not supported */
+	if (c->highest_inum >= INUM_WARN_WATERMARK) {
+		if (c->highest_inum >= INUM_WATERMARK) {
+			spin_unlock(&c->cnt_lock);
+			ubifs_err(c, "out of inode numbers");
+			iput(inode);
+			return ERR_PTR(-EINVAL);
+		}
+		ubifs_warn(c, "running out of inode numbers (current %lu, max %u)",
+			   (unsigned long)c->highest_inum, INUM_WATERMARK);
+	}
+
+	inode->i_ino = ++c->highest_inum;
+	/*
+	 * The creation sequence number remains with this inode for its
+	 * lifetime. All nodes for this inode have a greater sequence number,
+	 * and so it is possible to distinguish obsolete nodes belonging to a
+	 * previous incarnation of the same inode number - for example, for the
+	 * purpose of rebuilding the index.
+	 */
+	ui->creat_sqnum = ++c->max_sqnum;
+	spin_unlock(&c->cnt_lock);
+	return inode;
+}
+
+static int dbg_check_name(const struct ubifs_info *c,
+			  const struct ubifs_dent_node *dent,
+			  const struct qstr *nm)
+{
+	if (!dbg_is_chk_gen(c))
+		return 0;
+	if (le16_to_cpu(dent->nlen) != nm->len)
+		return -EINVAL;
+	if (memcmp(dent->name, nm->name, nm->len))
+		return -EINVAL;
+	return 0;
+}
+
+static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
+				   unsigned int flags)
+{
+	int err;
+	union ubifs_key key;
+	struct inode *inode = NULL;
+	struct ubifs_dent_node *dent;
+	struct ubifs_info *c = dir->i_sb->s_fs_info;
+
+	dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
+
+	if (dentry->d_name.len > UBIFS_MAX_NLEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
+	if (!dent)
+		return ERR_PTR(-ENOMEM);
+
+	dent_key_init(c, &key, dir->i_ino, &dentry->d_name);
+
+	err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
+	if (err) {
+		if (err == -ENOENT) {
+			dbg_gen("not found");
+			goto done;
+		}
+		goto out;
+	}
+
+	if (dbg_check_name(c, dent, &dentry->d_name)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
+	if (IS_ERR(inode)) {
+		/*
+		 * This should not happen. Probably the file-system needs
+		 * checking.
+		 */
+		err = PTR_ERR(inode);
+		ubifs_err(c, "dead directory entry '%pd', error %d",
+			dentry, err);
+		ubifs_ro_mode(c, err);
+		goto out;
+	}
+
+done:
+	kfree(dent);
+	/*
+	 * Note, d_splice_alias() would be required instead if we supported
+	 * NFS.
+	 */
+	d_add(dentry, inode);
+	return NULL;
+
+out:
+	kfree(dent);
+	return ERR_PTR(err);
+}
+
+/**
+ * vfs_dent_type - get VFS directory entry type.
+ * @type: UBIFS directory entry type
+ *
+ * This function converts UBIFS directory entry type into VFS directory entry
+ * type.
+ */
+static unsigned int vfs_dent_type(uint8_t type)
+{
+	switch (type) {
+	case UBIFS_ITYPE_REG:
+		return DT_REG;
+	case UBIFS_ITYPE_DIR:
+		return DT_DIR;
+	case UBIFS_ITYPE_LNK:
+		return DT_LNK;
+	case UBIFS_ITYPE_BLK:
+		return DT_BLK;
+	case UBIFS_ITYPE_CHR:
+		return DT_CHR;
+	case UBIFS_ITYPE_FIFO:
+		return DT_FIFO;
+	case UBIFS_ITYPE_SOCK:
+		return DT_SOCK;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+/*
+ * The classical Unix view for directory is that it is a linear array of
+ * (name, inode number) entries. Linux/VFS assumes this model as well.
+ * Particularly, 'readdir()' call wants us to return a directory entry offset
+ * which later may be used to continue 'readdir()'ing the directory or to
+ * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this
+ * model because directory entries are identified by keys, which may collide.
+ *
+ * UBIFS uses directory entry hash value for directory offsets, so
+ * 'seekdir()'/'telldir()' may not always work because of possible key
+ * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work
+ * properly by means of saving full directory entry name in the private field
+ * of the file description object.
+ *
+ * This means that UBIFS cannot support NFS which requires full
+ * 'seekdir()'/'telldir()' support.
+ */
+static int ubifs_readdir(struct file *file, struct dir_context *ctx)
+{
+	int err = 0;
+	struct qstr nm;
+	union ubifs_key key;
+	struct ubifs_dent_node *dent;
+	struct dentry *dentry = file->f_path.dentry;
+	struct inode *dir = d_inode(dentry);
+	struct ubifs_info *c = dir->i_sb->s_fs_info;
+
+	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);
+
+	if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2)
+		/*
+		 * The directory was seek'ed to a senseless position or there
+		 * are no more entries.
+		 */
+		return 0;
+
+	if (file->f_version == 0) {
+		/*
+		 * The file was seek'ed, which means that @file->private_data
+		 * is now invalid. This may also be just the first
+		 * 'ubifs_readdir()' invocation, in which case
+		 * @file->private_data is NULL, and the below code is
+		 * basically a no-op.
+		 */
+		kfree(file->private_data);
+		file->private_data = NULL;
+	}
+
+	/*
+	 * 'generic_file_llseek()' unconditionally sets @file->f_version to
+	 * zero, and we use this for detecting whether the file was seek'ed.
+	 */
+	file->f_version = 1;
+
+	/* File positions 0 and 1 correspond to "." and ".." */
+	if (ctx->pos < 2) {
+		ubifs_assert(!file->private_data);
+		dir_emit_dots(file, ctx);
+
+		/* Find the first entry in TNC and save it */
+		lowest_dent_key(c, &key, dir->i_ino);
+		nm.name = NULL;
+		dent = ubifs_tnc_next_ent(c, &key, &nm);
+		if (IS_ERR(dent)) {
+			err = PTR_ERR(dent);
+			goto out;
+		}
+
+		ctx->pos = key_hash_flash(c, &dent->key);
+		file->private_data = dent;
+	}
+
+	dent = file->private_data;
+	if (!dent) {
+		/*
+		 * The directory was seek'ed to and is now readdir'ed.
+		 * Find the entry corresponding to @ctx->pos or the closest one.
+		 */
+		dent_key_init_hash(c, &key, dir->i_ino, ctx->pos);
+		nm.name = NULL;
+		dent = ubifs_tnc_next_ent(c, &key, &nm);
+		if (IS_ERR(dent)) {
+			err = PTR_ERR(dent);
+			goto out;
+		}
+		ctx->pos = key_hash_flash(c, &dent->key);
+		file->private_data = dent;
+	}
+
+	while (1) {
+		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
+			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
+			key_hash_flash(c, &dent->key));
+		ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
+			     ubifs_inode(dir)->creat_sqnum);
+
+		nm.len = le16_to_cpu(dent->nlen);
+		dir_emit(ctx, dent->name, nm.len,
+			       le64_to_cpu(dent->inum),
+			       vfs_dent_type(dent->type));
+
+		/* Switch to the next entry */
+		key_read(c, &dent->key, &key);
+		nm.name = dent->name;
+		dent = ubifs_tnc_next_ent(c, &key, &nm);
+		if (IS_ERR(dent)) {
+			err = PTR_ERR(dent);
+			goto out;
+		}
+
+		kfree(file->private_data);
+		ctx->pos = key_hash_flash(c, &dent->key);
+		file->private_data = dent;
+		cond_resched();
+	}
+
+out:
+	kfree(file->private_data);
+	file->private_data = NULL;
+
+	if (err != -ENOENT)
+		ubifs_err(c, "cannot find next direntry, error %d", err);
+	else
+		/*
+		 * -ENOENT is a non-fatal error in this context, the TNC uses
+		 * it to indicate that the cursor moved past the current directory
+		 * and readdir() has to stop.
+		 */
+		err = 0;
+
+
+	/* 2 is a special value indicating that there are no more direntries */
+	ctx->pos = 2;
+	return err;
+}
+
+const struct inode_operations ubifs_dir_inode_operations = {
+	.lookup      = ubifs_lookup,
+};
+
+const struct file_operations ubifs_dir_operations = {
+	.iterate        = ubifs_readdir,
+};
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index b4eb76202b..abf8ef63c9 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -30,6 +30,7 @@
 
 #include <common.h>
 #include <init.h>
+#include <fs.h>
 #include <malloc.h>
 #include <linux/bug.h>
 #include <linux/log2.h>
@@ -49,8 +50,6 @@ struct vfsmount;
 struct super_block *ubifs_sb;
 LIST_HEAD(super_blocks);
 
-static struct inode *inodes_locked_down[INODE_LOCKED_MAX];
-
 int set_anon_super(struct super_block *s, void *data)
 {
 	return 0;
@@ -84,39 +83,6 @@ int ubifs_iput(struct inode *inode)
 	return 0;
 }
 
-/*
- * Lock (save) inode in inode array for readback after recovery
- */
-void iput(struct inode *inode)
-{
-	int i;
-	struct inode *ino;
-
-	/*
-	 * Search end of list
-	 */
-	for (i = 0; i < INODE_LOCKED_MAX; i++) {
-		if (inodes_locked_down[i] == NULL)
-			break;
-	}
-
-	if (i >= INODE_LOCKED_MAX) {
-		dbg_gen("Error, can't lock (save) more inodes while recovery!!!");
-		return;
-	}
-
-	/*
-	 * Allocate and use new inode
-	 */
-	ino = (struct inode *)kzalloc(sizeof(struct ubifs_inode), 0);
-	memcpy(ino, inode, sizeof(struct ubifs_inode));
-
-	/*
-	 * Finally save inode in array
-	 */
-	inodes_locked_down[i] = ino;
-}
-
 /* from fs/inode.c */
 /**
  * clear_nlink - directly zero an inode's link count
@@ -231,6 +197,9 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
 	return err;
 }
 
+const struct inode_operations ubifs_file_inode_operations;
+const struct file_operations ubifs_file_operations;
+
 struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 {
 	int err;
@@ -239,35 +208,9 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 	struct ubifs_info *c = sb->s_fs_info;
 	struct inode *inode;
 	struct ubifs_inode *ui;
-#ifdef __BAREBOX__
-	int i;
-#endif
 
 	dbg_gen("inode %lu", inum);
 
-#ifdef __BAREBOX__
-	/*
-	 * U-Boot special handling of locked down inodes via recovery
-	 * e.g. ubifs_recover_size()
-	 */
-	for (i = 0; i < INODE_LOCKED_MAX; i++) {
-		/*
-		 * Exit on last entry (NULL), inode not found in list
-		 */
-		if (inodes_locked_down[i] == NULL)
-			break;
-
-		if (inodes_locked_down[i]->i_ino == inum) {
-			/*
-			 * We found the locked down inode in our array,
-			 * so just return this pointer instead of creating
-			 * a new one.
-			 */
-			return inodes_locked_down[i];
-		}
-	}
-#endif
-
 	inode = iget_locked(sb, inum);
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
@@ -315,10 +258,8 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 	if (err)
 		goto out_invalid;
 
-#ifndef __BAREBOX__
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFREG:
-		inode->i_mapping->a_ops = &ubifs_file_address_operations;
 		inode->i_op = &ubifs_file_inode_operations;
 		inode->i_fop = &ubifs_file_operations;
 		if (ui->xattr) {
@@ -343,7 +284,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 		}
 		break;
 	case S_IFLNK:
-		inode->i_op = &ubifs_symlink_inode_operations;
+		inode->i_op = &simple_symlink_inode_operations;
 		if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) {
 			err = 12;
 			goto out_invalid;
@@ -357,60 +298,10 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 		((char *)ui->data)[ui->data_len] = '\0';
 		inode->i_link = ui->data;
 		break;
-	case S_IFBLK:
-	case S_IFCHR:
-	{
-		dev_t rdev;
-		union ubifs_dev_desc *dev;
-
-		ui->data = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
-		if (!ui->data) {
-			err = -ENOMEM;
-			goto out_ino;
-		}
-
-		dev = (union ubifs_dev_desc *)ino->data;
-		if (ui->data_len == sizeof(dev->new))
-			rdev = new_decode_dev(le32_to_cpu(dev->new));
-		else if (ui->data_len == sizeof(dev->huge))
-			rdev = huge_decode_dev(le64_to_cpu(dev->huge));
-		else {
-			err = 13;
-			goto out_invalid;
-		}
-		memcpy(ui->data, ino->data, ui->data_len);
-		inode->i_op = &ubifs_file_inode_operations;
-		init_special_inode(inode, inode->i_mode, rdev);
-		break;
-	}
-	case S_IFSOCK:
-	case S_IFIFO:
-		inode->i_op = &ubifs_file_inode_operations;
-		init_special_inode(inode, inode->i_mode, 0);
-		if (ui->data_len != 0) {
-			err = 14;
-			goto out_invalid;
-		}
-		break;
 	default:
 		err = 15;
 		goto out_invalid;
 	}
-#else
-	if ((inode->i_mode & S_IFMT) == S_IFLNK) {
-		if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) {
-			err = 12;
-			goto out_invalid;
-		}
-		ui->data = kmalloc(ui->data_len + 1, GFP_NOFS);
-		if (!ui->data) {
-			err = -ENOMEM;
-			goto out_ino;
-		}
-		memcpy(ui->data, ino->data, ui->data_len);
-		((char *)ui->data)[ui->data_len] = '\0';
-	}
-#endif
 
 	kfree(ino);
 #ifndef __BAREBOX__
@@ -447,22 +338,15 @@ static struct inode *ubifs_alloc_inode(struct super_block *sb)
 	return &ui->vfs_inode;
 };
 
-#ifndef __BAREBOX__
-static void ubifs_i_callback(struct rcu_head *head)
-{
-	struct inode *inode = container_of(head, struct inode, i_rcu);
-	struct ubifs_inode *ui = ubifs_inode(inode);
-	kmem_cache_free(ubifs_inode_slab, ui);
-}
-
 static void ubifs_destroy_inode(struct inode *inode)
 {
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
 	kfree(ui->data);
-	call_rcu(&inode->i_rcu, ubifs_i_callback);
+	kfree(ui);
 }
 
+#ifndef __BAREBOX__
 /*
  * Note, Linux write-back code calls this without 'i_mutex'.
  */
@@ -1330,15 +1214,9 @@ static int mount_ubifs(struct ubifs_info *c)
 	long long x, y;
 	size_t sz;
 
-	c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
+	c->ro_mount = true;
 	/* Suppress error messages while probing if MS_SILENT is set */
 	c->probing = !!(c->vfs_sb->s_flags & MS_SILENT);
-#ifdef __BAREBOX__
-	if (!c->ro_mount) {
-		printf("UBIFS: only ro mode in Barebox allowed.\n");
-		return -EACCES;
-	}
-#endif
 
 	err = init_constants_early(c);
 	if (err)
@@ -2099,8 +1977,8 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
 
 const struct super_operations ubifs_super_operations = {
 	.alloc_inode   = ubifs_alloc_inode,
-#ifndef __BAREBOX__
 	.destroy_inode = ubifs_destroy_inode,
+#ifndef __BAREBOX__
 	.put_super     = ubifs_put_super,
 	.write_inode   = ubifs_write_inode,
 	.evict_inode   = ubifs_evict_inode,
@@ -2298,15 +2176,11 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 		goto out_umount;
 	}
 
-#ifndef __BAREBOX__
 	sb->s_root = d_make_root(root);
 	if (!sb->s_root) {
 		err = -ENOMEM;
 		goto out_umount;
 	}
-#else
-	sb->s_root = NULL;
-#endif
 
 	mutex_unlock(&c->umount_mutex);
 	return 0;
@@ -2680,13 +2554,14 @@ MODULE_AUTHOR("Artem Bityutskiy, Adrian Hunter");
 MODULE_DESCRIPTION("UBIFS - UBI File System");
 #endif
 
-struct super_block *ubifs_get_super(struct device_d *dev, struct ubi_volume_desc *ubi, int silent)
+int ubifs_get_super(struct device_d *dev, struct ubi_volume_desc *ubi, int silent)
 {
+	struct fs_device_d *fsdev = dev_to_fs_device(dev);
 	struct super_block *sb;
 	struct ubifs_info *c;
 	int err;
 
-	sb = alloc_super(NULL, MS_RDONLY | MS_ACTIVE | MS_NOATIME);
+	sb = &fsdev->sb;
 	c = alloc_ubifs_info(ubi);
 
 	c->dev = dev;
@@ -2712,9 +2587,9 @@ struct super_block *ubifs_get_super(struct device_d *dev, struct ubi_volume_desc
 		goto out;
 	}
 
-	return sb;
+	return 0;
 out:
 	kfree(c);
 	kfree(sb);
-	return ERR_PTR(err);
+	return err;
 }
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index a525b044b8..f9b4f4babc 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -269,161 +269,6 @@ int __init ubifs_compressors_init(void)
 	return 0;
 }
 
-/*
- * ubifsls...
- */
-
-static int ubifs_finddir(struct super_block *sb, char *dirname,
-			 unsigned long root_inum, unsigned long *inum)
-{
-	int err;
-	struct qstr nm;
-	union ubifs_key key;
-	struct ubifs_dent_node *dent;
-	struct ubifs_info *c;
-	struct file *file;
-	struct dentry *dentry;
-	struct inode *dir;
-	int ret = 0;
-
-	file = kzalloc(sizeof(struct file), 0);
-	dentry = kzalloc(sizeof(struct dentry), 0);
-	dir = kzalloc(sizeof(struct inode), 0);
-	if (!file || !dentry || !dir) {
-		printf("%s: Error, no memory for malloc!\n", __func__);
-		err = -ENOMEM;
-		goto out;
-	}
-
-	dir->i_sb = sb;
-	file->f_path.dentry = dentry;
-	file->f_path.dentry->d_parent = dentry;
-	file->f_path.dentry->d_inode = dir;
-	file->f_path.dentry->d_inode->i_ino = root_inum;
-	c = sb->s_fs_info;
-
-	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
-
-	/* Find the first entry in TNC and save it */
-	lowest_dent_key(c, &key, dir->i_ino);
-	nm.name = NULL;
-	dent = ubifs_tnc_next_ent(c, &key, &nm);
-	if (IS_ERR(dent)) {
-		err = PTR_ERR(dent);
-		goto out;
-	}
-
-	file->f_pos = key_hash_flash(c, &dent->key);
-	file->private_data = dent;
-
-	while (1) {
-		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
-			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
-			key_hash_flash(c, &dent->key));
-		ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
-
-		nm.len = le16_to_cpu(dent->nlen);
-		if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
-		    (strlen(dirname) == nm.len)) {
-			*inum = le64_to_cpu(dent->inum);
-			ret = 1;
-			goto out_free;
-		}
-
-		/* Switch to the next entry */
-		key_read(c, &dent->key, &key);
-		nm.name = (char *)dent->name;
-		dent = ubifs_tnc_next_ent(c, &key, &nm);
-		if (IS_ERR(dent)) {
-			err = PTR_ERR(dent);
-			goto out;
-		}
-
-		kfree(file->private_data);
-		file->f_pos = key_hash_flash(c, &dent->key);
-		file->private_data = dent;
-		cond_resched();
-	}
-
-out:
-	if (err != -ENOENT)
-		dbg_gen("cannot find next direntry, error %d", err);
-
-out_free:
-	if (file->private_data)
-		kfree(file->private_data);
-	if (file)
-		free(file);
-	if (dentry)
-		free(dentry);
-	if (dir)
-		free(dir);
-
-	return ret;
-}
-
-static unsigned long ubifs_findfile(struct super_block *sb, const char *filename)
-{
-	int ret;
-	char *next;
-	char fpath[128];
-	char *name = fpath;
-	unsigned long root_inum = 1;
-	unsigned long inum;
-
-	strcpy(fpath, filename);
-
-	/* Remove all leading slashes */
-	while (*name == '/')
-		name++;
-
-	/*
-	 * Handle root-direcoty ('/')
-	 */
-	inum = root_inum;
-	if (!name || *name == '\0')
-		return inum;
-
-	for (;;) {
-		struct inode *inode;
-		struct ubifs_inode *ui;
-
-		/* Extract the actual part from the pathname.  */
-		next = strchr(name, '/');
-		if (next) {
-			/* Remove all leading slashes.  */
-			while (*next == '/')
-				*(next++) = '\0';
-		}
-
-		ret = ubifs_finddir(sb, name, root_inum, &inum);
-		if (!ret)
-			return 0;
-		inode = ubifs_iget(sb, inum);
-
-		if (IS_ERR(inode))
-			return 0;
-		ui = ubifs_inode(inode);
-
-		/*
-		 * Check if directory with this name exists
-		 */
-
-		/* Found the node!  */
-		if (!next || *next == '\0')
-			return inum;
-
-		root_inum = inum;
-		name = next;
-	}
-
-	return 0;
-}
-
-/*
- * ubifsload...
- */
-
 /* file.c */
 
 static inline void *kmap(struct page *page)
@@ -487,18 +332,8 @@ struct ubifs_file {
 
 static int ubifs_open(struct device_d *dev, FILE *file, const char *filename)
 {
-	struct ubifs_priv *priv = dev->priv;
-	struct inode *inode;
+	struct inode *inode = file->f_inode;
 	struct ubifs_file *uf;
-	unsigned long inum;
-
-	inum = ubifs_findfile(priv->sb, filename);
-	if (!inum)
-		return -ENOENT;
-
-	inode = ubifs_iget(priv->sb, inum);
-	if (IS_ERR(inode))
-		return -ENOENT;
 
 	uf = xzalloc(sizeof(*uf));
 
@@ -516,9 +351,6 @@ static int ubifs_open(struct device_d *dev, FILE *file, const char *filename)
 static int ubifs_close(struct device_d *dev, FILE *f)
 {
 	struct ubifs_file *uf = f->priv;
-	struct inode *inode = uf->inode;
-
-	ubifs_iput(inode);
 
 	free(uf->buf);
 	free(uf->dn);
@@ -596,163 +428,6 @@ static loff_t ubifs_lseek(struct device_d *dev, FILE *f, loff_t pos)
 	return pos;
 }
 
-struct ubifs_dir {
-	struct file file;
-	struct dentry dentry;
-	struct inode inode;
-	DIR dir;
-	union ubifs_key key;
-	struct ubifs_dent_node *dent;
-	struct ubifs_priv *priv;
-	struct qstr nm;
-};
-
-static DIR *ubifs_opendir(struct device_d *dev, const char *pathname)
-{
-	struct ubifs_priv *priv = dev->priv;
-	struct ubifs_dir *dir;
-	struct file *file;
-	struct dentry *dentry;
-	struct inode *inode;
-	unsigned long inum;
-	struct ubifs_info *c = priv->sb->s_fs_info;
-
-	inum = ubifs_findfile(priv->sb, pathname);
-	if (!inum)
-		return NULL;
-
-	inode = ubifs_iget(priv->sb, inum);
-	if (IS_ERR(inode))
-		return NULL;
-
-	ubifs_iput(inode);
-
-	dir = xzalloc(sizeof(*dir));
-
-	dir->priv = priv;
-
-	file = &dir->file;
-	dentry = &dir->dentry;
-	inode = &dir->inode;
-
-	inode->i_sb = priv->sb;
-	file->f_path.dentry = dentry;
-	file->f_path.dentry->d_parent = dentry;
-	file->f_path.dentry->d_inode = inode;
-	file->f_path.dentry->d_inode->i_ino = inum;
-	file->f_pos = 1;
-
-	/* Find the first entry in TNC and save it */
-	lowest_dent_key(c, &dir->key, inode->i_ino);
-
-	return &dir->dir;
-}
-
-static struct dirent *ubifs_readdir(struct device_d *dev, DIR *_dir)
-{
-	struct ubifs_dir *dir = container_of(_dir, struct ubifs_dir, dir);
-	struct ubifs_info *c = dir->priv->sb->s_fs_info;
-	struct ubifs_dent_node *dent;
-	struct qstr *nm = &dir->nm;
-	struct file *file = &dir->file;
-
-	dent = ubifs_tnc_next_ent(c, &dir->key, nm);
-	if (IS_ERR(dent))
-		return NULL;
-
-	debug("feed '%s', ino %llu, new f_pos %#x\n",
-		dent->name, (unsigned long long)le64_to_cpu(dent->inum),
-		key_hash_flash(c, &dent->key));
-
-	ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(&dir->inode)->creat_sqnum);
-
-	key_read(c, &dent->key, &dir->key);
-	file->f_pos = key_hash_flash(c, &dent->key);
-	file->private_data = dent;
-
-	nm->len = le16_to_cpu(dent->nlen);
-	nm->name = dent->name;
-
-	strcpy(_dir->d.d_name, dent->name);
-
-	free(dir->dent);
-	dir->dent = dent;
-
-	return &_dir->d;
-}
-
-static int ubifs_closedir(struct device_d *dev, DIR *_dir)
-{
-	struct ubifs_dir *dir = container_of(_dir, struct ubifs_dir, dir);
-
-	free(dir->dent);
-	free(dir);
-
-	return 0;
-}
-
-static int ubifs_stat(struct device_d *dev, const char *filename, struct stat *s)
-{
-	struct ubifs_priv *priv = dev->priv;
-	struct inode *inode;
-	unsigned long inum;
-
-	inum = ubifs_findfile(priv->sb, filename);
-	if (!inum)
-		return -ENOENT;
-
-	inode = ubifs_iget(priv->sb, inum);
-	if (IS_ERR(inode))
-		return -ENOENT;
-
-	s->st_size = inode->i_size;
-	s->st_mode = inode->i_mode;
-
-	ubifs_iput(inode);
-
-	return 0;
-}
-
-static char *ubifs_symlink(struct inode *inode)
-{
-	struct ubifs_inode *ui;
-	char *symlink;
-
-	ui = ubifs_inode(inode);
-	symlink = malloc(ui->data_len + 1);
-
-	memcpy(symlink, ui->data, ui->data_len);
-	symlink[ui->data_len] = '\0';
-
-	return symlink;
-}
-
-static int ubifs_readlink(struct device_d *dev, const char *pathname, char *buf,
-			size_t bufsz)
-{
-	struct ubifs_priv *priv = dev->priv;
-	struct inode *inode;
-	char *symlink;
-	int len;
-	unsigned long inum;
-
-	inum = ubifs_findfile(priv->sb, pathname);
-	if (!inum)
-		return -ENOENT;
-
-	inode = ubifs_iget(priv->sb, inum);
-	if (!inode)
-		return -ENOENT;
-
-	symlink = ubifs_symlink(inode);
-
-	len = min(bufsz, strlen(symlink));
-	memcpy(buf, symlink, len);
-	free(symlink);
-
-	return 0;
-}
-
 void ubifs_set_rootarg(struct ubifs_priv *priv, struct fs_device_d *fsdev)
 {
 	struct ubi_volume_info vi = {};
@@ -795,11 +470,11 @@ static int ubifs_probe(struct device_d *dev)
 		goto err_free;
 	}
 
-	priv->sb = ubifs_get_super(dev, priv->ubi, 0);
-	if (IS_ERR(priv->sb)) {
-		ret = PTR_ERR(priv->sb);
+	ret = ubifs_get_super(dev, priv->ubi, 0);
+	if (ret)
 		goto err;
-	}
+
+	priv->sb = &fsdev->sb;
 
 	ubifs_set_rootarg(priv, fsdev);
 
@@ -821,7 +496,6 @@ static void ubifs_remove(struct device_d *dev)
 	ubi_close_volume(priv->ubi);
 
 	free(c);
-	free(sb);
 
 	free(priv);
 }
@@ -831,11 +505,6 @@ static struct fs_driver_d ubifs_driver = {
 	.close     = ubifs_close,
 	.read      = ubifs_read,
 	.lseek     = ubifs_lseek,
-	.opendir   = ubifs_opendir,
-	.readdir   = ubifs_readdir,
-	.closedir  = ubifs_closedir,
-	.stat      = ubifs_stat,
-	.readlink  = ubifs_readlink,
 	.type = filetype_ubifs,
 	.flags     = 0,
 	.drv = {
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 22b24a1161..4c4c927de9 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -36,6 +36,7 @@
 #include <lzo.h>
 #include <crc.h>
 #include <linux/fs.h>
+#include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/ctype.h>
 #include <linux/time.h>
@@ -49,11 +50,9 @@
 
 #define crc32(seed, data, length)  crc32_no_comp(seed, (unsigned char const *)data, length)
 
-struct dentry;
 struct file;
 struct iattr;
 struct kstat;
-struct vfsmount;
 
 extern struct super_block *ubifs_sb;
 
@@ -72,8 +71,6 @@ struct page {
 	struct inode *inode;
 };
 
-void iput(struct inode *inode);
-
 struct kmem_cache { int sz; };
 
 struct kmem_cache *get_mem(int element_sz);
@@ -1901,7 +1898,7 @@ int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
 
 #ifdef __BAREBOX__
 void ubifs_umount(struct ubifs_info *c);
-struct super_block *ubifs_get_super(struct device_d *dev, struct ubi_volume_desc *ubi, int silent);
+int ubifs_get_super(struct device_d *dev, struct ubi_volume_desc *ubi, int silent);
 #endif
 
 #endif /* !__UBIFS_H__ */
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:40 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:40 +0200
Subject: [PATCH 08/19] fs: Fix finding correct directory for mkdir/rmdir
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-9-s.hauer@pengutronix.de>

When there are links in the path mkdir/rmdir are called with then
canonicalize_path is needed which resolves the links.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/fs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index 92f336b821..b66cc9b178 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -1660,7 +1660,7 @@ int mkdir (const char *pathname, mode_t mode)
 {
 	struct fs_driver_d *fsdrv;
 	struct fs_device_d *fsdev;
-	char *p = normalise_path(pathname);
+	char *p = canonicalize_path(pathname);
 	char *freep = p;
 	int ret;
 	struct stat s;
@@ -1700,7 +1700,7 @@ int rmdir (const char *pathname)
 {
 	struct fs_driver_d *fsdrv;
 	struct fs_device_d *fsdev;
-	char *p = normalise_path(pathname);
+	char *p = canonicalize_path(pathname);
 	char *freep = p;
 	int ret;
 	struct stat s;
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:32 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:32 +0200
Subject: [PATCH 00/19] Add Linux dcache implementation
Message-ID: <20180403074851.5411-1-s.hauer@pengutronix.de>

This series adds the Linux dcache implementation to barebox.

Until now every filesystem driver resolves the full path to a file for
itself. This leads to code duplication and is error prone since
resolving paths is a complicated task. Also it can narrow down the
lookup performance since barebox only knows ASCII paths and has no way
of caching lookups. Since with this barebox provides a interface to
dentries much like the Linux Kernel does it gets easier to share
filesystem code between barebox and Linux.

With this series we get the Linux dcache implementation. The path
resolving code from fs/namei.c is nearly taken as-is, minus the RCU and
locking code. Dcaching is made simple as of now: We simply cache
everything and never release any dentries. Although we do reference
counting for inodes and dentries it is effectively not used yet.  We
never free anything until a fs is unmounted in which case we free
everything no matter if references are taken or not.

This patch fundamentally changes the way lookups are done in the
filesystem drivers and I found no sane way to maintain a backwards
compatible code path for not yet converted filesystem drivers. This
means *all* filesystems are marked as broken with the introduction of
the dcache implementation.

I won't apply this series for now (except for the preparatory pathces).
The most important filesystems are already converted with this series,
but there are a few missing like FAT and squashfs and some more no so
prominent ones.

Overall I planned this change for longer now and I can say the new code
feels good. The performance is better, links are resolved more correctly
and the individual filesystem implementations get simpler. I'll continue
on this series soon, but it'll need some time to fix the remaining
filesystems (of course, feel free to do some of the work to speed things
up;)

Sascha

Sascha Hauer (19):
  rename file_operations -> cdev_operations
  ubifs: remove dead code
  ubifs: Remove Linux struct definitions we already have
  ubifs: remove dead code
  fs: Add super_operations
  fs: Move mem_write/mem_read to devfs-core
  fs: Cleanup whitespace damage
  fs: Fix finding correct directory for mkdir/rmdir
  glob: do not unnecessarily opendir() a directory
  ls: Do not depend on normalise_path()
  loadenv: Do not depend on normalise_path()
  fs: dcache implementation
  fs: ramfs: Switch to dcache implementation
  fs: devfs: Switch to dcache implementation
  fs: ext4: Switch to dcache implementation
  fs: ubifs: Switch to dcache implementation
  fs: nfs: Switch to dcache implementation
  fs: tftp: Switch to dcache implementation
  block: Adjust cache sizes

 arch/arm/mach-mxs/ocotp.c     |    2 +-
 arch/sandbox/board/hostfile.c |    2 +-
 commands/loadenv.c            |    6 +-
 commands/ls.c                 |    9 +-
 commands/mem.c                |    2 +-
 commands/stddev.c             |    8 +-
 common/block.c                |    6 +-
 common/firmware.c             |    2 +-
 drivers/base/regmap/regmap.c  |    2 +-
 drivers/eeprom/at24.c         |    2 +-
 drivers/eeprom/at25.c         |    2 +-
 drivers/hw_random/core.c      |    2 +-
 drivers/mfd/act8846.c         |    2 +-
 drivers/mfd/lp3972.c          |    2 +-
 drivers/mfd/mc34704.c         |    2 +-
 drivers/mfd/mc9sdz60.c        |    2 +-
 drivers/mfd/stmpe-i2c.c       |    2 +-
 drivers/mfd/twl-core.c        |    2 +-
 drivers/misc/jtag.c           |    2 +-
 drivers/misc/sram.c           |    2 +-
 drivers/mtd/core.c            |    2 +-
 drivers/mtd/mtdoob.c          |    2 +-
 drivers/mtd/mtdraw.c          |    4 +-
 drivers/mtd/nand/nand-bb.c    |    2 +-
 drivers/mtd/ubi/barebox.c     |    4 +-
 drivers/net/e1000/eeprom.c    |    4 +-
 drivers/net/ksz8864rmn.c      |    2 +-
 drivers/net/phy/mdio_bus.c    |    2 +-
 drivers/nvmem/core.c          |    2 +-
 drivers/video/fb.c            |    2 +-
 drivers/w1/slaves/w1_ds2431.c |    2 +-
 drivers/w1/slaves/w1_ds2433.c |    2 +-
 fs/Kconfig                    |    8 +
 fs/Makefile                   |    2 +-
 fs/devfs-core.c               |   70 +-
 fs/devfs.c                    |  150 +-
 fs/ext4/ext_barebox.c         |  280 ++--
 fs/ext4/ext_common.h          |    3 +
 fs/fat/Kconfig                |    1 +
 fs/fs.c                       | 3696 ++++++++++++++++++++++++++---------------
 fs/libfs.c                    |   87 +
 fs/nfs.c                      |  542 +++---
 fs/pstore/Kconfig             |    1 +
 fs/ramfs.c                    |  412 ++---
 fs/squashfs/Kconfig           |    1 +
 fs/tftp.c                     |   96 +-
 fs/ubifs/Makefile             |    2 +-
 fs/ubifs/dir.c                |  410 +++++
 fs/ubifs/super.c              |  157 +-
 fs/ubifs/ubifs.c              |  816 +--------
 fs/ubifs/ubifs.h              |  547 +-----
 include/console.h             |    2 +-
 include/dirent.h              |    3 +
 include/driver.h              |    4 +-
 include/fs.h                  |   25 +-
 include/linux/dcache.h        |  109 +-
 include/linux/fs.h            |  136 +-
 include/linux/mount.h         |    3 +
 include/linux/namei.h         |   52 +
 include/linux/stat.h          |    2 +
 include/mfd/twl-core.h        |    2 +-
 lib/glob.c                    |   15 +-
 62 files changed, 3960 insertions(+), 3765 deletions(-)
 create mode 100644 fs/libfs.c
 create mode 100644 fs/ubifs/dir.c
 create mode 100644 include/linux/namei.h

-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:46 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:46 +0200
Subject: [PATCH 14/19] fs: devfs: Switch to dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-15-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/Kconfig |   1 -
 fs/devfs.c | 150 ++++++++++++++++++++++++++++++++++---------------------------
 2 files changed, 85 insertions(+), 66 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index 9638e27dbd..e3460e4443 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -25,7 +25,6 @@ config FS_RAMFS
 config FS_DEVFS
 	bool
 	default y
-	depends on BROKEN
 	prompt "devfs support"
 
 config FS_TFTP
diff --git a/fs/devfs.c b/fs/devfs.c
index 2a7b1b3466..5d0bb2c674 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -33,6 +33,11 @@
 #include <linux/mtd/mtd-abi.h>
 #include <partition.h>
 
+struct devfs_inode {
+	struct inode inode;
+	struct cdev *cdev;
+};
+
 extern struct list_head cdev_list;
 
 static int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
@@ -110,14 +115,11 @@ static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags)
 
 static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
 {
-	struct cdev *cdev;
+	struct inode *inode = f->f_inode;
+	struct devfs_inode *node = container_of(inode, struct devfs_inode, inode);
+	struct cdev *cdev = node->cdev;
 	int ret;
 
-	cdev = cdev_by_name(filename + 1);
-
-	if (!cdev)
-		return -ENOENT;
-
 	f->size = cdev->flags & DEVFS_IS_CHARACTER_DEV ?
 			FILE_SIZE_STREAM : cdev->size;
 	f->priv = cdev;
@@ -180,71 +182,112 @@ static int devfs_truncate(struct device_d *dev, FILE *f, ulong size)
 	return 0;
 }
 
-static DIR* devfs_opendir(struct device_d *dev, const char *pathname)
+static struct inode *devfs_alloc_inode(struct super_block *sb)
 {
-	DIR *dir;
-
-	dir = xzalloc(sizeof(DIR));
+	struct devfs_inode *node;
 
-	if (!list_empty(&cdev_list))
-		dir->priv = list_first_entry(&cdev_list, struct cdev, list);
+	node = xzalloc(sizeof(*node));
+	if (!node)
+		return NULL;
 
-	return dir;
+	return &node->inode;
 }
 
-static struct dirent* devfs_readdir(struct device_d *_dev, DIR *dir)
+int devfs_iterate(struct file *file, struct dir_context *ctx)
 {
-	struct cdev *cdev = dir->priv;
+	struct cdev *cdev;
 
-	if (!cdev)
-		return NULL;
+	dir_emit_dots(file, ctx);
 
-	list_for_each_entry_from(cdev, &cdev_list, list) {
-		strcpy(dir->d.d_name, cdev->name);
-		dir->priv = list_entry(cdev->list.next, struct cdev, list);
-		return &dir->d;
+	list_for_each_entry(cdev, &cdev_list, list) {
+		dir_emit(ctx, cdev->name, strlen(cdev->name),
+				1 /* FIXME */, DT_REG);
 	}
-	return NULL;
+
+        return 0;
 }
 
-static int devfs_closedir(struct device_d *dev, DIR *dir)
+static const struct inode_operations devfs_file_inode_operations;
+static const struct file_operations devfs_dir_operations;
+static const struct inode_operations devfs_dir_inode_operations;
+static const struct file_operations devfs_file_operations;
+
+static struct inode *devfs_get_inode(struct super_block *sb, const struct inode *dir,
+                                     umode_t mode)
 {
-	free(dir);
-	return 0;
+	struct inode *inode = new_inode(sb);
+
+	if (!inode)
+		return NULL;
+
+	inode->i_ino = get_next_ino();
+	inode->i_mode = mode;
+
+	switch (mode & S_IFMT) {
+	default:
+		return NULL;
+	case S_IFREG:
+		inode->i_op = &devfs_file_inode_operations;
+		inode->i_fop = &devfs_file_operations;
+		break;
+	case S_IFDIR:
+		inode->i_op = &devfs_dir_inode_operations;
+		inode->i_fop = &devfs_dir_operations;
+		inc_nlink(inode);
+		break;
+	}
+
+	return inode;
 }
 
-static int devfs_stat(struct device_d *_dev, const char *filename, struct stat *s)
+static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry,
+				   unsigned int flags)
 {
+	struct devfs_inode *dinode;
+	struct inode *inode;
 	struct cdev *cdev;
 
-	cdev = lcdev_by_name(filename + 1);
+	cdev = cdev_by_name(dentry->name);
 	if (!cdev)
-		return -ENOENT;
+		return ERR_PTR(-ENOENT);
 
-	s->st_mode = S_IFCHR;
-	s->st_size = cdev->size;
+	inode = devfs_get_inode(dir->i_sb, dir, S_IFREG | S_IRWXUGO);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
 
-	if (cdev->link)
-		s->st_mode |= S_IFLNK;
+	dinode = container_of(inode, struct devfs_inode, inode);
 
-	cdev = cdev_readlink(cdev);
+	inode->i_size = cdev->size;
+	dinode->cdev = cdev;
 
-	if (cdev->ops->write)
-		s->st_mode |= S_IWUSR;
-	if (cdev->ops->read)
-		s->st_mode |= S_IRUSR;
+	d_add(dentry, inode);
 
-	return 0;
+	return NULL;
 }
 
+static const struct file_operations devfs_dir_operations = {
+	.iterate = devfs_iterate,
+};
+
+static const struct inode_operations devfs_dir_inode_operations =
+{
+	.lookup = devfs_lookup,
+};
+
+static const struct super_operations devfs_ops = {
+	.alloc_inode = devfs_alloc_inode,
+};
+
 static int devfs_probe(struct device_d *dev)
 {
+	struct inode *inode;
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
+	struct super_block *sb = &fsdev->sb;
 
-	if (strcmp(fsdev->path, "/dev")) {
-		dev_err(dev, "devfs can only be mounted on /dev/\n");
-		return -EINVAL;
-	}
+	sb->s_op = &devfs_ops;
+
+	inode = devfs_get_inode(sb, NULL, S_IFDIR);
+	sb->s_root = d_make_root(inode);
 
 	return 0;
 }
@@ -253,24 +296,6 @@ static void devfs_delete(struct device_d *dev)
 {
 }
 
-static int devfs_readlink(struct device_d *dev, const char *pathname,
-			  char *buf, size_t bufsz)
-{
-	struct cdev *cdev;
-
-	cdev = cdev_by_name(pathname + 1);
-	if (!cdev)
-		return -ENOENT;
-
-	while (cdev->link)
-		cdev = cdev->link;
-
-	bufsz = min(bufsz, strlen(cdev->name));
-	memcpy(buf, cdev->name, bufsz);
-
-	return 0;
-}
-
 static struct fs_driver_d devfs_driver = {
 	.read      = devfs_read,
 	.write     = devfs_write,
@@ -279,15 +304,10 @@ static struct fs_driver_d devfs_driver = {
 	.close     = devfs_close,
 	.flush     = devfs_flush,
 	.ioctl     = devfs_ioctl,
-	.opendir   = devfs_opendir,
-	.readdir   = devfs_readdir,
 	.truncate  = devfs_truncate,
-	.closedir  = devfs_closedir,
-	.stat      = devfs_stat,
 	.erase     = devfs_erase,
 	.protect   = devfs_protect,
 	.memmap    = devfs_memmap,
-	.readlink  = devfs_readlink,
 	.flags     = FS_DRIVER_NO_DEV,
 	.drv = {
 		.probe  = devfs_probe,
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:35 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:35 +0200
Subject: [PATCH 03/19] ubifs: Remove Linux struct definitions we already have
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-4-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ubifs/ubifs.h | 318 +------------------------------------------------------
 1 file changed, 1 insertion(+), 317 deletions(-)

diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 5589f99401..1391bd7283 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -42,6 +42,7 @@
 #include <linux/math64.h>
 #include <linux/rbtree.h>
 #include <linux/mtd/ubi.h>
+#include <linux/pagemap.h>
 #include <asm/atomic.h>
 #include <asm-generic/atomic-long.h>
 #include "ubifs-media.h"
@@ -131,328 +132,11 @@ struct super_operations {
 	long (*free_cached_objects)(struct super_block *, long, int);
 };
 
-#ifndef __BAREBOX__
-struct super_block {
-	struct list_head	s_list;		/* Keep this first */
-	dev_t			s_dev;		/* search index; _not_ kdev_t */
-	unsigned char		s_blocksize_bits;
-	unsigned long		s_blocksize;
-	loff_t			s_maxbytes;	/* Max file size */
-	struct file_system_type	*s_type;
-	const struct super_operations	*s_op;
-	const struct dquot_operations	*dq_op;
-	const struct quotactl_ops	*s_qcop;
-	const struct export_operations *s_export_op;
-	unsigned long		s_flags;
-	unsigned long		s_magic;
-	struct dentry		*s_root;
-	struct rw_semaphore	s_umount;
-	int			s_count;
-	atomic_t		s_active;
-#ifdef CONFIG_SECURITY
-	void                    *s_security;
-#endif
-	const struct xattr_handler **s_xattr;
-
-	struct list_head	s_inodes;	/* all inodes */
-#ifndef __BAREBOX__
-	struct hlist_bl_head	s_anon;		/* anonymous dentries for (nfs) exporting */
-#endif
-	struct list_head	s_mounts;	/* list of mounts; _not_ for fs use */
-	struct block_device	*s_bdev;
-#ifndef __BAREBOX__
-	struct backing_dev_info *s_bdi;
-#endif
-	struct mtd_info		*s_mtd;
-	struct hlist_node	s_instances;
-#ifndef __BAREBOX__
-	struct quota_info	s_dquot;	/* Diskquota specific options */
-#endif
-
-	struct sb_writers	s_writers;
-
-	char s_id[32];				/* Informational name */
-	u8 s_uuid[16];				/* UUID */
-
-	void 			*s_fs_info;	/* Filesystem private info */
-	unsigned int		s_max_links;
-#ifndef __BAREBOX__
-	fmode_t			s_mode;
-#endif
-
-	/* Granularity of c/m/atime in ns.
-	   Cannot be worse than a second */
-	u32		   s_time_gran;
-
-	/*
-	 * The next field is for VFS *only*. No filesystems have any business
-	 * even looking at it. You had been warned.
-	 */
-	struct mutex s_vfs_rename_mutex;	/* Kludge */
-
-	/*
-	 * Filesystem subtype.  If non-empty the filesystem type field
-	 * in /proc/mounts will be "type.subtype"
-	 */
-	char *s_subtype;
-
-#ifndef __BAREBOX__
-	/*
-	 * Saved mount options for lazy filesystems using
-	 * generic_show_options()
-	 */
-	char __rcu *s_options;
-#endif
-	const struct dentry_operations *s_d_op; /* default d_op for dentries */
-
-	/*
-	 * Saved pool identifier for cleancache (-1 means none)
-	 */
-	int cleancache_poolid;
-
-#ifndef __BAREBOX__
-	struct shrinker s_shrink;	/* per-sb shrinker handle */
-#endif
-
-	/* Number of inodes with nlink == 0 but still referenced */
-	atomic_long_t s_remove_count;
-
-	/* Being remounted read-only */
-	int s_readonly_remount;
-
-	/* AIO completions deferred from interrupt context */
-	struct workqueue_struct *s_dio_done_wq;
-
-#ifndef __BAREBOX__
-	/*
-	 * Keep the lru lists last in the structure so they always sit on their
-	 * own individual cachelines.
-	 */
-	struct list_lru		s_dentry_lru ____cacheline_aligned_in_smp;
-	struct list_lru		s_inode_lru ____cacheline_aligned_in_smp;
-#endif
-	struct rcu_head		rcu;
-};
-
-struct file_system_type {
-	const char *name;
-	int fs_flags;
-#define FS_REQUIRES_DEV		1
-#define FS_BINARY_MOUNTDATA	2
-#define FS_HAS_SUBTYPE		4
-#define FS_USERNS_MOUNT		8	/* Can be mounted by userns root */
-#define FS_USERNS_DEV_MOUNT	16 /* A userns mount does not imply MNT_NODEV */
-#define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
-	struct dentry *(*mount) (struct file_system_type *, int,
-		       const char *, void *);
-	void (*kill_sb) (struct super_block *);
-	struct module *owner;
-	struct file_system_type * next;
-	struct hlist_head fs_supers;
-
-#ifndef __BAREBOX__
-	struct lock_class_key s_lock_key;
-	struct lock_class_key s_umount_key;
-	struct lock_class_key s_vfs_rename_key;
-	struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];
-
-	struct lock_class_key i_lock_key;
-	struct lock_class_key i_mutex_key;
-	struct lock_class_key i_mutex_dir_key;
-#endif
-};
-
-/* include/linux/mount.h */
-struct vfsmount {
-	struct dentry *mnt_root;	/* root of the mounted tree */
-	struct super_block *mnt_sb;	/* pointer to superblock */
-	int mnt_flags;
-};
-
-struct path {
-	struct vfsmount *mnt;
-	struct dentry *dentry;
-};
-
-struct file {
-	struct path		f_path;
-#define f_dentry	f_path.dentry
-#define f_vfsmnt	f_path.mnt
-	const struct file_operations	*f_op;
-	unsigned int 		f_flags;
-	loff_t			f_pos;
-	unsigned int		f_uid, f_gid;
-
-	u64			f_version;
-#ifdef CONFIG_SECURITY
-	void			*f_security;
-#endif
-	/* needed for tty driver, and maybe others */
-	void			*private_data;
-
-#ifdef CONFIG_EPOLL
-	/* Used by fs/eventpoll.c to link all the hooks to this file */
-	struct list_head	f_ep_links;
-	spinlock_t		f_ep_lock;
-#endif /* #ifdef CONFIG_EPOLL */
-#ifdef CONFIG_DEBUG_WRITECOUNT
-	unsigned long f_mnt_write_state;
-#endif
-};
-#endif
-
 /*
  * get_seconds() not really needed in the read-only implmentation
  */
 #define get_seconds()		0
 
-/* 4k page size */
-#define PAGE_CACHE_SHIFT	12
-#define PAGE_CACHE_SIZE		(1 << PAGE_CACHE_SHIFT)
-
-#ifndef __BAREBOX__
-/* Page cache limit. The filesystems should put that into their s_maxbytes
-   limits, otherwise bad things can happen in VM. */
-#if BITS_PER_LONG==32
-#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
-#elif BITS_PER_LONG==64
-#define MAX_LFS_FILESIZE 	0x7fffffffffffffffUL
-#endif
-
-/*
- * These are the fs-independent mount-flags: up to 32 flags are supported
- */
-#define MS_RDONLY	 1	/* Mount read-only */
-#define MS_NOSUID	 2	/* Ignore suid and sgid bits */
-#define MS_NODEV	 4	/* Disallow access to device special files */
-#define MS_NOEXEC	 8	/* Disallow program execution */
-#define MS_SYNCHRONOUS	16	/* Writes are synced at once */
-#define MS_REMOUNT	32	/* Alter flags of a mounted FS */
-#define MS_MANDLOCK	64	/* Allow mandatory locks on an FS */
-#define MS_DIRSYNC	128	/* Directory modifications are synchronous */
-#define MS_NOATIME	1024	/* Do not update access times. */
-#define MS_NODIRATIME	2048	/* Do not update directory access times */
-#define MS_BIND		4096
-#define MS_MOVE		8192
-#define MS_REC		16384
-#define MS_VERBOSE	32768	/* War is peace. Verbosity is silence.
-				   MS_VERBOSE is deprecated. */
-#define MS_SILENT	32768
-#define MS_POSIXACL	(1<<16)	/* VFS does not apply the umask */
-#define MS_UNBINDABLE	(1<<17)	/* change to unbindable */
-#define MS_PRIVATE	(1<<18)	/* change to private */
-#define MS_SLAVE	(1<<19)	/* change to slave */
-#define MS_SHARED	(1<<20)	/* change to shared */
-#define MS_RELATIME	(1<<21)	/* Update atime relative to mtime/ctime. */
-#define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
-#define MS_I_VERSION	(1<<23) /* Update inode I_version field */
-#define MS_ACTIVE	(1<<30)
-#define MS_NOUSER	(1<<31)
-
-#define I_NEW			8
-
-/* Inode flags - they have nothing to superblock flags now */
-
-#define S_SYNC		1	/* Writes are synced at once */
-#define S_NOATIME	2	/* Do not update access times */
-#define S_APPEND	4	/* Append-only file */
-#define S_IMMUTABLE	8	/* Immutable file */
-#define S_DEAD		16	/* removed, but still open directory */
-#define S_NOQUOTA	32	/* Inode is not counted to quota */
-#define S_DIRSYNC	64	/* Directory modifications are synchronous */
-#define S_NOCMTIME	128	/* Do not update file c/mtime */
-#define S_SWAPFILE	256	/* Do not truncate: swapon got its bmaps */
-#define S_PRIVATE	512	/* Inode is fs-internal */
-
-/* include/linux/stat.h */
-
-#define S_IFMT  00170000
-#define S_IFSOCK 0140000
-#define S_IFLNK	 0120000
-#define S_IFREG  0100000
-#define S_IFBLK  0060000
-#define S_IFDIR  0040000
-#define S_IFCHR  0020000
-#define S_IFIFO  0010000
-#define S_ISUID  0004000
-#define S_ISGID  0002000
-#define S_ISVTX  0001000
-
-/* include/linux/fs.h */
-
-/*
- * File types
- *
- * NOTE! These match bits 12..15 of stat.st_mode
- * (ie "(i_mode >> 12) & 15").
- */
-#define DT_UNKNOWN	0
-#define DT_FIFO		1
-#define DT_CHR		2
-#define DT_DIR		4
-#define DT_BLK		6
-#define DT_REG		8
-#define DT_LNK		10
-#define DT_SOCK		12
-#define DT_WHT		14
-
-#define I_DIRTY_SYNC		1
-#define I_DIRTY_DATASYNC	2
-#define I_DIRTY_PAGES		4
-#define I_NEW			8
-#define I_WILL_FREE		16
-#define I_FREEING		32
-#define I_CLEAR			64
-#define __I_LOCK		7
-#define I_LOCK			(1 << __I_LOCK)
-#define __I_SYNC		8
-#define I_SYNC			(1 << __I_SYNC)
-
-#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
-
-/* linux/include/dcache.h */
-
-#define DNAME_INLINE_LEN_MIN 36
-
-struct dentry {
-	unsigned int d_flags;		/* protected by d_lock */
-	spinlock_t d_lock;		/* per dentry lock */
-	struct inode *d_inode;		/* Where the name belongs to - NULL is
-					 * negative */
-	/*
-	 * The next three fields are touched by __d_lookup.  Place them here
-	 * so they all fit in a cache line.
-	 */
-	struct hlist_node d_hash;	/* lookup hash list */
-	struct dentry *d_parent;	/* parent directory */
-	struct qstr d_name;
-
-	struct list_head d_lru;		/* LRU list */
-	/*
-	 * d_child and d_rcu can share memory
-	 */
-	struct list_head d_subdirs;	/* our children */
-	struct list_head d_alias;	/* inode alias list */
-	unsigned long d_time;		/* used by d_revalidate */
-	struct super_block *d_sb;	/* The root of the dentry tree */
-	void *d_fsdata;			/* fs-specific data */
-#ifdef CONFIG_PROFILING
-	struct dcookie_struct *d_cookie; /* cookie, if any */
-#endif
-	int d_mounted;
-	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* small names */
-};
-#endif
-static inline ino_t parent_ino(struct dentry *dentry)
-{
-	ino_t res;
-
-	spin_lock(&dentry->d_lock);
-	res = dentry->d_parent->d_inode->i_ino;
-	spin_unlock(&dentry->d_lock);
-	return res;
-}
-
 /* debug.c */
 
 #define module_param_named(...)
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:44 +0200
Subject: [PATCH 12/19] fs: dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-13-s.hauer@pengutronix.de>

This adds the Linux dcache implementation to barebox.

Until now every filesystem driver resolves the full path to a file for
itself. This leads to code duplication and is error prone since
resolving paths is a complicated task. Also it can narrow down the
lookup performance since barebox only knows ASCII paths and has no way
of caching lookups.

With this patch we get the Linux dcache implementation. The path
resolving code from fs/namei.c is nearly taken as-is, minus the RCU
and locking code. Dcaching is made simple as of now: We simply cache
everything and never release any dentries. Although we do reference
counting for inodes and dentries it is effectively not used yet.
We never free anything until a fs is unmounted in which case we free
everything no matter if references are taken or not.

This patch fundamentally changes the way lookups are done in the
filesystem drivers and I found no sane way to maintain a backwards
compatible code path for not yet converted filesystem drivers. This
means *all* filesystems are marked as broken in this patch, they need
to be fixed one by one afterwards.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/Kconfig             |   12 +
 fs/Makefile            |    2 +-
 fs/ext4/Kconfig        |    1 +
 fs/fat/Kconfig         |    1 +
 fs/fs.c                | 3584 ++++++++++++++++++++++++++++++++----------------
 fs/libfs.c             |   87 ++
 fs/pstore/Kconfig      |    1 +
 fs/squashfs/Kconfig    |    1 +
 fs/ubifs/Kconfig       |    1 +
 include/dirent.h       |    3 +
 include/fs.h           |   25 +-
 include/linux/dcache.h |  109 +-
 include/linux/fs.h     |  131 +-
 include/linux/mount.h  |    3 +
 include/linux/namei.h  |   52 +
 include/linux/stat.h   |    2 +
 16 files changed, 2746 insertions(+), 1269 deletions(-)
 create mode 100644 fs/libfs.c
 create mode 100644 include/linux/namei.h

diff --git a/fs/Kconfig b/fs/Kconfig
index 3512000556..c3a78eaae5 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -12,6 +12,7 @@ config FS_AUTOMOUNT
 config FS_CRAMFS
 	bool
 	select ZLIB
+	depends on BROKEN
 	prompt "cramfs support"
 
 source fs/ext4/Kconfig
@@ -19,15 +20,18 @@ source fs/ext4/Kconfig
 config FS_RAMFS
 	bool
 	default y
+	depends on BROKEN
 	prompt "ramfs support"
 
 config FS_DEVFS
 	bool
 	default y
+	depends on BROKEN
 	prompt "devfs support"
 
 config FS_TFTP
 	bool
+	depends on BROKEN
 	prompt "tftp support"
 	depends on NET
 
@@ -35,14 +39,17 @@ config FS_OMAP4_USBBOOT
 	bool
 	prompt "Filesystem over usb boot"
 	depends on OMAP4_USBBOOT
+	depends on BROKEN
 
 config FS_NFS
 	depends on NET
+	depends on BROKEN
 	bool
 	prompt "nfs support"
 
 config FS_EFI
 	depends on EFI_BOOTUP
+	depends on BROKEN
 	bool
 	prompt "EFI filesystem support"
 	help
@@ -51,6 +58,7 @@ config FS_EFI
 
 config FS_EFIVARFS
 	depends on EFI_BOOTUP
+	depends on BROKEN
 	bool
 	prompt "EFI variable filesystem support (efivarfs)"
 	help
@@ -62,6 +70,7 @@ source fs/ubifs/Kconfig
 config FS_BPKFS
 	bool
 	select CRC32
+	depends on BROKEN
 	prompt "BPKFS support"
 	help
 	  Simple update file format developed for Somfy, tools and library are
@@ -78,10 +87,12 @@ config FS_BPKFS
 config FS_UIMAGEFS
 	bool
 	select CRC32
+	depends on BROKEN
 	prompt "uImage FS support"
 
 config FS_SMHFS
 	depends on ARM_SEMIHOSTING
+	depends on BROKEN
 	bool
 	prompt "Semihosting FS support"
 	help
@@ -95,6 +106,7 @@ source fs/squashfs/Kconfig
 config FS_RATP
 	bool
 	depends on RATP
+	depends on BROKEN
 	prompt "RATP filesystem support"
 	help
 	  This enables support for transferring files over RATP. A host can
diff --git a/fs/Makefile b/fs/Makefile
index 8e3fd78e92..d3e46c2525 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_FS_RAMFS)	+= ramfs.o
 obj-y			+= devfs-core.o
 obj-$(CONFIG_FS_DEVFS)	+= devfs.o
 obj-$(CONFIG_FS_FAT)	+= fat/
-obj-y	+= fs.o
+obj-y	+= fs.o libfs.o
 obj-$(CONFIG_FS_UBIFS)	+= ubifs/
 obj-$(CONFIG_FS_TFTP)	+= tftp.o
 obj-$(CONFIG_FS_OMAP4_USBBOOT)	+= omap4_usbbootfs.o
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index f36043d9a7..ad1bf58536 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -1,3 +1,4 @@
 config FS_EXT4
 	bool
+	depends on BROKEN
 	prompt "ext4 filesystem support"
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index 0699728494..6fc486a207 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -1,4 +1,5 @@
 menuconfig FS_FAT
+	depends on BROKEN
 	bool
 	prompt "FAT filesystem support"
 
diff --git a/fs/fs.c b/fs/fs.c
index b66cc9b178..aa4a69a3eb 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -36,6 +36,7 @@
 #include <block.h>
 #include <libfile.h>
 #include <parseopt.h>
+#include <linux/namei.h>
 
 char *mkmodestr(unsigned long mode, char *str)
 {
@@ -69,8 +70,12 @@ char *mkmodestr(unsigned long mode, char *str)
 EXPORT_SYMBOL(mkmodestr);
 
 static char *cwd;
+static struct dentry *cwd_dentry;
+static struct vfsmount *cwd_mnt;
 
 static FILE *files;
+static struct dentry *d_root;
+static struct vfsmount *mnt_root;
 
 static int init_fs(void)
 {
@@ -84,226 +89,40 @@ static int init_fs(void)
 
 postcore_initcall(init_fs);
 
-char *normalise_path(const char *pathname)
-{
-	char *path = xzalloc(strlen(pathname) + strlen(cwd) + 2);
-        char *in, *out, *slashes[32];
-	int sl = 0;
-
-	debug("in: %s\n", pathname);
-
-	if (*pathname != '/')
-		strcpy(path, cwd);
-	strcat(path, "/");
-	strcat(path, pathname);
-
-	slashes[0] = in = out = path;
-
-	while (*in) {
-		if(*in == '/') {
-			slashes[sl++] = out;
-			*out++ = *in++;
-			while(*in == '/')
-				in++;
-		} else {
-			if (*in == '.' && (*(in + 1) == '/' || !*(in + 1))) {
-				sl--;
-				if (sl < 0)
-					sl = 0;
-				out = slashes[sl];
-				in++;
-				continue;
-			}
-			if (*in == '.' && *(in + 1) == '.') {
-				sl -= 2;
-				if (sl < 0)
-					sl = 0;
-				out = slashes[sl];
-				in += 2;
-				continue;
-			}
-                        *out++ = *in++;
-		}
-	}
-
-	*out-- = 0;
-
-	/*
-	 * Remove trailing slash
-	 */
-	if (*out == '/')
-		*out = 0;
-
-	if (!*path) {
-		*path = '/';
-		*(path + 1) = 0;
-	}
-
-	return path;
-}
-EXPORT_SYMBOL(normalise_path);
-
-static int __lstat(const char *filename, struct stat *s);
 static struct fs_device_d *get_fsdevice_by_path(const char *path);
 
-static char *__canonicalize_path(const char *_pathname, int level)
-{
-	char *path, *freep;
-	char *outpath;
-	int ret;
-	struct stat s;
-
-	if (level > 10)
-		return ERR_PTR(-ELOOP);
-
-	path = freep = xstrdup(_pathname);
-
-	if (*path == '/' || !strcmp(cwd, "/"))
-		outpath = xstrdup("");
-	else
-		outpath = __canonicalize_path(cwd, level + 1);
-
-	while (1) {
-		char *p = strsep(&path, "/");
-		char *tmp;
-		char link[PATH_MAX] = {};
-		struct fs_device_d *fsdev;
-
-		if (!p)
-			break;
-		if (p[0] == '\0')
-			continue;
-		if (!strcmp(p, "."))
-			continue;
-		if (!strcmp(p, "..")) {
-			tmp = xstrdup(dirname(outpath));
-			free(outpath);
-			outpath = tmp;
-			continue;
-		}
-
-		tmp = basprintf("%s/%s", outpath, p);
-		free(outpath);
-		outpath = tmp;
-
-		/*
-		 * Don't bother filesystems without link support
-		 * with an additional stat() call.
-		 */
-		fsdev = get_fsdevice_by_path(outpath);
-		if (!fsdev || !fsdev->driver->readlink)
-			continue;
-
-		ret = __lstat(outpath, &s);
-		if (ret)
-			goto out;
-
-		if (!S_ISLNK(s.st_mode))
-			continue;
-
-		ret = readlink(outpath, link, PATH_MAX - 1);
-		if (ret < 0)
-			goto out;
-
-		if (link[0] == '/') {
-			free(outpath);
-			outpath = __canonicalize_path(link, level + 1);
-		} else {
-			tmp = basprintf("%s/%s", dirname(outpath), link);
-			free(outpath);
-			outpath = __canonicalize_path(tmp, level + 1);
-			free(tmp);
-		}
-
-		if (IS_ERR(outpath))
-			goto out;
-	}
-out:
-	free(freep);
-
-	if (!*outpath) {
-		free(outpath);
-		outpath = xstrdup("/");
-	}
-
-	return outpath;
-}
+LIST_HEAD(fs_device_list);
 
-/*
- * canonicalize_path - resolve links in path
- * @pathname: The input path
- *
- * This function resolves all links in @pathname and returns
- * a path without links in it.
- *
- * Return: Path with links resolved. Allocated, must be freed after use.
- */
-char *canonicalize_path(const char *pathname)
+struct vfsmount *mntget(struct vfsmount *mnt)
 {
-	char *r, *p = __canonicalize_path(pathname, 0);
-
-	if (IS_ERR(p))
-		return ERR_CAST(p);
+	if (!mnt)
+		return NULL;
 
-	r = normalise_path(p);
-	free(p);
+	mnt->ref++;
 
-	return r;
+	return mnt;
 }
 
-/*
- * canonicalize_dir - resolve links in path
- * @pathname: The input path
- *
- * This function resolves all links except the last one. Needed to give
- * access to the link itself.
- *
- * Return: Path with links resolved. Allocated, must be freed after use.
- */
-static char *canonicalize_dir(const char *pathname)
+void mntput(struct vfsmount *mnt)
 {
-	char *f, *d, *r, *ret, *p;
-	char *freep1, *freep2;
-
-	freep1 = xstrdup(pathname);
-	freep2 = xstrdup(pathname);
-	f = basename(freep1);
-	d = dirname(freep2);
-
-	p = __canonicalize_path(d, 0);
-	if (IS_ERR(p)) {
-		ret = ERR_CAST(p);
-		goto out;
-	}
-
-	r = basprintf("%s/%s", p, f);
-
-	ret = normalise_path(r);
-
-	free(r);
-	free(p);
-out:
-	free(freep1);
-	free(freep2);
+	if (!mnt)
+		return;
 
-	return ret;
+	mnt->ref--;
 }
 
-LIST_HEAD(fs_device_list);
-static struct fs_device_d *fs_dev_root;
-
-static struct fs_device_d *get_fsdevice_by_path(const char *path)
+struct vfsmount *lookup_mnt(struct path *path)
 {
-	struct fs_device_d *fsdev = NULL;
+	struct fs_device_d *fsdev;
 
 	for_each_fs_device(fsdev) {
-		int len = strlen(fsdev->path);
-		if (!strncmp(path, fsdev->path, len) &&
-				(path[len] == '/' || path[len] == 0))
-			return fsdev;
+		if (path->dentry == fsdev->vfsmount.mountpoint) {
+			mntget(&fsdev->vfsmount);
+			return &fsdev->vfsmount;
+		}
 	}
 
-	return fs_dev_root;
+	return NULL;
 }
 
 /*
@@ -348,6 +167,8 @@ static void put_file(FILE *f)
 	free(f->path);
 	f->path = NULL;
 	f->in_use = 0;
+	iput(f->f_inode);
+	dput(f->dentry);
 }
 
 static int check_fd(int fd)
@@ -360,388 +181,284 @@ static int check_fd(int fd)
 	return 0;
 }
 
-#ifdef CONFIG_FS_AUTOMOUNT
-
-#define AUTOMOUNT_IS_FILE (1 << 0)
+int create(struct dentry *dir, struct dentry *dentry)
+{
+	struct inode *inode;
 
-struct automount {
-	char *path;
-	char *cmd;
-	struct list_head list;
-	unsigned int flags;
-};
+	if (d_is_negative(dir))
+		return -ENOENT;
 
-static LIST_HEAD(automount_list);
+	inode = d_inode(dir);
 
-void automount_remove(const char *_path)
-{
-	char *path = normalise_path(_path);
-	struct automount *am;
+	if (!inode->i_op->create)
+		return -EROFS;
 
-	list_for_each_entry(am, &automount_list, list) {
-		if (!strcmp(path, am->path))
-			goto found;
-	}
+	return inode->i_op->create(inode, dentry, S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
+}
 
-	return;
-found:
-	list_del(&am->list);
-	free(am->path);
-	free(am->cmd);
-	free(am);
+int creat(const char *pathname, mode_t mode)
+{
+	return open(pathname, O_CREAT | O_WRONLY | O_TRUNC);
 }
-EXPORT_SYMBOL(automount_remove);
+EXPORT_SYMBOL(creat);
 
-int automount_add(const char *path, const char *cmd)
+int ftruncate(int fd, loff_t length)
 {
-	struct automount *am = xzalloc(sizeof(*am));
-	struct stat s;
+	struct fs_driver_d *fsdrv;
+	FILE *f;
 	int ret;
 
-	am->path = normalise_path(path);
-	am->cmd = xstrdup(cmd);
+	if (check_fd(fd))
+		return -errno;
 
-	automount_remove(am->path);
+	f = &files[fd];
 
-	ret = stat(path, &s);
-	if (!ret) {
-		/*
-		 * If it exists it must be a directory
-		 */
-		if (!S_ISDIR(s.st_mode))
-			return -ENOTDIR;
-	} else {
-		am->flags |= AUTOMOUNT_IS_FILE;
-	}
+	fsdrv = f->fsdev->driver;
 
-	list_add_tail(&am->list, &automount_list);
+	ret = fsdrv->truncate(&f->fsdev->dev, f, length);
+	if (ret)
+		return ret;
+
+	f->size = length;
 
 	return 0;
 }
-EXPORT_SYMBOL(automount_add);
 
-void cdev_create_default_automount(struct cdev *cdev)
+int ioctl(int fd, int request, void *buf)
 {
-	char *path, *cmd;
-
-	path = basprintf("/mnt/%s", cdev->name);
-	cmd = basprintf("mount %s", cdev->name);
+	struct fs_driver_d *fsdrv;
+	FILE *f;
+	int ret;
 
-	make_directory(path);
-	automount_add(path, cmd);
+	if (check_fd(fd))
+		return -errno;
 
-	free(cmd);
-	free(path);
-}
+	f = &files[fd];
 
-void automount_print(void)
-{
-	struct automount *am;
+	fsdrv = f->fsdev->driver;
 
-	list_for_each_entry(am, &automount_list, list)
-		printf("%-20s %s\n", am->path, am->cmd);
+	if (fsdrv->ioctl)
+		ret = fsdrv->ioctl(&f->fsdev->dev, f, request, buf);
+	else
+		ret = -ENOSYS;
+	if (ret)
+		errno = -ret;
+	return ret;
 }
-EXPORT_SYMBOL(automount_print);
 
-static void automount_mount(const char *path, int instat)
+static ssize_t __read(FILE *f, void *buf, size_t count)
 {
-	struct automount *am;
+	struct fs_driver_d *fsdrv;
 	int ret;
-	static int in_automount;
-
-	if (in_automount)
-		return;
-
-	in_automount++;
 
-	if (fs_dev_root != get_fsdevice_by_path(path))
+	if ((f->flags & O_ACCMODE) == O_WRONLY) {
+		ret = -EBADF;
 		goto out;
+	}
 
-	list_for_each_entry(am, &automount_list, list) {
-		int len_path = strlen(path);
-		int len_am_path = strlen(am->path);
-
-		/*
-		 * stat is a bit special. We do not want to trigger
-		 * automount when someone calls stat() on the automount
-		 * directory itself.
-		 */
-		if (instat && !(am->flags & AUTOMOUNT_IS_FILE) &&
-				len_path == len_am_path) {
-			continue;
-		}
+	fsdrv = f->fsdev->driver;
 
-		if (len_path < len_am_path)
-			continue;
+	if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size)
+		count = f->size - f->pos;
 
-		if (strncmp(path, am->path, len_am_path))
-			continue;
+	if (!count)
+		return 0;
 
-		if (*(path + len_am_path) != 0 && *(path + len_am_path) != '/')
-			continue;
+	ret = fsdrv->read(&f->fsdev->dev, f, buf, count);
+out:
+	if (ret < 0)
+		errno = -ret;
+	return ret;
+}
 
-		setenv("automount_path", am->path);
-		export("automount_path");
-		ret = run_command(am->cmd);
-		setenv("automount_path", NULL);
+ssize_t pread(int fd, void *buf, size_t count, loff_t offset)
+{
+	loff_t pos;
+	FILE *f;
+	int ret;
 
-		if (ret)
-			printf("running automount command '%s' failed\n",
-					am->cmd);
+	if (check_fd(fd))
+		return -errno;
 
-		break;
-	}
-out:
-	in_automount--;
-}
+	f = &files[fd];
 
-BAREBOX_MAGICVAR(automount_path, "mountpath passed to automount scripts");
+	pos = f->pos;
+	f->pos = offset;
+	ret = __read(f, buf, count);
+	f->pos = pos;
 
-#else
-static void automount_mount(const char *path, int instat)
-{
+	return ret;
 }
-#endif /* CONFIG_FS_AUTOMOUNT */
+EXPORT_SYMBOL(pread);
 
-static struct fs_device_d *get_fs_device_and_root_path(char **path)
+ssize_t read(int fd, void *buf, size_t count)
 {
-	struct fs_device_d *fsdev;
+	FILE *f;
+	int ret;
 
-	automount_mount(*path, 0);
+	if (check_fd(fd))
+		return -errno;
 
-	fsdev = get_fsdevice_by_path(*path);
-	if (!fsdev)
-		return NULL;
-	if (fsdev != fs_dev_root)
-		*path += strlen(fsdev->path);
+	f = &files[fd];
 
-	return fsdev;
+	ret = __read(f, buf, count);
+
+	if (ret > 0)
+		f->pos += ret;
+	return ret;
 }
+EXPORT_SYMBOL(read);
 
-static int dir_is_empty(const char *pathname)
+static ssize_t __write(FILE *f, const void *buf, size_t count)
 {
-	DIR *dir;
-	struct dirent *d;
-	int ret = 1;
+	struct fs_driver_d *fsdrv;
+	int ret;
 
-	dir = opendir(pathname);
-	if (!dir) {
-		errno = ENOENT;
-		return -ENOENT;
+	if (!(f->flags & O_ACCMODE)) {
+		ret = -EBADF;
+		goto out;
 	}
 
-	while ((d = readdir(dir))) {
-		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
-				continue;
-		ret = 0;
-		break;
+	fsdrv = f->fsdev->driver;
+	if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) {
+		ret = fsdrv->truncate(&f->fsdev->dev, f, f->pos + count);
+		if (ret) {
+			if (ret != -ENOSPC)
+				goto out;
+			count = f->size - f->pos;
+			if (!count)
+				goto out;
+		} else {
+			f->size = f->pos + count;
+			f->f_inode->i_size = f->size;
+		}
 	}
-
-	closedir(dir);
+	ret = fsdrv->write(&f->fsdev->dev, f, buf, count);
+out:
+	if (ret < 0)
+		errno = -ret;
 	return ret;
 }
 
-static int parent_check_directory(const char *path)
+ssize_t pwrite(int fd, const void *buf, size_t count, loff_t offset)
 {
-	struct stat s;
+	loff_t pos;
+	FILE *f;
 	int ret;
-	char *dir = dirname(xstrdup(path));
 
-	ret = lstat(dir, &s);
-
-	free(dir);
-
-	if (ret)
-		return -ENOENT;
+	if (check_fd(fd))
+		return -errno;
 
-	if (!S_ISDIR(s.st_mode))
-		return -ENOTDIR;
+	f = &files[fd];
 
-	return 0;
-}
+	pos = f->pos;
+	f->pos = offset;
+	ret = __write(f, buf, count);
+	f->pos = pos;
 
-const char *getcwd(void)
-{
-	return cwd;
+	return ret;
 }
-EXPORT_SYMBOL(getcwd);
+EXPORT_SYMBOL(pwrite);
 
-int chdir(const char *pathname)
+ssize_t write(int fd, const void *buf, size_t count)
 {
-	char *p = normalise_path(pathname);
+	FILE *f;
 	int ret;
-	struct stat s;
-
-	ret = stat(p, &s);
-	if (ret)
-		goto out;
-
-	if (!S_ISDIR(s.st_mode)) {
-		ret = -ENOTDIR;
-		goto out;
-	}
-
-	automount_mount(p, 0);
 
-	strcpy(cwd, p);
+	if (check_fd(fd))
+		return -errno;
 
-out:
-	free(p);
+	f = &files[fd];
 
-	if (ret)
-		errno = -ret;
+	ret = __write(f, buf, count);
 
+	if (ret > 0)
+		f->pos += ret;
 	return ret;
 }
-EXPORT_SYMBOL(chdir);
+EXPORT_SYMBOL(write);
 
-int unlink(const char *pathname)
+int flush(int fd)
 {
-	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
-	char *p = canonicalize_dir(pathname);
-	char *freep = p;
+	FILE *f;
 	int ret;
-	struct stat s;
-
-	ret = lstat(p, &s);
-	if (ret)
-		goto out;
 
-	if (S_ISDIR(s.st_mode)) {
-		ret = -EISDIR;
-		goto out;
-	}
+	if (check_fd(fd))
+		return -errno;
 
-	fsdev = get_fs_device_and_root_path(&p);
-	if (!fsdev) {
-		ret = -ENOENT;
-		goto out;
-	}
-	fsdrv = fsdev->driver;
+	f = &files[fd];
 
-	if (!fsdrv->unlink) {
-		ret = -ENOSYS;
-		goto out;
-	}
+	fsdrv = f->fsdev->driver;
+	if (fsdrv->flush)
+		ret = fsdrv->flush(&f->fsdev->dev, f);
+	else
+		ret = 0;
 
-	ret = fsdrv->unlink(&fsdev->dev, p);
-	if (ret)
-		errno = -ret;
-out:
-	free(freep);
 	if (ret)
 		errno = -ret;
+
 	return ret;
 }
-EXPORT_SYMBOL(unlink);
 
-int open(const char *pathname, int flags, ...)
+loff_t lseek(int fildes, loff_t offset, int whence)
 {
-	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
 	FILE *f;
-	int exist_err = 0;
-	struct stat s;
-	char *path;
-	char *freep;
+	loff_t pos;
 	int ret;
 
-	path = canonicalize_path(pathname);
-	if (IS_ERR(path)) {
-		ret = PTR_ERR(path);
-		goto out2;
-	}
-
-	exist_err = stat(path, &s);
-
-	freep = path;
-
-	if (!exist_err && S_ISDIR(s.st_mode)) {
-		ret = -EISDIR;
-		goto out1;
-	}
-
-	if (exist_err && !(flags & O_CREAT)) {
-		ret = exist_err;
-		goto out1;
-	}
-
-	if (exist_err) {
-		ret = parent_check_directory(path);
-		if (ret)
-			goto out1;
-	}
-
-	f = get_file();
-	if (!f) {
-		ret = -EMFILE;
-		goto out1;
-	}
+	if (check_fd(fildes))
+		return -1;
 
-	fsdev = get_fs_device_and_root_path(&path);
-	if (!fsdev) {
-		ret = -ENOENT;
+	f = &files[fildes];
+	fsdrv = f->fsdev->driver;
+	if (!fsdrv->lseek) {
+		ret = -ENOSYS;
 		goto out;
 	}
 
-	fsdrv = fsdev->driver;
-
-	f->fsdev = fsdev;
-	f->flags = flags;
-
-	if ((flags & O_ACCMODE) && !fsdrv->write) {
-		ret = -EROFS;
-		goto out;
-	}
+	ret = -EINVAL;
 
-	if (exist_err) {
-		if (NULL != fsdrv->create)
-			ret = fsdrv->create(&fsdev->dev, path,
-					S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
-		else
-			ret = -EROFS;
-		if (ret)
+	switch (whence) {
+	case SEEK_SET:
+		if (f->size != FILE_SIZE_STREAM && offset > f->size)
 			goto out;
-	}
-
-	f->path = xstrdup(path);
-
-	ret = fsdrv->open(&fsdev->dev, f, path);
-	if (ret)
-		goto out;
-
-	if (flags & O_TRUNC) {
-		ret = fsdrv->truncate(&fsdev->dev, f, 0);
-		f->size = 0;
-		if (ret)
+		if (offset < 0)
+			goto out;
+		pos = offset;
+		break;
+	case SEEK_CUR:
+		if (f->size != FILE_SIZE_STREAM && offset + f->pos > f->size)
+			goto out;
+		pos = f->pos + offset;
+		break;
+	case SEEK_END:
+		if (offset > 0)
 			goto out;
+		pos = f->size + offset;
+		break;
+	default:
+		goto out;
 	}
 
-	if (flags & O_APPEND)
-		f->pos = f->size;
+	pos = fsdrv->lseek(&f->fsdev->dev, f, pos);
+	if (pos < 0) {
+		errno = -pos;
+		return -1;
+	}
 
-	free(freep);
-	return f->no;
+	return pos;
 
 out:
-	put_file(f);
-out1:
-	free(freep);
-out2:
 	if (ret)
 		errno = -ret;
-	return ret;
-}
-EXPORT_SYMBOL(open);
 
-int creat(const char *pathname, mode_t mode)
-{
-	return open(pathname, O_CREAT | O_WRONLY | O_TRUNC);
+	return -1;
 }
-EXPORT_SYMBOL(creat);
+EXPORT_SYMBOL(lseek);
 
-int ftruncate(int fd, loff_t length)
+int erase(int fd, loff_t count, loff_t offset)
 {
 	struct fs_driver_d *fsdrv;
 	FILE *f;
@@ -749,21 +466,28 @@ int ftruncate(int fd, loff_t length)
 
 	if (check_fd(fd))
 		return -errno;
-
 	f = &files[fd];
+	if (offset >= f->size)
+		return 0;
+	if (count == ERASE_SIZE_ALL || count > f->size - offset)
+		count = f->size - offset;
+	if (count < 0)
+		return -EINVAL;
 
 	fsdrv = f->fsdev->driver;
+	if (fsdrv->erase)
+		ret = fsdrv->erase(&f->fsdev->dev, f, count, offset);
+	else
+		ret = -ENOSYS;
 
-	ret = fsdrv->truncate(&f->fsdev->dev, f, length);
 	if (ret)
-		return ret;
-
-	f->size = length;
+		errno = -ret;
 
-	return 0;
+	return ret;
 }
+EXPORT_SYMBOL(erase);
 
-int ioctl(int fd, int request, void *buf)
+int protect(int fd, size_t count, loff_t offset, int prot)
 {
 	struct fs_driver_d *fsdrv;
 	FILE *f;
@@ -771,387 +495,1981 @@ int ioctl(int fd, int request, void *buf)
 
 	if (check_fd(fd))
 		return -errno;
-
 	f = &files[fd];
+	if (offset >= f->size)
+		return 0;
+	if (count > f->size - offset)
+		count = f->size - offset;
 
 	fsdrv = f->fsdev->driver;
-
-	if (fsdrv->ioctl)
-		ret = fsdrv->ioctl(&f->fsdev->dev, f, request, buf);
+	if (fsdrv->protect)
+		ret = fsdrv->protect(&f->fsdev->dev, f, count, offset, prot);
 	else
 		ret = -ENOSYS;
+
 	if (ret)
 		errno = -ret;
+
 	return ret;
 }
+EXPORT_SYMBOL(protect);
 
-static ssize_t __read(FILE *f, void *buf, size_t count)
+int protect_file(const char *file, int prot)
 {
-	struct fs_driver_d *fsdrv;
-	int ret;
-
-	if ((f->flags & O_ACCMODE) == O_WRONLY) {
-		ret = -EBADF;
-		goto out;
-	}
+	int fd, ret;
 
-	fsdrv = f->fsdev->driver;
+	fd = open(file, O_WRONLY);
+	if (fd < 0)
+		return fd;
 
-	if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size)
-		count = f->size - f->pos;
+	ret = protect(fd, ~0, 0, prot);
 
-	if (!count)
-		return 0;
+	close(fd);
 
-	ret = fsdrv->read(&f->fsdev->dev, f, buf, count);
-out:
-	if (ret < 0)
-		errno = -ret;
 	return ret;
 }
 
-ssize_t pread(int fd, void *buf, size_t count, loff_t offset)
+void *memmap(int fd, int flags)
 {
-	loff_t pos;
+	struct fs_driver_d *fsdrv;
 	FILE *f;
+	void *retp = (void *)-1;
 	int ret;
 
 	if (check_fd(fd))
-		return -errno;
+		return retp;
 
 	f = &files[fd];
 
-	pos = f->pos;
-	f->pos = offset;
-	ret = __read(f, buf, count);
-	f->pos = pos;
+	fsdrv = f->fsdev->driver;
 
-	return ret;
+	if (fsdrv->memmap)
+		ret = fsdrv->memmap(&f->fsdev->dev, f, &retp, flags);
+	else
+		ret = -EINVAL;
+
+	if (ret)
+		errno = -ret;
+
+	return retp;
 }
-EXPORT_SYMBOL(pread);
+EXPORT_SYMBOL(memmap);
 
-ssize_t read(int fd, void *buf, size_t count)
+int close(int fd)
 {
+	struct fs_driver_d *fsdrv;
 	FILE *f;
-	int ret;
+	int ret = 0;
 
 	if (check_fd(fd))
 		return -errno;
 
 	f = &files[fd];
 
-	ret = __read(f, buf, count);
+	fsdrv = f->fsdev->driver;
+
+	if (fsdrv->close)
+		ret = fsdrv->close(&f->fsdev->dev, f);
+
+	put_file(f);
+
+	if (ret)
+		errno = -ret;
 
-	if (ret > 0)
-		f->pos += ret;
 	return ret;
 }
-EXPORT_SYMBOL(read);
+EXPORT_SYMBOL(close);
 
-static ssize_t __write(FILE *f, const void *buf, size_t count)
+static int fs_match(struct device_d *dev, struct driver_d *drv)
 {
-	struct fs_driver_d *fsdrv;
+	return strcmp(dev->name, drv->name) ? -1 : 0;
+}
+
+static int fs_probe(struct device_d *dev)
+{
+	struct fs_device_d *fsdev = dev_to_fs_device(dev);
+	struct driver_d *drv = dev->driver;
+	struct fs_driver_d *fsdrv = container_of(drv, struct fs_driver_d, drv);
 	int ret;
 
-	if (!(f->flags & O_ACCMODE)) {
-		ret = -EBADF;
-		goto out;
+	ret = dev->driver->probe(dev);
+	if (ret)
+		return ret;
+
+	fsdev->driver = fsdrv;
+
+	list_add_tail(&fsdev->list, &fs_device_list);
+
+	return 0;
+}
+
+void dentry_kill(struct dentry *dentry)
+{
+	if (dentry->d_inode)
+		iput(dentry->d_inode);
+
+	if (!IS_ROOT(dentry))
+		dput(dentry->d_parent);
+
+	list_del(&dentry->d_child);
+	free(dentry->name);
+	free(dentry);
+}
+
+int dentry_delete_subtree(struct super_block *sb, struct dentry *parent)
+{
+	struct dentry *dentry, *tmp;
+
+	if (!parent)
+		return 0;
+
+	list_for_each_entry_safe(dentry, tmp, &parent->d_subdirs, d_child)
+		dentry_delete_subtree(sb, dentry);
+
+	dentry_kill(parent);
+
+	return 0;
+}
+
+static void destroy_inode(struct inode *inode)
+{
+	if (inode->i_sb->s_op->destroy_inode)
+		inode->i_sb->s_op->destroy_inode(inode);
+	else
+		free(inode);
+}
+
+static void fs_remove(struct device_d *dev)
+{
+	struct fs_device_d *fsdev = dev_to_fs_device(dev);
+	struct super_block *sb = &fsdev->sb;
+	struct inode *inode, *tmp;
+
+	if (fsdev->dev.driver) {
+		dev->driver->remove(dev);
+		list_del(&fsdev->list);
 	}
 
-	fsdrv = f->fsdev->driver;
-	if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) {
-		ret = fsdrv->truncate(&f->fsdev->dev, f, f->pos + count);
-		if (ret) {
-			if (ret != -ENOSPC)
-				goto out;
-			count = f->size - f->pos;
-			if (!count)
-				goto out;
-		} else {
-			f->size = f->pos + count;
+	free(fsdev->path);
+	free(fsdev->options);
+
+	if (fsdev->cdev)
+		cdev_close(fsdev->cdev);
+
+	if (fsdev->loop)
+		cdev_remove_loop(fsdev->cdev);
+
+	dput(sb->s_root);
+	dentry_delete_subtree(sb, sb->s_root);
+
+	list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list)
+		destroy_inode(inode);
+
+	if (fsdev->vfsmount.mountpoint)
+		fsdev->vfsmount.mountpoint->d_flags &= ~DCACHE_MOUNTED;
+
+	mntput(fsdev->vfsmount.parent);
+
+	free(fsdev->backingstore);
+	free(fsdev);
+}
+
+struct bus_type fs_bus = {
+	.name = "fs",
+	.match = fs_match,
+	.probe = fs_probe,
+	.remove = fs_remove,
+};
+
+static int fs_bus_init(void)
+{
+	return bus_register(&fs_bus);
+}
+pure_initcall(fs_bus_init);
+
+int register_fs_driver(struct fs_driver_d *fsdrv)
+{
+	fsdrv->drv.bus = &fs_bus;
+	register_driver(&fsdrv->drv);
+
+	return 0;
+}
+EXPORT_SYMBOL(register_fs_driver);
+
+static const char *detect_fs(const char *filename, const char *fsoptions)
+{
+	enum filetype type;
+	struct driver_d *drv;
+	struct fs_driver_d *fdrv;
+	bool loop = false;
+	unsigned long long offset = 0;
+
+	parseopt_b(fsoptions, "loop", &loop);
+	parseopt_llu_suffix(fsoptions, "offset", &offset);
+	if (loop)
+		type = file_name_detect_type_offset(filename, offset);
+	else
+		type = cdev_detect_type(filename);
+
+	if (type == filetype_unknown)
+		return NULL;
+
+	bus_for_each_driver(&fs_bus, drv) {
+		fdrv = drv_to_fs_driver(drv);
+
+		if (type == fdrv->type)
+			return drv->name;
+	}
+
+	return NULL;
+}
+
+int fsdev_open_cdev(struct fs_device_d *fsdev)
+{
+	unsigned long long offset = 0;
+
+	parseopt_b(fsdev->options, "loop", &fsdev->loop);
+	parseopt_llu_suffix(fsdev->options, "offset", &offset);
+	if (fsdev->loop)
+		fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR,
+					       offset);
+	else
+		fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR);
+	if (!fsdev->cdev)
+		return -EINVAL;
+
+	fsdev->dev.parent = fsdev->cdev->dev;
+	fsdev->parent_device = fsdev->cdev->dev;
+
+	return 0;
+}
+
+static void init_super(struct super_block *sb)
+{
+	INIT_LIST_HEAD(&sb->s_inodes);
+}
+
+static int fsdev_umount(struct fs_device_d *fsdev)
+{
+	if (fsdev->vfsmount.ref)
+		return -EBUSY;
+
+	return unregister_device(&fsdev->dev);
+}
+
+/**
+ * umount_by_cdev Use a cdev struct to umount all mounted filesystems
+ * @param cdev cdev to the according device
+ * @return 0 on success or if cdev was not mounted, -errno otherwise
+ */
+int umount_by_cdev(struct cdev *cdev)
+{
+	struct fs_device_d *fs;
+	struct fs_device_d *fs_tmp;
+	int first_error = 0;
+
+	for_each_fs_device_safe(fs_tmp, fs) {
+		int ret;
+
+		if (fs->cdev == cdev) {
+			ret = fsdev_umount(fs);
+			if (ret) {
+				pr_err("Failed umounting %s, %d, continuing anyway\n",
+				       fs->path, ret);
+				if (!first_error)
+					first_error = ret;
+			}
 		}
 	}
-	ret = fsdrv->write(&f->fsdev->dev, f, buf, count);
-out:
-	if (ret < 0)
-		errno = -ret;
-	return ret;
+
+	return first_error;
 }
+EXPORT_SYMBOL(umount_by_cdev);
 
-ssize_t pwrite(int fd, const void *buf, size_t count, loff_t offset)
+struct readdir_entry {
+	struct dirent d;
+	struct list_head list;
+};
+
+struct readdir_callback {
+	struct dir_context ctx;
+	DIR *dir;
+};
+
+static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
+		      loff_t offset, u64 ino, unsigned int d_type)
 {
-	loff_t pos;
-	FILE *f;
-	int ret;
+	struct readdir_callback *rd = container_of(ctx, struct readdir_callback, ctx);
+	struct readdir_entry *entry;
 
-	if (check_fd(fd))
-		return -errno;
+	entry = xzalloc(sizeof(*entry));
+	if (!entry)
+		return -ENOMEM;
 
-	f = &files[fd];
+	memcpy(entry->d.d_name, name, namlen);
+	list_add_tail(&entry->list, &rd->dir->entries);
 
-	pos = f->pos;
-	f->pos = offset;
-	ret = __write(f, buf, count);
-	f->pos = pos;
+	return 0;
+}
 
-	return ret;
+struct dirent *readdir(DIR *dir)
+{
+	struct readdir_entry *entry;
+
+	if (!dir)
+		return NULL;
+
+	if (list_empty(&dir->entries))
+		return NULL;
+
+	entry = list_first_entry(&dir->entries, struct readdir_entry, list);
+
+	list_del(&entry->list);
+	strcpy(dir->d.d_name, entry->d.d_name);
+	free(entry);
+
+	return &dir->d;
 }
-EXPORT_SYMBOL(pwrite);
+EXPORT_SYMBOL(readdir);
 
-ssize_t write(int fd, const void *buf, size_t count)
+int fstat(int fd, struct stat *s)
 {
 	FILE *f;
-	int ret;
+	struct fs_device_d *fsdev;
 
 	if (check_fd(fd))
 		return -errno;
 
 	f = &files[fd];
 
-	ret = __write(f, buf, count);
+	fsdev = f->fsdev;
+
+	return -ENOENT;
+//	return fsdev->driver->stat(&fsdev->dev, f->path, s);
+}
+EXPORT_SYMBOL(fstat);
+
+/*
+ * cdev_get_mount_path - return the path a cdev is mounted on
+ *
+ * If a cdev is mounted return the path it's mounted on, NULL
+ * otherwise.
+ */
+const char *cdev_get_mount_path(struct cdev *cdev)
+{
+	struct fs_device_d *fsdev;
+
+	for_each_fs_device(fsdev) {
+		if (fsdev->cdev && fsdev->cdev == cdev)
+			return fsdev->path;
+	}
+
+	return NULL;
+}
+
+/*
+ * cdev_mount_default - mount a cdev to the default path
+ *
+ * If a cdev is already mounted return the path it's mounted on, otherwise
+ * mount it to /mnt/<cdevname> and return the path. Returns an error pointer
+ * on failure.
+ */
+const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions)
+{
+	const char *path;
+	char *newpath, *devpath;
+	int ret;
+
+	/*
+	 * If this cdev is already mounted somewhere use this path
+	 * instead of mounting it again to avoid corruption on the
+	 * filesystem. Note this ignores eventual fsoptions though.
+	 */
+	path = cdev_get_mount_path(cdev);
+	if (path)
+		return path;
+
+	newpath = basprintf("/mnt/%s", cdev->name);
+	make_directory(newpath);
+
+	devpath = basprintf("/dev/%s", cdev->name);
+
+	ret = mount(devpath, NULL, newpath, fsoptions);
+
+	free(devpath);
+
+	if (ret) {
+		free(newpath);
+		return ERR_PTR(ret);
+	}
+
+	return cdev_get_mount_path(cdev);
+}
+
+/*
+ * mount_all - iterate over block devices and mount all devices we are able to
+ */
+void mount_all(void)
+{
+	struct device_d *dev;
+	struct block_device *bdev;
+
+	if (!IS_ENABLED(CONFIG_BLOCK))
+		return;
+
+	for_each_device(dev)
+		device_detect(dev);
+
+	for_each_block_device(bdev) {
+		struct cdev *cdev = &bdev->cdev;
+
+		list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list)
+			cdev_mount_default(cdev, NULL);
+	}
+}
+
+void fsdev_set_linux_rootarg(struct fs_device_d *fsdev, const char *str)
+{
+	fsdev->linux_rootarg = xstrdup(str);
+
+	dev_add_param_fixed(&fsdev->dev, "linux.bootargs", fsdev->linux_rootarg);
+}
+
+/**
+ * path_get_linux_rootarg() - Given a path return a suitable root= option for
+ *                            Linux
+ * @path: The path
+ *
+ * Return: A string containing the root= option or an ERR_PTR. the returned
+ *         string must be freed by the caller.
+ */
+char *path_get_linux_rootarg(const char *path)
+{
+	struct fs_device_d *fsdev;
+	const char *str;
+
+	fsdev = get_fsdevice_by_path(path);
+	if (!fsdev)
+		return ERR_PTR(-EINVAL);
+
+	str = dev_get_param(&fsdev->dev, "linux.bootargs");
+	if (!str)
+		return ERR_PTR(-ENOSYS);
+
+	return xstrdup(str);
+}
+
+/**
+ * __is_tftp_fs() - return true when path is mounted on TFTP
+ * @path: The path
+ *
+ * Do not use directly, use is_tftp_fs instead.
+ *
+ * Return: true when @path is on TFTP, false otherwise
+ */
+bool __is_tftp_fs(const char *path)
+{
+	struct fs_device_d *fsdev;
+
+	fsdev = get_fsdevice_by_path(path);
+	if (!fsdev)
+		return false;
+
+	if (strcmp(fsdev->driver->drv.name, "tftp"))
+		return false;
+
+	return true;
+}
+
+/* inode.c */
+unsigned int get_next_ino(void)
+{
+	static unsigned int ino;
+
+	return ++ino;
+}
+
+void drop_nlink(struct inode *inode)
+{
+	WARN_ON(inode->i_nlink == 0);
+	inode->__i_nlink--;
+}
+
+void inc_nlink(struct inode *inode)
+{
+	inode->__i_nlink++;
+}
+
+static struct inode *alloc_inode(struct super_block *sb)
+{
+	static const struct inode_operations empty_iops;
+	static const struct file_operations no_open_fops;
+	struct inode *inode;
+
+	if (sb->s_op->alloc_inode)
+		inode = sb->s_op->alloc_inode(sb);
+	else
+		inode = xzalloc(sizeof(*inode));
+
+	inode->i_op = &empty_iops;
+	inode->i_fop = &no_open_fops;
+	inode->__i_nlink = 1;
+	inode->i_count = 1;
+
+	return inode;
+}
+
+struct inode *new_inode(struct super_block *sb)
+{
+	struct inode *inode;
+
+	inode = alloc_inode(sb);
+	if (!inode)
+		return NULL;
+
+	inode->i_sb = sb;
+
+	list_add(&inode->i_sb_list, &sb->s_inodes);
+
+	return inode;
+}
+
+void iput(struct inode *inode)
+{
+	if (!inode->i_count)
+		return;
+
+	inode->i_count--;
+}
+
+struct inode *iget(struct inode *inode)
+{
+	inode->i_count++;
+
+	return inode;
+}
+
+/* dcache.c */
+
+/*
+ * refcounting is implemented but right now we do not do anything with
+ * the refcounting information. Dentries are never freed unless the
+ * filesystem they are on is unmounted. In this case we do not care
+ * about the refcounts so we may free up a dentry that is actually used
+ * (file is opened). This leaves room for improvements.
+ */
+void dput(struct dentry *dentry)
+{
+	if (!dentry)
+		return;
+
+	if (!dentry->d_count)
+		return;
+
+	dentry->d_count--;
+}
+
+struct dentry *dget(struct dentry *dentry)
+{
+	dentry->d_count++;
+
+	return dentry;
+}
+
+const struct qstr slash_name = QSTR_INIT("/", 1);
+
+void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
+{
+	dentry->d_op = op;
+}
+
+/**
+ * __d_alloc	-	allocate a dcache entry
+ * @sb: filesystem it will belong to
+ * @name: qstr of the name
+ *
+ * Allocates a dentry. It returns %NULL if there is insufficient memory
+ * available. On a success the dentry is returned. The name passed in is
+ * copied and the copy passed in may be reused after this call.
+ */
+struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
+{
+	struct dentry *dentry;
+
+	dentry = xzalloc(sizeof(*dentry));
+	if (!dentry)
+		return NULL;
+
+	if (!name)
+		name = &slash_name;
+
+	dentry->name = malloc(name->len + 1);
+	if (!dentry->name)
+		return NULL;
+
+	memcpy(dentry->name, name->name, name->len);
+	dentry->name[name->len] = 0;
+
+	dentry->d_name.len = name->len;
+	dentry->d_name.name = dentry->name;
+
+	dentry->d_count = 1;
+	dentry->d_parent = dentry;
+	dentry->d_sb = sb;
+	INIT_LIST_HEAD(&dentry->d_subdirs);
+	INIT_LIST_HEAD(&dentry->d_child);
+	d_set_d_op(dentry, dentry->d_sb->s_d_op);
+
+	return dentry;
+}
+
+/**
+ * d_alloc	-	allocate a dcache entry
+ * @parent: parent of entry to allocate
+ * @name: qstr of the name
+ *
+ * Allocates a dentry. It returns %NULL if there is insufficient memory
+ * available. On a success the dentry is returned. The name passed in is
+ * copied and the copy passed in may be reused after this call.
+ */
+struct dentry *d_alloc(struct dentry *parent, const struct qstr *name)
+{
+	struct dentry *dentry = __d_alloc(parent->d_sb, name);
+	if (!dentry)
+		return NULL;
+
+	dget(parent);
+
+	dentry->d_parent = parent;
+	list_add(&dentry->d_child, &parent->d_subdirs);
+
+	return dentry;
+}
+
+struct dentry *d_alloc_anon(struct super_block *sb)
+{
+	return __d_alloc(sb, NULL);
+}
+
+static unsigned d_flags_for_inode(struct inode *inode)
+{
+        if (!inode)
+                return DCACHE_MISS_TYPE;
+
+	if (S_ISDIR(inode->i_mode))
+		return DCACHE_DIRECTORY_TYPE;
+
+	if (inode->i_op->get_link)
+		return DCACHE_SYMLINK_TYPE;
+
+	return DCACHE_REGULAR_TYPE;
+}
+
+void d_instantiate(struct dentry *dentry, struct inode *inode)
+{
+	dentry->d_inode = inode;
+	dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
+	dentry->d_flags |= d_flags_for_inode(inode);
+}
+
+struct dentry *d_make_root(struct inode *inode)
+{
+	struct dentry *res;
+
+	if (!inode)
+		return NULL;
+
+	res = d_alloc_anon(inode->i_sb);
+	if (!res)
+		return NULL;
+
+	d_instantiate(res, inode);
+
+	return res;
+}
+
+void d_add(struct dentry *dentry, struct inode *inode)
+{
+	dentry->d_inode = inode;
+	dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
+	dentry->d_flags |= d_flags_for_inode(inode);
+}
+
+static bool d_same_name(const struct dentry *dentry,
+			const struct dentry *parent,
+			const struct qstr *name)
+{
+	if (dentry->d_name.len != name->len)
+		return false;
+
+	return strncmp(dentry->d_name.name, name->name, name->len) == 0;
+}
+
+struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)
+{
+	struct dentry *dentry;
+
+	list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
+		if (!d_same_name(dentry, parent, name))
+			continue;
+
+		dget(dentry);
+
+		return dentry;
+	}
+
+	return NULL;
+}
+
+void d_invalidate(struct dentry *dentry)
+{
+}
+
+static inline void __d_clear_type_and_inode(struct dentry *dentry)
+{
+	dentry->d_flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
+
+	dentry->d_inode = NULL;
+}
+
+/*
+ * Release the dentry's inode, using the filesystem
+ * d_iput() operation if defined.
+ */
+static void dentry_unlink_inode(struct dentry * dentry)
+{
+	struct inode *inode = dentry->d_inode;
+
+	__d_clear_type_and_inode(dentry);
+	iput(inode);
+}
+
+void d_delete(struct dentry * dentry)
+{
+	dentry_unlink_inode(dentry);
+}
+
+/*
+ * These are the Linux name resolve functions from fs/namei.c
+ *
+ * The implementation is more or less directly ported from the
+ * Linux Kernel (as of Linux-4.16) minus the RCU and locking code.
+ */
+
+enum {WALK_FOLLOW = 1, WALK_MORE = 2};
+
+/*
+ * Define EMBEDDED_LEVELS to MAXSYMLINKS so we do not have to
+ * dynamically allocate a path stack.
+ */
+#define EMBEDDED_LEVELS MAXSYMLINKS
+
+struct nameidata {
+	struct path	path;
+	struct qstr	last;
+	struct inode	*inode; /* path.dentry.d_inode */
+	unsigned int	flags;
+	unsigned	seq, m_seq;
+	int		last_type;
+	unsigned	depth;
+	int		total_link_count;
+	struct saved {
+		struct path link;
+		const char *name;
+		unsigned seq;
+	} *stack, internal[EMBEDDED_LEVELS];
+	struct filename	*name;
+	struct nameidata *saved;
+	struct inode	*link_inode;
+	unsigned	root_seq;
+	int		dfd;
+};
+
+struct filename {
+	char *name;
+	int refcnt;
+};
+
+static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
+{
+	p->stack = p->internal;
+	p->dfd = dfd;
+	p->name = name;
+	p->total_link_count = 0;
+}
+
+void path_get(const struct path *path)
+{
+	mntget(path->mnt);
+	dget(path->dentry);
+}
+
+void path_put(const struct path *path)
+{
+	dput(path->dentry);
+	mntput(path->mnt);
+}
+
+static inline void get_root(struct path *root)
+{
+	root->dentry = d_root;
+	root->mnt = mnt_root;
+
+	path_get(root);
+}
+
+static inline void get_pwd(struct path *pwd)
+{
+	if (!cwd_dentry) {
+		cwd_dentry = d_root;
+		cwd_mnt = mnt_root;
+	}
+
+	pwd->dentry = cwd_dentry;
+	pwd->mnt = cwd_mnt;
+
+	path_get(pwd);
+}
+
+static inline void put_link(struct nameidata *nd)
+{
+	struct saved *last = nd->stack + --nd->depth;
+	path_put(&last->link);
+}
+
+static int automount_mount(struct dentry *dentry);
+
+static void path_put_conditional(struct path *path, struct nameidata *nd)
+{
+	dput(path->dentry);
+	if (path->mnt != nd->path.mnt)
+		mntput(path->mnt);
+}
+
+static int follow_automount(struct path *path, struct nameidata *nd,
+			    bool *need_mntput)
+{
+	/* We don't want to mount if someone's just doing a stat -
+	 * unless they're stat'ing a directory and appended a '/' to
+	 * the name.
+	 *
+	 * We do, however, want to mount if someone wants to open or
+	 * create a file of any type under the mountpoint, wants to
+	 * traverse through the mountpoint or wants to open the
+	 * mounted directory.  Also, autofs may mark negative dentries
+	 * as being automount points.  These will need the attentions
+	 * of the daemon to instantiate them before they can be used.
+	 */
+	if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
+			LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) &&
+			path->dentry->d_inode)
+		return -EISDIR;
+
+	return automount_mount(path->dentry);
+}
+
+/*
+ * Handle a dentry that is managed in some way.
+ * - Flagged for transit management (autofs)
+ * - Flagged as mountpoint
+ * - Flagged as automount point
+ *
+ * This may only be called in refwalk mode.
+ *
+ * Serialization is taken care of in namespace.c
+ */
+static int follow_managed(struct path *path, struct nameidata *nd)
+{
+	struct vfsmount *mnt = path->mnt;
+	unsigned managed = path->dentry->d_flags;
+	bool need_mntput = false;
+	int ret = 0;
+
+	while (managed = path->dentry->d_flags,
+		managed &= DCACHE_MANAGED_DENTRY,
+		managed != 0) {
+
+		if (managed & DCACHE_MOUNTED) {
+			struct vfsmount *mounted = lookup_mnt(path);
+
+			if (mounted) {
+				dput(path->dentry);
+				if (need_mntput)
+					mntput(path->mnt);
+				path->mnt = mounted;
+				path->dentry = dget(mounted->mnt_root);
+				need_mntput = true;
+				continue;
+			}
+		}
+
+		/* Handle an automount point */
+		if (managed & DCACHE_NEED_AUTOMOUNT) {
+			ret = follow_automount(path, nd, &need_mntput);
+			if (ret < 0)
+				break;
+			continue;
+		}
+
+		/* We didn't change the current path point */
+		break;
+	}
+
+	if (need_mntput && path->mnt == mnt)
+		mntput(path->mnt);
+	if (ret == -EISDIR || !ret)
+		ret = 1;
+	if (need_mntput)
+		nd->flags |= LOOKUP_JUMPED;
+	if (ret < 0)
+		path_put_conditional(path, nd);
+	return ret;
+}
+
+static struct dentry *__lookup_hash(const struct qstr *name,
+		struct dentry *base, unsigned int flags)
+{
+	struct dentry *dentry;
+	struct dentry *old;
+	struct inode *dir = base->d_inode;
+
+	dentry = d_lookup(base, name);
+	if (dentry)
+		return dentry;
+
+	dentry = d_alloc(base, name);
+	if (unlikely(!dentry))
+		return ERR_PTR(-ENOMEM);
+
+	old = dir->i_op->lookup(dir, dentry, flags);
+	if (IS_ERR(old)) {
+		dput(dentry);
+		return old;
+	}
+
+	if (unlikely(old)) {
+		dput(dentry);
+		dentry = old;
+	}
+
+	return dentry;
+}
+
+static int lookup_fast(struct nameidata *nd, struct path *path)
+{
+	struct dentry *dentry, *parent = nd->path.dentry;
+
+	dentry = __lookup_hash(&nd->last, parent, 0);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
+	if (d_is_negative(dentry)) {
+		dput(dentry);
+		return -ENOENT;
+	}
+
+	path->dentry = dentry;
+	path->mnt = nd->path.mnt;
+
+	return follow_managed(path, nd);
+}
+
+/*
+ * follow_up - Find the mountpoint of path's vfsmount
+ *
+ * Given a path, find the mountpoint of its source file system.
+ * Replace @path with the path of the mountpoint in the parent mount.
+ * Up is towards /.
+ *
+ * Return 1 if we went up a level and 0 if we were already at the
+ * root.
+ */
+int follow_up(struct path *path)
+{
+	struct vfsmount *parent, *mnt = path->mnt;
+	struct dentry *mountpoint;
+
+	parent = mnt->parent;
+	if (parent == mnt)
+		return 0;
+
+	mntget(parent);
+	mountpoint = dget(mnt->mountpoint);
+	dput(path->dentry);
+	path->dentry = mountpoint;
+	mntput(path->mnt);
+	path->mnt = mnt->parent;
+
+	return 1;
+}
+
+static void follow_mount(struct path *path)
+{
+	while (d_mountpoint(path->dentry)) {
+		struct vfsmount *mounted = lookup_mnt(path);
+		if (!mounted)
+			break;
+		dput(path->dentry);
+		path->mnt = mounted;
+		path->dentry = dget(mounted->mnt_root);
+	}
+}
+
+static int path_parent_directory(struct path *path)
+{
+	struct dentry *old = path->dentry;
+
+	path->dentry = dget(path->dentry->d_parent);
+	dput(old);
+
+	return 0;
+}
+
+static int follow_dotdot(struct nameidata *nd)
+{
+	while (1) {
+		if (nd->path.dentry != nd->path.mnt->mnt_root) {
+			int ret = path_parent_directory(&nd->path);
+			if (ret)
+				return ret;
+			break;
+		}
+
+		if (!follow_up(&nd->path))
+			break;
+	}
 
-	if (ret > 0)
-		f->pos += ret;
-	return ret;
+	follow_mount(&nd->path);
+
+	nd->inode = nd->path.dentry->d_inode;
+
+	return 0;
 }
-EXPORT_SYMBOL(write);
 
-int flush(int fd)
+static inline int handle_dots(struct nameidata *nd, int type)
+{
+	if (type == LAST_DOTDOT) {
+		return follow_dotdot(nd);
+	}
+	return 0;
+}
+
+static inline void path_to_nameidata(const struct path *path,
+					struct nameidata *nd)
+{
+	dput(nd->path.dentry);
+	if (nd->path.mnt != path->mnt)
+		mntput(nd->path.mnt);
+	nd->path.mnt = path->mnt;
+	nd->path.dentry = path->dentry;
+}
+
+static const char *get_link(struct nameidata *nd)
+{
+	struct saved *last = nd->stack + nd->depth - 1;
+	struct dentry *dentry = last->link.dentry;
+	struct inode *inode = nd->link_inode;
+	const char *res;
+
+	nd->last_type = LAST_BIND;
+	res = inode->i_link;
+	if (!res) {
+		res = inode->i_op->get_link(dentry, inode);
+		if (IS_ERR_OR_NULL(res))
+			return res;
+	}
+	if (*res == '/') {
+		while (unlikely(*++res == '/'))
+			;
+	}
+	if (!*res)
+		res = NULL;
+	return res;
+}
+
+static int pick_link(struct nameidata *nd, struct path *link,
+		     struct inode *inode)
+{
+	struct saved *last;
+
+	if (unlikely(nd->total_link_count++ >= MAXSYMLINKS)) {
+		path_to_nameidata(link, nd);
+		return -ELOOP;
+	}
+
+	if (link->mnt == nd->path.mnt)
+		mntget(link->mnt);
+
+	last = nd->stack + nd->depth++;
+	last->link = *link;
+	nd->link_inode = inode;
+
+	return 1;
+}
+
+/*
+ * Do we need to follow links? We _really_ want to be able
+ * to do this check without having to look at inode->i_op,
+ * so we keep a cache of "no, this doesn't need follow_link"
+ * for the common case.
+ */
+static inline int step_into(struct nameidata *nd, struct path *path,
+			    int flags, struct inode *inode)
+{
+	if (!(flags & WALK_MORE) && nd->depth)
+		put_link(nd);
+
+	if (likely(!d_is_symlink(path->dentry)) ||
+	   !(flags & WALK_FOLLOW || nd->flags & LOOKUP_FOLLOW)) {
+		/* not a symlink or should not follow */
+		path_to_nameidata(path, nd);
+		nd->inode = inode;
+		return 0;
+	}
+
+	return pick_link(nd, path, inode);
+}
+
+static int walk_component(struct nameidata *nd, int flags)
+{
+	struct path path;
+	int err;
+
+	/*
+	 * "." and ".." are special - ".." especially so because it has
+	 * to be able to know about the current root directory and
+	 * parent relationships.
+	 */
+	if (nd->last_type != LAST_NORM) {
+		err = handle_dots(nd, nd->last_type);
+		if (!(flags & WALK_MORE) && nd->depth)
+			put_link(nd);
+		return err;
+	}
+
+	err = lookup_fast(nd, &path);
+	if (err < 0)
+		return err;
+
+	if (err == 0) {
+		path.mnt = nd->path.mnt;
+		err = follow_managed(&path, nd);
+		if (err < 0)
+			return err;
+
+		if (d_is_negative(path.dentry)) {
+			path_to_nameidata(&path, nd);
+			return -ENOENT;
+		}
+	}
+
+	return step_into(nd, &path, flags, d_inode(path.dentry));
+}
+
+static int component_len(const char *name, char separator)
+{
+	int len = 0;
+
+	while (name[len] && name[len] != separator)
+		len++;
+
+	return len;
+}
+
+struct filename *getname(const char *filename)
+{
+	struct filename *result;
+
+	result = malloc(sizeof(*result));
+	if (!result)
+		return NULL;
+
+	result->name = strdup(filename);
+	if (!result->name) {
+		free(result);
+		return NULL;
+	}
+
+	result->refcnt = 1;
+
+	return result;
+}
+
+void putname(struct filename *name)
+{
+	BUG_ON(name->refcnt <= 0);
+
+	if (--name->refcnt > 0)
+		return;
+
+	free(name->name);
+	free(name);
+}
+
+static struct fs_device_d *get_fsdevice_by_dentry(struct dentry *dentry)
+{
+	struct super_block *sb;
+
+	sb = dentry->d_sb;
+
+	return container_of(sb, struct fs_device_d, sb);
+}
+
+static bool dentry_is_tftp(struct dentry *dentry)
+{
+	struct fs_device_d *fsdev;
+
+	fsdev = get_fsdevice_by_dentry(dentry);
+	if (!fsdev)
+		return false;
+
+	if (strcmp(fsdev->driver->drv.name, "tftp"))
+		return false;
+
+	return true;
+}
+
+/*
+ * Name resolution.
+ * This is the basic name resolution function, turning a pathname into
+ * the final dentry. We expect 'base' to be positive and a directory.
+ *
+ * Returns 0 and nd will have valid dentry and mnt on success.
+ * Returns error and drops reference to input namei data on failure.
+ */
+static int link_path_walk(const char *name, struct nameidata *nd)
+{
+	int err;
+	char separator = '/';
+
+	while (*name=='/')
+		name++;
+	if (!*name)
+		return 0;
+
+	/* At this point we know we have a real path component. */
+	for(;;) {
+		int len;
+		int type;
+
+		len = component_len(name, separator);
+
+		type = LAST_NORM;
+		if (name[0] == '.') switch (len) {
+			case 2:
+				if (name[1] == '.') {
+					type = LAST_DOTDOT;
+					nd->flags |= LOOKUP_JUMPED;
+				}
+				break;
+			case 1:
+				type = LAST_DOT;
+		}
+		if (likely(type == LAST_NORM))
+			nd->flags &= ~LOOKUP_JUMPED;
+
+		nd->last.len = len;
+		nd->last.name = name;
+		nd->last_type = type;
+
+		name += len;
+		if (!*name)
+			goto OK;
+
+		/*
+		 * If it wasn't NUL, we know it was '/'. Skip that
+		 * slash, and continue until no more slashes.
+		 */
+		do {
+			name++;
+		} while (unlikely(*name == separator));
+
+		if (unlikely(!*name)) {
+OK:
+			/* pathname body, done */
+			if (!nd->depth)
+				return 0;
+			name = nd->stack[nd->depth - 1].name;
+			/* trailing symlink, done */
+			if (!name)
+				return 0;
+			/* last component of nested symlink */
+			err = walk_component(nd, WALK_FOLLOW);
+		} else {
+			/* not the last component */
+			err = walk_component(nd, WALK_FOLLOW | WALK_MORE);
+		}
+
+		if (err < 0)
+			return err;
+
+		/*
+		 * barebox specific hack for TFTP. TFTP does not support
+		 * looking up directories, only the files in directories.
+		 * Since the filename is not known at this point we replace
+		 * the path separator with an invalid char so that TFTP will
+		 * get the full remaining path including slashes.
+		 */
+		if (dentry_is_tftp(nd->path.dentry))
+			separator = 0x1;
+
+		if (err) {
+			const char *s = get_link(nd);
+
+			if (IS_ERR(s))
+				return PTR_ERR(s);
+			err = 0;
+			if (unlikely(!s)) {
+				/* jumped */
+				put_link(nd);
+			} else {
+				nd->stack[nd->depth - 1].name = name;
+				name = s;
+				continue;
+			}
+		}
+		if (unlikely(!d_can_lookup(nd->path.dentry)))
+			return -ENOTDIR;
+	}
+}
+
+static const char *path_init(struct nameidata *nd, unsigned flags)
+{
+	const char *s = nd->name->name;
+
+	nd->last_type = LAST_ROOT; /* if there are only slashes... */
+	nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
+	nd->depth = 0;
+
+	nd->path.mnt = NULL;
+	nd->path.dentry = NULL;
+
+	if (*s == '/') {
+		get_root(&nd->path);
+		return s;
+	} else if (nd->dfd == AT_FDCWD) {
+		get_pwd(&nd->path);
+		nd->inode = nd->path.dentry->d_inode;
+		return s;
+	}
+
+	return s;
+}
+
+static const char *trailing_symlink(struct nameidata *nd)
+{
+	const char *s;
+
+	nd->flags |= LOOKUP_PARENT;
+	nd->stack[0].name = NULL;
+	s = get_link(nd);
+
+	return s ? s : "";
+}
+
+static inline int lookup_last(struct nameidata *nd)
+{
+	if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
+		nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+
+	nd->flags &= ~LOOKUP_PARENT;
+	return walk_component(nd, 0);
+}
+
+static void terminate_walk(struct nameidata *nd)
+{
+	int i;
+
+	path_put(&nd->path);
+	for (i = 0; i < nd->depth; i++)
+		path_put(&nd->stack[i].link);
+
+	nd->depth = 0;
+}
+
+/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
+static int path_parentat(struct nameidata *nd, unsigned flags,
+				struct path *parent)
+{
+	const char *s = path_init(nd, flags);
+	int err;
+
+	if (IS_ERR(s))
+		return PTR_ERR(s);
+
+	err = link_path_walk(s, nd);
+	if (!err) {
+		*parent = nd->path;
+		nd->path.mnt = NULL;
+		nd->path.dentry = NULL;
+	}
+	terminate_walk(nd);
+	return err;
+}
+
+static struct filename *filename_parentat(int dfd, struct filename *name,
+				unsigned int flags, struct path *parent,
+				struct qstr *last, int *type)
+{
+	int retval;
+	struct nameidata nd;
+
+	if (IS_ERR(name))
+		return name;
+
+	set_nameidata(&nd, dfd, name);
+
+	retval = path_parentat(&nd, flags, parent);
+	if (likely(!retval)) {
+		*last = nd.last;
+		*type = nd.last_type;
+	} else {
+		putname(name);
+		name = ERR_PTR(retval);
+	}
+
+	return name;
+}
+
+static struct dentry *filename_create(int dfd, struct filename *name,
+				struct path *path, unsigned int lookup_flags)
+{
+	struct dentry *dentry = ERR_PTR(-EEXIST);
+	struct qstr last;
+	int type;
+	int error;
+	bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
+
+	/*
+	 * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
+	 * other flags passed in are ignored!
+	 */
+	lookup_flags &= LOOKUP_REVAL;
+
+	name = filename_parentat(dfd, name, 0, path, &last, &type);
+	if (IS_ERR(name))
+		return ERR_CAST(name);
+
+	/*
+	 * Yucky last component or no last component at all?
+	 * (foo/., foo/.., /////)
+	 */
+	if (unlikely(type != LAST_NORM))
+		goto out;
+
+	/*
+	 * Do the final lookup.
+	 */
+	lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL;
+	dentry = __lookup_hash(&last, path->dentry, lookup_flags);
+	if (IS_ERR(dentry))
+		goto unlock;
+
+	error = -EEXIST;
+	if (d_is_positive(dentry))
+		goto fail;
+
+	/*
+	 * Special case - lookup gave negative, but... we had foo/bar/
+	 * From the vfs_mknod() POV we just have a negative dentry -
+	 * all is fine. Let's be bastards - you had / on the end, you've
+	 * been asking for (non-existent) directory. -ENOENT for you.
+	 */
+	if (unlikely(!is_dir && last.name[last.len])) {
+		error = -ENOENT;
+		goto fail;
+	}
+	putname(name);
+	return dentry;
+fail:
+	dput(dentry);
+	dentry = ERR_PTR(error);
+unlock:
+out:
+	path_put(path);
+	putname(name);
+	return dentry;
+}
+
+static int filename_lookup(int dfd, struct filename *name, unsigned flags,
+			   struct path *path)
+{
+	int err;
+	struct nameidata nd;
+	const char *s;
+
+	set_nameidata(&nd, dfd, name);
+
+	s = path_init(&nd, flags);
+
+	while (!(err = link_path_walk(s, &nd)) && ((err = lookup_last(&nd)) > 0)) {
+		s = trailing_symlink(&nd);
+		if (IS_ERR(s)) {
+			err = PTR_ERR(s);
+			break;
+		}
+	}
+
+	if (!err && nd.flags & LOOKUP_DIRECTORY)
+		if (!d_can_lookup(nd.path.dentry))
+			err = -ENOTDIR;
+	if (!err) {
+		*path = nd.path;
+		nd.path.mnt = NULL;
+		nd.path.dentry = NULL;
+	}
+
+	terminate_walk(&nd);
+	putname(name);
+
+	return err;
+}
+
+static struct fs_device_d *get_fsdevice_by_path(const char *pathname)
+{
+	struct fs_device_d *fsdev;
+	struct path path;
+	int ret;
+
+	ret = filename_lookup(AT_FDCWD, getname(pathname), 0, &path);
+	if (ret)
+		return NULL;
+
+	fsdev = get_fsdevice_by_dentry(path.dentry);
+
+	path_put(&path);
+
+	return fsdev;
+}
+
+int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int error;
+
+	if (!dir->i_op->rmdir)
+		return -EPERM;
+
+	dget(dentry);
+
+	error = dir->i_op->rmdir(dir, dentry);
+	if (error)
+		goto out;
+
+	dentry->d_inode->i_flags |= S_DEAD;
+
+out:
+	dput(dentry);
+
+	if (!error)
+		d_delete(dentry);
+
+	return error;
+}
+
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	int error;
+
+	if (!dir->i_op->mkdir)
+		return -EPERM;
+
+	mode &= (S_IRWXUGO|S_ISVTX);
+
+	error = dir->i_op->mkdir(dir, dentry, mode);
+
+	return error;
+}
+
+/* libfs.c */
+
+/* ---------------------------------------------------------------- */
+int mkdir (const char *pathname, mode_t mode)
+{
+	struct dentry *dentry;
+	struct path path;
+	int error;
+	unsigned int lookup_flags = LOOKUP_DIRECTORY;
+
+	dentry = filename_create(AT_FDCWD, getname(pathname), &path, lookup_flags);
+	if (IS_ERR(dentry)) {
+		error = PTR_ERR(dentry);
+		goto out;
+	}
+
+	error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+
+	dput(dentry);
+	path_put(&path);
+out:
+	if (error)
+		errno = -error;
+
+	return error;
+}
+EXPORT_SYMBOL(mkdir);
+
+int rmdir (const char *pathname)
+{
+	int error = 0;
+	struct filename *name;
+	struct dentry *dentry;
+	struct path path;
+	struct qstr last;
+	int type;
+
+	name = filename_parentat(AT_FDCWD, getname(pathname), 0,
+				&path, &last, &type);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
+
+	switch (type) {
+	case LAST_DOTDOT:
+		error = -ENOTEMPTY;
+		goto out;
+	case LAST_DOT:
+		error = -EINVAL;
+		goto out;
+	case LAST_ROOT:
+		error = -EBUSY;
+		goto out;
+	}
+
+	dentry = __lookup_hash(&last, path.dentry, 0);
+	if (d_is_negative(dentry)) {
+		error = -ENOENT;
+		goto out;
+	}
+	if (d_mountpoint(dentry)) {
+		error = -EBUSY;
+		goto out;
+	}
+
+	if (!d_is_dir(dentry)) {
+		error = -ENOTDIR;
+		goto out;
+	}
+
+	error = vfs_rmdir(path.dentry->d_inode, dentry);
+
+	dput(dentry);
+out:
+	path_put(&path);
+	putname(name);
+
+	if (error)
+		errno = -error;
+
+	return error;
+}
+EXPORT_SYMBOL(rmdir);
+
+int open(const char *pathname, int flags, ...)
 {
+	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
+	struct super_block *sb;
 	FILE *f;
-	int ret;
+	int error = 0;
+	struct inode *inode = NULL;
+	struct dentry *dentry = NULL;
+	struct nameidata nd;
+	const char *s;
 
-	if (check_fd(fd))
-		return -errno;
+	set_nameidata(&nd, AT_FDCWD, getname(pathname));
+	s = path_init(&nd, LOOKUP_FOLLOW);
 
-	f = &files[fd];
+	while (1) {
+		error = link_path_walk(s, &nd);
 
-	fsdrv = f->fsdev->driver;
-	if (fsdrv->flush)
-		ret = fsdrv->flush(&f->fsdev->dev, f);
-	else
-		ret = 0;
+		if (!d_is_dir(nd.path.dentry)) {
+			error = -ENOTDIR;
+			break;
+		}
 
-	if (ret)
-		errno = -ret;
+		dentry = __lookup_hash(&nd.last, nd.path.dentry, 0);
+		if (IS_ERR(dentry)) {
+			error = PTR_ERR(dentry);
+			break;
+		}
 
-	return ret;
-}
+		if (!d_is_symlink(dentry))
+			break;
 
-loff_t lseek(int fildes, loff_t offset, int whence)
-{
-	struct fs_driver_d *fsdrv;
-	FILE *f;
-	loff_t pos;
-	int ret;
+		dput(dentry);
 
-	if (check_fd(fildes))
-		return -1;
+		error = lookup_last(&nd);
+		if (error <= 0)
+			break;
 
-	f = &files[fildes];
-	fsdrv = f->fsdev->driver;
-	if (!fsdrv->lseek) {
-		ret = -ENOSYS;
-		goto out;
+		s = trailing_symlink(&nd);
+		if (IS_ERR(s)) {
+			error = PTR_ERR(s);
+			break;
+		}
 	}
 
-	ret = -EINVAL;
+	terminate_walk(&nd);
+	putname(nd.name);
 
-	switch (whence) {
-	case SEEK_SET:
-		if (f->size != FILE_SIZE_STREAM && offset > f->size)
-			goto out;
-		if (offset < 0)
-			goto out;
-		pos = offset;
-		break;
-	case SEEK_CUR:
-		if (f->size != FILE_SIZE_STREAM && offset + f->pos > f->size)
-			goto out;
-		pos = f->pos + offset;
-		break;
-	case SEEK_END:
-		if (offset > 0)
+	if (error)
+		return error;
+
+	if (d_is_negative(dentry)) {
+		if (flags & O_CREAT) {
+			error = create(nd.path.dentry, dentry);
+			if (error)
+				goto out1;
+		} else {
+			dput(dentry);
+			error = -ENOENT;
+			goto out1;
+		}
+	} else {
+		if (d_is_dir(dentry) && !dentry_is_tftp(dentry)) {
+			error = -EISDIR;
+			goto out1;
+		}
+	}
+
+	inode = d_inode(dentry);
+
+	f = get_file();
+	if (!f) {
+		error = -EMFILE;
+		goto out1;
+	}
+
+	f->path = xstrdup(pathname);
+	f->dentry = dentry;
+	f->f_inode = iget(inode);
+	f->flags = flags;
+	f->size = inode->i_size;
+
+	sb = inode->i_sb;
+	fsdev = container_of(sb, struct fs_device_d, sb);
+	fsdrv = fsdev->driver;
+
+	f->fsdev = fsdev;
+
+	if (fsdrv->open) {
+		error = fsdrv->open(&fsdev->dev, f, NULL);
+		if (error)
 			goto out;
-		pos = f->size + offset;
-		break;
-	default:
-		goto out;
 	}
 
-	pos = fsdrv->lseek(&f->fsdev->dev, f, pos);
-	if (pos < 0) {
-		errno = -pos;
-		return -1;
+	if (flags & O_TRUNC) {
+		error = fsdrv->truncate(&fsdev->dev, f, 0);
+		f->size = 0;
+		inode->i_size = 0;
+		if (error)
+			goto out;
 	}
 
-	return pos;
+	if (flags & O_APPEND)
+		f->pos = f->size;
+
+	return f->no;
 
 out:
-	if (ret)
-		errno = -ret;
+	put_file(f);
+out1:
 
-	return -1;
+	if (error)
+		errno = -error;
+	return error;
 }
-EXPORT_SYMBOL(lseek);
+EXPORT_SYMBOL(open);
 
-int erase(int fd, loff_t count, loff_t offset)
+int unlink(const char *pathname)
 {
-	struct fs_driver_d *fsdrv;
-	FILE *f;
 	int ret;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct path path;
 
-	if (check_fd(fd))
-		return -errno;
-	f = &files[fd];
-	if (offset >= f->size)
-		return 0;
-	if (count == ERASE_SIZE_ALL || count > f->size - offset)
-		count = f->size - offset;
-	if (count < 0)
-		return -EINVAL;
+	ret = filename_lookup(AT_FDCWD, getname(pathname), 0, &path);
+	if (ret)
+		goto out;
 
-	fsdrv = f->fsdev->driver;
-	if (fsdrv->erase)
-		ret = fsdrv->erase(&f->fsdev->dev, f, count, offset);
-	else
-		ret = -ENOSYS;
+	dentry = path.dentry;
 
-	if (ret)
-		errno = -ret;
+	if (d_is_dir(dentry)) {
+		ret = -EISDIR;
+		goto out_put;
+	}
 
-	return ret;
-}
-EXPORT_SYMBOL(erase);
+	inode = d_inode(dentry->d_parent);
 
-int protect(int fd, size_t count, loff_t offset, int prot)
-{
-	struct fs_driver_d *fsdrv;
-	FILE *f;
-	int ret;
+	if (!inode->i_op->unlink) {
+		ret = -EPERM;
+		goto out_put;
+	}
 
-	if (check_fd(fd))
-		return -errno;
-	f = &files[fd];
-	if (offset >= f->size)
-		return 0;
-	if (count > f->size - offset)
-		count = f->size - offset;
+	ret = inode->i_op->unlink(inode, dentry);
+	if (ret)
+		goto out_put;
 
-	fsdrv = f->fsdev->driver;
-	if (fsdrv->protect)
-		ret = fsdrv->protect(&f->fsdev->dev, f, count, offset, prot);
-	else
-		ret = -ENOSYS;
+	d_delete(dentry);
 
+out_put:
+	path_put(&path);
+out:
 	if (ret)
 		errno = -ret;
-
 	return ret;
 }
-EXPORT_SYMBOL(protect);
+EXPORT_SYMBOL(unlink);
 
-int protect_file(const char *file, int prot)
+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 {
-	int fd, ret;
+	if (!dir->i_op->symlink)
+		return -EPERM;
 
-	fd = open(file, O_WRONLY);
-	if (fd < 0)
-		return fd;
+	return dir->i_op->symlink(dir, dentry, oldname);
+}
 
-	ret = protect(fd, ~0, 0, prot);
+int symlink(const char *pathname, const char *newpath)
+{
+	struct dentry *dentry;
+	struct path path;
+	int error;
+	unsigned int lookup_flags = LOOKUP_DIRECTORY;
 
-	close(fd);
+	dentry = filename_create(AT_FDCWD, getname(newpath), &path, lookup_flags);
+	if (IS_ERR(dentry)) {
+		error = PTR_ERR(dentry);
+		goto out;
+	}
 
-	return ret;
+	error = vfs_symlink(path.dentry->d_inode, dentry, pathname);
+out:
+	if (error)
+		errno = -error;
+
+	return error;
 }
+EXPORT_SYMBOL(symlink);
 
-void *memmap(int fd, int flags)
+static void release_dir(DIR *d)
+{
+	struct readdir_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &d->entries, list) {
+		free(entry);
+	}
+
+	free(d);
+}
+
+DIR *opendir(const char *pathname)
 {
-	struct fs_driver_d *fsdrv;
-	FILE *f;
-	void *retp = (void *)-1;
 	int ret;
+	struct dentry *dir;
+	struct inode *inode;
+	struct file file = {};
+	DIR *d;
+	struct path path = {};
+	struct readdir_callback rd = {
+		.ctx = {
+			.actor = fillonedir,
+		},
+	};
+
+	ret = filename_lookup(AT_FDCWD, getname(pathname),
+			      LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
+	if (ret)
+		goto out;
 
-	if (check_fd(fd))
-		return retp;
+	dir = path.dentry;
 
-	f = &files[fd];
+	if (d_is_negative(dir)) {
+		ret = -ENOENT;
+		goto out_put;
+	}
 
-	fsdrv = f->fsdev->driver;
+	inode = d_inode(dir);
 
-	if (fsdrv->memmap)
-		ret = fsdrv->memmap(&f->fsdev->dev, f, &retp, flags);
-	else
-		ret = -EINVAL;
+	if (!S_ISDIR(inode->i_mode)) {
+		ret = -ENOTDIR;
+		goto out_put;
+	}
+
+	file.f_path.dentry = dir;
+	file.f_op = dir->d_inode->i_fop;
 
+	d = xzalloc(sizeof(*d));
+
+	INIT_LIST_HEAD(&d->entries);
+	rd.dir = d;
+
+	ret = file.f_op->iterate(&file, &rd.ctx);
 	if (ret)
-		errno = -ret;
+		goto out_release;
 
-	return retp;
-}
-EXPORT_SYMBOL(memmap);
+	path_put(&path);
 
-int close(int fd)
-{
-	struct fs_driver_d *fsdrv;
-	FILE *f;
-	int ret;
+	return d;
 
-	if (check_fd(fd))
-		return -errno;
+out_release:
+	release_dir(d);
+out_put:
+	path_put(&path);
+out:
+	errno = -ret;
 
-	f = &files[fd];
+	return NULL;
+}
+EXPORT_SYMBOL(opendir);
 
-	fsdrv = f->fsdev->driver;
-	ret = fsdrv->close(&f->fsdev->dev, f);
+int closedir(DIR *dir)
+{
+	int ret;
 
-	put_file(f);
+	if (!dir) {
+		errno = EBADF;
+		return -EBADF;
+	}
 
-	if (ret)
-		errno = -ret;
+	release_dir(dir);
 
 	return ret;
 }
-EXPORT_SYMBOL(close);
+EXPORT_SYMBOL(closedir);
 
 int readlink(const char *pathname, char *buf, size_t bufsiz)
 {
-	struct fs_driver_d *fsdrv;
-	struct fs_device_d *fsdev;
-	char *p = canonicalize_dir(pathname);
-	char *freep = p;
 	int ret;
-	struct stat s;
+	struct dentry *dentry;
+	struct inode *inode;
+	const char *link;
+	struct path path = {};
 
-	ret = lstat(pathname, &s);
+	ret = filename_lookup(AT_FDCWD, getname(pathname), 0, &path);
 	if (ret)
 		goto out;
 
-	if (!S_ISLNK(s.st_mode)) {
+	dentry = path.dentry;
+
+	if (!d_is_symlink(dentry)) {
 		ret = -EINVAL;
-		goto out;
+		goto out_put;
 	}
 
-	fsdev = get_fs_device_and_root_path(&p);
-	if (!fsdev) {
-		ret = -ENODEV;
-		goto out;
+	inode = d_inode(dentry);
+
+	if (!inode->i_op->get_link) {
+		ret = -EPERM;
+		goto out_put;
 	}
-	fsdrv = fsdev->driver;
 
-	if (fsdrv->readlink)
-		ret = fsdrv->readlink(&fsdev->dev, p, buf, bufsiz);
-	else
-		ret = -ENOSYS;
+	link = inode->i_op->get_link(dentry, inode);
 
-	if (ret)
-		goto out;
+	strncpy(buf, link, bufsiz);
 
+	ret = 0;
+out_put:
+	path_put(&path);
 out:
-	free(freep);
-
 	if (ret)
 		errno = -ret;
 
@@ -1159,225 +2477,224 @@ out:
 }
 EXPORT_SYMBOL(readlink);
 
-int symlink(const char *pathname, const char *newpath)
+static int __stat(const char *filename, struct stat *s, unsigned int flags)
 {
-	struct fs_driver_d *fsdrv;
-	struct fs_device_d *fsdev;
-	char *p;
 	int ret;
-	struct stat s;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct path path = {};
 
-	p = canonicalize_path(newpath);
-	if (IS_ERR(p)) {
-		ret = PTR_ERR(p);
+	ret = filename_lookup(AT_FDCWD, getname(filename), flags, &path);
+	if (ret)
 		goto out;
-	}
 
-	ret = lstat(p, &s);
-	if (!ret) {
-		ret = -EEXIST;
-		goto out;
-	}
+	dentry = path.dentry;
 
-	fsdev = get_fs_device_and_root_path(&p);
-	if (!fsdev) {
-		ret = -ENODEV;
-		goto out;
+	if (d_is_negative(dentry)) {
+		ret = -ENOENT;
+		goto out_put;
 	}
-	fsdrv = fsdev->driver;
 
-	if (fsdrv->symlink) {
-		ret = fsdrv->symlink(&fsdev->dev, pathname, p);
-	} else {
-		ret = -EPERM;
-	}
+	inode = d_inode(dentry);
 
-out:
-	free(p);
-	if (ret)
-		errno = -ret;
+	s->st_dev = 0;
+	s->st_ino = inode->i_ino;
+	s->st_mode = inode->i_mode;
+	s->st_uid = inode->i_uid;
+	s->st_gid = inode->i_gid;
+	s->st_size = inode->i_size;
 
+	ret = 0;
+out_put:
+	path_put(&path);
+out:
 	return ret;
 }
-EXPORT_SYMBOL(symlink);
 
-static int fs_match(struct device_d *dev, struct driver_d *drv)
+int stat(const char *filename, struct stat *s)
+{
+	return __stat(filename, s, LOOKUP_FOLLOW);
+}
+EXPORT_SYMBOL(stat);
+
+int lstat(const char *filename, struct stat *s)
 {
-	return strcmp(dev->name, drv->name) ? -1 : 0;
+	return __stat(filename, s, 0);
 }
+EXPORT_SYMBOL(lstat);
 
-static int fs_probe(struct device_d *dev)
+static char *__dpath(struct dentry *dentry, struct dentry *root)
 {
-	struct fs_device_d *fsdev = dev_to_fs_device(dev);
-	struct driver_d *drv = dev->driver;
-	struct fs_driver_d *fsdrv = container_of(drv, struct fs_driver_d, drv);
-	int ret;
+	char *res, *ppath;
 
-	ret = dev->driver->probe(dev);
-	if (ret)
-		return ret;
+	if (dentry == root)
+		return NULL;
+	if (dentry == d_root)
+		return NULL;
 
-	fsdev->driver = fsdrv;
+	while (IS_ROOT(dentry)) {
+		struct fs_device_d *fsdev;
 
-	list_add_tail(&fsdev->list, &fs_device_list);
+		for_each_fs_device(fsdev) {
+			if (dentry == fsdev->vfsmount.mnt_root) {
+				dentry = fsdev->vfsmount.mountpoint;
+				break;
+			}
+		}
+	}
 
-	if (!fs_dev_root)
-		fs_dev_root = fsdev;
+	ppath = __dpath(dentry->d_parent, root);
+	if (ppath)
+		res = basprintf("%s/%s", ppath, dentry->name);
+	else
+		res = basprintf("/%s", dentry->name);
+	free(ppath);
 
-	return 0;
+	return res;
 }
 
-static void fs_remove(struct device_d *dev)
+/** dpath - return path of a dentry
+ * @dentry: The dentry to return the path from
+ * @root:   The dentry up to which the path is followed
+ *
+ * Get the path of a dentry. The path is followed up to
+ * @root or the root ("/") dentry, whatever is found first.
+ *
+ * Return: Dynamically allocated string containing the path
+ */
+char *dpath(struct dentry *dentry, struct dentry *root)
 {
-	struct fs_device_d *fsdev = dev_to_fs_device(dev);
-
-	if (fsdev->dev.driver) {
-		dev->driver->remove(dev);
-		list_del(&fsdev->list);
-	}
+	char *res;
 
-	free(fsdev->path);
-	free(fsdev->options);
+	if (dentry == root && dentry == d_root)
+		return strdup("/");
 
-	if (fsdev == fs_dev_root)
-		fs_dev_root = NULL;
+	res = __dpath(dentry, root);
 
-	if (fsdev->cdev)
-		cdev_close(fsdev->cdev);
+	return res;
+}
 
-	if (fsdev->loop)
-		cdev_remove_loop(fsdev->cdev);
+/**
+ * canonicalize_path - resolve links in path
+ * @pathname: The input path
+ *
+ * This function resolves all links in @pathname and returns
+ * a path without links in it.
+ *
+ * Return: Path with links resolved. Allocated, must be freed after use.
+ */
+char *canonicalize_path(const char *pathname)
+{
+	char *res = NULL;
+	struct path path;
+	int ret;
 
-	free(fsdev->backingstore);
-	free(fsdev);
-}
+	ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+	if (ret)
+		goto out;
 
-struct bus_type fs_bus = {
-	.name = "fs",
-	.match = fs_match,
-	.probe = fs_probe,
-	.remove = fs_remove,
-};
+	res = dpath(path.dentry, d_root);
+out:
+	if (ret)
+		errno = -ret;
 
-static int fs_bus_init(void)
-{
-	return bus_register(&fs_bus);
+	return res;
 }
-pure_initcall(fs_bus_init);
 
-int register_fs_driver(struct fs_driver_d *fsdrv)
+const char *getcwd(void)
 {
-	fsdrv->drv.bus = &fs_bus;
-	register_driver(&fsdrv->drv);
-
-	return 0;
+	return cwd;
 }
-EXPORT_SYMBOL(register_fs_driver);
+EXPORT_SYMBOL(getcwd);
 
-static const char *detect_fs(const char *filename, const char *fsoptions)
+int chdir(const char *pathname)
 {
-	enum filetype type;
-	struct driver_d *drv;
-	struct fs_driver_d *fdrv;
-	bool loop = false;
-	unsigned long long offset = 0;
-
-	parseopt_b(fsoptions, "loop", &loop);
-	parseopt_llu_suffix(fsoptions, "offset", &offset);
-	if (loop)
-		type = file_name_detect_type_offset(filename, offset);
-	else
-		type = cdev_detect_type(filename);
-
-	if (type == filetype_unknown)
-		return NULL;
+	char *realpath;
+	struct path path;
+	int ret;
 
-	bus_for_each_driver(&fs_bus, drv) {
-		fdrv = drv_to_fs_driver(drv);
+	ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+	if (ret)
+		goto out;
 
-		if (type == fdrv->type)
-			return drv->name;
+	if (!d_is_dir(path.dentry)) {
+		ret = -ENOTDIR;
+		goto out;
 	}
 
-	return NULL;
-}
-
-int fsdev_open_cdev(struct fs_device_d *fsdev)
-{
-	unsigned long long offset = 0;
+	realpath = dpath(path.dentry, d_root);
+	strcpy(cwd, realpath);
+	free(realpath);
+	cwd_dentry = path.dentry;
+	cwd_mnt = path.mnt;
 
-	parseopt_b(fsdev->options, "loop", &fsdev->loop);
-	parseopt_llu_suffix(fsdev->options, "offset", &offset);
-	if (fsdev->loop)
-		fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR,
-					       offset);
-	else
-		fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR);
-	if (!fsdev->cdev)
-		return -EINVAL;
+	ret = 0;
 
-	fsdev->dev.parent = fsdev->cdev->dev;
-	fsdev->parent_device = fsdev->cdev->dev;
+out:
+	if (ret)
+		errno = -ret;
 
-	return 0;
+	return ret;
 }
+EXPORT_SYMBOL(chdir);
 
 /*
  * Mount a device to a directory.
  * We do this by registering a new device on which the filesystem
  * driver will match.
  */
-int mount(const char *device, const char *fsname, const char *_path,
+int mount(const char *device, const char *fsname, const char *pathname,
 		const char *fsoptions)
 {
 	struct fs_device_d *fsdev;
 	int ret;
-	char *path = normalise_path(_path);
-
-	if (!fsoptions)
-		fsoptions = "";
+	struct path path = {};
 
-	debug("mount: %s on %s type %s, options=%s\n",
-			device, path, fsname, fsoptions);
+	if (d_root) {
+		ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+		if (ret)
+			goto out;
 
-	if (fs_dev_root) {
-		struct stat s;
+		if (!d_is_dir(path.dentry)) {
+			ret = -ENOTDIR;
+			goto out;
+		}
 
-		fsdev = get_fsdevice_by_path(path);
-		if (fsdev != fs_dev_root) {
-			printf("sorry, no nested mounts\n");
+		if (IS_ROOT(path.dentry) || d_mountpoint(path.dentry)) {
 			ret = -EBUSY;
-			goto err_free_path;
-		}
-		ret = lstat(path, &s);
-		if (ret)
-			goto err_free_path;
-		if (!S_ISDIR(s.st_mode)) {
-			ret = -ENOTDIR;
-			goto err_free_path;
+			goto out;
 		}
 	} else {
-		/* no mtab, so we only allow to mount on '/' */
-		if (*path != '/' || *(path + 1)) {
-			ret = -ENOTDIR;
-			goto err_free_path;
-		}
+		if (pathname[0] != '/' || pathname[1])
+			return -EINVAL;
 	}
 
+	if (!fsoptions)
+		fsoptions = "";
+
+	debug("mount: %s on %s type %s, options=%s\n",
+			device, pathname, fsname, fsoptions);
+
 	if (!fsname)
 		fsname = detect_fs(device, fsoptions);
 
-	if (!fsname)
-		return -ENOENT;
+	if (!fsname) {
+		ret = -ENOENT;
+		goto out;
+	}
 
 	fsdev = xzalloc(sizeof(struct fs_device_d));
 	fsdev->backingstore = xstrdup(device);
 	safe_strncpy(fsdev->dev.name, fsname, MAX_DRIVER_NAME);
 	fsdev->dev.id = get_free_deviceid(fsdev->dev.name);
-	fsdev->path = xstrdup(path);
 	fsdev->dev.bus = &fs_bus;
 	fsdev->options = xstrdup(fsoptions);
 
+	init_super(&fsdev->sb);
+
+	if (path.mnt)
+		mntget(path.mnt);
+
 	ret = register_device(&fsdev->dev);
 	if (ret)
 		goto err_register;
@@ -1391,6 +2708,22 @@ int mount(const char *device, const char *fsname, const char *_path,
 		goto err_no_driver;
 	}
 
+	if (d_root) {
+		fsdev->vfsmount.mountpoint = path.dentry;
+		fsdev->vfsmount.parent = path.mnt;
+		fsdev->vfsmount.mountpoint->d_flags |= DCACHE_MOUNTED;
+	} else {
+		d_root = fsdev->sb.s_root;
+		path.dentry = d_root;
+		mnt_root = &fsdev->vfsmount;
+		fsdev->vfsmount.mountpoint = d_root;
+		fsdev->vfsmount.parent = &fsdev->vfsmount;
+	}
+
+	fsdev->path = dpath(path.dentry, d_root);
+
+	fsdev->vfsmount.mnt_root = fsdev->sb.s_root;
+
 	if (!fsdev->linux_rootarg && fsdev->cdev && fsdev->cdev->partuuid[0] != 0) {
 		char *str = basprintf("root=PARTUUID=%s",
 					fsdev->cdev->partuuid);
@@ -1398,7 +2731,7 @@ int mount(const char *device, const char *fsname, const char *_path,
 		fsdev_set_linux_rootarg(fsdev, str);
 	}
 
-	free(path);
+	path_put(&path);
 
 	return 0;
 
@@ -1406,8 +2739,8 @@ err_no_driver:
 	unregister_device(&fsdev->dev);
 err_register:
 	fs_remove(&fsdev->dev);
-err_free_path:
-	free(path);
+out:
+	path_put(&path);
 
 	errno = -ret;
 
@@ -1415,69 +2748,39 @@ err_free_path:
 }
 EXPORT_SYMBOL(mount);
 
-static int fsdev_umount(struct fs_device_d *fsdev)
-{
-	return unregister_device(&fsdev->dev);
-}
-
-/**
- * umount_by_cdev Use a cdev struct to umount all mounted filesystems
- * @param cdev cdev to the according device
- * @return 0 on success or if cdev was not mounted, -errno otherwise
- */
-int umount_by_cdev(struct cdev *cdev)
+int umount(const char *pathname)
 {
-	struct fs_device_d *fs;
-	struct fs_device_d *fs_tmp;
-	int first_error = 0;
+	struct fs_device_d *fsdev = NULL, *f;
+	struct path path = {};
+	int ret;
 
-	for_each_fs_device_safe(fs_tmp, fs) {
-		int ret;
+	ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+	if (ret)
+		return ret;
 
-		if (fs->cdev == cdev) {
-			ret = fsdev_umount(fs);
-			if (ret) {
-				pr_err("Failed umounting %s, %d, continuing anyway\n",
-				       fs->path, ret);
-				if (!first_error)
-					first_error = ret;
-			}
-		}
+	if (path.dentry == d_root) {
+		path_put(&path);
+		return -EBUSY;
 	}
 
-	return first_error;
-}
-EXPORT_SYMBOL(umount_by_cdev);
-
-int umount(const char *pathname)
-{
-	struct fs_device_d *fsdev = NULL, *f;
-	char *p = normalise_path(pathname);
-
 	for_each_fs_device(f) {
-		if (!strcmp(p, f->path)) {
+		if (path.dentry == f->vfsmount.mnt_root) {
 			fsdev = f;
 			break;
 		}
 	}
 
+	path_put(&path);
+
 	if (!fsdev) {
-		struct cdev *cdev = cdev_open(p, O_RDWR);
+		struct cdev *cdev = cdev_open(pathname, O_RDWR);
 
 		if (cdev) {
-			free(p);
 			cdev_close(cdev);
 			return umount_by_cdev(cdev);
 		}
 	}
 
-	free(p);
-
-	if (f == fs_dev_root && !list_is_singular(&fs_device_list)) {
-		errno = EBUSY;
-		return -EBUSY;
-	}
-
 	if (!fsdev) {
 		errno = EFAULT;
 		return -EFAULT;
@@ -1487,386 +2790,249 @@ int umount(const char *pathname)
 }
 EXPORT_SYMBOL(umount);
 
-DIR *opendir(const char *pathname)
-{
-	DIR *dir = NULL;
-	struct fs_device_d *fsdev;
-	struct fs_driver_d *fsdrv;
-	char *p = canonicalize_path(pathname);
-	char *freep = p;
-	int ret;
-	struct stat s;
-
-	ret = stat(pathname, &s);
-	if (ret)
-		goto out;
-
-	if (!S_ISDIR(s.st_mode)) {
-		ret = -ENOTDIR;
-		goto out;
-	}
-
-	fsdev = get_fs_device_and_root_path(&p);
-	if (!fsdev) {
-		ret = -ENOENT;
-		goto out;
-	}
-	fsdrv = fsdev->driver;
-
-	debug("opendir: fsdrv: %p\n",fsdrv);
-
-	dir = fsdrv->opendir(&fsdev->dev, p);
-	if (dir) {
-		dir->dev = &fsdev->dev;
-		dir->fsdrv = fsdrv;
-	} else {
-		/*
-		 * FIXME: The fs drivers should return ERR_PTR here so that
-		 * we are able to forward the error
-		 */
-		ret = -EINVAL;
-	}
-
-out:
-	free(freep);
-
-	if (ret)
-		errno = -ret;
-
-	return dir;
-}
-EXPORT_SYMBOL(opendir);
-
-struct dirent *readdir(DIR *dir)
-{
-	struct dirent *ent;
-
-	if (!dir)
-		return NULL;
+#ifdef CONFIG_FS_AUTOMOUNT
 
-	ent = dir->fsdrv->readdir(dir->dev, dir);
+#define AUTOMOUNT_IS_FILE (1 << 0)
 
-	if (!ent)
-		errno = EBADF;
+struct automount {
+	char *path;
+	struct dentry *dentry;
+	char *cmd;
+	struct list_head list;
+	unsigned int flags;
+};
 
-	return ent;
-}
-EXPORT_SYMBOL(readdir);
+static LIST_HEAD(automount_list);
 
-int closedir(DIR *dir)
+static void automount_remove_dentry(struct dentry *dentry)
 {
-	int ret;
+	struct automount *am;
 
-	if (!dir) {
-		errno = EBADF;
-		return -EBADF;
+	list_for_each_entry(am, &automount_list, list) {
+		if (dentry == am->dentry)
+			goto found;
 	}
 
-	ret = dir->fsdrv->closedir(dir->dev, dir);
-	if (ret)
-		errno = -ret;
-
-	return ret;
+	return;
+found:
+	list_del(&am->list);
+	dput(am->dentry);
+	free(am->path);
+	free(am->cmd);
+	free(am);
 }
-EXPORT_SYMBOL(closedir);
 
-int stat(const char *filename, struct stat *s)
+void automount_remove(const char *pathname)
 {
-	char *path = canonicalize_path(filename);
+	struct path path;
 	int ret;
 
-	if (IS_ERR(path))
-		return PTR_ERR(path);
-
-	ret = lstat(path, s);
+	ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+	if (ret)
+		return;
 
-	free(path);
+	automount_remove_dentry(path.dentry);
 
-	return ret;
+	path_put(&path);
 }
-EXPORT_SYMBOL(stat);
+EXPORT_SYMBOL(automount_remove);
 
-static int __lstat(const char *filename, struct stat *s)
+int automount_add(const char *pathname, const char *cmd)
 {
-	struct fs_driver_d *fsdrv;
-	struct fs_device_d *fsdev;
-	char *f = normalise_path(filename);
-	char *freep = f;
+	struct automount *am = xzalloc(sizeof(*am));
+	struct path path;
 	int ret;
 
-	automount_mount(f, 1);
-
-	memset(s, 0, sizeof(struct stat));
+	ret = filename_lookup(AT_FDCWD, getname(pathname), LOOKUP_FOLLOW, &path);
+	if (ret)
+		return ret;
 
-	fsdev = get_fsdevice_by_path(f);
-	if (!fsdev) {
-		ret = -ENOENT;
+	if (!d_is_dir(path.dentry)) {
+		ret = -ENOTDIR;
 		goto out;
 	}
 
-	if (fsdev != fs_dev_root && strcmp(f, fsdev->path))
-		f += strlen(fsdev->path);
-	else
-		fsdev = fs_dev_root;
+	am->path = dpath(path.dentry, d_root);
+	am->dentry = dget(path.dentry);
+	am->dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+	am->cmd = xstrdup(cmd);
 
-	fsdrv = fsdev->driver;
+	automount_remove_dentry(am->dentry);
 
-	if (*f == 0)
-		f = "/";
+	list_add_tail(&am->list, &automount_list);
 
-	ret = fsdrv->stat(&fsdev->dev, f, s);
+	ret = 0;
 out:
-	free(freep);
-
-	if (ret)
-		errno = -ret;
+	path_put(&path);
 
 	return ret;
 }
+EXPORT_SYMBOL(automount_add);
 
-int lstat(const char *filename, struct stat *s)
+void cdev_create_default_automount(struct cdev *cdev)
 {
-	char *f = canonicalize_dir(filename);
-	int ret;
-
-	if (IS_ERR(f))
-		return PTR_ERR(f);
+	char *path, *cmd;
 
-	ret = __lstat(f, s);
+	path = basprintf("/mnt/%s", cdev->name);
+	cmd = basprintf("mount %s", cdev->name);
 
-	free(f);
+	make_directory(path);
+	automount_add(path, cmd);
 
-	return ret;
+	free(cmd);
+	free(path);
 }
-EXPORT_SYMBOL(lstat);
 
-int fstat(int fd, struct stat *s)
+void automount_print(void)
 {
-	FILE *f;
-	struct fs_device_d *fsdev;
-
-	if (check_fd(fd))
-		return -errno;
-
-	f = &files[fd];
-
-	fsdev = f->fsdev;
+	struct automount *am;
 
-	return fsdev->driver->stat(&fsdev->dev, f->path, s);
+	list_for_each_entry(am, &automount_list, list)
+		printf("%-20s %s\n", am->path, am->cmd);
 }
-EXPORT_SYMBOL(fstat);
+EXPORT_SYMBOL(automount_print);
 
-int mkdir (const char *pathname, mode_t mode)
+static int automount_mount(struct dentry *dentry)
 {
-	struct fs_driver_d *fsdrv;
-	struct fs_device_d *fsdev;
-	char *p = canonicalize_path(pathname);
-	char *freep = p;
-	int ret;
-	struct stat s;
-
-	ret = parent_check_directory(p);
-	if (ret)
-		goto out;
-
-	ret = stat(pathname, &s);
-	if (!ret) {
-		ret = -EEXIST;
-		goto out;
-	}
-
-	fsdev = get_fs_device_and_root_path(&p);
-	if (!fsdev) {
-		ret = -ENOENT;
-		goto out;
-	}
-	fsdrv = fsdev->driver;
-
-	if (fsdrv->mkdir)
-		ret = fsdrv->mkdir(&fsdev->dev, p);
-	else
-		ret = -EROFS;
-out:
-	free(freep);
+	struct automount *am;
+	int ret = -ENOENT;
+	static int in_automount;
 
-	if (ret)
-		errno = -ret;
+	if (in_automount)
+		return -EINVAL;
 
-	return ret;
-}
-EXPORT_SYMBOL(mkdir);
+	in_automount++;
 
-int rmdir (const char *pathname)
-{
-	struct fs_driver_d *fsdrv;
-	struct fs_device_d *fsdev;
-	char *p = canonicalize_path(pathname);
-	char *freep = p;
-	int ret;
-	struct stat s;
+	list_for_each_entry(am, &automount_list, list) {
+		if (am->dentry != dentry)
+			continue;
 
-	ret = lstat(pathname, &s);
-	if (ret)
-		goto out;
-	if (!S_ISDIR(s.st_mode)) {
-		ret = -ENOTDIR;
-		goto out;
-	}
+		setenv("automount_path", am->path);
+		export("automount_path");
+		ret = run_command(am->cmd);
+		setenv("automount_path", NULL);
 
-	if (!dir_is_empty(pathname)) {
-		ret = -ENOTEMPTY;
-		goto out;
-	}
+		if (ret) {
+			printf("running automount command '%s' failed\n",
+					am->cmd);
+			ret = -ENODEV;
+		}
 
-	fsdev = get_fs_device_and_root_path(&p);
-	if (!fsdev) {
-		ret = -ENODEV;
-		goto out;
+		break;
 	}
-	fsdrv = fsdev->driver;
-
-	if (fsdrv->rmdir)
-		ret = fsdrv->rmdir(&fsdev->dev, p);
-	else
-		ret = -EROFS;
-out:
-	free(freep);
 
-	if (ret)
-		errno = -ret;
+	in_automount--;
 
 	return ret;
 }
-EXPORT_SYMBOL(rmdir);
-
-/*
- * cdev_get_mount_path - return the path a cdev is mounted on
- *
- * If a cdev is mounted return the path it's mounted on, NULL
- * otherwise.
- */
-const char *cdev_get_mount_path(struct cdev *cdev)
-{
-	struct fs_device_d *fsdev;
 
-	for_each_fs_device(fsdev) {
-		if (fsdev->cdev && fsdev->cdev == cdev)
-			return fsdev->path;
-	}
+BAREBOX_MAGICVAR(automount_path, "mountpath passed to automount scripts");
 
-	return NULL;
+#else
+static int automount_mount(const char *path)
+{
+	return 0;
 }
+#endif /* CONFIG_FS_AUTOMOUNT */
+
+#ifdef DEBUG
 
 /*
- * cdev_mount_default - mount a cdev to the default path
- *
- * If a cdev is already mounted return the path it's mounted on, otherwise
- * mount it to /mnt/<cdevname> and return the path. Returns an error pointer
- * on failure.
+ * Some debug commands, helpful to debug the dcache implementation
  */
-const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions)
+#include <command.h>
+
+static int do_lookup_dentry(int argc, char *argv[])
 {
-	const char *path;
-	char *newpath, *devpath;
+	struct path path;
 	int ret;
+	char *canon;
+	char mode[16];
 
-	/*
-	 * If this cdev is already mounted somewhere use this path
-	 * instead of mounting it again to avoid corruption on the
-	 * filesystem. Note this ignores eventual fsoptions though.
-	 */
-	path = cdev_get_mount_path(cdev);
-	if (path)
-		return path;
-
-	newpath = basprintf("/mnt/%s", cdev->name);
-	make_directory(newpath);
-
-	devpath = basprintf("/dev/%s", cdev->name);
-
-	ret = mount(devpath, NULL, newpath, fsoptions);
-
-	free(devpath);
+	if (argc < 2)
+		return COMMAND_ERROR_USAGE;
 
+	ret = filename_lookup(AT_FDCWD, getname(argv[1]), 0, &path);
 	if (ret) {
-		free(newpath);
-		return ERR_PTR(ret);
+		printf("Cannot lookup path \"%s\": %s\n",
+		       argv[1], strerror(-ret));
+		return 1;
 	}
 
-	return cdev_get_mount_path(cdev);
-}
+	canon = canonicalize_path(argv[1]);
+	
+	printf("path \"%s\":\n", argv[1]);
+	printf("dentry: 0x%p\n", path.dentry);
+	printf("dentry refcnt: %d\n", path.dentry->d_count);
+	if (path.dentry->d_inode) {
+		struct inode *inode = path.dentry->d_inode;
+		printf("inode: 0x%p\n", inode);
+		printf("inode refcnt: %d\n", inode->i_count);
+		printf("Type: %s\n", mkmodestr(inode->i_mode, mode));
+	}
+	printf("canonical path: \"%s\"\n", canon);
 
-/*
- * mount_all - iterate over block devices and mount all devices we are able to
- */
-void mount_all(void)
-{
-	struct device_d *dev;
-	struct block_device *bdev;
+	path_put(&path);
+	free(canon);
 
-	if (!IS_ENABLED(CONFIG_BLOCK))
-		return;
+        return 0;
+}
 
-	for_each_device(dev)
-		device_detect(dev);
+BAREBOX_CMD_START(lookup_dentry)
+        .cmd            = do_lookup_dentry,
+BAREBOX_CMD_END
 
-	for_each_block_device(bdev) {
-		struct cdev *cdev = &bdev->cdev;
+static struct dentry *debug_follow_mount(struct dentry *dentry)
+{
+	struct fs_device_d *fsdev;
+	unsigned managed = dentry->d_flags;
 
-		list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list)
-			cdev_mount_default(cdev, NULL);
+	if (managed & DCACHE_MOUNTED) {
+		for_each_fs_device(fsdev) {
+			if (dentry == fsdev->vfsmount.mountpoint)
+				return fsdev->vfsmount.mnt_root;
+		}
+		return NULL;
+	} else {
+		return dentry;
 	}
 }
 
-void fsdev_set_linux_rootarg(struct fs_device_d *fsdev, const char *str)
+static void debug_dump_dentries(struct dentry *parent, int indent)
 {
-	fsdev->linux_rootarg = xstrdup(str);
+	int i;
+	struct dentry *dentry, *mp;
 
-	dev_add_param_fixed(&fsdev->dev, "linux.bootargs", fsdev->linux_rootarg);
-}
+	for (i = 0; i < indent; i++)
+		printf("\t");
+again:
+	printf("%s d: %p refcnt: %d, inode %p refcnt %d\n",
+	       parent->name, parent, parent->d_count, parent->d_inode,
+		parent->d_inode ? parent->d_inode->i_count : -1);
 
-/**
- * path_get_linux_rootarg() - Given a path return a suitable root= option for
- *                            Linux
- * @path: The path
- *
- * Return: A string containing the root= option or an ERR_PTR. the returned
- *         string must be freed by the caller.
- */
-char *path_get_linux_rootarg(const char *path)
-{
-	struct fs_device_d *fsdev;
-	const char *str;
+	mp = debug_follow_mount(parent);
+	if (mp != parent) {
+		for (i = 0; i < indent; i++)
+			printf("\t");
+		printf("MOUNT: ");
 
-	fsdev = get_fsdevice_by_path(path);
-	if (!fsdev)
-		return ERR_PTR(-EINVAL);
+		parent = mp;
 
-	str = dev_get_param(&fsdev->dev, "linux.bootargs");
-	if (!str)
-		return ERR_PTR(-ENOSYS);
+		goto again;
+	}
 
-	return xstrdup(str);
+	list_for_each_entry(dentry, &parent->d_subdirs, d_child)
+		debug_dump_dentries(dentry, indent + 1);
 }
 
-/**
- * __is_tftp_fs() - return true when path is mounted on TFTP
- * @path: The path
- *
- * Do not use directly, use is_tftp_fs instead.
- *
- * Return: true when @path is on TFTP, false otherwise
- */
-bool __is_tftp_fs(const char *path)
+static int do_debug_fs_dump(int argc, char *argv[])
 {
-	struct fs_device_d *fsdev;
-
-	fsdev = get_fsdevice_by_path(path);
-	if (!fsdev)
-		return false;
-
-	if (strcmp(fsdev->driver->drv.name, "tftp"))
-		return false;
+	debug_dump_dentries(d_root, 0);
 
-	return true;
+        return 0;
 }
+
+BAREBOX_CMD_START(debug_fs_dump)
+        .cmd            = do_debug_fs_dump,
+BAREBOX_CMD_END
+#endif
diff --git a/fs/libfs.c b/fs/libfs.c
new file mode 100644
index 0000000000..e1c038757b
--- /dev/null
+++ b/fs/libfs.c
@@ -0,0 +1,87 @@
+#include <common.h>
+#include <fs.h>
+#include <linux/fs.h>
+
+/*
+ * Lookup the data. This is trivial - if the dentry didn't already
+ * exist, we know it is negative.  Set d_op to delete negative dentries.
+ */
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
+	return NULL;
+}
+
+/* Relationship between i_mode and the DT_xxx types */
+static inline unsigned char dt_type(struct inode *inode)
+{
+	return (inode->i_mode >> 12) & 15;
+}
+
+int dcache_readdir(struct file *file, struct dir_context *ctx)
+{
+	struct dentry *dentry = file->f_path.dentry;
+	struct dentry *d;
+
+	dir_emit_dots(file, ctx);
+
+	list_for_each_entry(d, &dentry->d_subdirs, d_child) {
+		if (d_is_negative(d))
+			continue;
+		dir_emit(ctx, d->d_name.name, d->d_name.len,
+				d_inode(d)->i_ino, dt_type(d_inode(d)));
+	}
+
+        return 0;
+}
+
+const struct file_operations simple_dir_operations = {
+	.iterate = dcache_readdir,
+};
+
+int simple_empty(struct dentry *dentry)
+{
+	struct dentry *child;
+	int ret = 0;
+
+	list_for_each_entry(child, &dentry->d_subdirs, d_child) {
+		if (d_is_positive(child))
+			goto out;
+	}
+	ret = 1;
+out:
+	return ret;
+}
+
+int simple_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = d_inode(dentry);
+
+	drop_nlink(inode);
+	dput(dentry);
+
+	return 0;
+}
+
+int simple_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	if (IS_ROOT(dentry))
+		return -EBUSY;
+
+	if (!simple_empty(dentry))
+		return -ENOTEMPTY;
+
+	drop_nlink(d_inode(dentry));
+	simple_unlink(dir, dentry);
+	drop_nlink(dir);
+
+	return 0;
+}
+
+const char *simple_get_link(struct dentry *dentry, struct inode *inode)
+{
+	return inode->i_link;
+}
+
+const struct inode_operations simple_symlink_inode_operations = {
+	.get_link = simple_get_link,
+};
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
index 0c6f136920..a0e9a302f9 100644
--- a/fs/pstore/Kconfig
+++ b/fs/pstore/Kconfig
@@ -1,4 +1,5 @@
 menuconfig FS_PSTORE
+	depends on BROKEN
 	bool
 	prompt "pstore fs support"
 	help
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 19b8297af6..d58843b640 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -1,6 +1,7 @@
 menuconfig FS_SQUASHFS
 	bool
 	prompt "squashfs support"
+	depends on BROKEN
 	help
 	  Saying Y here includes support for SquashFS 4.0 (a Compressed
 	  Read-Only File System).  Squashfs is a highly compressed read-only
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index 889a2be97a..d013ea5780 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -1,6 +1,7 @@
 menuconfig FS_UBIFS
 	bool
 	depends on MTD_UBI
+	depends on BROKEN
 	prompt "ubifs support"
 
 if FS_UBIFS
diff --git a/include/dirent.h b/include/dirent.h
index 5ee4c2063e..1df5d90452 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -1,6 +1,8 @@
 #ifndef __DIRENT_H
 #define __DIRENT_H
 
+#include <linux/list.h>
+
 struct dirent {
 	char d_name[256];
 };
@@ -11,6 +13,7 @@ typedef struct dir {
 	struct node_d *node;
 	struct dirent d;
 	void *priv; /* private data for the fs driver */
+	struct list_head entries;
 } DIR;
 
 DIR *opendir(const char *pathname);
diff --git a/include/fs.h b/include/fs.h
index e6fcd044dd..dcb64405b3 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -31,14 +31,15 @@ typedef struct filep {
 	/* private fields. Mapping between FILE and filedescriptor number     */
 	int no;
 	char in_use;
+
+	struct inode *f_inode;
+	struct dentry *dentry;
 } FILE;
 
 #define FS_DRIVER_NO_DEV	1
 
 struct fs_driver_d {
 	int (*probe) (struct device_d *dev);
-	int (*mkdir)(struct device_d *dev, const char *pathname);
-	int (*rmdir)(struct device_d *dev, const char *pathname);
 
 	/* create a file. The file is guaranteed to not exist */
 	int (*create)(struct device_d *dev, const char *pathname, mode_t mode);
@@ -47,11 +48,6 @@ struct fs_driver_d {
 	/* Truncate a file to given size */
 	int (*truncate)(struct device_d *dev, FILE *f, ulong size);
 
-	int (*symlink)(struct device_d *dev, const char *pathname,
-		       const char *newpath);
-	int (*readlink)(struct device_d *dev, const char *pathname, char *name,
-			size_t size);
-
 	int (*open)(struct device_d *dev, FILE *f, const char *pathname);
 	int (*close)(struct device_d *dev, FILE *f);
 	int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size);
@@ -59,11 +55,6 @@ struct fs_driver_d {
 	int (*flush)(struct device_d *dev, FILE *f);
 	loff_t (*lseek)(struct device_d *dev, FILE *f, loff_t pos);
 
-	struct dir* (*opendir)(struct device_d *dev, const char *pathname);
-	struct dirent* (*readdir)(struct device_d *dev, struct dir *dir);
-	int (*closedir)(struct device_d *dev, DIR *dir);
-	int (*stat)(struct device_d *dev, const char *file, struct stat *stat);
-
 	int (*ioctl)(struct device_d *dev, FILE *f, int request, void *buf);
 	int (*erase)(struct device_d *dev, FILE *f, loff_t count,
 			loff_t offset);
@@ -99,6 +90,10 @@ struct fs_device_d {
 	struct list_head list;
 	char *options;
 	char *linux_rootarg;
+
+	struct super_block sb;
+
+	struct vfsmount vfsmount;
 };
 
 bool __is_tftp_fs(const char *path);
@@ -135,12 +130,6 @@ int ls(const char *path, ulong flags);
 
 char *mkmodestr(unsigned long mode, char *str);
 
-/*
- * This function turns 'path' into an absolute path and removes all occurrences
- * of "..", "." and double slashes. The returned string must be freed wit free().
- */
-char *normalise_path(const char *path);
-
 char *canonicalize_path(const char *pathname);
 
 char *get_mounted_path(const char *path);
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index dfb466722c..16244129bf 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -53,6 +53,10 @@ struct dentry {
 	spinlock_t d_lock;		/* per dentry lock */
 	struct inode *d_inode;		/* Where the name belongs to - NULL is
 					 * negative */
+
+	unsigned int d_count;
+	const struct dentry_operations *d_op;
+
 	/*
 	 * The next three fields are touched by __d_lookup.  Place them here
 	 * so they all fit in a cache line.
@@ -65,8 +69,8 @@ struct dentry {
 	/*
 	 * d_child and d_rcu can share memory
 	 */
+	struct list_head d_child;       /* child of parent list */
 	struct list_head d_subdirs;	/* our children */
-	struct list_head d_alias;	/* inode alias list */
 	unsigned long d_time;		/* used by d_revalidate */
 	struct super_block *d_sb;	/* The root of the dentry tree */
 	void *d_fsdata;			/* fs-specific data */
@@ -74,7 +78,108 @@ struct dentry {
 	struct dcookie_struct *d_cookie; /* cookie, if any */
 #endif
 	int d_mounted;
-	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* small names */
+	unsigned char *name;		/* all names */
+};
+
+struct dentry_operations {
 };
 
+struct dentry * d_make_root(struct inode *);
+void d_add(struct dentry *, struct inode *);
+struct dentry * d_alloc_anon(struct super_block *);
+void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op);
+void d_instantiate(struct dentry *dentry, struct inode *inode);
+void d_delete(struct dentry *);
+struct dentry *dget(struct dentry *);
+void dput(struct dentry *);
+
+#define DCACHE_ENTRY_TYPE		0x00700000
+#define DCACHE_MISS_TYPE		0x00000000 /* Negative dentry (maybe fallthru to nowhere) */
+#define DCACHE_WHITEOUT_TYPE		0x00100000 /* Whiteout dentry (stop pathwalk) */
+#define DCACHE_DIRECTORY_TYPE		0x00200000 /* Normal directory */
+#define DCACHE_AUTODIR_TYPE		0x00300000 /* Lookupless directory (presumed automount) */
+#define DCACHE_REGULAR_TYPE		0x00400000 /* Regular file type (or fallthru to such) */
+#define DCACHE_SPECIAL_TYPE		0x00500000 /* Other file type (or fallthru to such) */
+#define DCACHE_SYMLINK_TYPE		0x00600000 /* Symlink (or fallthru to such) */
+
+#define DCACHE_FALLTHRU			0x01000000 /* Fall through to lower layer */
+#define DCACHE_CANT_MOUNT		0x00000100
+#define DCACHE_MOUNTED                  0x00010000 /* is a mountpoint */
+#define DCACHE_NEED_AUTOMOUNT           0x00020000 /* handle automount on this dir */
+#define DCACHE_MANAGED_DENTRY \
+		(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT)
+
+static inline bool d_mountpoint(const struct dentry *dentry)
+{
+	return dentry->d_flags & DCACHE_MOUNTED;
+}
+
+/*
+ * Directory cache entry type accessor functions.
+ */
+static inline unsigned __d_entry_type(const struct dentry *dentry)
+{
+	return dentry->d_flags & DCACHE_ENTRY_TYPE;
+}
+
+static inline bool d_is_miss(const struct dentry *dentry)
+{
+	return __d_entry_type(dentry) == DCACHE_MISS_TYPE;
+}
+
+static inline bool d_can_lookup(const struct dentry *dentry)
+{
+	return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE;
+}
+
+static inline bool d_is_autodir(const struct dentry *dentry)
+{
+	return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE;
+}
+
+static inline bool d_is_dir(const struct dentry *dentry)
+{
+	return d_can_lookup(dentry) || d_is_autodir(dentry);
+}
+
+static inline bool d_is_symlink(const struct dentry *dentry)
+{
+	return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE;
+}
+
+static inline bool d_is_reg(const struct dentry *dentry)
+{
+	return __d_entry_type(dentry) == DCACHE_REGULAR_TYPE;
+}
+
+static inline bool d_is_special(const struct dentry *dentry)
+{
+	return __d_entry_type(dentry) == DCACHE_SPECIAL_TYPE;
+}
+
+static inline bool d_is_file(const struct dentry *dentry)
+{
+	return d_is_reg(dentry) || d_is_special(dentry);
+}
+
+static inline bool d_is_negative(const struct dentry *dentry)
+{
+	// TODO: check d_is_whiteout(dentry) also.
+	return d_is_miss(dentry);
+}
+
+static inline bool d_is_positive(const struct dentry *dentry)
+{
+	return !d_is_negative(dentry);
+}
+
+static inline struct inode *d_inode(const struct dentry *dentry)
+{
+	return dentry->d_inode;
+}
+
+#define IS_ROOT(x) ((x) == (x)->d_parent)
+
+char *dpath(struct dentry *dentry, struct dentry *root);
+
 #endif	/* __LINUX_DCACHE_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 153c464470..4550e8feeb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -34,7 +34,18 @@
 #define DT_SOCK		12
 #define DT_WHT		14
 
+/*
+ * This is the "filldir" function type, used by readdir() to let
+ * the kernel specify what kind of dirent layout it wants to have.
+ * This allows the kernel to read directories into kernel space or
+ * to have different dirent layouts depending on the binary type.
+ */
+struct dir_context;
+typedef int (*filldir_t)(struct dir_context *, const char *, int, loff_t, u64,
+			 unsigned);
+
 struct dir_context {
+	const filldir_t actor;
 	loff_t pos;
 };
 
@@ -94,12 +105,8 @@ struct inode {
 	};
 	uid_t			i_uid;
 	gid_t			i_gid;
-	dev_t			i_rdev;
 	u64			i_version;
 	loff_t			i_size;
-#ifdef __NEED_I_SIZE_ORDERED
-	seqcount_t		i_size_seqcount;
-#endif
 	struct timespec		i_atime;
 	struct timespec		i_mtime;
 	struct timespec		i_ctime;
@@ -107,39 +114,19 @@ struct inode {
 	blkcnt_t		i_blocks;
 	unsigned short          i_bytes;
 	umode_t			i_mode;
-	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
-	struct mutex		i_mutex;
-	struct rw_semaphore	i_alloc_sem;
 	const struct inode_operations	*i_op;
 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct super_block	*i_sb;
-	struct file_lock	*i_flock;
-#ifdef CONFIG_QUOTA
-	struct dquot		*i_dquot[MAXQUOTAS];
-#endif
-	struct list_head	i_devices;
-	int			i_cindex;
 
 	__u32			i_generation;
 
-#ifdef CONFIG_DNOTIFY
-	unsigned long		i_dnotify_mask; /* Directory notify events */
-	struct dnotify_struct	*i_dnotify; /* for directory notifications */
-#endif
-
-#ifdef CONFIG_INOTIFY
-	struct list_head	inotify_watches; /* watches on this inode */
-	struct mutex		inotify_mutex;	/* protects the watches list */
-#endif
-
 	unsigned long		i_state;
-	unsigned long		dirtied_when;	/* jiffies of first dirtying */
 
 	unsigned int		i_flags;
+	unsigned int		i_count;
+
+	char			*i_link;
 
-#ifdef CONFIG_SECURITY
-	void			*i_security;
-#endif
 	void			*i_private; /* fs or device private pointer */
 };
 
@@ -199,19 +186,9 @@ struct super_block {
 	   Cannot be worse than a second */
 	u32		   s_time_gran;
 
-	/*
-	 * Filesystem subtype.  If non-empty the filesystem type field
-	 * in /proc/mounts will be "type.subtype"
-	 */
-	char *s_subtype;
-
-	/*
-	 * Saved mount options for lazy filesystems using
-	 * generic_show_options()
-	 */
-	char *s_options;
-
 	/* Number of inodes with nlink == 0 but still referenced */
+
+	const struct dentry_operations *s_d_op; /* default d_op for dentries */
 };
 
 struct file_system_type {
@@ -405,4 +382,80 @@ static inline loff_t i_size_read(const struct inode *inode)
 	return inode->i_size;
 }
 
+struct inode *new_inode(struct super_block *sb);
+unsigned int get_next_ino(void);
+void iput(struct inode *);
+struct inode *iget(struct inode *);
+void inc_nlink(struct inode *inode);
+
+struct inode_operations {
+	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
+
+	const char *(*get_link) (struct dentry *dentry, struct inode *inode);
+
+	int (*create) (struct inode *,struct dentry *, umode_t);
+	int (*link) (struct dentry *,struct inode *,struct dentry *);
+	int (*unlink) (struct inode *,struct dentry *);
+	int (*symlink) (struct inode *,struct dentry *,const char *);
+	int (*mkdir) (struct inode *,struct dentry *,umode_t);
+	int (*rmdir) (struct inode *,struct dentry *);
+	int (*rename) (struct inode *, struct dentry *,
+		       struct inode *, struct dentry *, unsigned int);
+};
+
+static inline ino_t parent_ino(struct dentry *dentry)
+{
+	return dentry->d_parent->d_inode->i_ino;
+}
+
+static inline bool dir_emit(struct dir_context *ctx,
+			    const char *name, int namelen,
+			    u64 ino, unsigned type)
+{
+	return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0;
+}
+
+static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
+{
+	return ctx->actor(ctx, ".", 1, ctx->pos,
+			file->f_path.dentry->d_inode->i_ino, DT_DIR) == 0;
+}
+static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
+{
+	return ctx->actor(ctx, "..", 2, ctx->pos,
+			parent_ino(file->f_path.dentry), DT_DIR) == 0;
+}
+
+static inline void dir_emit_dots(struct file *file, struct dir_context *ctx)
+{
+	if (ctx->pos == 0) {
+		dir_emit_dot(file, ctx);
+		ctx->pos = 1;
+	}
+	if (ctx->pos == 1) {
+		dir_emit_dotdot(file, ctx);
+		ctx->pos = 2;
+	}
+}
+
+struct file_operations {
+	int (*iterate) (struct file *, struct dir_context *);
+	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+	int (*ioctl) (struct file *, int request, void *buf);
+	int (*truncate) (struct file *, loff_t);
+};
+
+void drop_nlink(struct inode *inode);
+
+extern const struct file_operations simple_dir_operations;
+extern const struct inode_operations simple_symlink_inode_operations;
+
+int simple_empty(struct dentry *dentry);
+int simple_unlink(struct inode *dir, struct dentry *dentry);
+int simple_rmdir(struct inode *dir, struct dentry *dentry);
+struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags);
+int dcache_readdir(struct file *, struct dir_context *);
+const char *simple_get_link(struct dentry *dentry, struct inode *inode);
+
 #endif /* _LINUX_FS_H */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 57d5ba9523..9557365fb5 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -14,8 +14,11 @@
 
 struct vfsmount {
 	struct dentry *mnt_root;	/* root of the mounted tree */
+	struct dentry *mountpoint;	/* where it's mounted (barebox specific, no support */
+	struct vfsmount *parent;	/* for bind mounts and the like) */
 	struct super_block *mnt_sb;	/* pointer to superblock */
 	int mnt_flags;
+	int ref;
 };
 
 #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/namei.h b/include/linux/namei.h
new file mode 100644
index 0000000000..8ed7f8a1cd
--- /dev/null
+++ b/include/linux/namei.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_NAMEI_H
+#define _LINUX_NAMEI_H
+
+#include <linux/kernel.h>
+#include <linux/path.h>
+
+enum { MAX_NESTED_LINKS = 8 };
+
+#define MAXSYMLINKS 40
+
+/*
+ * Type of the last component on LOOKUP_PARENT
+ */
+enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
+
+/*
+ * The bitmask for a lookup event:
+ *  - follow links at the end
+ *  - require a directory
+ *  - ending slashes ok even for nonexistent files
+ *  - internal "there are more path components" flag
+ *  - dentry cache is untrusted; force a real lookup
+ *  - suppress terminal automount
+ */
+#define LOOKUP_FOLLOW		0x0001
+#define LOOKUP_DIRECTORY	0x0002
+#define LOOKUP_AUTOMOUNT	0x0004
+
+#define LOOKUP_PARENT		0x0010
+#define LOOKUP_REVAL		0x0020
+#define LOOKUP_RCU		0x0040
+#define LOOKUP_NO_REVAL		0x0080
+
+/*
+ * Intent data
+ */
+#define LOOKUP_OPEN		0x0100
+#define LOOKUP_CREATE		0x0200
+#define LOOKUP_EXCL		0x0400
+#define LOOKUP_RENAME_TARGET	0x0800
+
+#define LOOKUP_JUMPED		0x1000
+#define LOOKUP_ROOT		0x2000
+#define LOOKUP_EMPTY		0x4000
+#define LOOKUP_DOWN		0x8000
+
+#define AT_FDCWD                -100    /* Special value used to indicate
+                                           openat should use the current
+                                           working directory. */
+
+#endif /* _LINUX_NAMEI_H */
diff --git a/include/linux/stat.h b/include/linux/stat.h
index af022c5c79..87fe068396 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -42,6 +42,8 @@ extern "C" {
 #define S_IWOTH 00002		/* read permission for other */
 #define S_IXOTH 00001		/* execute/search permission for other */
 
+#define S_IRWXUGO	(S_IRWXU|S_IRWXG|S_IRWXO)
+
 struct stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:33 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:33 +0200
Subject: [PATCH 01/19] rename file_operations -> cdev_operations
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-2-s.hauer@pengutronix.de>

Linux also has struct file_operations which are something different.
Rename our file_operations to cdev_operations which better matches
what we have.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/mach-mxs/ocotp.c     | 2 +-
 arch/sandbox/board/hostfile.c | 2 +-
 commands/mem.c                | 2 +-
 commands/stddev.c             | 8 ++++----
 common/block.c                | 2 +-
 common/firmware.c             | 2 +-
 drivers/base/regmap/regmap.c  | 2 +-
 drivers/eeprom/at24.c         | 2 +-
 drivers/eeprom/at25.c         | 2 +-
 drivers/hw_random/core.c      | 2 +-
 drivers/mfd/act8846.c         | 2 +-
 drivers/mfd/lp3972.c          | 2 +-
 drivers/mfd/mc34704.c         | 2 +-
 drivers/mfd/mc9sdz60.c        | 2 +-
 drivers/mfd/stmpe-i2c.c       | 2 +-
 drivers/mfd/twl-core.c        | 2 +-
 drivers/misc/jtag.c           | 2 +-
 drivers/misc/sram.c           | 2 +-
 drivers/mtd/core.c            | 2 +-
 drivers/mtd/mtdoob.c          | 2 +-
 drivers/mtd/mtdraw.c          | 4 ++--
 drivers/mtd/nand/nand-bb.c    | 2 +-
 drivers/mtd/ubi/barebox.c     | 4 ++--
 drivers/net/e1000/eeprom.c    | 4 ++--
 drivers/net/ksz8864rmn.c      | 2 +-
 drivers/net/phy/mdio_bus.c    | 2 +-
 drivers/nvmem/core.c          | 2 +-
 drivers/video/fb.c            | 2 +-
 drivers/w1/slaves/w1_ds2431.c | 2 +-
 drivers/w1/slaves/w1_ds2433.c | 2 +-
 fs/devfs-core.c               | 2 +-
 include/console.h             | 2 +-
 include/driver.h              | 4 ++--
 include/mfd/twl-core.h        | 2 +-
 34 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
index 72f3e8240b..b41fde9919 100644
--- a/arch/arm/mach-mxs/ocotp.c
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -172,7 +172,7 @@ free_mem:
 	return ret;
 }
 
-static struct file_operations mxs_ocotp_ops = {
+static struct cdev_operations mxs_ocotp_ops = {
 	.read	= mxs_ocotp_cdev_read,
 	.lseek	= dev_lseek_default,
 };
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c
index e7d92ea031..3fc1503799 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -64,7 +64,7 @@ static void hf_info(struct device_d *dev)
 	printf("file: %s\n", priv->filename);
 }
 
-static struct file_operations hf_fops = {
+static struct cdev_operations hf_fops = {
 	.read  = hf_read,
 	.write = hf_write,
 	.lseek = dev_lseek_default,
diff --git a/commands/mem.c b/commands/mem.c
index 29eaa80b23..eb91ade05a 100644
--- a/commands/mem.c
+++ b/commands/mem.c
@@ -81,7 +81,7 @@ int mem_parse_options(int argc, char *argv[], char *optstr, int *mode,
 	return 0;
 }
 
-static struct file_operations memops = {
+static struct cdev_operations memops = {
 	.read  = mem_read,
 	.write = mem_write,
 	.memmap = generic_memmap_rw,
diff --git a/commands/stddev.c b/commands/stddev.c
index 93da2c7398..4d1b6f5108 100644
--- a/commands/stddev.c
+++ b/commands/stddev.c
@@ -25,7 +25,7 @@ static ssize_t zero_read(struct cdev *cdev, void *buf, size_t count, loff_t offs
 	return count;
 }
 
-static struct file_operations zeroops = {
+static struct cdev_operations zeroops = {
 	.read  = zero_read,
 	.lseek = dev_lseek_default,
 };
@@ -53,7 +53,7 @@ static ssize_t full_read(struct cdev *cdev, void *buf, size_t count, loff_t offs
 	return count;
 }
 
-static struct file_operations fullops = {
+static struct cdev_operations fullops = {
 	.read  = full_read,
 	.lseek = dev_lseek_default,
 };
@@ -80,7 +80,7 @@ static ssize_t null_write(struct cdev *cdev, const void *buf, size_t count, loff
 	return count;
 }
 
-static struct file_operations nullops = {
+static struct cdev_operations nullops = {
 	.write = null_write,
 	.lseek = dev_lseek_default,
 };
@@ -108,7 +108,7 @@ static ssize_t prng_read(struct cdev *cdev, void *buf, size_t count, loff_t offs
 	return count;
 }
 
-static struct file_operations prngops = {
+static struct cdev_operations prngops = {
 	.read  = prng_read,
 	.lseek = dev_lseek_default,
 };
diff --git a/common/block.c b/common/block.c
index e2ba9d4296..55d8d1637e 100644
--- a/common/block.c
+++ b/common/block.c
@@ -332,7 +332,7 @@ static int block_op_flush(struct cdev *cdev)
 	return writebuffer_flush(blk);
 }
 
-static struct file_operations block_ops = {
+static struct cdev_operations block_ops = {
 	.read	= block_op_read,
 #ifdef CONFIG_BLOCK_WRITE
 	.write	= block_op_write,
diff --git a/common/firmware.c b/common/firmware.c
index 664f9107d0..250fef5378 100644
--- a/common/firmware.c
+++ b/common/firmware.c
@@ -153,7 +153,7 @@ static int firmware_close(struct cdev *cdev)
 	return 0;
 }
 
-static struct file_operations firmware_ops = {
+static struct cdev_operations firmware_ops = {
 	.open = firmware_open,
 	.write = firmware_write,
 	.close = firmware_close,
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 67d95fe30a..8bbc2373fc 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -352,7 +352,7 @@ static ssize_t regmap_cdev_write(struct cdev *cdev, const void *buf, size_t coun
 	return count;
 }
 
-static struct file_operations regmap_fops = {
+static struct cdev_operations regmap_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= regmap_cdev_read,
 	.write	= regmap_cdev_write,
diff --git a/drivers/eeprom/at24.c b/drivers/eeprom/at24.c
index 11f23319b6..4fae3a12e4 100644
--- a/drivers/eeprom/at24.c
+++ b/drivers/eeprom/at24.c
@@ -52,7 +52,7 @@ struct at24_data {
 	struct at24_platform_data chip;
 
 	struct cdev		cdev;
-	struct file_operations	fops;
+	struct cdev_operations	fops;
 
 	u8 *writebuf;
 	unsigned write_max;
diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c
index 9f16f964a8..a9050d6c16 100644
--- a/drivers/eeprom/at25.c
+++ b/drivers/eeprom/at25.c
@@ -232,7 +232,7 @@ static ssize_t at25_ee_write(struct cdev *cdev,
 	return written ? written : status;
 }
 
-static struct file_operations at25_fops = {
+static struct cdev_operations at25_fops = {
 	.read	= at25_ee_read,
 	.write	= at25_ee_write,
 	.lseek	= dev_lseek_default,
diff --git a/drivers/hw_random/core.c b/drivers/hw_random/core.c
index ef2a988c76..1c68a379f7 100644
--- a/drivers/hw_random/core.c
+++ b/drivers/hw_random/core.c
@@ -61,7 +61,7 @@ static ssize_t rng_dev_read(struct cdev *cdev, void *buf, size_t size,
 	return cur;
 }
 
-static struct file_operations rng_chrdev_ops = {
+static struct cdev_operations rng_chrdev_ops = {
 	.read  = rng_dev_read,
 	.lseek = dev_lseek_default,
 };
diff --git a/drivers/mfd/act8846.c b/drivers/mfd/act8846.c
index 60029acf76..dfca0498b1 100644
--- a/drivers/mfd/act8846.c
+++ b/drivers/mfd/act8846.c
@@ -117,7 +117,7 @@ static ssize_t act8846_write(struct cdev *cdev, const void *_buf, size_t count,
 	return count;
 }
 
-static struct file_operations act8846_fops = {
+static struct cdev_operations act8846_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= act8846_read,
 	.write	= act8846_write,
diff --git a/drivers/mfd/lp3972.c b/drivers/mfd/lp3972.c
index ee794df2d8..054713b942 100644
--- a/drivers/mfd/lp3972.c
+++ b/drivers/mfd/lp3972.c
@@ -70,7 +70,7 @@ static ssize_t lp_read(struct cdev *cdev, void *_buf, size_t count, loff_t offse
 	return count;
 }
 
-static struct file_operations lp_fops = {
+static struct cdev_operations lp_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= lp_read,
 };
diff --git a/drivers/mfd/mc34704.c b/drivers/mfd/mc34704.c
index 3dc85f5474..bfda169aaa 100644
--- a/drivers/mfd/mc34704.c
+++ b/drivers/mfd/mc34704.c
@@ -100,7 +100,7 @@ static ssize_t mc34704_write(struct cdev *cdev, const void *_buf, size_t count,
 	return count;
 }
 
-static struct file_operations mc34704_fops = {
+static struct cdev_operations mc34704_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= mc34704_read,
 	.write	= mc34704_write,
diff --git a/drivers/mfd/mc9sdz60.c b/drivers/mfd/mc9sdz60.c
index 0d2c56b480..9993efc5de 100644
--- a/drivers/mfd/mc9sdz60.c
+++ b/drivers/mfd/mc9sdz60.c
@@ -112,7 +112,7 @@ static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, loff_
 	return count;
 }
 
-static struct file_operations mc_fops = {
+static struct cdev_operations mc_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= mc_read,
 	.write	= mc_write,
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index fb91ffa008..51c56bbf56 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -101,7 +101,7 @@ static ssize_t stmpe_write(struct cdev *cdev, const void *_buf, size_t count, lo
 	return count;
 }
 
-static struct file_operations stmpe_fops = {
+static struct cdev_operations stmpe_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= stmpe_read,
 	.write	= stmpe_write,
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 20bde2cf89..fb435f510f 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -149,7 +149,7 @@ static ssize_t twl_write(struct cdev *cdev, const void *_buf, size_t count,
 	return count;
 }
 
-struct file_operations twl_fops = {
+struct cdev_operations twl_fops = {
 	.lseek	= dev_lseek_default,
 	.read	= twl_read,
 	.write	= twl_write,
diff --git a/drivers/misc/jtag.c b/drivers/misc/jtag.c
index f5d0c72ed5..9accefa342 100644
--- a/drivers/misc/jtag.c
+++ b/drivers/misc/jtag.c
@@ -265,7 +265,7 @@ static int jtag_ioctl(struct cdev *inode, int cmd, void *arg)
 	return ret;
 }
 
-static struct file_operations jtag_operations = {
+static struct cdev_operations jtag_operations = {
 	.ioctl = jtag_ioctl,
 };
 
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 4fb6f801d2..27b4c681fd 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -25,7 +25,7 @@ struct sram {
 	struct cdev cdev;
 };
 
-static struct file_operations memops = {
+static struct cdev_operations memops = {
 	.read  = mem_read,
 	.write = mem_write,
 	.memmap = generic_memmap_rw,
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 1950ee87ee..d2012b5f70 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -438,7 +438,7 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 	return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
 }
 
-static struct file_operations mtd_ops = {
+static struct cdev_operations mtd_ops = {
 	.read   = mtd_op_read,
 #ifdef CONFIG_MTD_WRITE
 	.write  = mtd_op_write,
diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c
index 86076f028d..ffaf9506f3 100644
--- a/drivers/mtd/mtdoob.c
+++ b/drivers/mtd/mtdoob.c
@@ -63,7 +63,7 @@ static ssize_t mtd_op_read_oob(struct cdev *cdev, void *buf, size_t count,
 	return mtd->oobsize;
 }
 
-static struct file_operations mtd_ops_oob = {
+static struct cdev_operations mtd_ops_oob = {
 	.read   = mtd_op_read_oob,
 	.ioctl  = mtd_ioctl,
 	.lseek  = dev_lseek_default,
diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c
index ab360b7862..4f7c3b836c 100644
--- a/drivers/mtd/mtdraw.c
+++ b/drivers/mtd/mtdraw.c
@@ -287,7 +287,7 @@ static ssize_t mtdraw_erase(struct cdev *cdev, loff_t count, loff_t offset)
 }
 #endif
 
-static const struct file_operations mtd_raw_fops = {
+static const struct cdev_operations mtd_raw_fops = {
 	.read		= mtdraw_read,
 	.write		= mtdraw_write,
 	.erase		= mtdraw_erase,
@@ -305,7 +305,7 @@ static int add_mtdraw_device(struct mtd_info *mtd, const char *devname, void **p
 	mtdraw->writebuf = xmalloc(RAW_WRITEBUF_SIZE);
 	mtdraw->mtd = mtd;
 
-	mtdraw->cdev.ops = (struct file_operations *)&mtd_raw_fops;
+	mtdraw->cdev.ops = (struct cdev_operations *)&mtd_raw_fops;
 	mtdraw->cdev.size = mtd_div_by_wb(mtd->size, mtd) *
 		(mtd->writesize + mtd->oobsize);
 	mtdraw->cdev.name = basprintf("%s.raw", mtd->cdev.name);
diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c
index a1523c3c89..c1977381d4 100644
--- a/drivers/mtd/nand/nand-bb.c
+++ b/drivers/mtd/nand/nand-bb.c
@@ -264,7 +264,7 @@ static loff_t nand_bb_lseek(struct cdev *cdev, loff_t __offset)
 	return -EINVAL;
 }
 
-static struct file_operations nand_bb_ops = {
+static struct cdev_operations nand_bb_ops = {
 	.open   = nand_bb_open,
 	.close  = nand_bb_close,
 	.read  	= nand_bb_read,
diff --git a/drivers/mtd/ubi/barebox.c b/drivers/mtd/ubi/barebox.c
index d67e566db6..65f5456455 100644
--- a/drivers/mtd/ubi/barebox.c
+++ b/drivers/mtd/ubi/barebox.c
@@ -218,7 +218,7 @@ static int ubi_volume_cdev_ioctl(struct cdev *cdev, int cmd, void *buf)
 	return err;
 }
 
-static struct file_operations ubi_volume_fops = {
+static struct cdev_operations ubi_volume_fops = {
 	.open	= ubi_volume_cdev_open,
 	.close	= ubi_volume_cdev_close,
 	.read   = ubi_volume_cdev_read,
@@ -467,7 +467,7 @@ static int ubi_cdev_ioctl(struct cdev *cdev, int cmd, void *buf)
 	return 0;
 }
 
-static struct file_operations ubi_fops = {
+static struct cdev_operations ubi_fops = {
 	.ioctl	= ubi_cdev_ioctl,
 };
 
diff --git a/drivers/net/e1000/eeprom.c b/drivers/net/e1000/eeprom.c
index 319910103e..3f39db7164 100644
--- a/drivers/net/e1000/eeprom.c
+++ b/drivers/net/e1000/eeprom.c
@@ -1294,7 +1294,7 @@ exit:
 	return ret;
 }
 
-static struct file_operations e1000_invm_ops = {
+static struct cdev_operations e1000_invm_ops = {
 	.read	= e1000_invm_cdev_read,
 	.write	= e1000_invm_cdev_write,
 	.lseek	= dev_lseek_default,
@@ -1320,7 +1320,7 @@ static ssize_t e1000_eeprom_cdev_read(struct cdev *cdev, void *buf,
 		return (count / 2) * 2;
 };
 
-static struct file_operations e1000_eeprom_ops = {
+static struct cdev_operations e1000_eeprom_ops = {
 	.read = e1000_eeprom_cdev_read,
 	.lseek = dev_lseek_default,
 };
diff --git a/drivers/net/ksz8864rmn.c b/drivers/net/ksz8864rmn.c
index 860af448ea..8b9d66019b 100644
--- a/drivers/net/ksz8864rmn.c
+++ b/drivers/net/ksz8864rmn.c
@@ -120,7 +120,7 @@ static ssize_t micel_switch_write(struct cdev *cdev, const void *_buf, size_t co
 	return count;
 }
 
-static struct file_operations micrel_switch_ops = {
+static struct cdev_operations micrel_switch_ops = {
 	.read  = micel_switch_read,
 	.write = micel_switch_write,
 	.lseek = dev_lseek_default,
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index d209716a14..5d4218f7c0 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -285,7 +285,7 @@ static ssize_t phydev_write(struct cdev *cdev, const void *_buf, size_t count, l
 	return count;
 }
 
-static struct file_operations phydev_ops = {
+static struct cdev_operations phydev_ops = {
 	.read  = phydev_read,
 	.write = phydev_write,
 	.lseek = dev_lseek_default,
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 4e50a8843f..172fa8b720 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -82,7 +82,7 @@ static ssize_t nvmem_cdev_write(struct cdev *cdev, const void *buf, size_t count
 	return retlen;
 }
 
-static struct file_operations nvmem_chrdev_ops = {
+static struct cdev_operations nvmem_chrdev_ops = {
 	.read  = nvmem_cdev_read,
 	.write  = nvmem_cdev_write,
 	.lseek = dev_lseek_default,
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 004df1e604..5e829e832d 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -221,7 +221,7 @@ static int fb_set_modename(struct param_d *param, void *priv)
 	return 0;
 }
 
-static struct file_operations fb_ops = {
+static struct cdev_operations fb_ops = {
 	.read	= mem_read,
 	.write	= mem_write,
 	.memmap	= generic_memmap_rw,
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c
index e3e929670d..13691d7bab 100644
--- a/drivers/w1/slaves/w1_ds2431.c
+++ b/drivers/w1/slaves/w1_ds2431.c
@@ -257,7 +257,7 @@ out_up:
 #define ds2431_cdev_write NULL
 #endif
 
-static struct file_operations ds2431_ops = {
+static struct cdev_operations ds2431_ops = {
 	.read	= ds2431_cdev_read,
 	.write	= ds2431_cdev_write,
 	.lseek	= dev_lseek_default,
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index a907c6bf3c..f521a46a75 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -156,7 +156,7 @@ out_up:
 #define ds2433_cdev_write NULL
 #endif
 
-static struct file_operations ds2433_ops = {
+static struct cdev_operations ds2433_ops = {
 	.read	= ds2433_cdev_read,
 	.write	= ds2433_cdev_write,
 	.lseek	= dev_lseek_default,
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index ea5887c720..d06a534b57 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -457,7 +457,7 @@ static ssize_t loop_write(struct cdev *cdev, const void *buf, size_t count,
 	return write(priv->fd, buf, count);
 }
 
-static const struct file_operations loop_ops = {
+static const struct cdev_operations loop_ops = {
 	.read = loop_read,
 	.write = loop_write,
 	.memmap = generic_memmap_rw,
diff --git a/include/console.h b/include/console.h
index a8b2663a4c..3c14e35935 100644
--- a/include/console.h
+++ b/include/console.h
@@ -63,7 +63,7 @@ struct console_device {
 	const char *linux_console_name;
 
 	struct cdev devfs;
-	struct file_operations fops;
+	struct cdev_operations fops;
 };
 
 int console_register(struct console_device *cdev);
diff --git a/include/driver.h b/include/driver.h
index f37805db17..91653b7946 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -420,7 +420,7 @@ int platform_driver_register(struct driver_d *drv);
 
 int platform_device_register(struct device_d *new_device);
 
-struct file_operations {
+struct cdev_operations {
 	/*! Called in response of reading from this device. Required */
 	ssize_t (*read)(struct cdev*, void* buf, size_t count, loff_t offset, ulong flags);
 
@@ -441,7 +441,7 @@ struct file_operations {
 #define MAX_PARTUUID_STR	sizeof("00112233-4455-6677-8899-AABBCCDDEEFF")
 
 struct cdev {
-	const struct file_operations *ops;
+	const struct cdev_operations *ops;
 	void *priv;
 	struct device_d *dev;
 	struct device_node *device_node;
diff --git a/include/mfd/twl-core.h b/include/mfd/twl-core.h
index f090032b3f..88d29f019b 100644
--- a/include/mfd/twl-core.h
+++ b/include/mfd/twl-core.h
@@ -21,7 +21,7 @@ struct twlcore {
 	struct i2c_client	*client;
 };
 
-extern struct file_operations twl_fops;
+extern struct cdev_operations twl_fops;
 
 extern int twlcore_reg_read(struct twlcore *twlcore, u16 reg, u8 *val);
 extern int twlcore_reg_write(struct twlcore *twlcore, u16 reg, u8 val);
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:41 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:41 +0200
Subject: [PATCH 09/19] glob: do not unnecessarily opendir() a directory
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-10-s.hauer@pengutronix.de>

opendir() can trigger automounts, so do not use it when the
pattern we examine doesn't have any wildcards.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 lib/glob.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/lib/glob.c b/lib/glob.c
index 5a997ca092..32f7afdce8 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -313,7 +313,7 @@ static int prefix_array(const char *dirname, char **array, size_t n,
 static int glob_in_dir(const char *pattern, const char *directory,
 		int flags, int (*errfunc) __P((const char *, int)), glob_t *pglob)
 {
-	__ptr_t stream;
+	__ptr_t stream = NULL;
 
 	struct globlink {
 		struct globlink *next;
@@ -323,7 +323,13 @@ static int glob_in_dir(const char *pattern, const char *directory,
 	size_t nfound = 0;
 	int meta;
 
-	stream = opendir(directory);
+	meta = glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE));
+
+	if (meta)
+		flags |= GLOB_MAGCHAR;
+
+	if (meta)
+		stream = opendir(directory);
 
 	if (stream == NULL) {
 		if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
@@ -331,11 +337,6 @@ static int glob_in_dir(const char *pattern, const char *directory,
 			return GLOB_ABORTED;
 	}
 
-	meta = glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE));
-
-	if (meta)
-		flags |= GLOB_MAGCHAR;
-
 	while (1) {
 		const char *name;
 		size_t len;
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:47 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:47 +0200
Subject: [PATCH 15/19] fs: ext4: Switch to dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-16-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ext4/Kconfig       |   1 -
 fs/ext4/ext_barebox.c | 280 ++++++++++++++++++++++++++++----------------------
 fs/ext4/ext_common.h  |   3 +
 3 files changed, 161 insertions(+), 123 deletions(-)

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index ad1bf58536..f36043d9a7 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -1,4 +1,3 @@
 config FS_EXT4
 	bool
-	depends on BROKEN
 	prompt "ext4 filesystem support"
diff --git a/fs/ext4/ext_barebox.c b/fs/ext4/ext_barebox.c
index e40278a5bd..8406b1d6a4 100644
--- a/fs/ext4/ext_barebox.c
+++ b/fs/ext4/ext_barebox.c
@@ -36,6 +36,7 @@ int ext4fs_devread(struct ext_filesystem *fs, int __sector, int byte_offset,
 	ssize_t size;
 	uint64_t sector = __sector;
 
+//	printf("%s: sec: %5d, ofs: %d len: %d\n", __func__, __sector, byte_offset, byte_len);
 	size = cdev_read(fs->cdev, buf, byte_len, sector * SECTOR_SIZE + byte_offset, 0);
 	if (size < 0) {
 		dev_err(fs->dev, "read error at sector %d: %s\n", __sector,
@@ -46,34 +47,17 @@ int ext4fs_devread(struct ext_filesystem *fs, int __sector, int byte_offset,
 	return 0;
 }
 
-static int ext_open(struct device_d *dev, FILE *file, const char *filename)
+static inline struct ext2fs_node *to_ext2_node(struct inode *inode)
 {
-	struct ext_filesystem *fs = dev->priv;
-	struct ext2fs_node *inode;
-	int ret;
-
-	ret = ext4fs_open(fs->data, filename, &inode);
-	if (ret)
-		return ret;
-
-	file->size = le32_to_cpu(inode->inode.size);
-	file->priv = inode;
-
-	return 0;
-}
-
-static int ext_close(struct device_d *dev, FILE *f)
-{
-	struct ext_filesystem *fs = dev->priv;
-
-	ext4fs_free_node(f->priv, &fs->data->diropen);
-
-	return 0;
+	return container_of(inode, struct ext2fs_node, i);
 }
 
 static int ext_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
 {
-	return ext4fs_read_file(f->priv, f->pos, insize, buf);
+	struct inode *inode = f->f_inode;
+	struct ext2fs_node *node = to_ext2_node(inode);
+
+	return ext4fs_read_file(node, f->pos, insize, buf);
 }
 
 static loff_t ext_lseek(struct device_d *dev, FILE *f, loff_t pos)
@@ -83,143 +67,195 @@ static loff_t ext_lseek(struct device_d *dev, FILE *f, loff_t pos)
 	return f->pos;
 }
 
-struct ext4fs_dir {
-	struct ext2fs_node *dirnode;
-	int fpos;
-	DIR dir;
-};
-
-static DIR *ext_opendir(struct device_d *dev, const char *pathname)
+struct inode *ext_alloc_inode(struct super_block *sb)
 {
-	struct ext_filesystem *fs = dev->priv;
-	struct ext4fs_dir *ext4_dir;
-	int type, ret;
-
-	ext4_dir = xzalloc(sizeof(*ext4_dir));
-
-	ret = ext4fs_find_file(pathname, &fs->data->diropen, &ext4_dir->dirnode,
-				  &type);
-	if (ret) {
-		free(ext4_dir);
-		return NULL;
-	}
+	struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+	struct ext_filesystem *fs = fsdev->dev.priv;
+	struct ext2fs_node *node;
 
-	if (type != FILETYPE_DIRECTORY)
+	node = xzalloc(sizeof(*node));
+	if (!node)
 		return NULL;
 
-	ext4_dir->dir.priv = ext4_dir;
+	node->data = fs->data;
 
-	ret = ext4fs_read_inode(ext4_dir->dirnode->data, ext4_dir->dirnode->ino,
-			&ext4_dir->dirnode->inode);
-	if (ret) {
-		ext4fs_free_node(ext4_dir->dirnode, &fs->data->diropen);
-		free(ext4_dir);
+	return &node->i;
+}
 
-		return NULL;
-	}
+static const struct super_operations ext_ops = {
+	.alloc_inode = ext_alloc_inode,
+};
 
-	return &ext4_dir->dir;
-}
+struct inode *ext_get_inode(struct super_block *sb, int ino);
 
-static struct dirent *ext_readdir(struct device_d *dev, DIR *dir)
+static int ext4fs_get_ino(struct ext2fs_node *dir, struct qstr *name, int *inum)
 {
-	struct ext4fs_dir *ext4_dir = dir->priv;
-	struct ext2_dirent dirent;
-	struct ext2fs_node *diro = ext4_dir->dirnode;
+	unsigned int fpos = 0;
 	int ret;
-	char *filename;
 
-	if (ext4_dir->fpos >= le32_to_cpu(diro->inode.size))
-		return NULL;
+	while (fpos < le32_to_cpu(dir->inode.size)) {
+		struct ext2_dirent dirent;
 
-	ret = ext4fs_read_file(diro, ext4_dir->fpos, sizeof(struct ext2_dirent),
-			(char *) &dirent);
-	if (ret < 0)
-		return NULL;
+		ret = ext4fs_read_file(dir, fpos, sizeof(dirent), (char *)&dirent);
+		if (ret < 1)
+			return -EINVAL;
 
-	if (dirent.namelen == 0)
-		return NULL;
+		if (dirent.namelen != 0) {
+			char filename[dirent.namelen];
+			int ino;
 
-	filename = xzalloc(dirent.namelen + 1);
+			ret = ext4fs_read_file(dir, fpos + sizeof(dirent),
+						  dirent.namelen, filename);
+			if (ret < 1)
+				return -EINVAL;
 
-	ret = ext4fs_read_file(diro, ext4_dir->fpos + sizeof(struct ext2_dirent),
-			dirent.namelen, filename);
-	if (ret < 0) {
-		free(filename);
-		return NULL;
+			ino = le32_to_cpu(dirent.inode);
+
+			if (name->len == dirent.namelen &&
+			    !strncmp(name->name, filename, name->len)) {
+				*inum = ino;
+				return 0;
+			}
+		}
+		fpos += le16_to_cpu(dirent.direntlen);
 	}
 
-	filename[dirent.namelen] = '\0';
+	*inum = 0;
 
-	ext4_dir->fpos += le16_to_cpu(dirent.direntlen);
+	return 0;
+}
 
-	strcpy(dir->d.d_name, filename);
+static struct dentry *ext_lookup(struct inode *dir, struct dentry *dentry,
+				 unsigned int flags)
+{
+	struct ext2fs_node *e2dir = to_ext2_node(dir);
+	int ret, ino;
+	struct inode *inode;
 
-	free(filename);
+	ret = ext4fs_get_ino(e2dir, &dentry->d_name, &ino);
+	if (ret)
+		return ERR_PTR(ret);
 
-	return &dir->d;
+	if (ino) {
+		inode = ext_get_inode(dir->i_sb, ino);
+
+		d_add(dentry, inode);
+	}
+
+	return NULL;
 }
 
-static int ext_closedir(struct device_d *dev, DIR *dir)
+static const struct inode_operations ext_inode_operations = {
+	.lookup = ext_lookup,
+};
+
+static int ext_iterate(struct file *file, struct dir_context *ctx)
 {
-	struct ext_filesystem *fs = dev->priv;
-	struct ext4fs_dir *ext4_dir = dir->priv;
+	struct dentry *dentry = file->f_path.dentry;
+	struct inode *dir = d_inode(dentry);
+	unsigned int fpos = 0;
+	int status, ret;
+	struct ext2fs_node *diro = to_ext2_node(dir);
+	void *buf;
 
-	ext4fs_free_node(ext4_dir->dirnode, &fs->data->diropen);
+	buf = malloc(dir->i_size);
+	if (!buf)
+		return -ENOMEM;
 
-	free(ext4_dir);
+	status = ext4fs_read_file(diro, 0, dir->i_size, buf);
+	if (status < 1) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	while (fpos < dir->i_size) {
+		const struct ext2_dirent *dirent = buf + fpos;
+		const char *filename = buf + fpos + sizeof(*dirent);
+
+		if (dirent->namelen != 0)
+			dir_emit(ctx, filename, dirent->namelen,
+				 le32_to_cpu(dirent->inode), DT_UNKNOWN);
+
+		fpos += le16_to_cpu(dirent->direntlen);
+	}
+	ret = 0;
+out:
+	free(buf);
+
+	return ret;
 
-	return 0;
 }
 
-static int ext_stat(struct device_d *dev, const char *filename, struct stat *s)
+const struct file_operations ext_dir_operations = {
+	.iterate = ext_iterate,
+};
+
+static const char *ext_get_link(struct dentry *dentry, struct inode *inode)
 {
-	struct ext_filesystem *fs = dev->priv;
-	struct ext2fs_node *node;
-	int status, ret;
+	struct ext2fs_node *node = to_ext2_node(inode);
+	int ret;
 
-	status = ext4fs_find_file(filename, &fs->data->diropen, &node, NULL);
-	if (status)
-		return -ENOENT;
+	if (inode->i_size < sizeof(node->inode.b.symlink))
+		return inode->i_link;
 
-	ret = ext4fs_read_inode(node->data, node->ino, &node->inode);
-	if (ret)
-		return ret;
+	BUG_ON(inode->i_link);
 
-	s->st_size = le32_to_cpu(node->inode.size);
-	s->st_mode = le16_to_cpu(node->inode.mode);
+	inode->i_link = zalloc(inode->i_size + 1);
 
-	ext4fs_free_node(node, &fs->data->diropen);
+	ret = ext4fs_read_file(node, 0, inode->i_size, inode->i_link);
+	if (ret == 0) {
+		free(inode->i_link);
+		inode->i_link = NULL;
+	}
 
-	return 0;
+	return inode->i_link;
 }
 
-static int ext_readlink(struct device_d *dev, const char *pathname,
-		char *buf, size_t bufsiz)
+static const struct inode_operations ext_symlink_inode_operations =
 {
-	struct ext_filesystem *fs = dev->priv;
-	struct ext2fs_node *node;
-	char *symlink;
-	int ret, len, type;
+	.get_link = ext_get_link,
+};
 
-	ret = ext4fs_find_file(pathname, &fs->data->diropen, &node, &type);
-	if (ret)
-		return ret;
+struct inode *ext_get_inode(struct super_block *sb, int ino)
+{
+	struct inode *inode;
+	struct ext2fs_node *node;
+	struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb);
+	struct ext_filesystem *fs = fsdev->dev.priv;
+	int ret;
 
-	if (type != FILETYPE_SYMLINK)
-		return -EINVAL;
+	inode = new_inode(sb);
 
-	symlink = ext4fs_read_symlink(node);
-	if (!symlink)
-		return -ENOENT;
+	node = container_of(inode, struct ext2fs_node, i);
 
-	len = min(bufsiz, strlen(symlink));
+	ret = ext4fs_read_inode(fs->data, ino, &node->inode);
 
-	memcpy(buf, symlink, len);
+	inode->i_ino = ino;
+	inode->i_mode = le16_to_cpu(node->inode.mode);
+	inode->i_size = le32_to_cpu(node->inode.size);
 
-	free(symlink);
+	switch (inode->i_mode & S_IFMT) {
+	default:
+		return NULL;
+	case S_IFREG:
+		inode->i_op = &ext_inode_operations;
+		break;
+	case S_IFDIR:
+		inode->i_op = &ext_inode_operations;
+		inode->i_fop = &ext_dir_operations;
+		inc_nlink(inode);
+		break;
+	case S_IFLNK:
+		inode->i_op = &ext_symlink_inode_operations;
+		if (inode->i_size < sizeof(node->inode.b.symlink)) {
+			inode->i_link = zalloc(inode->i_size + 1);
+			strncpy(inode->i_link, node->inode.b.symlink,
+				inode->i_size);
+		}
+		break;
+	}
 
-	return 0;
+	return inode;
 }
 
 static int ext_probe(struct device_d *dev)
@@ -227,6 +263,8 @@ static int ext_probe(struct device_d *dev)
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
 	int ret;
 	struct ext_filesystem *fs;
+	struct super_block *sb = &fsdev->sb;
+	struct inode *inode;
 
 	fs = xzalloc(sizeof(*fs));
 
@@ -243,6 +281,11 @@ static int ext_probe(struct device_d *dev)
 	if (ret)
 		goto err_mount;
 
+	sb->s_op = &ext_ops;
+
+	inode = ext_get_inode(sb, 2);
+	sb->s_root = d_make_root(inode);
+
 	return 0;
 
 err_mount:
@@ -261,15 +304,8 @@ static void ext_remove(struct device_d *dev)
 }
 
 static struct fs_driver_d ext_driver = {
-	.open      = ext_open,
-	.close     = ext_close,
 	.read      = ext_read,
 	.lseek     = ext_lseek,
-	.opendir   = ext_opendir,
-	.readdir   = ext_readdir,
-	.closedir  = ext_closedir,
-	.stat      = ext_stat,
-	.readlink  = ext_readlink,
 	.type      = filetype_ext,
 	.flags     = 0,
 	.drv = {
diff --git a/fs/ext4/ext_common.h b/fs/ext4/ext_common.h
index e82b56b86a..c084cf9a32 100644
--- a/fs/ext4/ext_common.h
+++ b/fs/ext4/ext_common.h
@@ -30,6 +30,8 @@
 #ifndef __EXT_COMMON__
 #define __EXT_COMMON__
 
+#include <linux/fs.h>
+
 #define SECTOR_SIZE		0x200
 #define SECTOR_BITS		9
 
@@ -208,6 +210,7 @@ struct ext2_dirent {
 };
 
 struct ext2fs_node {
+	struct inode i;
 	struct ext2_data *data;
 	struct ext2_inode inode;
 	int ino;
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:49 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:49 +0200
Subject: [PATCH 17/19] fs: nfs: Switch to dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-18-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/Kconfig |   1 -
 fs/nfs.c   | 542 ++++++++++++++++++++++++++-----------------------------------
 2 files changed, 234 insertions(+), 309 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index e3460e4443..b2d4242e63 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -41,7 +41,6 @@ config FS_OMAP4_USBBOOT
 
 config FS_NFS
 	depends on NET
-	depends on BROKEN
 	bool
 	prompt "nfs support"
 
diff --git a/fs/nfs.c b/fs/nfs.c
index 75cd127eeb..eb5db344db 100644
--- a/fs/nfs.c
+++ b/fs/nfs.c
@@ -20,6 +20,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#define pr_fmt(fmt) "NFS: " fmt
 
 #include <common.h>
 #include <net.h>
@@ -127,6 +128,11 @@ struct rpc_reply {
 #define NFS_TIMEOUT	(2 * SECOND)
 #define NFS_MAX_RESEND	5
 
+struct nfs_fh {
+	unsigned short size;
+	unsigned char data[NFS3_FHSIZE];
+};
+
 struct nfs_priv {
 	struct net_connection *con;
 	IPaddr_t server;
@@ -136,18 +142,34 @@ struct nfs_priv {
 	uint16_t nfs_port;
 	unsigned manual_nfs_port:1;
 	uint32_t rpc_id;
-	uint32_t rootfh_len;
-	char rootfh[NFS3_FHSIZE];
+	struct nfs_fh rootfh;
 };
 
 struct file_priv {
 	struct kfifo *fifo;
 	void *buf;
-	uint32_t filefh_len;
-	char filefh[NFS3_FHSIZE];
+	struct nfs_priv *npriv;
+	struct nfs_fh fh;
+};
+
+struct nfs_inode {
+	struct inode inode;
+	struct nfs_fh fh;
 	struct nfs_priv *npriv;
 };
 
+static inline struct nfs_inode *nfsi(struct inode *inode)
+{
+	return container_of(inode, struct nfs_inode, inode);
+}
+
+static void nfs_set_fh(struct inode *inode, struct nfs_fh *fh)
+{
+	struct nfs_inode *ninode = nfsi(inode);
+
+	ninode->fh = *fh;
+}
+
 static uint64_t nfs_timer_start;
 
 static int nfs_state;
@@ -234,17 +256,14 @@ struct xdr_stream {
 #define XDR_QUADLEN(l)		(((l) + 3) >> 2)
 
 struct nfs_dir {
-	DIR dir;
-
 	/*
 	 * stream points to the next entry3 in the reply member of READDIR3res
 	 * (if any, to the end indicator otherwise).
 	 */
 	struct xdr_stream stream;
-	struct dirent ent;
-	struct file_priv *priv;
 	uint64_t cookie;
 	char cookieverf[NFS3_COOKIEVERFSIZE];
+	struct nfs_fh fh;
 };
 
 static void xdr_init(struct xdr_stream *stream, void *buf, int len)
@@ -300,11 +319,11 @@ static int decode_filename(struct xdr_stream *xdr, char *name, u32 *length)
 	return 0;
 
 out_nametoolong:
-	printf("%s: returned a too long filename: %u\n", __func__, count);
+	pr_err("%s: returned a too long filename: %u\n", __func__, count);
 	return -ENAMETOOLONG;
 
 out_overflow:
-	printf("%s: premature end of packet\n", __func__);
+	pr_err("%s: premature end of packet\n", __func__);
 	return -EIO;
 }
 
@@ -486,16 +505,16 @@ static uint32_t *nfs_add_uint64(uint32_t *p, uint64_t val)
 	return p + 2;
 }
 
-static uint32_t *nfs_add_fh3(uint32_t *p, unsigned fh_len, const char *fh)
+static uint32_t *nfs_add_fh3(uint32_t *p, struct nfs_fh *fh)
 {
-	*p++ = hton32(fh_len);
+	*p++ = hton32(fh->size);
 
 	/* zero padding */
-	if (fh_len & 3)
-		p[fh_len / 4] = 0;
+	if (fh->size & 3)
+		p[fh->size / 4] = 0;
 
-	memcpy(p, fh, fh_len);
-	p += DIV_ROUND_UP(fh_len, 4);
+	memcpy(p, fh->data, fh->size);
+	p += DIV_ROUND_UP(fh->size, 4);
 	return p;
 }
 
@@ -532,33 +551,36 @@ static const struct {
 	{ 0x00800, S_ISUID },
 };
 
-static int nfs_fattr3_to_stat(uint32_t *p, struct stat *s)
+static int nfs_fattr3_to_stat(uint32_t *p, struct inode *inode)
 {
 	uint32_t mode;
 	size_t i;
 
+	if (!inode)
+		return 0;
+
 	/* offsetof(struct fattr3, type) = 0 */
 	switch (ntoh32(net_read_uint32(p + 0))) {
 	case NF3REG:
-		s->st_mode = S_IFREG;
+		inode->i_mode = S_IFREG;
 		break;
 	case NF3DIR:
-		s->st_mode = S_IFDIR;
+		inode->i_mode = S_IFDIR;
 		break;
 	case NF3BLK:
-		s->st_mode = S_IFBLK;
+		inode->i_mode = S_IFBLK;
 		break;
 	case NF3CHR:
-		s->st_mode = S_IFCHR;
+		inode->i_mode = S_IFCHR;
 		break;
 	case NF3LNK:
-		s->st_mode = S_IFLNK;
+		inode->i_mode = S_IFLNK;
 		break;
 	case NF3SOCK:
-		s->st_mode = S_IFSOCK;
+		inode->i_mode = S_IFSOCK;
 		break;
 	case NF3FIFO:
-		s->st_mode = S_IFIFO;
+		inode->i_mode = S_IFIFO;
 		break;
 	default:
 		printf("%s: invalid mode %x\n",
@@ -570,18 +592,17 @@ static int nfs_fattr3_to_stat(uint32_t *p, struct stat *s)
 	mode = ntoh32(net_read_uint32(p + 1));
 	for (i = 0; i < ARRAY_SIZE(nfs3_mode_bits); ++i) {
 		if (mode & nfs3_mode_bits[i].nfsmode)
-			s->st_mode |= nfs3_mode_bits[i].statmode;
+			inode->i_mode |= nfs3_mode_bits[i].statmode;
 	}
 
 	/* offsetof(struct fattr3, size) = 20 */
-	s->st_size = ntoh64(net_read_uint64(p + 5));
+	inode->i_size = ntoh64(net_read_uint64(p + 5));
 
 	return 0;
 }
 
-static uint32_t *nfs_read_post_op_attr(uint32_t *p, struct stat **s)
+static uint32_t *nfs_read_post_op_attr(uint32_t *p, struct inode *inode)
 {
-	struct stat dummy;
 	/*
 	 * union post_op_attr switch (bool attributes_follow) {
 	 * case TRUE:
@@ -592,11 +613,8 @@ static uint32_t *nfs_read_post_op_attr(uint32_t *p, struct stat **s)
 	 */
 
 	if (ntoh32(net_read_uint32(p++))) {
-		nfs_fattr3_to_stat(p, s ? *s : &dummy);
+		nfs_fattr3_to_stat(p, inode);
 		p += 21;
-	} else if (s) {
-		/* no attributes available */
-		*s = NULL;
 	}
 
 	return p;
@@ -635,14 +653,14 @@ static int nfs_mount_req(struct nfs_priv *npriv)
 
 	p = nfs_packet + sizeof(struct rpc_reply) + 4;
 
-	npriv->rootfh_len = ntoh32(net_read_uint32(p++));
-	if (npriv->rootfh_len > NFS3_FHSIZE) {
+	npriv->rootfh.size = ntoh32(net_read_uint32(p++));
+	if (npriv->rootfh.size > NFS3_FHSIZE) {
 		printf("%s: file handle too big: %lu\n", __func__,
-				(unsigned long)npriv->rootfh_len);
+				(unsigned long)npriv->rootfh.size);
 		return -EIO;
 	}
-	memcpy(npriv->rootfh, p, npriv->rootfh_len);
-	p += DIV_ROUND_UP(npriv->rootfh_len, 4);
+	memcpy(npriv->rootfh.data, p, npriv->rootfh.size);
+	p += DIV_ROUND_UP(npriv->rootfh.size, 4);
 
 	return 0;
 }
@@ -674,9 +692,10 @@ static void nfs_umount_req(struct nfs_priv *npriv)
  *
  * *s is set to NULL if LOOKUP3resok doesn't contain obj_attributes.
  */
-static int nfs_lookup_req(struct file_priv *priv,
-		uint32_t filename_len, const char *filename, struct stat **s)
+static int nfs_lookup_req(struct nfs_priv *npriv, struct nfs_fh *fh,
+			  const char *filename, struct inode *inode)
 {
+	struct nfs_inode *ninode = nfsi(inode);
 	uint32_t data[1024];
 	uint32_t *p;
 	int len;
@@ -709,73 +728,29 @@ static int nfs_lookup_req(struct file_priv *priv,
 	p = rpc_add_credentials(p);
 
 	/* what.dir */
-	p = nfs_add_fh3(p, priv->filefh_len, priv->filefh);
+	p = nfs_add_fh3(p, fh);
 
 	/* what.name */
-	p = nfs_add_filename(p, filename_len, filename);
+	p = nfs_add_filename(p, strlen(filename), filename);
 
 	len = p - &(data[0]);
 
-	ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_LOOKUP, data, len);
+	ret = rpc_req(npriv, PROG_NFS, NFSPROC3_LOOKUP, data, len);
 	if (ret)
 		return ret;
 
 	p = nfs_packet + sizeof(struct rpc_reply) + 4;
 
-	priv->filefh_len = ntoh32(net_read_uint32(p++));
-	if (priv->filefh_len > NFS3_FHSIZE) {
-		debug("%s: file handle too big: %lu\n", __func__,
-				(unsigned long)priv->filefh_len);
+	ninode->fh.size = ntoh32(net_read_uint32(p++));
+	if (ninode->fh.size > NFS3_FHSIZE) {
+		debug("%s: file handle too big: %u\n", __func__,
+		      ninode->fh.size);
 		return -EIO;
 	}
-	memcpy(priv->filefh, p, priv->filefh_len);
-	p += DIV_ROUND_UP(priv->filefh_len, 4);
-
-	if (s)
-		nfs_read_post_op_attr(p, s);
-
-	return 0;
-}
-
-static int nfs_attr_req(struct file_priv *priv, struct stat *s)
-{
-	uint32_t data[1024];
-	uint32_t *p;
-	int len;
-	int ret;
-
-	/*
-	 * struct GETATTR3args {
-	 * 	nfs_fh3 object;
-	 * }
-	 *
-	 * struct GETATTR3resok {
-	 * 	fattr3 obj_attributes;
-	 * };
-	 *
-	 * union GETATTR3res switch (nfsstat3 status) {
-	 * case NFS3_OK:
-	 * 	GETATTR3resok resok;
-	 * default:
-	 * 	void;
-	 * }
-	 */
-
-	p = &(data[0]);
-	p = rpc_add_credentials(p);
-
-	/* object */
-	p = nfs_add_fh3(p, priv->filefh_len, priv->filefh);
-
-	len = p - &(data[0]);
-
-	ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_GETATTR, data, len);
-	if (ret)
-		return ret;
+	memcpy(ninode->fh.data, p, ninode->fh.size);
+	p += DIV_ROUND_UP(ninode->fh.size, 4);
 
-	p = nfs_packet + sizeof(struct rpc_reply) + 4;
-
-	nfs_fattr3_to_stat(p, s);
+	nfs_read_post_op_attr(p, inode);
 
 	return 0;
 }
@@ -784,7 +759,7 @@ static int nfs_attr_req(struct file_priv *priv, struct stat *s)
  * returns with dir->stream pointing to the first entry
  * of dirlist3 res.resok.reply
  */
-static void *nfs_readdirattr_req(struct file_priv *priv, struct nfs_dir *dir)
+static void *nfs_readdirattr_req(struct nfs_priv *npriv, struct nfs_dir *dir)
 {
 	uint32_t data[1024];
 	uint32_t *p;
@@ -833,7 +808,7 @@ static void *nfs_readdirattr_req(struct file_priv *priv, struct nfs_dir *dir)
 	p = &(data[0]);
 	p = rpc_add_credentials(p);
 
-	p = nfs_add_fh3(p, priv->filefh_len, priv->filefh);
+	p = nfs_add_fh3(p, &dir->fh);
 	p = nfs_add_uint64(p, dir->cookie);
 
 	memcpy(p, dir->cookieverf, NFS3_COOKIEVERFSIZE);
@@ -841,7 +816,7 @@ static void *nfs_readdirattr_req(struct file_priv *priv, struct nfs_dir *dir)
 
 	p = nfs_add_uint32(p, 1024); /* count */
 
-	ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_READDIR, data, p - data);
+	ret = rpc_req(npriv, PROG_NFS, NFSPROC3_READDIR, data, p - data);
 	if (ret)
 		return NULL;
 
@@ -909,7 +884,7 @@ static int nfs_read_req(struct file_priv *priv, uint64_t offset,
 	p = &(data[0]);
 	p = rpc_add_credentials(p);
 
-	p = nfs_add_fh3(p, priv->filefh_len, priv->filefh);
+	p = nfs_add_fh3(p, &priv->fh);
 	p = nfs_add_uint64(p, offset);
 	p = nfs_add_uint32(p, readlen);
 
@@ -953,82 +928,11 @@ static void nfs_handler(void *ctx, char *packet, unsigned len)
 	nfs_len = len;
 }
 
-static int nfs_create(struct device_d *dev, const char *pathname, mode_t mode)
-{
-	return -ENOSYS;
-}
-
-static int nfs_unlink(struct device_d *dev, const char *pathname)
-{
-	return -ENOSYS;
-}
-
-static int nfs_mkdir(struct device_d *dev, const char *pathname)
-{
-	return -ENOSYS;
-}
-
-static int nfs_rmdir(struct device_d *dev, const char *pathname)
-{
-	return -ENOSYS;
-}
-
 static int nfs_truncate(struct device_d *dev, FILE *f, ulong size)
 {
 	return -ENOSYS;
 }
 
-static struct file_priv *nfs_do_open(struct device_d *dev,
-		const char *filename, struct stat **s)
-{
-	struct file_priv *priv;
-	struct nfs_priv *npriv = dev->priv;
-	int ret;
-	const char *tok;
-
-	debug("%s: filename = %s\n", __func__, filename);
-	priv = xzalloc(sizeof(*priv));
-
-	priv->npriv = npriv;
-
-	if (!*filename) {
-		priv->filefh_len = npriv->rootfh_len;
-		memcpy(priv->filefh, npriv->rootfh, npriv->rootfh_len);
-		return priv;
-	}
-
-	filename++;
-
-	priv->filefh_len = npriv->rootfh_len;
-	memcpy(priv->filefh, npriv->rootfh, NFS3_FHSIZE);
-
-	while (*filename) {
-		size_t flen;
-
-		tok = strchr(filename, '/');
-		if (tok)
-			flen = tok - filename;
-		else
-			flen = strlen(filename);
-
-		ret = nfs_lookup_req(priv, flen, filename, s);
-		if (ret)
-			goto out;
-
-		if (tok)
-			filename += flen + 1;
-		else
-			break;
-	}
-
-	return priv;
-
-out:
-	free(priv);
-
-	return ERR_PTR(ret);
-}
-
 static void nfs_do_close(struct file_priv *priv)
 {
 	if (priv->fifo)
@@ -1037,34 +941,8 @@ static void nfs_do_close(struct file_priv *priv)
 	free(priv);
 }
 
-static struct file_priv *nfs_do_stat(struct device_d *dev,
-		const char *filename, struct stat *s)
-{
-	struct file_priv *priv;
-	int ret;
-	struct stat **sptr = &s;
-
-	debug("%s: filename = %s\n", __func__, filename);
-	priv = nfs_do_open(dev, filename, sptr);
-	if (IS_ERR(priv))
-		return priv;
-
-	if (!*sptr) {
-		/*
-		 * The nfs server didn't provide obj_attributes in the lookup
-		 * reply, so ask for them explicitly.
-		 */
-		ret = nfs_attr_req(priv, s);
-		if (ret) {
-			nfs_do_close(priv);
-			return ERR_PTR(ret);
-		}
-	}
-
-	return priv;
-}
-
-static int nfs_readlink_req(struct file_priv *priv, char* buf, size_t size)
+static int nfs_readlink_req(struct nfs_priv *npriv, struct nfs_fh *fh,
+			    char **target)
 {
 	uint32_t data[1024];
 	uint32_t *p;
@@ -1095,11 +973,11 @@ static int nfs_readlink_req(struct file_priv *priv, char* buf, size_t size)
 	p = &(data[0]);
 	p = rpc_add_credentials(p);
 
-	p = nfs_add_fh3(p, priv->filefh_len, priv->filefh);
+	p = nfs_add_fh3(p, fh);
 
 	len = p - &(data[0]);
 
-	ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_READLINK, data, len);
+	ret = rpc_req(npriv, PROG_NFS, NFSPROC3_READLINK, data, len);
 	if (ret)
 		return ret;
 
@@ -1110,44 +988,37 @@ static int nfs_readlink_req(struct file_priv *priv, char* buf, size_t size)
 	len = ntoh32(net_read_uint32(p)); /* new path length */
 	p++;
 
-	if (len > size)
-		return -ENOMEM;
-
-	memcpy(buf, p, len);
+	*target = xzalloc(len + 1);
+	memcpy(*target, p, len);
 
 	return 0;
 }
 
-static int nfs_readlink(struct device_d *dev, const char *filename,
-			char *realname, size_t size)
+static const char *nfs_get_link(struct dentry *dentry, struct inode *inode)
 {
-	struct file_priv *priv;
+	struct nfs_inode *ninode = nfsi(inode);
+	struct nfs_priv *npriv = ninode->npriv;
 	int ret;
 
-	priv = nfs_do_open(dev, filename, NULL);
-	if (IS_ERR(priv))
-		return PTR_ERR(priv);
-
-	ret = nfs_readlink_req(priv, realname, size);
-	if (ret) {
-		nfs_do_close(priv);
-		return ret;
-	}
+	ret = nfs_readlink_req(npriv, &ninode->fh, &inode->i_link);
+	if (ret)
+		return ERR_PTR(ret);
 
-	return 0;
+	return inode->i_link;
 }
 
 static int nfs_open(struct device_d *dev, FILE *file, const char *filename)
 {
+	struct inode *inode = file->f_inode;
+	struct nfs_inode *ninode = nfsi(inode);
+	struct nfs_priv *npriv = ninode->npriv;
 	struct file_priv *priv;
-	struct stat s;
-
-	priv = nfs_do_stat(dev, filename, &s);
-	if (IS_ERR(priv))
-		return PTR_ERR(priv);
 
+	priv = xzalloc(sizeof(*priv));
+	priv->fh = ninode->fh;
+	priv->npriv = npriv;
 	file->priv = priv;
-	file->size = s.st_size;
+	file->size = inode->i_size;
 
 	priv->fifo = kfifo_alloc(1024);
 	if (!priv->fifo) {
@@ -1199,115 +1070,170 @@ static loff_t nfs_lseek(struct device_d *dev, FILE *file, loff_t pos)
 	return file->pos;
 }
 
-static DIR *nfs_opendir(struct device_d *dev, const char *pathname)
+static int nfs_iterate(struct file *file, struct dir_context *ctx)
 {
-	struct file_priv *priv;
+	struct dentry *dentry = file->f_path.dentry;
+	struct inode *dir = d_inode(dentry);
+	struct nfs_priv *npriv = nfsi(dir)->npriv;
 	void *buf = NULL;
-	struct nfs_dir *dir;
+	struct nfs_dir *ndir;
+	struct xdr_stream *xdr;
+	int ret;
+	uint32_t *p, len;
 
-	priv = nfs_do_open(dev, pathname, NULL);
-	if (IS_ERR(priv))
-		return NULL;
+	ndir = xzalloc(sizeof(*ndir));
+	ndir->fh = nfsi(dir)->fh;
 
-	dir = xzalloc(sizeof(*dir));
-	dir->priv = priv;
+	while (1) {
+		/* cookie == 0 and cookieverf == 0 means start of dir */
+		buf = nfs_readdirattr_req(npriv, ndir);
+		if (!buf) {
+			pr_err("%s: nfs_readdirattr_req failed\n", __func__);
+			ret = -EINVAL;
+			goto out;
+		}
 
-	/* cookie == 0 and cookieverf == 0 means start of dir */
-	buf = nfs_readdirattr_req(priv, dir);
-	if (!buf) {
-		debug("%s: nfs_readdirattr_req failed\n", __func__);
-		goto err;
-	}
+		xdr = &ndir->stream;
 
-	return &dir->dir;
+		while (1) {
+			char name[256];
 
-err:
-	free(buf);
-	free(dir);
-	nfs_do_close(priv);
-	return NULL;
-}
+			p = xdr_inline_decode(xdr, 4);
+			if (!p)
+				goto err_eop;
 
-static struct dirent *nfs_readdir(struct device_d *dev, DIR *dir)
-{
-	struct nfs_dir *ndir = container_of(dir, struct nfs_dir, dir);
-	uint32_t *p;
-	int ret;
-	int len;
-	struct xdr_stream *xdr = &ndir->stream;
+			if (!net_read_uint32(p)) {
+				/* eof? */
+				p = xdr_inline_decode(xdr, 4);
+				if (!p)
+					goto err_eop;
 
-again:
-	p = xdr_inline_decode(xdr, 4);
-	if (!p) {
-		printf("%s: premature end of packet\n", __func__);
-		return NULL;
-	}
+				if (net_read_uint32(p)) {
+					ret = 0;
+					goto out;
+				}
 
-	if (!net_read_uint32(p)) {
-		/* eof? */
-		p = xdr_inline_decode(xdr, 4);
-		if (!p) {
-			printf("%s: premature end of packet\n", __func__);
-			return NULL;
-		}
-		if (net_read_uint32(p))
-			return NULL;
+				break;
+			}
 
-		if (!nfs_readdirattr_req(ndir->priv, ndir)) {
-			printf("%s: nfs_readdirattr_req failed\n", __func__);
-			return NULL;
-		}
+			/* skip over fileid */
+			p = xdr_inline_decode(xdr, 8);
+			if (!p)
+				goto err_eop;
 
-		goto again;
-	}
+			ret = decode_filename(xdr, name, &len);
+			if (ret)
+				goto out;
 
-	/* there is another entry available in the last reply */
+			dir_emit(ctx, name, len, 0, DT_UNKNOWN);
 
-	/* skip over fileid */
-	p = xdr_inline_decode(xdr, 8);
-	if (!p) {
-		printf("%s: premature end of packet\n", __func__);
-		return NULL;
+			p = xdr_inline_decode(xdr, 8);
+			if (!p)
+				goto err_eop;
+
+			ndir->cookie = ntoh64(net_read_uint64(p));
+		}
+		free(buf);
 	}
 
-	ret = decode_filename(xdr, ndir->ent.d_name, &len);
-	if (ret)
-		return NULL;
+	ret = 0;
 
-	p = xdr_inline_decode(xdr, 8);
-	if (!p) {
-		printf("%s: premature end of packet\n", __func__);
+out:
+	free(ndir->stream.buf);
+	free(ndir);
+
+	return ret;
+
+err_eop:
+	pr_err("Unexpected end of packet\n");
+
+	return -EIO;
+}
+
+static struct inode *nfs_alloc_inode(struct super_block *sb)
+{
+	struct nfs_inode *node;
+
+	node = xzalloc(sizeof(*node));
+	if (!node)
 		return NULL;
-	}
-	ndir->cookie = ntoh64(net_read_uint64(p));
 
-	return &ndir->ent;
+	return &node->inode;
 }
 
-static int nfs_closedir(struct device_d *dev, DIR *dir)
+static const struct inode_operations nfs_file_inode_operations;
+static const struct file_operations nfs_dir_operations;
+static const struct inode_operations nfs_dir_inode_operations;
+static const struct file_operations nfs_file_operations;
+static const struct inode_operations nfs_symlink_inode_operations = {
+	.get_link = nfs_get_link,
+};
+
+static int nfs_init_inode(struct nfs_priv *npriv, struct inode *inode,
+			  unsigned int mode)
 {
-	struct nfs_dir *ndir = (void *)dir;
+	struct nfs_inode *ninode = nfsi(inode);
 
-	nfs_do_close(ndir->priv);
-	free(ndir->stream.buf);
-	free(ndir);
+	ninode->npriv = npriv;
+
+	inode->i_ino = get_next_ino();
+	inode->i_mode = mode;
+
+	switch (inode->i_mode & S_IFMT) {
+	default:
+		return -EINVAL;
+	case S_IFREG:
+		inode->i_op = &nfs_file_inode_operations;
+		inode->i_fop = &nfs_file_operations;
+		break;
+	case S_IFDIR:
+		inode->i_op = &nfs_dir_inode_operations;
+		inode->i_fop = &nfs_dir_operations;
+		inc_nlink(inode);
+		break;
+	case S_IFLNK:
+		inode->i_op = &nfs_symlink_inode_operations;
+		break;
+	}
 
 	return 0;
 }
 
-static int nfs_stat(struct device_d *dev, const char *filename, struct stat *s)
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry *dentry,
+				   unsigned int flags)
 {
-	struct file_priv *priv;
+	struct nfs_inode *ndir = nfsi(dir);
+	struct inode *inode = new_inode(dir->i_sb);
+	struct nfs_priv *npriv = ndir->npriv;
+	int ret;
 
-	priv = nfs_do_stat(dev, filename, s);
-	if (IS_ERR(priv)) {
-		return PTR_ERR(priv);
-	} else {
-		nfs_do_close(priv);
-		return 0;
-	}
+	if (!inode)
+		return NULL;
+
+	ret = nfs_lookup_req(npriv, &ndir->fh, dentry->name, inode);
+	if (ret)
+		return NULL;
+
+	nfs_init_inode(npriv, inode, inode->i_mode);
+
+	d_add(dentry, inode);
+
+	return NULL;
 }
 
+static const struct file_operations nfs_dir_operations = {
+	.iterate = nfs_iterate,
+};
+
+static const struct inode_operations nfs_dir_inode_operations =
+{
+	.lookup = nfs_lookup,
+};
+
+static const struct super_operations nfs_ops = {
+	.alloc_inode = nfs_alloc_inode,
+};
+
 static char *rootnfsopts;
 
 static void nfs_set_rootarg(struct nfs_priv *npriv, struct fs_device_d *fsdev)
@@ -1347,8 +1273,10 @@ static int nfs_probe(struct device_d *dev)
 {
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
 	struct nfs_priv *npriv = xzalloc(sizeof(struct nfs_priv));
+	struct super_block *sb = &fsdev->sb;
 	char *tmp = xstrdup(fsdev->backingstore);
 	char *path;
+	struct inode *inode;
 	int ret;
 
 	dev->priv = npriv;
@@ -1414,6 +1342,13 @@ static int nfs_probe(struct device_d *dev)
 
 	free(tmp);
 
+	sb->s_op = &nfs_ops;
+
+	inode = new_inode(sb);
+	nfs_set_fh(inode, &npriv->rootfh);
+	nfs_init_inode(npriv, inode, S_IFDIR);
+	sb->s_root = d_make_root(inode);
+
 	return 0;
 
 err2:
@@ -1443,17 +1378,8 @@ static struct fs_driver_d nfs_driver = {
 	.close     = nfs_close,
 	.read      = nfs_read,
 	.lseek     = nfs_lseek,
-	.opendir   = nfs_opendir,
-	.readdir   = nfs_readdir,
-	.closedir  = nfs_closedir,
-	.stat      = nfs_stat,
-	.create    = nfs_create,
-	.unlink    = nfs_unlink,
-	.mkdir     = nfs_mkdir,
-	.rmdir     = nfs_rmdir,
 	.write     = nfs_write,
 	.truncate  = nfs_truncate,
-	.readlink  = nfs_readlink,
 	.flags     = 0,
 	.drv = {
 		.probe  = nfs_probe,
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:45 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:45 +0200
Subject: [PATCH 13/19] fs: ramfs: Switch to dcache implementation
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-14-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/Kconfig |   1 -
 fs/ramfs.c | 412 +++++++++++++++----------------------------------------------
 2 files changed, 101 insertions(+), 312 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index c3a78eaae5..9638e27dbd 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -20,7 +20,6 @@ source fs/ext4/Kconfig
 config FS_RAMFS
 	bool
 	default y
-	depends on BROKEN
 	prompt "ramfs support"
 
 config FS_DEVFS
diff --git a/fs/ramfs.c b/fs/ramfs.c
index a97f0a6ebf..d346a4e755 100644
--- a/fs/ramfs.c
+++ b/fs/ramfs.c
@@ -35,6 +35,7 @@ struct ramfs_chunk {
 };
 
 struct ramfs_inode {
+	struct inode inode;
 	char *name;
 	struct ramfs_inode *parent;
 	struct ramfs_inode *next;
@@ -52,84 +53,52 @@ struct ramfs_inode {
 	struct ramfs_chunk *recent_chunkp;
 };
 
+static inline struct ramfs_inode *to_ramfs_inode(struct inode *inode)
+{
+	return container_of(inode, struct ramfs_inode, inode);
+}
+
 struct ramfs_priv {
 	struct ramfs_inode root;
 };
 
 /* ---------------------------------------------------------------*/
-static struct ramfs_inode * lookup(struct ramfs_inode *node, const char *name)
-{
-	debug("lookup: %s in %p\n",name, node);
-	if(!S_ISDIR(node->mode))
-		return NULL;
 
-	node = node->child;
-	if (!node)
-		return NULL;
+static const struct super_operations ramfs_ops;
+static const struct inode_operations ramfs_dir_inode_operations;
+static const struct inode_operations ramfs_file_inode_operations;
+static const struct inode_operations ramfs_symlink_inode_operations;
+static const struct file_operations ramfs_file_operations;
 
-	while (node) {
-		debug("lookup: %s\n", node->name);
-		if (!strcmp(node->name, name)) {
-			debug("lookup: found: 0x%p\n",node);
-			return node;
-		}
-		node = node->next;
-	}
-        return NULL;
-}
-
-static struct ramfs_inode* rlookup(struct ramfs_priv *priv, const char *path)
+static struct inode *ramfs_get_inode(struct super_block *sb, const struct inode *dir,
+				     umode_t mode)
 {
-	struct ramfs_inode *node = &priv->root;
-        static char *buf;
-        char *part;
-
-	debug("rlookup %s in %p\n",path, node);
-        buf = strdup(path);
-
-        part = strtok(buf, "/");
-        if (!part)
-		goto out;
-
-        do {
-                node = lookup(node, part);
-                if (!node)
-			goto out;
-                part = strtok(NULL, "/");
-        } while(part);
-
-out:
-	free(buf);
-        return node;
-}
+	struct inode *inode = new_inode(sb);
 
-static struct ramfs_inode* rlookup_parent(struct ramfs_priv *priv, const char *pathname, char **file)
-{
-	char *path;
-	struct ramfs_inode *node;
-
-	pathname++;
-	path = strdup(pathname);
+	if (!inode)
+		return NULL;
 
-	if ((*file = strrchr((char *) pathname, '/'))) {
-		char *tmp;
-		(*file)++;
+	inode->i_ino = get_next_ino();
+	inode->i_mode = mode;
 
-		tmp = strrchr(path, '/');
-		*tmp = 0;
-		node = rlookup(priv, path);
-		if (!node) {
-			errno = -ENOENT;
-			goto out;
-		}
-	} else {
-		*file = (char *)pathname;
-		node = &priv->root;
+	switch (mode & S_IFMT) {
+	default:
+		return NULL;
+	case S_IFREG:
+		inode->i_op = &ramfs_file_inode_operations;
+		inode->i_fop = &ramfs_file_operations;
+		break;
+	case S_IFDIR:
+		inode->i_op = &ramfs_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+		inc_nlink(inode);
+		break;
+	case S_IFLNK:
+		inode->i_op = &ramfs_symlink_inode_operations;
+		break;
 	}
 
-out:
-	free(path);
-	return node;
+	return inode;
 }
 
 static int chunks = 0;
@@ -158,168 +127,75 @@ static void ramfs_put_chunk(struct ramfs_chunk *data)
 	chunks--;
 }
 
-static struct ramfs_inode* ramfs_get_inode(void)
-{
-	struct ramfs_inode *node = xzalloc(sizeof(struct ramfs_inode));
-	return node;
-}
-
-static void ramfs_put_inode(struct ramfs_inode *node)
-{
-	struct ramfs_chunk *data = node->data;
-
-	while (data) {
-		struct ramfs_chunk *tmp = data->next;
-		ramfs_put_chunk(data);
-		data = tmp;
-	}
-
-	free(node->symlink);
-	free(node->name);
-	free(node);
-}
-
-static struct ramfs_inode* node_insert(struct ramfs_inode *parent_node, const char *filename, ulong mode)
-{
-	struct ramfs_inode *node, *new_node = ramfs_get_inode();
-	new_node->name = strdup(filename);
-	new_node->mode = mode;
-
-	node = parent_node->child;
-
-	if (S_ISDIR(mode)) {
-		struct ramfs_inode *n = ramfs_get_inode();
-		n->name = strdup(".");
-		n->mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
-		n->child = n;
-		n->parent = new_node;
-		new_node->child = n;
-		n = ramfs_get_inode();
-		n->name = strdup("..");
-		n->mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
-		n->parent = new_node;
-		n->child = parent_node->child;
-		new_node->child->next = n;
-	}
-
-	while (node->next)
-		node = node->next;
-
-	node->next = new_node;
-	return new_node;
-}
-
 /* ---------------------------------------------------------------*/
 
-static int __ramfs_create(struct device_d *dev, const char *pathname,
-			  mode_t mode, const char *symlink)
+static int
+ramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-	struct ramfs_priv *priv = dev->priv;
-	struct ramfs_inode *node;
-	char *file;
-	char *__symlink = NULL;
-
-	node = rlookup_parent(priv, pathname, &file);
-	if (!node)
-		return -ENOENT;
+	struct inode *inode = ramfs_get_inode(dir->i_sb, dir, mode);
 
-	if (symlink) {
-		__symlink = strdup(symlink);
-		if (!__symlink)
-			return -ENOMEM;
-	}
+	if (!inode)
+		return -ENOSPC;
 
-	node = node_insert(node, file, mode);
-	if (!node) {
-		free(__symlink);
-		return -ENOMEM;
+	if (inode) {
+		d_instantiate(dentry, inode);
+		dget(dentry);   /* Extra count - pin the dentry in core */
 	}
 
-	node->symlink = __symlink;
-
 	return 0;
 }
 
-static int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode)
+static int ramfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-	return __ramfs_create(dev, pathname, mode, NULL);
-}
+	int ret;
 
-static int ramfs_unlink(struct device_d *dev, const char *pathname)
-{
-	struct ramfs_priv *priv = dev->priv;
-	struct ramfs_inode *node, *lastnode;
-	char *file;
-
-	node = rlookup_parent(priv, pathname, &file);
-
-	lastnode = node->child->next;
-	node = lastnode->next;
-
-	while (node) {
-		if (!strcmp(node->name, file)) {
-			struct ramfs_inode *tmp;
-			tmp = node;
-			lastnode->next = node->next;
-			ramfs_put_inode(tmp);
-			return 0;
-		}
-		lastnode = node;
-		node = node->next;
-	};
-	return -ENOENT;
-}
+	ret = ramfs_mknod(dir, dentry, mode | S_IFDIR);
+	if (!ret)
+		inc_nlink(dir);
 
-static int ramfs_mkdir(struct device_d *dev, const char *pathname)
-{
-	return ramfs_create(dev, pathname, S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
+	return ret;
 }
 
-static int ramfs_rmdir(struct device_d *dev, const char *pathname)
+static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-	struct ramfs_priv *priv = dev->priv;
-	struct ramfs_inode *node, *lastnode;
-	char *file;
-
-	node = rlookup_parent(priv, pathname, &file);
-
-	lastnode = node->child->next;
-	node = lastnode->next;
-
-	while (node) {
-		if (!strcmp(node->name, file)) {
-			struct ramfs_inode *tmp;
-			tmp = node;
-			lastnode->next = node->next;
-			ramfs_put_inode(tmp->child->next);
-			ramfs_put_inode(tmp->child);
-			ramfs_put_inode(tmp);
-			return 0;
-		}
-		lastnode = node;
-		node = node->next;
-	};
-	return -ENOENT;
+	return ramfs_mknod(dir, dentry, mode | S_IFREG);
 }
 
-static int ramfs_open(struct device_d *dev, FILE *file, const char *filename)
+static int ramfs_symlink(struct inode *dir, struct dentry *dentry,
+			 const char *symname)
 {
-	struct ramfs_priv *priv = dev->priv;
-	struct ramfs_inode *node = rlookup(priv, filename);
+	struct inode *inode;
 
-	if (!node)
-		return -ENOENT;
+	inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK | S_IRWXG);
+	if (!inode)
+		return -ENOSPC;
+
+	inode->i_link = xstrdup(symname);
+	d_instantiate(dentry, inode);
 
-	file->size = node->size;
-	file->priv = node;
 	return 0;
 }
 
-static int ramfs_close(struct device_d *dev, FILE *f)
+static const char *ramfs_get_link(struct dentry *dentry, struct inode *inode)
 {
-	return 0;
+	return inode->i_link;
 }
 
+static const struct inode_operations ramfs_symlink_inode_operations =
+{
+	.get_link = ramfs_get_link,
+};
+
+static const struct inode_operations ramfs_dir_inode_operations =
+{
+	.lookup = simple_lookup,
+	.symlink = ramfs_symlink,
+	.mkdir = ramfs_mkdir,
+	.rmdir = simple_rmdir,
+	.unlink = simple_unlink,
+	.create = ramfs_create,
+};
+
 static struct ramfs_chunk *ramfs_find_chunk(struct ramfs_inode *node, int chunk)
 {
 	struct ramfs_chunk *data;
@@ -351,7 +227,8 @@ static struct ramfs_chunk *ramfs_find_chunk(struct ramfs_inode *node, int chunk)
 
 static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
 {
-	struct ramfs_inode *node = f->priv;
+	struct inode *inode = f->f_inode;
+	struct ramfs_inode *node = to_ramfs_inode(inode);
 	int chunk;
 	struct ramfs_chunk *data;
 	int ofs;
@@ -359,12 +236,12 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
 	int pos = f->pos;
 	int size = insize;
 
-	chunk = f->pos / CHUNK_SIZE;
+	chunk = pos / CHUNK_SIZE;
 	debug("%s: reading from chunk %d\n", __FUNCTION__, chunk);
 
 	/* Position ourself in stream */
 	data = ramfs_find_chunk(node, chunk);
-	ofs = f->pos % CHUNK_SIZE;
+	ofs = pos % CHUNK_SIZE;
 
 	/* Read till end of current chunk */
 	if (ofs) {
@@ -400,7 +277,8 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
 
 static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
 {
-	struct ramfs_inode *node = f->priv;
+	struct inode *inode = f->f_inode;
+	struct ramfs_inode *node = to_ramfs_inode(inode);
 	int chunk;
 	struct ramfs_chunk *data;
 	int ofs;
@@ -447,15 +325,10 @@ static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i
 	return insize;
 }
 
-static loff_t ramfs_lseek(struct device_d *dev, FILE *f, loff_t pos)
-{
-	f->pos = pos;
-	return f->pos;
-}
-
 static int ramfs_truncate(struct device_d *dev, FILE *f, ulong size)
 {
-	struct ramfs_inode *node = f->priv;
+	struct inode *inode = f->f_inode;
+	struct ramfs_inode *node = to_ramfs_inode(inode);
 	int oldchunks, newchunks;
 	struct ramfs_chunk *data = node->data;
 
@@ -502,108 +375,38 @@ static int ramfs_truncate(struct device_d *dev, FILE *f, ulong size)
 	return 0;
 }
 
-static DIR* ramfs_opendir(struct device_d *dev, const char *pathname)
+static struct inode *ramfs_alloc_inode(struct super_block *sb)
 {
-	DIR *dir;
-	struct ramfs_priv *priv = dev->priv;
 	struct ramfs_inode *node;
 
-	debug("opendir: %s\n", pathname);
-
-	node = rlookup(priv, pathname);
-
+	node = xzalloc(sizeof(*node));
 	if (!node)
 		return NULL;
 
-	if (!S_ISDIR(node->mode))
-		return NULL;
-
-	dir = xmalloc(sizeof(DIR));
-
-	dir->priv = node->child;
-
-	return dir;
-}
-
-static struct dirent* ramfs_readdir(struct device_d *dev, DIR *dir)
-{
-	struct ramfs_inode *node = dir->priv;
-
-	if (node) {
-		strcpy(dir->d.d_name, node->name);
-		dir->priv = node->next;
-		return &dir->d;
-	}
-	return NULL;
-}
-
-static int ramfs_closedir(struct device_d *dev, DIR *dir)
-{
-	free(dir);
-	return 0;
-}
-
-static int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s)
-{
-	struct ramfs_priv *priv = dev->priv;
-	struct ramfs_inode *node = rlookup(priv, filename);
-
-	if (!node)
-		return -ENOENT;
-
-	s->st_size = node->symlink ? strlen(node->symlink) : node->size;
-	s->st_mode = node->mode;
-
-	return 0;
-}
-
-static int ramfs_symlink(struct device_d *dev, const char *pathname,
-		       const char *newpath)
-{
-	mode_t mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
-
-	return __ramfs_create(dev, newpath, mode, pathname);
+	return &node->inode;
 }
 
-static int ramfs_readlink(struct device_d *dev, const char *pathname,
-			char *buf, size_t bufsiz)
-{
-	struct ramfs_priv *priv = dev->priv;
-	struct ramfs_inode *node = rlookup(priv, pathname);
-	int len;
-
-	if (!node || !node->symlink)
-		return -ENOENT;
-
-	len = min(bufsiz, strlen(node->symlink));
-
-	memcpy(buf, node->symlink, len);
-
-	return 0;
-}
+static const struct super_operations ramfs_ops = {
+	.alloc_inode = ramfs_alloc_inode,
+};
 
 static int ramfs_probe(struct device_d *dev)
 {
-	struct ramfs_inode *n;
+	struct inode *inode;
 	struct ramfs_priv *priv = xzalloc(sizeof(struct ramfs_priv));
+	struct fs_device_d *fsdev = dev_to_fs_device(dev);
+	struct super_block *sb = &fsdev->sb;
 
 	dev->priv = priv;
 
 	priv->root.name = "/";
 	priv->root.mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
 	priv->root.parent = &priv->root;
-	n = ramfs_get_inode();
-	n->name = strdup(".");
-	n->mode = S_IFDIR;
-	n->parent = &priv->root;
-	n->child = n;
-	priv->root.child = n;
-	n = ramfs_get_inode();
-	n->name = strdup("..");
-	n->mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
-	n->parent = &priv->root;
-	n->child = priv->root.child;
-	priv->root.child->next = n;
+
+	sb->s_op = &ramfs_ops;
+
+	inode = ramfs_get_inode(sb, NULL, S_IFDIR);
+	sb->s_root = d_make_root(inode);
 
 	return 0;
 }
@@ -614,22 +417,9 @@ static void ramfs_remove(struct device_d *dev)
 }
 
 static struct fs_driver_d ramfs_driver = {
-	.create    = ramfs_create,
-	.unlink    = ramfs_unlink,
-	.open      = ramfs_open,
-	.close     = ramfs_close,
-	.truncate  = ramfs_truncate,
-	.read      = ramfs_read,
-	.write     = ramfs_write,
-	.lseek     = ramfs_lseek,
-	.mkdir     = ramfs_mkdir,
-	.rmdir     = ramfs_rmdir,
-	.opendir   = ramfs_opendir,
-	.readdir   = ramfs_readdir,
-	.closedir  = ramfs_closedir,
-	.stat      = ramfs_stat,
-	.symlink   = ramfs_symlink,
-	.readlink  = ramfs_readlink,
+	.read = ramfs_read,
+	.write = ramfs_write,
+	.truncate = ramfs_truncate,
 	.flags     = FS_DRIVER_NO_DEV,
 	.drv = {
 		.probe  = ramfs_probe,
-- 
2.16.1



From s.hauer at pengutronix.de  Tue Apr  3 00:48:37 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  3 Apr 2018 09:48:37 +0200
Subject: [PATCH 05/19] fs: Add super_operations
In-Reply-To: <20180403074851.5411-1-s.hauer@pengutronix.de>
References: <20180403074851.5411-1-s.hauer@pengutronix.de>
Message-ID: <20180403074851.5411-6-s.hauer@pengutronix.de>

Add a struct super_operations we can use later when we get a fs
implementation closer to Linux. Only add the functions we'll likely
need though.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ubifs/super.c   |  4 ----
 fs/ubifs/ubifs.h   | 35 -----------------------------------
 include/linux/fs.h |  5 +++++
 3 files changed, 5 insertions(+), 39 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index ce6e95e373..b4eb76202b 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -556,7 +556,6 @@ out:
 done:
 	clear_inode(inode);
 }
-#endif
 
 static void ubifs_dirty_inode(struct inode *inode, int flags)
 {
@@ -569,7 +568,6 @@ static void ubifs_dirty_inode(struct inode *inode, int flags)
 	}
 }
 
-#ifndef __BAREBOX__
 static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct ubifs_info *c = dentry->d_sb->s_fs_info;
@@ -2107,9 +2105,7 @@ const struct super_operations ubifs_super_operations = {
 	.write_inode   = ubifs_write_inode,
 	.evict_inode   = ubifs_evict_inode,
 	.statfs        = ubifs_statfs,
-#endif
 	.dirty_inode   = ubifs_dirty_inode,
-#ifndef __BAREBOX__
 	.remount_fs    = ubifs_remount_fs,
 	.show_options  = ubifs_show_options,
 	.sync_fs       = ubifs_sync_fs,
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 1391bd7283..22b24a1161 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -97,41 +97,6 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp);
 /* uapi/linux/limits.h */
 #define XATTR_LIST_MAX 65536	/* size of extended attribute namelist (64k) */
 
-struct super_operations {
-   	struct inode *(*alloc_inode)(struct super_block *sb);
-	void (*destroy_inode)(struct inode *);
-
-   	void (*dirty_inode) (struct inode *, int flags);
-#ifndef __BAREBOX__
-	int (*write_inode) (struct inode *, struct writeback_control *wbc);
-#endif
-	int (*drop_inode) (struct inode *);
-	void (*evict_inode) (struct inode *);
-	void (*put_super) (struct super_block *);
-	int (*sync_fs)(struct super_block *sb, int wait);
-	int (*freeze_fs) (struct super_block *);
-	int (*unfreeze_fs) (struct super_block *);
-#ifndef __BAREBOX__
-	int (*statfs) (struct dentry *, struct kstatfs *);
-#endif
-	int (*remount_fs) (struct super_block *, int *, char *);
-	void (*umount_begin) (struct super_block *);
-
-#ifndef __BAREBOX__
-	int (*show_options)(struct seq_file *, struct dentry *);
-	int (*show_devname)(struct seq_file *, struct dentry *);
-	int (*show_path)(struct seq_file *, struct dentry *);
-	int (*show_stats)(struct seq_file *, struct dentry *);
-#endif
-#ifdef CONFIG_QUOTA
-	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
-	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
-#endif
-	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
-	long (*nr_cached_objects)(struct super_block *, int);
-	long (*free_cached_objects)(struct super_block *, long, int);
-};
-
 /*
  * get_seconds() not really needed in the read-only implmentation
  */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c1a5802eea..153c464470 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -252,6 +252,11 @@ struct file {
 #endif
 };
 
+struct super_operations {
+	struct inode *(*alloc_inode)(struct super_block *sb);
+	void (*destroy_inode)(struct inode *);
+};
+
 /*
  * Inode flags - they have no relation to superblock flags now
  */
-- 
2.16.1



From linux at rempel-privat.de  Tue Apr  3 09:08:54 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Tue,  3 Apr 2018 18:08:54 +0200
Subject: [PATCH] Documentation: framebuffer: update documentation to current
 state
Message-ID: <20180403160854.5654-1-linux@rempel-privat.de>

Framebuffer console support was added in 2015.

Reported-by: TobSnyder at #barebox irc
Signed-off-by: Oleksij Rempel <linux at rempel-privat.de>
---
 Documentation/user/framebuffer.rst | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Documentation/user/framebuffer.rst b/Documentation/user/framebuffer.rst
index 7d004fa1c..d033ff08f 100644
--- a/Documentation/user/framebuffer.rst
+++ b/Documentation/user/framebuffer.rst
@@ -1,9 +1,10 @@
 Framebuffer support
 ===================
 
-barebox has support for framebuffer devices. Currently there is no console support
-for framebuffers, so framebuffer usage is limited to splash screens only. barebox
-supports BMP and PNG graphics using the :ref:`command_splash` command. barebox
+Framebuffer spash screen
+------------------------
+
+barebox supports BMP and PNG graphics using the :ref:`command_splash` command. barebox
 currently has no support for backlights, so unless there is a board specific enable
 hook for enabling a display it must be done manually with a script. Since barebox
 has nothing useful to show on the framebuffer it doesn't enable it during startup.
-- 
2.14.1



From s.hauer at pengutronix.de  Tue Apr  3 22:55:01 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 4 Apr 2018 07:55:01 +0200
Subject: [PATCH] Documentation: framebuffer: update documentation to
 current state
In-Reply-To: <20180403160854.5654-1-linux@rempel-privat.de>
References: <20180403160854.5654-1-linux@rempel-privat.de>
Message-ID: <20180404055501.pqohi44y2yec74ki@pengutronix.de>

On Tue, Apr 03, 2018 at 06:08:54PM +0200, Oleksij Rempel wrote:
> Framebuffer console support was added in 2015.
> 
> Reported-by: TobSnyder at #barebox irc
> Signed-off-by: Oleksij Rempel <linux at rempel-privat.de>
> ---
>  Documentation/user/framebuffer.rst | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/Documentation/user/framebuffer.rst b/Documentation/user/framebuffer.rst
> index 7d004fa1c..d033ff08f 100644
> --- a/Documentation/user/framebuffer.rst
> +++ b/Documentation/user/framebuffer.rst
> @@ -1,9 +1,10 @@
>  Framebuffer support
>  ===================
>  
> -barebox has support for framebuffer devices. Currently there is no console support
> -for framebuffers, so framebuffer usage is limited to splash screens only. barebox
> -supports BMP and PNG graphics using the :ref:`command_splash` command. barebox
> +Framebuffer spash screen
> +------------------------
> +
> +barebox supports BMP and PNG graphics using the :ref:`command_splash` command. barebox
>  currently has no support for backlights, so unless there is a board specific enable
>  hook for enabling a display it must be done manually with a script. Since barebox
>  has nothing useful to show on the framebuffer it doesn't enable it during startup.
> -- 
> 2.14.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From r.hieber at pengutronix.de  Wed Apr  4 05:48:58 2018
From: r.hieber at pengutronix.de (Roland Hieber)
Date: Wed, 4 Apr 2018 14:48:58 +0200
Subject: [PATCH] Documentation: framebuffer: update documentation to
 current state
In-Reply-To: <20180403160854.5654-1-linux@rempel-privat.de>
References: <20180403160854.5654-1-linux@rempel-privat.de>
Message-ID: <20180404124858.g2kij5eb5vuoavuq@pengutronix.de>

On Tue, Apr 03, 2018 at 06:08:54PM +0200, Oleksij Rempel wrote:
> Framebuffer console support was added in 2015.
> 
> Reported-by: TobSnyder at #barebox irc
> Signed-off-by: Oleksij Rempel <linux at rempel-privat.de>
> ---
>  Documentation/user/framebuffer.rst | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/user/framebuffer.rst b/Documentation/user/framebuffer.rst
> index 7d004fa1c..d033ff08f 100644
> --- a/Documentation/user/framebuffer.rst
> +++ b/Documentation/user/framebuffer.rst
> @@ -1,9 +1,10 @@
>  Framebuffer support
>  ===================
>  
> -barebox has support for framebuffer devices. Currently there is no console support
> -for framebuffers, so framebuffer usage is limited to splash screens only. barebox
> -supports BMP and PNG graphics using the :ref:`command_splash` command. barebox
> +Framebuffer spash screen

s/spash/splash/

 - Roland

> +------------------------
> +
> +barebox supports BMP and PNG graphics using the :ref:`command_splash` command. barebox
>  currently has no support for backlights, so unless there is a board specific enable
>  hook for enabling a display it must be done manually with a script. Since barebox
>  has nothing useful to show on the framebuffer it doesn't enable it during startup.
> -- 
> 2.14.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Roland Hieber                     | r.hieber at pengutronix.de     |
Pengutronix e.K.                  | https://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Thu Apr  5 00:30:38 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 5 Apr 2018 09:30:38 +0200
Subject: [PATCH v3 04/10] ARM: add file for HYP mode related setup
In-Reply-To: <20180326192025.28809-4-l.stach@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-4-l.stach@pengutronix.de>
Message-ID: <20180405073038.r2afhw3lhmkfq7jy@pengutronix.de>

On Mon, Mar 26, 2018 at 09:20:19PM +0200, Lucas Stach wrote:
> This adds routines to add hyp mode vectors and switch back to HYP
> mode from SVC. This is needed in both the PBL and Barebox proper.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> ---
> v3:
> - fix whitespace
> - use __BARE_INIT
> ---
>  arch/arm/cpu/Makefile         |   4 ++
>  arch/arm/cpu/hyp.S            | 116 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/cpu/sm_as.S          |  11 ----
>  arch/arm/include/asm/secure.h |   8 +++
>  4 files changed, 128 insertions(+), 11 deletions(-)
>  create mode 100644 arch/arm/cpu/hyp.S
> 
> diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
> index 13fe12c31f6f..f86dff975bb4 100644
> --- a/arch/arm/cpu/Makefile
> +++ b/arch/arm/cpu/Makefile
> @@ -9,6 +9,10 @@ obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o
>  obj-$(CONFIG_MMU) += mmu.o mmu-early.o
>  pbl-$(CONFIG_MMU) += mmu-early.o
>  lwl-y += lowlevel.o
> +obj-y += hyp.o
> +AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> +pbl-y += hyp.o
> +AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
>  endif

For building files regularly and pbl we have obj-pbl-y. Also I would
really prefer to depend that on CONFIG_CPU_32v7

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Thu Apr  5 00:42:24 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 5 Apr 2018 09:42:24 +0200
Subject: [PATCH v3 07/10] ARM: install HYP vectors at PBL and Barebox entry
In-Reply-To: <20180326192025.28809-7-l.stach@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-7-l.stach@pengutronix.de>
Message-ID: <20180405074224.mvjlnvmwfhgmn3m3@pengutronix.de>

On Mon, Mar 26, 2018 at 09:20:22PM +0200, Lucas Stach wrote:
> If the CPU was already in HYP mode when entering the PBL, install a
> simple trap handler to allow to get back from SVC to HYP before
> switching to HYP mode.
> 
> As the vectors are part of the currently running binary, we need to
> do the same setup when starting the real Barebox binary, as the PBL
> setup vectors might get overwritten. To do this we trap into HYP mode
> just before jumping to Barebox and then re-do the vector setup and
> SVC switch as the first thing in Barebox proper.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> ---
>  arch/arm/cpu/lowlevel.S   | 3 +++
>  arch/arm/cpu/start-pbl.c  | 4 ++++
>  arch/arm/cpu/start.c      | 3 +++
>  arch/arm/cpu/uncompress.c | 4 ++++
>  4 files changed, 14 insertions(+)
> 
> diff --git a/arch/arm/cpu/lowlevel.S b/arch/arm/cpu/lowlevel.S
> index 43665981e48b..13dfe496ad17 100644
> --- a/arch/arm/cpu/lowlevel.S
> +++ b/arch/arm/cpu/lowlevel.S
> @@ -8,6 +8,9 @@ ENTRY(arm_cpu_lowlevel_init)
>  	/* save lr, since it may be banked away with a processor mode change */
>  	mov	r2, lr
>  
> +	/* careful: the hyp install corrupts r0 and r1 */
> +	bl	__hyp_install
> +
>  	/* set the cpu to SVC32 mode, mask irq and fiq */
>  	mrs	r12, cpsr
>  	eor	r12, r12, #HYP_MODE
> diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c
> index e851b4a2da5e..e0793579e2e8 100644
> --- a/arch/arm/cpu/start-pbl.c
> +++ b/arch/arm/cpu/start-pbl.c
> @@ -26,6 +26,7 @@
>  #include <asm/barebox-arm-head.h>
>  #include <asm-generic/memory_layout.h>
>  #include <asm/sections.h>
> +#include <asm/secure.h>
>  #include <asm/pgtable.h>
>  #include <asm/cache.h>
>  #include <asm/unaligned.h>
> @@ -100,5 +101,8 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
>  	else
>  		barebox = (void *)barebox_base;
>  
> +	if (__boot_cpu_mode == HYP_MODE)
> +		armv7_switch_to_hyp();
> +
>  	barebox(membase, memsize, boarddata);
>  }
> diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> index 171e6ad0eb7a..a0db6436f387 100644
> --- a/arch/arm/cpu/start.c
> +++ b/arch/arm/cpu/start.c
> @@ -24,6 +24,7 @@
>  #include <asm/barebox-arm-head.h>
>  #include <asm-generic/memory_layout.h>
>  #include <asm/sections.h>
> +#include <asm/secure.h>
>  #include <asm/unaligned.h>
>  #include <asm/cache.h>
>  #include <memory.h>
> @@ -145,6 +146,8 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
>  	unsigned long malloc_start, malloc_end;
>  	unsigned long barebox_size = barebox_image_size + MAX_BSS_SIZE;
>  
> +	armv7_hyp_install();

Calling a armv7 specific function in a generic code path is not so nice.
If this is really necessary then I suggest to #ifdef it here rather than
in the header file (where armv7_hyp_install() expands to a noop for
armv8. And what about the older architectures? A quick test revealed
this works on armv5, but is this intentional or by accident?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Thu Apr  5 00:47:03 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 5 Apr 2018 09:47:03 +0200
Subject: [PATCH v3 04/10] ARM: add file for HYP mode related setup
In-Reply-To: <20180326192025.28809-4-l.stach@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-4-l.stach@pengutronix.de>
Message-ID: <20180405074703.s7jywugclkxd47qm@pengutronix.de>

On Mon, Mar 26, 2018 at 09:20:19PM +0200, Lucas Stach wrote:
> This adds routines to add hyp mode vectors and switch back to HYP
> mode from SVC. This is needed in both the PBL and Barebox proper.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> ---
> v3:
> - fix whitespace
> - use __BARE_INIT
> ---
>  arch/arm/cpu/Makefile         |   4 ++
>  arch/arm/cpu/hyp.S            | 116 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/cpu/sm_as.S          |  11 ----
>  arch/arm/include/asm/secure.h |   8 +++
>  4 files changed, 128 insertions(+), 11 deletions(-)
>  create mode 100644 arch/arm/cpu/hyp.S
> 
> diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
> index 13fe12c31f6f..f86dff975bb4 100644
> --- a/arch/arm/cpu/Makefile
> +++ b/arch/arm/cpu/Makefile
> @@ -9,6 +9,10 @@ obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o
>  obj-$(CONFIG_MMU) += mmu.o mmu-early.o
>  pbl-$(CONFIG_MMU) += mmu-early.o
>  lwl-y += lowlevel.o
> +obj-y += hyp.o
> +AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> +pbl-y += hyp.o
> +AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
>  endif
>  
>  obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o
> diff --git a/arch/arm/cpu/hyp.S b/arch/arm/cpu/hyp.S
> new file mode 100644
> index 000000000000..1314b56eab25
> --- /dev/null
> +++ b/arch/arm/cpu/hyp.S
> @@ -0,0 +1,116 @@
> +#include <linux/linkage.h>
> +#include <asm/system.h>
> +#include <asm/opcodes-virt.h>
> +#include <init.h>
> +
> +.arch_extension sec
> +.arch_extension virt
> +
> +__BARE_INIT
> +
> +.data
> +	.align  2
> +ENTRY(__boot_cpu_mode)
> +	.long   0
> +.text
> +
> +ENTRY(__hyp_install)
> +	mrs	r12, cpsr
> +	and	r12, r12, #MODE_MASK
> +
> +	@ Save the initial CPU state
> +	adr	r0, .L__boot_cpu_mode_offset
> +	ldr	r1, [r0]
> +	str	r12, [r0, r1]
> +
> +	cmp	r12, #HYP_MODE
> +	movne	pc, lr			@ give up if the CPU is not in HYP mode
> +
> +	@ Now install the hypervisor stub:
> +	adr	r12, __hyp_vectors
> +	mcr	p15, 4, r12, c12, c0, 0	@ set hypervisor vector base (HVBAR)
> +
> +	@ Disable all traps, so we don't get any nasty surprise
> +	mov	r12, #0
> +	mcr	p15, 4, r12, c1, c1, 0	@ HCR
> +	mcr	p15, 4, r12, c1, c1, 2	@ HCPTR
> +	mcr	p15, 4, r12, c1, c1, 3	@ HSTR
> +
> +THUMB(	orr	r12, #(1 << 30)	)	@ HSCTLR.TE
> +	mcr	p15, 4, r12, c1, c0, 0	@ HSCTLR
> +
> +	mrc	p15, 4, r12, c1, c1, 1	@ HDCR
> +	and	r12, #0x1f		@ Preserve HPMN
> +	mcr	p15, 4, r12, c1, c1, 1	@ HDCR
> +
> +	@ Make sure NS-SVC is initialised appropriately
> +	mrc	p15, 0, r12, c1, c0, 0	@ SCTLR
> +	orr	r12, #(1 << 5)		@ CP15 barriers enabled
> +	bic	r12, #(3 << 7)		@ Clear SED/ITD for v8 (RES0 for v7)
> +	bic	r12, #(3 << 19)		@ WXN and UWXN disabled
> +	mcr	p15, 0, r12, c1, c0, 0	@ SCTLR
> +
> +	mrc	p15, 0, r12, c0, c0, 0	@ MIDR
> +	mcr	p15, 4, r12, c0, c0, 0	@ VPIDR
> +
> +	mrc	p15, 0, r12, c0, c0, 5	@ MPIDR
> +	mcr	p15, 4, r12, c0, c0, 5	@ VMPIDR
> +	bx	lr
> +ENDPROC(__hyp_install)
> +
> +ENTRY(armv7_hyp_install)
> +	mov	r2, lr
> +
> +	bl	__hyp_install
> +
> +	/* set the cpu to SVC32 mode, mask irq and fiq */
> +	mrs	r12, cpsr
> +	eor	r12, r12, #HYP_MODE
> +	tst	r12, #MODE_MASK
> +	bic	r12, r12, #MODE_MASK
> +	orr	r12, r12, #(PSR_I_BIT | PSR_F_BIT | SVC_MODE)
> +THUMB(	orr	r12, r12, #PSR_T_BIT	)
> +	bne	1f
> +	orr	r12, r12, #PSR_A_BIT
> +	adr	lr, 2f
> +	msr	spsr_cxsf, r12
> +	__MSR_ELR_HYP(14)
> +	__ERET
> +1:	msr	cpsr_c, r12
> +2:
> +	mov	pc, r2
> +ENDPROC(armv7_hyp_install)

armv7_hyp_install does the same as arm_cpu_lowlevel_init().
arm_cpu_lowlevel_init() was called by the board code already, why do you
have to do this again in the generic startup path?

I understand that you have to call __hyp_install in non-pbl code again,
but wouldn't it be sufficient to call only that?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Thu Apr  5 00:54:02 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 5 Apr 2018 09:54:02 +0200
Subject: [PATCH v3 04/10] ARM: add file for HYP mode related setup
In-Reply-To: <20180326192025.28809-4-l.stach@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-4-l.stach@pengutronix.de>
Message-ID: <20180405075402.gbplqqwoubu7cqpg@pengutronix.de>

On Mon, Mar 26, 2018 at 09:20:19PM +0200, Lucas Stach wrote:
> This adds routines to add hyp mode vectors and switch back to HYP
> mode from SVC. This is needed in both the PBL and Barebox proper.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> ---
> v3:
> - fix whitespace
> - use __BARE_INIT
> ---
>  arch/arm/cpu/Makefile         |   4 ++
>  arch/arm/cpu/hyp.S            | 116 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/cpu/sm_as.S          |  11 ----
>  arch/arm/include/asm/secure.h |   8 +++
>  4 files changed, 128 insertions(+), 11 deletions(-)
>  create mode 100644 arch/arm/cpu/hyp.S
> 
> diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
> index 13fe12c31f6f..f86dff975bb4 100644
> --- a/arch/arm/cpu/Makefile
> +++ b/arch/arm/cpu/Makefile
> @@ -9,6 +9,10 @@ obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o
>  obj-$(CONFIG_MMU) += mmu.o mmu-early.o
>  pbl-$(CONFIG_MMU) += mmu-early.o
>  lwl-y += lowlevel.o
> +obj-y += hyp.o
> +AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> +pbl-y += hyp.o
> +AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
>  endif
>  
>  obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o
> diff --git a/arch/arm/cpu/hyp.S b/arch/arm/cpu/hyp.S
> new file mode 100644
> index 000000000000..1314b56eab25
> --- /dev/null
> +++ b/arch/arm/cpu/hyp.S
> @@ -0,0 +1,116 @@
> +#include <linux/linkage.h>
> +#include <asm/system.h>
> +#include <asm/opcodes-virt.h>
> +#include <init.h>
> +
> +.arch_extension sec
> +.arch_extension virt
> +
> +__BARE_INIT
> +
> +.data
> +	.align  2
> +ENTRY(__boot_cpu_mode)
> +	.long   0
> +.text
> +
> +ENTRY(__hyp_install)
> +	mrs	r12, cpsr
> +	and	r12, r12, #MODE_MASK
> +
> +	@ Save the initial CPU state
> +	adr	r0, .L__boot_cpu_mode_offset
> +	ldr	r1, [r0]
> +	str	r12, [r0, r1]

Naa, this won't work. You save the cpsr value in __boot_cpu_mode, but
this variable exists both in PBL and regular barebox, __hyp_install
is called multiple times and cpsr is modified right after saving it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From chf.fritz at googlemail.com  Thu Apr  5 06:15:49 2018
From: chf.fritz at googlemail.com (Christoph Fritz)
Date: Thu, 05 Apr 2018 15:15:49 +0200
Subject: [PATCH] ARM: Add Advantech imx6 board support
Message-ID: <1522934149.24545.3.camel@googlemail.com>

Add support for Advantech i.MX6 SOM named ROM-7421.

Signed-off-by: Christoph Fritz <chf.fritz at googlemail.com>
---
 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/advantech-mx6/Makefile             |   2 +
 arch/arm/boards/advantech-mx6/board.c              |  93 +++++++++
 .../flash-header-advantech-rom-7421.imxcfg         |  73 +++++++
 arch/arm/boards/advantech-mx6/lowlevel.c           |  58 ++++++
 arch/arm/configs/imx_v7_defconfig                  |   1 +
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/imx6dl-advantech-rom-7421.dts         | 227 +++++++++++++++++++++
 arch/arm/mach-imx/Kconfig                          |   6 +
 images/Makefile.imx                                |   5 +
 10 files changed, 467 insertions(+)
 create mode 100644 arch/arm/boards/advantech-mx6/Makefile
 create mode 100644 arch/arm/boards/advantech-mx6/board.c
 create mode 100644 arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
 create mode 100644 arch/arm/boards/advantech-mx6/lowlevel.c
 create mode 100755 arch/arm/dts/imx6dl-advantech-rom-7421.dts

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index ca187cc..521f37d 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -1,4 +1,5 @@
 # keep sorted by CONFIG_* macro name.
+obj-$(CONFIG_MACH_ADVANTECH_ROM_742X)		+= advantech-mx6/
 obj-$(CONFIG_MACH_AFI_GF)			+= afi-gf/
 obj-$(CONFIG_MACH_ANIMEO_IP)			+= animeo_ip/
 obj-$(CONFIG_MACH_ARCHOSG9)			+= archosg9/
diff --git a/arch/arm/boards/advantech-mx6/Makefile b/arch/arm/boards/advantech-mx6/Makefile
new file mode 100644
index 0000000..01c7a25
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/Makefile
@@ -0,0 +1,2 @@
+obj-y += board.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/advantech-mx6/board.c b/arch/arm/boards/advantech-mx6/board.c
new file mode 100644
index 0000000..8686a5e
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/board.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <platform_data/eth-fec.h>
+#include <bootsource.h>
+#include <mach/bbu.h>
+
+static int ar8035_phy_fixup(struct phy_device *dev)
+{
+	u16 val;
+
+	/* Ar803x phy SmartEEE feature cause link status generates glitch,
+	 * which cause ethernet link down/up issue, so disable SmartEEE
+	 */
+	phy_write(dev, 0xd, 0x3);
+	phy_write(dev, 0xe, 0x805d);
+	phy_write(dev, 0xd, 0x4003);
+
+	val = phy_read(dev, 0xe);
+	phy_write(dev, 0xe, val & ~(1 << 8));
+
+	/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+	phy_write(dev, 0xd, 0x7);
+	phy_write(dev, 0xe, 0x8016);
+	phy_write(dev, 0xd, 0x4007);
+
+	val = phy_read(dev, 0xe);
+	val &= 0xffe3;
+	val |= 0x18;
+	phy_write(dev, 0xe, val);
+
+	/* introduce tx clock delay */
+	phy_write(dev, 0x1d, 0x5);
+	val = phy_read(dev, 0x1e);
+	val |= 0x0100;
+	phy_write(dev, 0x1e, val);
+
+	return 0;
+}
+
+static int advantech_mx6_devices_init(void)
+{
+	int ret;
+	char *environment_path, *envdev;
+
+	if (!of_machine_is_compatible("advantech,imx6dl-rom-7421"))
+		return 0;
+
+	phy_register_fixup_for_uid(0x004dd072, 0xffffffef, ar8035_phy_fixup);
+
+	switch (bootsource_get()) {
+	case BOOTSOURCE_MMC:
+		environment_path = basprintf("/chosen/environment-sd%d",
+					     bootsource_get_instance() + 1);
+		envdev = "MMC";
+		break;
+	case BOOTSOURCE_SPI:
+	default:
+		environment_path = basprintf("/chosen/environment-sd4");
+		envdev = "MMC";
+		break;
+	}
+
+	if (environment_path) {
+		ret = of_device_enable_path(environment_path);
+		if (ret < 0)
+			pr_warn("Failed to enable env partition '%s' (%d)\n",
+				environment_path, ret);
+		free(environment_path);
+	}
+
+	pr_notice("Using environment in %s\n", envdev);
+
+	imx6_bbu_internal_mmc_register_handler("mmc3", "/dev/mmc3",
+						BBU_HANDLER_FLAG_DEFAULT);
+
+	return 0;
+}
+device_initcall(advantech_mx6_devices_init);
diff --git a/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
new file mode 100644
index 0000000..611e06b
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
@@ -0,0 +1,73 @@
+soc imx6
+loadaddr 0x10000000
+dcdofs 0x400
+
+wm 32 0x020e0774 0x000C0000
+wm 32 0x020e0754 0x00000000
+wm 32 0x020e04ac 0x00000030
+wm 32 0x020e04b0 0x00000030
+wm 32 0x020e0464 0x00000030
+wm 32 0x020e0490 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e0494 0x00000030
+wm 32 0x020e04a0 0x00000000
+wm 32 0x020e04b4 0x00000030
+wm 32 0x020e04b8 0x00000030
+wm 32 0x020e076c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e04bc 0x00000030
+wm 32 0x020e04c0 0x00000030
+wm 32 0x020e04c4 0x00000030
+wm 32 0x020e04c8 0x00000030
+wm 32 0x020e0760 0x00020000
+wm 32 0x020e0764 0x00000030
+wm 32 0x020e0770 0x00000030
+wm 32 0x020e0778 0x00000030
+wm 32 0x020e077c 0x00000030
+wm 32 0x020e0470 0x00000030
+wm 32 0x020e0474 0x00000030
+wm 32 0x020e0478 0x00000030
+wm 32 0x020e047c 0x00000030
+wm 32 0x021b0800 0xa1390003
+wm 32 0x021b080c 0x001F001F
+wm 32 0x021b0810 0x001F001F
+wm 32 0x021b083c 0x42480248
+wm 32 0x021b0840 0x022C0234
+wm 32 0x021b0848 0x3E404244
+wm 32 0x021b0850 0x30302C30
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+wm 32 0x021b0824 0x33333333
+wm 32 0x021b0828 0x33333333
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b0004 0x0002002D
+wm 32 0x021b0008 0x00333030
+wm 32 0x021b000c 0x3F435333
+wm 32 0x021b0010 0xB68E8B63
+wm 32 0x021b0014 0x01FF00DB
+wm 32 0x021b0018 0x00001740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b002c 0x000026d2
+wm 32 0x021b0030 0x00431023
+wm 32 0x021b0040 0x00000017
+wm 32 0x021b0000 0x83190000
+wm 32 0x021b001c 0x04008032
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x05208030
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b0020 0x00005800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b0004 0x0002556D
+wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
+wm 32 0x020c4068 0x00C03F3F
+wm 32 0x020c406c 0x0030FC03
+wm 32 0x020c4070 0x0FFFC000
+wm 32 0x020c4074 0x3FF00000
+wm 32 0x020c4078 0x00FFF300
+wm 32 0x020c407c 0x0F0000C3
+wm 32 0x020c4080 0x000003FF
+wm 32 0x020e0010 0xF00000CF
+wm 32 0x020e0018 0x007F007F
+wm 32 0x020e001c 0x007F007F
diff --git a/arch/arm/boards/advantech-mx6/lowlevel.c b/arch/arm/boards/advantech-mx6/lowlevel.c
new file mode 100644
index 0000000..5efb91a
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/lowlevel.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <debug_ll.h>
+#include <common.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <image-metadata.h>
+#include <mach/generic.h>
+#include <mach/esdctl.h>
+#include <linux/sizes.h>
+
+static inline void setup_uart(void)
+{
+	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+	writel(0x3, iomuxbase + 0x4c);
+
+	imx6_ungate_all_peripherals();
+	imx6_uart_setup_ll();
+
+	putc_ll('>');
+}
+
+extern char __dtb_imx6dl_advantech_rom_7421_start[];
+
+BAREBOX_IMD_TAG_STRING(advantech_imx6dl_memsize_512M, IMD_TYPE_PARAMETER,
+		       "memsize=512", 0);
+
+ENTRY_FUNCTION(start_advantech_imx6dl_rom_7421, r0, r1, r2)
+{
+	void *fdt;
+
+	imx6_cpu_lowlevel_init();
+
+	arm_setup_stack(0x00920000 - 8);
+
+	IMD_USED(advantech_imx6dl_memsize_512M);
+
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+		setup_uart();
+
+	fdt = __dtb_imx6dl_advantech_rom_7421_start - get_runtime_offset();
+
+	barebox_arm_entry(0x10000000, SZ_512M, fdt);
+}
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 62d6238..b3aac42 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -12,6 +12,7 @@ CONFIG_MACH_TQMA53=y
 CONFIG_MACH_FREESCALE_MX53_VMX53=y
 CONFIG_MACH_PHYTEC_SOM_IMX6=y
 CONFIG_MACH_DFI_FS700_M60=y
+CONFIG_MACH_ADVANTECH_ROM_742X=y
 CONFIG_MACH_GUF_SANTARO=y
 CONFIG_MACH_REALQ7=y
 CONFIG_MACH_GK802=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0526a6f..f094bdb 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -7,6 +7,7 @@ endif
 # created.
 obj- += dummy.o
 
+pbl-dtb-$(CONFIG_MACH_ADVANTECH_ROM_742X) += imx6dl-advantech-rom-7421.dtb.o
 pbl-dtb-$(CONFIG_MACH_AFI_GF) += am335x-afi-gf.dtb.o
 pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
 pbl-dtb-$(CONFIG_MACH_CM_FX6) += imx6dl-cm-fx6.dtb.o imx6q-cm-fx6.dtb.o imx6q-utilite.dtb.o
diff --git a/arch/arm/dts/imx6dl-advantech-rom-7421.dts b/arch/arm/dts/imx6dl-advantech-rom-7421.dts
new file mode 100755
index 0000000..f6dba93
--- /dev/null
+++ b/arch/arm/dts/imx6dl-advantech-rom-7421.dts
@@ -0,0 +1,227 @@
+/*
+ * Copyright(c) 2018 Christoph Fritz <chf.fritz at googlemail.com>
+ *
+ * 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 <dt-bindings/gpio/gpio.h>
+#include <arm/imx6dl.dtsi>
+#include "imx6dl.dtsi"
+
+/ {
+	model = "Advantech i.MX6 ROM-7421";
+	compatible = "advantech,imx6dl-rom-7421", "fsl,imx6dl";
+
+	chosen {
+		linux,stdout-path = &uart1;
+
+		environment-sd2 {			/* Micro SD */
+			compatible = "barebox,environment";
+			device-path = &usdhc2, "partname:barebox-environment";
+			status = "disabled";
+		};
+
+		environment-sd4 {			/* eMMC */
+			compatible = "barebox,environment";
+			device-path = &usdhc4, "partname:barebox-environment";
+			status = "disabled";
+		};
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 0>;
+	status = "okay";
+
+	flash: m25p80 at 0 {
+		compatible = "m25p80";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+		status = "okay";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition at 400 {
+			label = "SPL";
+			reg = <0x400 0xa0000>;
+		};
+
+		partition at d0000 {
+			label = "MAC";
+			reg = <0xd0000 0x1000>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+	fsl,magic-packet;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc2 {					/* Micro SD */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <8>;
+	cd-gpios = <&gpio2 0 0>;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition at 0 {
+		label = "barebox";
+		reg = <0x0 0xe0000>;
+	};
+
+	partition at e0000 {
+		label = "barebox-environment";
+		reg = <0xe0000 0x20000>;
+	};
+};
+
+&usdhc3 {					/* SD Card */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	bus-width = <4>;
+	cd-gpios = <&gpio2 1 0>;
+	en-gpios = <&gpio2 2 0>;
+	wp-gpios = <&gpio2 3 0>;
+	status = "okay";
+};
+
+&usdhc4 {					/* eMMC */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <8>;
+	non-removable;
+	no-1-8-v;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition at 400 {
+		label = "CRC";
+		reg = <0x200000 0x200>;
+	};
+
+	partition at 600 {
+		label = "barebox_CRCed";
+		reg = <0x200200 0x96000>;
+	};
+
+	partition at 96600 {
+		label = "barebox-environment";
+		reg = <0x296200 0x20000>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+
+	imx6dl-advantech-rom-742 {
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x80000000
+			>;
+		};
+
+		pinctrl_enet1: enet1grp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0A0B1
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25	0x80000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		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_NANDF_D0__GPIO2_IO00		0x1b0b0
+			>;
+		};
+
+		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
+				MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+				MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
+			>;
+		};
+
+		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
+			>;
+		};
+	};
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index eb135c3..e4de3d1 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -39,6 +39,7 @@ config ARCH_TEXT_BASE
 	default 0x4fc00000 if MACH_UDOO
 	default 0x4fc00000 if MACH_VARISCITE_MX6
 	default 0x4fc00000 if MACH_PHYTEC_SOM_IMX6
+	default 0x4fc00000 if MACH_ADVANTECH_ROM_742X
 	default 0x9fc00000 if MACH_WARP7
 
 config ARCH_IMX_IMXIMAGE
@@ -383,6 +384,11 @@ config MACH_CM_FX6
 	bool "CM FX6"
 	select ARCH_IMX6
 
+config MACH_ADVANTECH_ROM_742X
+	bool "Advantech ROM 742X"
+	select ARCH_IMX6
+	select ARM_USE_COMPRESSED_DTB
+
 config MACH_WARP7
 	bool "NXP i.MX7: element 14 WaRP7 Board"
 	select ARCH_IMX7
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 5e0043f..131b3f2 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -465,6 +465,11 @@ CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-head
 FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
 image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
 
+pblx-$(CONFIG_MACH_ADVANTECH_ROM_742X) += start_advantech_imx6dl_rom_7421
+CFG_start_advantech_imx6dl_rom_7421.pblx.imximg = $(board)/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
+FILE_barebox-advantech-imx6dl-rom-7421.img = start_advantech_imx6dl_rom_7421.pblx.imximg
+image-$(CONFIG_MACH_ADVANTECH_ROM_742X) += barebox-advantech-imx6dl-rom-7421.img
+
 pblx-$(CONFIG_MACH_WARP7) += start_imx7s_element14_warp7
 CFG_start_imx7s_element14_warp7.pblx.imximg = $(board)/element14-warp7/flash-header-mx7-warp.imxcfg
 FILE_barebox-element14-imx7s-warp7.img = start_imx7s_element14_warp7.pblx.imximg
-- 
2.1.4



From s.hauer at pengutronix.de  Fri Apr  6 05:41:38 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 6 Apr 2018 14:41:38 +0200
Subject: v2018.04.0
Message-ID: <20180406124138.t5o4luk3wkbhw4gp@pengutronix.de>

Hi all,

barebox-2018.04.0 is out. Nothing fundamentally, small improvements
here and there.

Sascha

----------------------------------------------------------------
Aleksander Morgado (9):
      ratp: implement generic command support
      ratp: moved logic to its own subdirectory
      ratp: allow building without full console support
      ratp: implement ping as a standard ratp command
      ratp: implement getenv as a standard ratp command
      ratp: use xstrndup() instead of a custom xmemdup_add_zero()
      ratp: new md and mw commands
      ratp: new reset command
      docs: add reference to libratp-barebox in the remote-control docs

Andreas Schmidt (1):
      net: cpsw: fix probe with fixed-link

Antony Pavlov (1):
      commands: i2c_write: enable raw write to address

Denis 'GNUtoo' Carikli (1):
      Backport "ARM: dts: am335x-bone*: usb0 is hardwired for peripheral" from linux

Enrico Jorns (1):
      efi: add bootsource detection

Eugen Wiens (1):
      console: added colored print out of log levels

Ga?l PORTAY (1):
      fs: check pointer returned by get_fsdevice_by_path before dereferencing

Juergen Borleis (1):
      ARM/i.MX53: fix SDRAM setup routines

Lucas Stach (6):
      watchdog: implement bcm2835 watchdog
      ARM: rpi: enable watchdog in defconfig
      arm: ARM64 doen't provide the armlinux_ functions
      lib: add weak clz/ctz functions
      at91sam9263ek: don't build legacy init when OFDEVICE is enabled
      arm: ARM64 doen't provide the armlinux_ functions

Marc Kleine-Budde (2):
      Makefile.lib: imx hab: fix hab files with embedded variables
      bootm: fit: add option to add DT snipped that contains fit public key

Michael Grzeschik (1):
      mtd: spi-nor: add support for w25q16dw

Oleksij Rempel (5):
      MIPS: add initial qca4531 support
      MIPS: add initial 8devices-lima board
      MIPS: dts: enable heartbeat led for ar9331-dptechnics-dpt-module
      MIPS: ath79: fix different typos
      Documentation: framebuffer: update documentation to current state

Philipp Zabel (2):
      improve soc revision calculation
      of: partition: fix typo when writing #address-cells

Sascha Hauer (34):
      ubiformat: Allow to ubiformat with a buffer given
      usb: gadget: fastboot: Make sparse support optional
      usb: gadget: fastboot: pass struct f_fastboot * around
      usb: gadget: fastboot: use read_file_2
      usb: gadget: fastboot: Always remove temporary file
      usb: gadget: fastboot: fix typo
      usb: gadget: fastboot: beautify fb_run_command()
      usb: gadget: fastboot: Add option to download to a buffer
      usb: gadget: fastboot: Add external command execution support
      ARM: i.MX25: Fix restoring of volatile register
      arm: crypto: initialize digests earlier
      net: cpsw: Call phy_device_connect() earlier
      console: move global.allow_color handling to C code
      Use globalvar_add_simple_string for model and hostname
      ARM/i.MX53: fix compiler warning
      dts: update to v4.15-rc9
      arm: crypto: initialize digests earlier
      dts: update to v4.16-rc1
      dts: update to v4.16-rc2
      of: Make locally used function static
      of: Make locally used function static
      Merge branch 'for-next/arm'
      Merge branch 'for-next/arm-1'
      Merge branch 'for-next/dts'
      Merge branch 'for-next/efi'
      Merge branch 'for-next/fastboot'
      Merge branch 'for-next/imx'
      Merge branch 'for-next/mips'
      Merge branch 'for-next/misc'
      Merge branch 'for-next/ratp'
      Merge branch 'for-next/rpi'
      Revert "startup: Load default environment earlier"
      ARM: zbarebox: Fix linking with new ld
      Release v2018.04.0

Steffen Trumtrar (3):
      ARM: imx25: clk: add rngb clock
      hw_random: add driver for Freescale RNGC
      gitignore: ignore pblx.simximg files

Yegor Yefremov (1):
      DHCP: fix option 54 passing

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Fri Apr  6 06:16:39 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri,  6 Apr 2018 15:16:39 +0200
Subject: [PATCH] net: on ifup -a only detect devices when necessary
Message-ID: <20180406131639.14100-1-s.hauer@pengutronix.de>

For network boot we once used to hardcode eth0, but in latest changes
this was changed to work with different network devices and the 'ifup
eth0' was replaced with 'ifup -a' which lead to the result that we now
detect all devices in order to eventually also bring up USB network
adapters. In most of the cases this is not desired. When a board has
internal network support this is likely to be used. With this patch
we only detect all devices when we do not have a network device already.
For the unusual case in which a USB network adapter shall be used
even when an internal network interface is present we introduce the
global variable "global.net.ifup_force_detect" which can be used to
force detection of devices.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 net/ifup.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/net/ifup.c b/net/ifup.c
index 827c5c03d1..d550f82530 100644
--- a/net/ifup.c
+++ b/net/ifup.c
@@ -28,6 +28,9 @@
 #include <globalvar.h>
 #include <string.h>
 #include <driver.h>
+#include <init.h>
+#include <globalvar.h>
+#include <magicvar.h>
 #include <linux/stat.h>
 
 static int eth_discover(char *file)
@@ -245,6 +248,8 @@ int ifup(const char *ethname, unsigned flags)
 	return ifup_edev(edev, flags);
 }
 
+static int net_ifup_force_detect;
+
 int ifup_all(unsigned flags)
 {
 	struct eth_device *edev;
@@ -266,7 +271,9 @@ int ifup_all(unsigned flags)
 
 	closedir(dir);
 
-	device_detect_all();
+	if ((flags & IFUP_FLAG_FORCE) || net_ifup_force_detect ||
+	    list_empty(&netdev_list))
+		device_detect_all();
 
 	for_each_netdev(edev)
 		ifup_edev(edev, flags);
@@ -274,6 +281,18 @@ int ifup_all(unsigned flags)
 	return 0;
 }
 
+static int ifup_all_init(void)
+{
+	globalvar_add_simple_bool("net.ifup_force_detect", &net_ifup_force_detect);
+
+	return 0;
+}
+late_initcall(ifup_all_init);
+
+BAREBOX_MAGICVAR_NAMED(global_net_ifup_force_detect,
+                       global.net.ifup_force_detect,
+                       "net: force detection of devices on ifup -a");
+
 #if IS_ENABLED(CONFIG_NET_CMD_IFUP)
 
 static int do_ifup(int argc, char *argv[])
-- 
2.16.1



From l.stach at pengutronix.de  Fri Apr  6 08:23:23 2018
From: l.stach at pengutronix.de (Lucas Stach)
Date: Fri,  6 Apr 2018 17:23:23 +0200
Subject: [PATCH] fb: reject enable request when framebuffer has no mode
Message-ID: <20180406152323.16879-1-l.stach@pengutronix.de>

If no display is connected or the display modes are incompatible with
the scanout hardware we might end up with a registered framebuffer with
no modes. Trying to enable such a framebuffer will blow up with NULL
ptr dereferences in various places, so just don't do it.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 drivers/video/fb.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 004df1e604d6..599ac5b75e0a 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -124,6 +124,9 @@ static int fb_enable_set(struct param_d *param, void *priv)
 	struct fb_info *info = priv;
 	int enable;
 
+	if (!info->mode)
+		return -EINVAL;
+
 	enable = info->p_enable;
 
 	if (enable)
-- 
2.16.1



From l.stach at pengutronix.de  Fri Apr  6 08:49:29 2018
From: l.stach at pengutronix.de (Lucas Stach)
Date: Fri,  6 Apr 2018 17:49:29 +0200
Subject: [PATCH] video: IPUv3-LDB: demote dual-channel message to info level
Message-ID: <20180406154929.8604-1-l.stach@pengutronix.de>

Dual channel mode is a valid mode of operation, so there is no reason to
print this at the warning level.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 drivers/video/imx-ipu-v3/imx-ldb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
index 33dbade87007..9b4524274c4e 100644
--- a/drivers/video/imx-ipu-v3/imx-ldb.c
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -347,7 +347,7 @@ static int imx_ldb_probe(struct device_d *dev)
 			return -EINVAL;
 
 		if (dual && i > 0) {
-			dev_warn(dev, "dual-channel mode, ignoring second output\n");
+			dev_info(dev, "dual-channel mode, ignoring second output\n");
 			continue;
 		}
 
-- 
2.16.1



From andrey.gusakov at cogentembedded.com  Fri Apr  6 09:33:22 2018
From: andrey.gusakov at cogentembedded.com (Andrey Gusakov)
Date: Fri,  6 Apr 2018 19:33:22 +0300
Subject: [PATCH 0/2] mfd: mc13xxx: ADC support
Message-ID: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>

This set of pathces adds ADC support for MC13783 and MC13892 PMICs.

Andrey Gusakov (2):
  mfd: mc13xxx: add function returning mc13xxx type
  aiodev: mc13xxx: add adc support

 drivers/aiodev/Kconfig       |   6 ++
 drivers/aiodev/Makefile      |   1 +
 drivers/aiodev/mc13xxx_adc.c | 234 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/mc13xxx.c        |  15 +++
 include/mfd/mc13xxx.h        |  19 ++++
 5 files changed, 275 insertions(+)
 create mode 100644 drivers/aiodev/mc13xxx_adc.c

-- 
1.9.1


From andrey.gusakov at cogentembedded.com  Fri Apr  6 09:33:24 2018
From: andrey.gusakov at cogentembedded.com (Andrey Gusakov)
Date: Fri,  6 Apr 2018 19:33:24 +0300
Subject: [PATCH 2/2] aiodev: mc13xxx: add adc support
In-Reply-To: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>
References: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>
Message-ID: <1523032404-7416-3-git-send-email-andrey.gusakov@cogentembedded.com>

Signed-off-by: Andrey Gusakov <andrey.gusakov at cogentembedded.com>
---
 drivers/aiodev/Kconfig       |   6 ++
 drivers/aiodev/Makefile      |   1 +
 drivers/aiodev/mc13xxx_adc.c | 234 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/mc13xxx.c        |   3 +
 include/mfd/mc13xxx.h        |   9 ++
 5 files changed, 253 insertions(+)
 create mode 100644 drivers/aiodev/mc13xxx_adc.c

diff --git a/drivers/aiodev/Kconfig b/drivers/aiodev/Kconfig
index 1c5fabe..8bad946 100644
--- a/drivers/aiodev/Kconfig
+++ b/drivers/aiodev/Kconfig
@@ -20,4 +20,10 @@ config LM75
 	help
 	  Support for LM75 and similar devices
 
+config MC13XXX_ADC
+	tristate "MC13XXX ADC driver"
+	depends on MFD_MC13XXX
+	help
+	  Support for MC13783, MC13892, MC34708 ADC
+
 endif
diff --git a/drivers/aiodev/Makefile b/drivers/aiodev/Makefile
index c3d2b08..1dcf6cd 100644
--- a/drivers/aiodev/Makefile
+++ b/drivers/aiodev/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_AIODEV) += core.o
 obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
 obj-$(CONFIG_LM75) += lm75.o
+obj-$(CONFIG_MC13XXX_ADC) += mc13xxx_adc.o
diff --git a/drivers/aiodev/mc13xxx_adc.c b/drivers/aiodev/mc13xxx_adc.c
new file mode 100644
index 0000000..4e72048
--- /dev/null
+++ b/drivers/aiodev/mc13xxx_adc.c
@@ -0,0 +1,234 @@
+/*
+ * mc13xxx_adc
+ *
+ * Copyright (c) 2018 Zodiac Inflight Innovation
+ * Author: Andrey Gusakov <andrey.gusakov at cogentembedded.com>
+ * Based on the code of analogous driver from Linux:
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 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 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 <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <aiodev.h>
+#include <mfd/mc13xxx.h>
+#include <linux/err.h>
+
+#define MC13XXX_ADC0_LICELLCON		(1 << 0)
+#define MC13XXX_ADC0_CHRGICON		(1 << 1)
+#define MC13XXX_ADC0_BATICON		(1 << 2)
+#define MC13XXX_ADC0_BUFEN		(1 << 3)
+#define MC13XXX_ADC0_ADIN7SEL_DIE	(1 << 4)
+#define MC13XXX_ADC0_ADIN7SEL_UID	(2 << 4)
+#define MC13XXX_ADC0_ADREFEN		(1 << 10)
+#define MC13XXX_ADC0_TSMOD0		(1 << 12)
+#define MC13XXX_ADC0_TSMOD1		(1 << 13)
+#define MC13XXX_ADC0_TSMOD2		(1 << 14)
+#define MC13XXX_ADC0_ADINC1		(1 << 16)
+#define MC13XXX_ADC0_ADINC2		(1 << 17)
+
+#define MC13XXX_ADC0_TSMOD_MASK		(MC13XXX_ADC0_TSMOD0 | \
+					MC13XXX_ADC0_TSMOD1 | \
+					MC13XXX_ADC0_TSMOD2)
+
+#define MC13XXX_ADC0_CONFIG_MASK	(MC13XXX_ADC0_TSMOD_MASK | \
+					MC13XXX_ADC0_LICELLCON | \
+					MC13XXX_ADC0_CHRGICON | \
+					MC13XXX_ADC0_BATICON)
+
+#define MC13XXX_ADC1_ADEN		(1 << 0)
+#define MC13XXX_ADC1_RAND		(1 << 1)
+#define MC13XXX_ADC1_ADSEL		(1 << 3)
+#define MC13XXX_ADC1_CHAN0_SHIFT	5
+#define MC13XXX_ADC1_CHAN1_SHIFT	8
+#define MC13XXX_ADC1_ASC		(1 << 20)
+#define MC13XXX_ADC1_ADTRIGIGN		(1 << 21)
+
+struct mc13xx_adc_data {
+	struct mc13xxx *mc_dev;
+
+	struct aiodevice aiodev;
+	struct aiochannel *aiochan;
+};
+
+static inline struct mc13xx_adc_data *
+to_mc13xx_adc_data(struct aiochannel *chan)
+{
+	return container_of(chan->aiodev, struct mc13xx_adc_data, aiodev);
+}
+
+int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx,
+		unsigned int channel, unsigned int *sample)
+{
+	int i;
+	int timeout = 100;
+	u32 adc0, adc1, old_adc0;
+
+	mc13xxx_reg_read(mc13xxx, MC13783_REG_ADC(0), &old_adc0);
+
+	adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 | MC13XXX_ADC0_BUFEN;
+	adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
+
+	/* Channels mapped through ADIN7:
+	 * 7  - General purpose ADIN7
+	 * 16 - UID
+	 * 17 - Die temperature */
+	if (channel > 7 && channel < 16) {
+		adc1 |= MC13XXX_ADC1_ADSEL;
+	} else if (channel == 16) {
+		adc0 |= MC13XXX_ADC0_ADIN7SEL_UID;
+		channel = 7;
+	} else if (channel == 17) {
+		adc0 |= MC13XXX_ADC0_ADIN7SEL_DIE;
+		channel = 7;
+	}
+
+	adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
+	adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
+	adc1 |= MC13XXX_ADC1_RAND;
+
+	mc13xxx_reg_write(mc13xxx, MC13783_REG_ADC(0), adc0);
+	mc13xxx_reg_write(mc13xxx, MC13783_REG_ADC(1), adc1);
+
+	/* wait for completion. ASC will set to zero */
+	do {
+		mc13xxx_reg_read(mc13xxx, MC13783_REG_ADC(1), &adc1);
+	} while ((adc1 & MC13XXX_ADC1_ASC) && (--timeout > 0));
+
+	if (timeout == 0)
+		return -ETIMEDOUT;
+
+	for (i = 0; i < 4; ++i) {
+		mc13xxx_reg_read(mc13xxx,
+			MC13783_REG_ADC(2), &sample[i]);
+	}
+
+	return 0;
+}
+
+static int mc13xx_adc_read(struct aiochannel *chan, int *val)
+{
+	int i;
+	int ret;
+	int mc_type;
+	unsigned int sample[4];
+	struct mc13xx_adc_data *mc13xxx_adc;
+	int acc = 0;
+	int index = chan->index;
+
+	mc13xxx_adc = to_mc13xx_adc_data(chan);
+	mc_type = mc13xxx_type(mc13xxx_adc->mc_dev);
+
+	/* add offset for all 8 channel devices becouse t and UID
+	 * inputs are mapped to channels 16 and 17 */
+	if ((mc_type != MC13783_TYPE) && (chan->index > 7))
+		index += 8;
+
+	ret = mc13xxx_adc_do_conversion(mc13xxx_adc->mc_dev, index, sample);
+	if (ret < 0)
+		goto err;
+
+	for (i = 0; i < 4; i++) {
+		acc += (sample[i] >> 2 & 0x3ff);
+		acc += (sample[i] >> 14 & 0x3ff);
+	}
+	/* div 8 */
+	acc = acc >> 3;
+
+	if (index == 16) {
+		/* UID */
+		if (mc_type == MC13892_TYPE) {
+			/* MC13892 have 1/2 divider
+			 * input range is [0, 4.800V] */
+			acc = DIV_ROUND_CLOSEST(acc * 4800, 1024);
+		} else {
+			/* MC13783 have 0.9 divider
+			 *input range is [0, 2.555V] */
+			acc = DIV_ROUND_CLOSEST(acc * 2555, 1024);
+		}
+	} else if (index == 17) {
+		/* Die temperature */
+		if (mc_type == MC13892_TYPE) {
+			/* MC13892:
+			 * Die Temperature Read Out Code at 25C 680
+			 * Temperature change per LSB +0.4244C */
+			acc = DIV_ROUND_CLOSEST(-2635920 + acc * 4244, 10);
+		} else {
+			/* MC13783:
+			 * Die Temperature Read Out Code at 25C 282
+			 * Temperature change per LSB -1.14C */
+			acc = 346480 - 1140 * acc;
+		}
+	} else {
+		/* GP input
+		 * input range is [0, 2.3V], value has 10 bits */
+		acc = DIV_ROUND_CLOSEST(acc * 2300, 1024);
+	}
+
+	*val = acc;
+err:
+	return ret;
+}
+
+int mc13xxx_adc_probe(struct device_d *dev, struct mc13xxx *mc_dev)
+{
+	int i;
+	int ret;
+	int chans;
+	struct mc13xx_adc_data *mc13xxx_adc;
+
+	mc13xxx_adc = xzalloc(sizeof(*mc13xxx_adc));
+
+	if (mc13xxx_type(mc_dev) == MC13783_TYPE) {
+		/* mc13783 has 16 channels */
+		chans = 16 + 2;
+	} else {
+		chans = 8 + 2;
+	}
+
+	mc13xxx_adc->mc_dev = mc_dev;
+	mc13xxx_adc->aiodev.num_channels = chans;
+	mc13xxx_adc->aiochan = xmalloc(mc13xxx_adc->aiodev.num_channels *
+			sizeof(*mc13xxx_adc->aiochan));
+	mc13xxx_adc->aiodev.hwdev = dev;
+	mc13xxx_adc->aiodev.channels =
+		xmalloc(mc13xxx_adc->aiodev.num_channels *
+			sizeof(mc13xxx_adc->aiodev.channels[0]));
+	/* all channels are voltage inputs, expect last one */
+	for (i = 0; i < chans - 1; i++) {
+		mc13xxx_adc->aiodev.channels[i] = &mc13xxx_adc->aiochan[i];
+		mc13xxx_adc->aiochan[i].unit = "mV";
+	}
+	/* temperature input */
+	mc13xxx_adc->aiodev.channels[i] = &mc13xxx_adc->aiochan[i];
+	mc13xxx_adc->aiochan[i].unit = "mC";
+
+	mc13xxx_adc->aiodev.read = mc13xx_adc_read;
+
+	ret = aiodevice_register(&mc13xxx_adc->aiodev);
+	if (!ret)
+		goto done;
+
+	dev_err(dev, "Failed to register AIODEV: %d\n", ret);
+	kfree(mc13xxx_adc);
+done:
+	return ret;
+}
diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c
index 654313f..a5877db 100644
--- a/drivers/mfd/mc13xxx.c
+++ b/drivers/mfd/mc13xxx.c
@@ -364,6 +364,9 @@ static int __init mc13xxx_probe(struct device_d *dev)
 	if (mc13xxx_init_callback)
 		mc13xxx_init_callback(mc_dev);
 
+	if (of_property_read_bool(dev->device_node, "fsl,mc13xxx-uses-adc"))
+		mc13xxx_adc_probe(dev, mc_dev);
+
 	return 0;
 }
 
diff --git a/include/mfd/mc13xxx.h b/include/mfd/mc13xxx.h
index 66ce2ea..b389180 100644
--- a/include/mfd/mc13xxx.h
+++ b/include/mfd/mc13xxx.h
@@ -215,4 +215,13 @@ static inline int mc13xxx_register_init_callback(void(*callback)(struct mc13xxx
 }
 #endif
 
+#ifdef CONFIG_MC13XXX_ADC
+int mc13xxx_adc_probe(struct device_d *dev, struct mc13xxx *mc_dev);
+#else
+static inline int mc13xxx_adc_probe(struct device_d *dev, struct mc13xxx *mc_dev)
+{
+	return 0;
+}
+#endif
+
 #endif /* __MFD_MC13XXX_H */
-- 
1.9.1



From andrey.gusakov at cogentembedded.com  Fri Apr  6 09:33:23 2018
From: andrey.gusakov at cogentembedded.com (Andrey Gusakov)
Date: Fri,  6 Apr 2018 19:33:23 +0300
Subject: [PATCH 1/2] mfd: mc13xxx: add function returning mc13xxx type
In-Reply-To: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>
References: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>
Message-ID: <1523032404-7416-2-git-send-email-andrey.gusakov@cogentembedded.com>

Signed-off-by: Andrey Gusakov <andrey.gusakov at cogentembedded.com>
---
 drivers/mfd/mc13xxx.c | 12 ++++++++++++
 include/mfd/mc13xxx.h | 10 ++++++++++
 2 files changed, 22 insertions(+)

diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c
index f6aa922..654313f 100644
--- a/drivers/mfd/mc13xxx.c
+++ b/drivers/mfd/mc13xxx.c
@@ -40,10 +40,12 @@ struct mc13xxx {
 		struct spi_device	*spi;
 	};
 	int				revision;
+	int				type;
 };
 
 struct mc13xxx_devtype {
 	int	(*revision)(struct mc13xxx*);
+	int	type;
 };
 
 #define to_mc13xxx(a)		container_of(a, struct mc13xxx, cdev)
@@ -56,6 +58,12 @@ struct mc13xxx *mc13xxx_get(void)
 }
 EXPORT_SYMBOL(mc13xxx_get);
 
+int mc13xxx_type(struct mc13xxx *mc13xxx)
+{
+	return mc13xxx->type;
+}
+EXPORT_SYMBOL(mc13xxx_type);
+
 int mc13xxx_revision(struct mc13xxx *mc13xxx)
 {
 	return mc13xxx->revision;
@@ -347,6 +355,7 @@ static int __init mc13xxx_probe(struct device_d *dev)
 	}
 
 	mc_dev->revision = rev;
+	mc_dev->type = devtype->type;
 
 	ret = regmap_register_cdev(mc_dev->map, NULL);
 	if (ret)
@@ -360,14 +369,17 @@ static int __init mc13xxx_probe(struct device_d *dev)
 
 static struct mc13xxx_devtype mc13783_devtype = {
 	.revision	= mc13783_revision,
+	.type		= MC13783_TYPE,
 };
 
 static struct mc13xxx_devtype mc13892_devtype = {
 	.revision	= mc13892_revision,
+	.type		= MC13892_TYPE,
 };
 
 static struct mc13xxx_devtype mc34708_devtype = {
 	.revision	= mc34708_revision,
+	.type		= MC34708_TYPE,
 };
 
 static struct platform_device_id mc13xxx_ids[] = {
diff --git a/include/mfd/mc13xxx.h b/include/mfd/mc13xxx.h
index d351c47..66ce2ea 100644
--- a/include/mfd/mc13xxx.h
+++ b/include/mfd/mc13xxx.h
@@ -16,6 +16,10 @@
 
 #define MC13XXX_REG_IDENTIFICATION	0x07
 
+#define MC13783_TYPE			1
+#define MC13892_TYPE			2
+#define MC34708_TYPE			3
+
 #define MC13783_REG_INT_STATUS0		0x00
 #define MC13783_REG_INT_MASK0		0x01
 #define MC13783_REG_INT_SENSE0		0x02
@@ -168,6 +172,7 @@ struct mc13xxx;
 
 #ifdef CONFIG_MFD_MC13XXX
 extern struct mc13xxx *mc13xxx_get(void);
+extern int mc13xxx_type(struct mc13xxx *mc13xxx);
 extern int mc13xxx_revision(struct mc13xxx *mc13xxx);
 extern int mc13xxx_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val);
 extern int mc13xxx_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val);
@@ -179,6 +184,11 @@ static inline struct mc13xxx *mc13xxx_get(void)
 	return NULL;
 }
 
+static inline int mc13xxx_type(struct mc13xxx *mc13xxx)
+{
+	return -ENODEV;
+}
+
 static inline int mc13xxx_revision(struct mc13xxx *mc13xxx)
 {
 	return -ENODEV;
-- 
1.9.1



From s.hauer at pengutronix.de  Fri Apr  6 12:21:34 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 6 Apr 2018 21:21:34 +0200
Subject: [PATCH] ARM: Add Advantech imx6 board support
In-Reply-To: <1522934149.24545.3.camel@googlemail.com>
References: <1522934149.24545.3.camel@googlemail.com>
Message-ID: <20180406192134.bqnu3gpf2w33matc@pengutronix.de>

Hi Christoph,

On Thu, Apr 05, 2018 at 03:15:49PM +0200, Christoph Fritz wrote:
> +	phy_register_fixup_for_uid(0x004dd072, 0xffffffef, ar8035_phy_fixup);
> +
> +	switch (bootsource_get()) {
> +	case BOOTSOURCE_MMC:
> +		environment_path = basprintf("/chosen/environment-sd%d",
> +					     bootsource_get_instance() + 1);
> +		envdev = "MMC";
> +		break;
> +	case BOOTSOURCE_SPI:
> +	default:
> +		environment_path = basprintf("/chosen/environment-sd4");
> +		envdev = "MMC";
> +		break;
> +	}
> +
> +	if (environment_path) {
> +		ret = of_device_enable_path(environment_path);
> +		if (ret < 0)
> +			pr_warn("Failed to enable env partition '%s' (%d)\n",
> +				environment_path, ret);
> +		free(environment_path);
> +	}
> +
> +	pr_notice("Using environment in %s\n", envdev);

This is always "MMC", not very informative. Maybe "eMMC" and "external
SD"?

> +
> +	imx6_bbu_internal_mmc_register_handler("mmc3", "/dev/mmc3",
> +						BBU_HANDLER_FLAG_DEFAULT);

That would be the eMMC, right? For this I can recommend putting barebox
into the boot partitions of the eMMC. Normally there are two of them
and with imx6_bbu_internal_mmcboot_register_handler() you even get a
robust barebox A/B update mechanism.

> +
> +	return 0;
> +}
> +device_initcall(advantech_mx6_devices_init);
> diff --git a/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> new file mode 100644
> index 0000000..611e06b
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> @@ -0,0 +1,73 @@
> +soc imx6
> +loadaddr 0x10000000
> +dcdofs 0x400
> +
> +wm 32 0x020e0774 0x000C0000

[...]

> +wm 32 0x021b0004 0x0002556D
> +wm 32 0x021b0404 0x00011006
> +wm 32 0x021b001c 0x00000000

> +wm 32 0x020c4068 0x00C03F3F
> +wm 32 0x020c406c 0x0030FC03
> +wm 32 0x020c4070 0x0FFFC000
> +wm 32 0x020c4074 0x3FF00000
> +wm 32 0x020c4078 0x00FFF300
> +wm 32 0x020c407c 0x0F0000C3
> +wm 32 0x020c4080 0x000003FF

Please remove writing these clock registers here. The registers get
overwritten in a few moments by barebox anyway. Often enough these gate
settings disable the USB clocks and then booting this image from USB is
no longer possible.

> +wm 32 0x020e0010 0xF00000CF
> +wm 32 0x020e0018 0x007F007F
> +wm 32 0x020e001c 0x007F007F
> diff --git a/arch/arm/boards/advantech-mx6/lowlevel.c b/arch/arm/boards/advantech-mx6/lowlevel.c
> new file mode 100644
> index 0000000..5efb91a
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/lowlevel.c
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <debug_ll.h>
> +#include <common.h>
> +#include <asm/barebox-arm-head.h>
> +#include <asm/barebox-arm.h>
> +#include <image-metadata.h>
> +#include <mach/generic.h>
> +#include <mach/esdctl.h>
> +#include <linux/sizes.h>
> +
> +static inline void setup_uart(void)
> +{
> +	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
> +
> +	writel(0x3, iomuxbase + 0x4c);
> +
> +	imx6_ungate_all_peripherals();
> +	imx6_uart_setup_ll();
> +
> +	putc_ll('>');
> +}
> +
> +extern char __dtb_imx6dl_advantech_rom_7421_start[];
> +
> +BAREBOX_IMD_TAG_STRING(advantech_imx6dl_memsize_512M, IMD_TYPE_PARAMETER,
> +		       "memsize=512", 0);
> +
> +ENTRY_FUNCTION(start_advantech_imx6dl_rom_7421, r0, r1, r2)
> +{
> +	void *fdt;
> +
> +	imx6_cpu_lowlevel_init();
> +
> +	arm_setup_stack(0x00920000 - 8);
> +
> +	IMD_USED(advantech_imx6dl_memsize_512M);
> +
> +	if (IS_ENABLED(CONFIG_DEBUG_LL))
> +		setup_uart();
> +
> +	fdt = __dtb_imx6dl_advantech_rom_7421_start - get_runtime_offset();

Since "a43e2bbc46 ARM: return positive offset in get_runtime_offset()"
this must be '+' get_runtime_offset();

> +#include <dt-bindings/gpio/gpio.h>
> +#include <arm/imx6dl.dtsi>
> +#include "imx6dl.dtsi"
> +
> +/ {
> +	model = "Advantech i.MX6 ROM-7421";
> +	compatible = "advantech,imx6dl-rom-7421", "fsl,imx6dl";
> +
> +	chosen {
> +		linux,stdout-path = &uart1;

just stdout-path. linux,stdout-path is the old binding.

> +
> +		environment-sd2 {			/* Micro SD */
> +			compatible = "barebox,environment";
> +			device-path = &usdhc2, "partname:barebox-environment";
> +			status = "disabled";
> +		};
> +
> +		environment-sd4 {			/* eMMC */
> +			compatible = "barebox,environment";
> +			device-path = &usdhc4, "partname:barebox-environment";
> +			status = "disabled";
> +		};
> +	};
> +};
> +
> +&ecspi1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_ecspi1>;
> +	fsl,spi-num-chipselects = <1>;
> +	cs-gpios = <&gpio3 19 0>;
> +	status = "okay";
> +
> +	flash: m25p80 at 0 {
> +		compatible = "m25p80";
> +		spi-max-frequency = <20000000>;
> +		reg = <0>;
> +		status = "okay";
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		partition at 400 {
> +			label = "SPL";
> +			reg = <0x400 0xa0000>;
> +		};
> +
> +		partition at d0000 {
> +			label = "MAC";
> +			reg = <0xd0000 0x1000>;
> +		};

What's in the free space? If you can use the space up to 0xd0000 then
you could put a full barebox before it instead of just a SPL (I guess
this partitioning comes from the original vendor, right?)

> +	};
> +};
> +
> +&usdhc4 {					/* eMMC */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usdhc4>;
> +	bus-width = <8>;
> +	non-removable;
> +	no-1-8-v;
> +	status = "okay";
> +
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	partition at 400 {
> +		label = "CRC";
> +		reg = <0x200000 0x200>;
> +	};
> +
> +	partition at 600 {
> +		label = "barebox_CRCed";
> +		reg = <0x200200 0x96000>;
> +	};
> +
> +	partition at 96600 {
> +		label = "barebox-environment";
> +		reg = <0x296200 0x20000>;
> +	};

the @adr in the partition names do not match the actual start of the
partitions, this should be fixed. Overall the partitions look strange.
Aren't barebox_CRCed and barebox-environment in somewhere in the middle
of the device which is already occupied by the regular partitions?

> +};
> +
> +&iomuxc {
> +	pinctrl-names = "default";
> +
> +	imx6dl-advantech-rom-742 {

This additional subnode is obsolete, please remove and move the pinctrl
nodes one level up.

> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index eb135c3..e4de3d1 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -39,6 +39,7 @@ config ARCH_TEXT_BASE
>  	default 0x4fc00000 if MACH_UDOO
>  	default 0x4fc00000 if MACH_VARISCITE_MX6
>  	default 0x4fc00000 if MACH_PHYTEC_SOM_IMX6
> +	default 0x4fc00000 if MACH_ADVANTECH_ROM_742X

You shouldn't need this.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From l.stach at pengutronix.de  Fri Apr  6 12:33:37 2018
From: l.stach at pengutronix.de (Lucas Stach)
Date: Fri, 06 Apr 2018 21:33:37 +0200
Subject: [PATCH] net: on ifup -a only detect devices when necessary
In-Reply-To: <20180406131639.14100-1-s.hauer@pengutronix.de>
References: <20180406131639.14100-1-s.hauer@pengutronix.de>
Message-ID: <1523043217.12903.5.camel@pengutronix.de>

Am Freitag, den 06.04.2018, 15:16 +0200 schrieb Sascha Hauer:
> For network boot we once used to hardcode eth0, but in latest changes
> this was changed to work with different network devices and the 'ifup
> eth0' was replaced with 'ifup -a' which lead to the result that we
> now
> detect all devices in order to eventually also bring up USB network
> adapters. In most of the cases this is not desired. When a board has
> internal network support this is likely to be used. With this patch
> we only detect all devices when we do not have a network device
> already.
> For the unusual case in which a USB network adapter shall be used
> even when an internal network interface is present we introduce the
> global variable "global.net.ifup_force_detect" which can be used to
> force detection of devices.

This may warrant some more documentation. Without the code change and
the above commit message, the variable doc isn't too verbose about what
it does exactly.

Otherwise I love this change, it makes ifup -a much more useful.

Regards,
Lucas

> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  net/ifup.c | 21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/net/ifup.c b/net/ifup.c
> index 827c5c03d1..d550f82530 100644
> --- a/net/ifup.c
> +++ b/net/ifup.c
> @@ -28,6 +28,9 @@
>  #include <globalvar.h>
>  #include <string.h>
>  #include <driver.h>
> +#include <init.h>
> +#include <globalvar.h>
> +#include <magicvar.h>
>  #include <linux/stat.h>
>  
>  static int eth_discover(char *file)
> @@ -245,6 +248,8 @@ int ifup(const char *ethname, unsigned flags)
>  	return ifup_edev(edev, flags);
>  }
>  
> +static int net_ifup_force_detect;
> +
>  int ifup_all(unsigned flags)
>  {
>  	struct eth_device *edev;
> @@ -266,7 +271,9 @@ int ifup_all(unsigned flags)
>  
>  	closedir(dir);
>  
> -	device_detect_all();
> +	if ((flags & IFUP_FLAG_FORCE) || net_ifup_force_detect ||
> +	    list_empty(&netdev_list))
> +		device_detect_all();
>  
>  	for_each_netdev(edev)
>  		ifup_edev(edev, flags);
> @@ -274,6 +281,18 @@ int ifup_all(unsigned flags)
>  	return 0;
>  }
>  
> +static int ifup_all_init(void)
> +{
> +	globalvar_add_simple_bool("net.ifup_force_detect",
> &net_ifup_force_detect);
> +
> +	return 0;
> +}
> +late_initcall(ifup_all_init);
> +
> +BAREBOX_MAGICVAR_NAMED(global_net_ifup_force_detect,
> +                       global.net.ifup_force_detect,
> +                       "net: force detection of devices on ifup
> -a");
> +
>  #if IS_ENABLED(CONFIG_NET_CMD_IFUP)
>  
>  static int do_ifup(int argc, char *argv[])


From andrew.smirnov at gmail.com  Fri Apr  6 13:05:06 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 6 Apr 2018 13:05:06 -0700
Subject: [PATCH] ARM: Add Advantech imx6 board support
In-Reply-To: <1522934149.24545.3.camel@googlemail.com>
References: <1522934149.24545.3.camel@googlemail.com>
Message-ID: <CAHQ1cqFnNum_jgC_R-TxB3Y0+SU-68eny3Zq=YkSCmz9a=jFSw@mail.gmail.com>

On Thu, Apr 5, 2018 at 6:15 AM, Christoph Fritz
<chf.fritz at googlemail.com> wrote:
> Add support for Advantech i.MX6 SOM named ROM-7421.
>

I don't have any serious comments about this, just a bunch of nits below.

> Signed-off-by: Christoph Fritz <chf.fritz at googlemail.com>
> ---
>  arch/arm/boards/Makefile                           |   1 +
>  arch/arm/boards/advantech-mx6/Makefile             |   2 +
>  arch/arm/boards/advantech-mx6/board.c              |  93 +++++++++
>  .../flash-header-advantech-rom-7421.imxcfg         |  73 +++++++
>  arch/arm/boards/advantech-mx6/lowlevel.c           |  58 ++++++
>  arch/arm/configs/imx_v7_defconfig                  |   1 +
>  arch/arm/dts/Makefile                              |   1 +
>  arch/arm/dts/imx6dl-advantech-rom-7421.dts         | 227 +++++++++++++++++++++
>  arch/arm/mach-imx/Kconfig                          |   6 +
>  images/Makefile.imx                                |   5 +
>  10 files changed, 467 insertions(+)
>  create mode 100644 arch/arm/boards/advantech-mx6/Makefile
>  create mode 100644 arch/arm/boards/advantech-mx6/board.c
>  create mode 100644 arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
>  create mode 100644 arch/arm/boards/advantech-mx6/lowlevel.c
>  create mode 100755 arch/arm/dts/imx6dl-advantech-rom-7421.dts
>
> diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
> index ca187cc..521f37d 100644
> --- a/arch/arm/boards/Makefile
> +++ b/arch/arm/boards/Makefile
> @@ -1,4 +1,5 @@
>  # keep sorted by CONFIG_* macro name.
> +obj-$(CONFIG_MACH_ADVANTECH_ROM_742X)          += advantech-mx6/
>  obj-$(CONFIG_MACH_AFI_GF)                      += afi-gf/
>  obj-$(CONFIG_MACH_ANIMEO_IP)                   += animeo_ip/
>  obj-$(CONFIG_MACH_ARCHOSG9)                    += archosg9/
> diff --git a/arch/arm/boards/advantech-mx6/Makefile b/arch/arm/boards/advantech-mx6/Makefile
> new file mode 100644
> index 0000000..01c7a25
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/Makefile
> @@ -0,0 +1,2 @@
> +obj-y += board.o
> +lwl-y += lowlevel.o
> diff --git a/arch/arm/boards/advantech-mx6/board.c b/arch/arm/boards/advantech-mx6/board.c
> new file mode 100644
> index 0000000..8686a5e
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/board.c
> @@ -0,0 +1,93 @@
> +/*
> + * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <platform_data/eth-fec.h>
> +#include <bootsource.h>
> +#include <mach/bbu.h>
> +
> +static int ar8035_phy_fixup(struct phy_device *dev)
> +{
> +       u16 val;
> +
> +       /* Ar803x phy SmartEEE feature cause link status generates glitch,
> +        * which cause ethernet link down/up issue, so disable SmartEEE
> +        */
> +       phy_write(dev, 0xd, 0x3);
> +       phy_write(dev, 0xe, 0x805d);
> +       phy_write(dev, 0xd, 0x4003);
> +
> +       val = phy_read(dev, 0xe);
> +       phy_write(dev, 0xe, val & ~(1 << 8));
> +

BIT(8)?

> +       /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
> +       phy_write(dev, 0xd, 0x7);
> +       phy_write(dev, 0xe, 0x8016);
> +       phy_write(dev, 0xd, 0x4007);
> +
> +       val = phy_read(dev, 0xe);
> +       val &= 0xffe3;
> +       val |= 0x18;
> +       phy_write(dev, 0xe, val);
> +
> +       /* introduce tx clock delay */
> +       phy_write(dev, 0x1d, 0x5);
> +       val = phy_read(dev, 0x1e);
> +       val |= 0x0100;
> +       phy_write(dev, 0x1e, val);
> +
> +       return 0;
> +}
> +
> +static int advantech_mx6_devices_init(void)
> +{
> +       int ret;
> +       char *environment_path, *envdev;
> +
> +       if (!of_machine_is_compatible("advantech,imx6dl-rom-7421"))
> +               return 0;
> +
> +       phy_register_fixup_for_uid(0x004dd072, 0xffffffef, ar8035_phy_fixup);
> +
> +       switch (bootsource_get()) {
> +       case BOOTSOURCE_MMC:
> +               environment_path = basprintf("/chosen/environment-sd%d",
> +                                            bootsource_get_instance() + 1);
> +               envdev = "MMC";
> +               break;
> +       case BOOTSOURCE_SPI:
> +       default:
> +               environment_path = basprintf("/chosen/environment-sd4");
> +               envdev = "MMC";
> +               break;
> +       }
> +
> +       if (environment_path) {
> +               ret = of_device_enable_path(environment_path);
> +               if (ret < 0)
> +                       pr_warn("Failed to enable env partition '%s' (%d)\n",
> +                               environment_path, ret);
> +               free(environment_path);
> +       }
> +
> +       pr_notice("Using environment in %s\n", envdev);
> +
> +       imx6_bbu_internal_mmc_register_handler("mmc3", "/dev/mmc3",
> +                                               BBU_HANDLER_FLAG_DEFAULT);
> +
> +       return 0;
> +}
> +device_initcall(advantech_mx6_devices_init);
> diff --git a/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> new file mode 100644
> index 0000000..611e06b
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> @@ -0,0 +1,73 @@
> +soc imx6
> +loadaddr 0x10000000
> +dcdofs 0x400
> +
> +wm 32 0x020e0774 0x000C0000
> +wm 32 0x020e0754 0x00000000
> +wm 32 0x020e04ac 0x00000030
> +wm 32 0x020e04b0 0x00000030
> +wm 32 0x020e0464 0x00000030
> +wm 32 0x020e0490 0x00000030
> +wm 32 0x020e074c 0x00000030
> +wm 32 0x020e0494 0x00000030
> +wm 32 0x020e04a0 0x00000000
> +wm 32 0x020e04b4 0x00000030
> +wm 32 0x020e04b8 0x00000030
> +wm 32 0x020e076c 0x00000030
> +wm 32 0x020e0750 0x00020000
> +wm 32 0x020e04bc 0x00000030
> +wm 32 0x020e04c0 0x00000030
> +wm 32 0x020e04c4 0x00000030
> +wm 32 0x020e04c8 0x00000030
> +wm 32 0x020e0760 0x00020000
> +wm 32 0x020e0764 0x00000030
> +wm 32 0x020e0770 0x00000030
> +wm 32 0x020e0778 0x00000030
> +wm 32 0x020e077c 0x00000030
> +wm 32 0x020e0470 0x00000030
> +wm 32 0x020e0474 0x00000030
> +wm 32 0x020e0478 0x00000030
> +wm 32 0x020e047c 0x00000030
> +wm 32 0x021b0800 0xa1390003
> +wm 32 0x021b080c 0x001F001F
> +wm 32 0x021b0810 0x001F001F
> +wm 32 0x021b083c 0x42480248
> +wm 32 0x021b0840 0x022C0234
> +wm 32 0x021b0848 0x3E404244
> +wm 32 0x021b0850 0x30302C30
> +wm 32 0x021b081c 0x33333333
> +wm 32 0x021b0820 0x33333333
> +wm 32 0x021b0824 0x33333333
> +wm 32 0x021b0828 0x33333333
> +wm 32 0x021b08b8 0x00000800
> +wm 32 0x021b0004 0x0002002D
> +wm 32 0x021b0008 0x00333030
> +wm 32 0x021b000c 0x3F435333
> +wm 32 0x021b0010 0xB68E8B63
> +wm 32 0x021b0014 0x01FF00DB
> +wm 32 0x021b0018 0x00001740
> +wm 32 0x021b001c 0x00008000
> +wm 32 0x021b002c 0x000026d2
> +wm 32 0x021b0030 0x00431023
> +wm 32 0x021b0040 0x00000017
> +wm 32 0x021b0000 0x83190000
> +wm 32 0x021b001c 0x04008032
> +wm 32 0x021b001c 0x00008033
> +wm 32 0x021b001c 0x00048031
> +wm 32 0x021b001c 0x05208030
> +wm 32 0x021b001c 0x04008040
> +wm 32 0x021b0020 0x00005800
> +wm 32 0x021b0818 0x00011117
> +wm 32 0x021b0004 0x0002556D
> +wm 32 0x021b0404 0x00011006
> +wm 32 0x021b001c 0x00000000
> +wm 32 0x020c4068 0x00C03F3F
> +wm 32 0x020c406c 0x0030FC03
> +wm 32 0x020c4070 0x0FFFC000
> +wm 32 0x020c4074 0x3FF00000
> +wm 32 0x020c4078 0x00FFF300
> +wm 32 0x020c407c 0x0F0000C3
> +wm 32 0x020c4080 0x000003FF
> +wm 32 0x020e0010 0xF00000CF
> +wm 32 0x020e0018 0x007F007F
> +wm 32 0x020e001c 0x007F007F
> diff --git a/arch/arm/boards/advantech-mx6/lowlevel.c b/arch/arm/boards/advantech-mx6/lowlevel.c
> new file mode 100644
> index 0000000..5efb91a
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/lowlevel.c
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <debug_ll.h>
> +#include <common.h>
> +#include <asm/barebox-arm-head.h>
> +#include <asm/barebox-arm.h>
> +#include <image-metadata.h>
> +#include <mach/generic.h>
> +#include <mach/esdctl.h>
> +#include <linux/sizes.h>
> +
> +static inline void setup_uart(void)
> +{
> +       void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
> +
> +       writel(0x3, iomuxbase + 0x4c);

You could use imx_setup_pad(iomuxbase,
MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA) instead here (I might have
gotten the pad constant that you need wrong).

> +
> +       imx6_ungate_all_peripherals();
> +       imx6_uart_setup_ll();
> +
> +       putc_ll('>');
> +}
> +
> +extern char __dtb_imx6dl_advantech_rom_7421_start[];
> +
> +BAREBOX_IMD_TAG_STRING(advantech_imx6dl_memsize_512M, IMD_TYPE_PARAMETER,
> +                      "memsize=512", 0);
> +
> +ENTRY_FUNCTION(start_advantech_imx6dl_rom_7421, r0, r1, r2)
> +{
> +       void *fdt;
> +
> +       imx6_cpu_lowlevel_init();
> +
> +       arm_setup_stack(0x00920000 - 8);
> +

Is this stack setup really needed? It'll be overridden as part of
barebox_arm_entry() a few lines below and the rest of the code doesn't
seem complicated enough to not warrant initializing the stack here.

> +       IMD_USED(advantech_imx6dl_memsize_512M);
> +
> +       if (IS_ENABLED(CONFIG_DEBUG_LL))
> +               setup_uart();
> +
> +       fdt = __dtb_imx6dl_advantech_rom_7421_start - get_runtime_offset();
> +
> +       barebox_arm_entry(0x10000000, SZ_512M, fdt);

imx6q_barebox_entry(fdt) instead?

Thanks,
Andrey Smirnov


From s.hauer at pengutronix.de  Sun Apr  8 23:51:05 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Apr 2018 08:51:05 +0200
Subject: [PATCH] net: on ifup -a only detect devices when necessary
In-Reply-To: <1523043217.12903.5.camel@pengutronix.de>
References: <20180406131639.14100-1-s.hauer@pengutronix.de>
 <1523043217.12903.5.camel@pengutronix.de>
Message-ID: <20180409065105.ew2jszpd35rpncqw@pengutronix.de>

On Fri, Apr 06, 2018 at 09:33:37PM +0200, Lucas Stach wrote:
> Am Freitag, den 06.04.2018, 15:16 +0200 schrieb Sascha Hauer:
> > For network boot we once used to hardcode eth0, but in latest changes
> > this was changed to work with different network devices and the 'ifup
> > eth0' was replaced with 'ifup -a' which lead to the result that we
> > now
> > detect all devices in order to eventually also bring up USB network
> > adapters. In most of the cases this is not desired. When a board has
> > internal network support this is likely to be used. With this patch
> > we only detect all devices when we do not have a network device
> > already.
> > For the unusual case in which a USB network adapter shall be used
> > even when an internal network interface is present we introduce the
> > global variable "global.net.ifup_force_detect" which can be used to
> > force detection of devices.
> 
> This may warrant some more documentation. Without the code change and
> the above commit message, the variable doc isn't too verbose about what
> it does exactly.

You're right. I added the following to the docs:

 +------------------------------+--------------+------------------------------------------------+
 | global.net.ifup_force_detect | boolean      | Set to true if your network device is not      |
 |                              |              | detected automatically during start (i.e. for  |
 |                              |              | USB network adapters)                          |
 +------------------------------+--------------+------------------------------------------------+

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr  8 23:55:21 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Apr 2018 08:55:21 +0200
Subject: [PATCH 61/78] ARM: aarch64: mmu: Make zero page faulting
In-Reply-To: <CAHQ1cqEAim+g-NWynFYkX_0MeB9PYzOiXPFiV5=uyfzqnDBy8A@mail.gmail.com>
References: <20180316125354.23462-1-s.hauer@pengutronix.de>
 <20180316125354.23462-62-s.hauer@pengutronix.de>
 <CAHQ1cqEAim+g-NWynFYkX_0MeB9PYzOiXPFiV5=uyfzqnDBy8A@mail.gmail.com>
Message-ID: <20180409065521.xdup45765li67d4w@pengutronix.de>

Hi Andrey,

On Tue, Mar 20, 2018 at 09:53:56PM -0700, Andrey Smirnov wrote:
> On Fri, Mar 16, 2018 at 5:53 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > Make zero page faulting which allows us to catch NULL pointer derefs.
> >
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > ---
> >  arch/arm/cpu/mmu_64.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c
> > index 20f6c387f3..094bc0ac62 100644
> > --- a/arch/arm/cpu/mmu_64.c
> > +++ b/arch/arm/cpu/mmu_64.c
> > @@ -316,6 +316,8 @@ static int mmu_init(void)
> >         for_each_memory_bank(bank)
> >                 create_sections(bank->start, bank->start, bank->size, CACHED_MEM);
> >
> > +       create_sections(0x0, 0x0, 0x1000, 0x0);
> 
> Sascha:
> 
> Maybe add commit message as comment to the line above as well?

Sorry, somehow I ended up ignoring this mail. I added a separate patch
adding a comment.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr  8 23:57:02 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Apr 2018 08:57:02 +0200
Subject: [PATCH] fb: reject enable request when framebuffer has no mode
In-Reply-To: <20180406152323.16879-1-l.stach@pengutronix.de>
References: <20180406152323.16879-1-l.stach@pengutronix.de>
Message-ID: <20180409065702.566dt7ylvg6qpdmn@pengutronix.de>

On Fri, Apr 06, 2018 at 05:23:23PM +0200, Lucas Stach wrote:
> If no display is connected or the display modes are incompatible with
> the scanout hardware we might end up with a registered framebuffer with
> no modes. Trying to enable such a framebuffer will blow up with NULL
> ptr dereferences in various places, so just don't do it.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> ---
>  drivers/video/fb.c | 3 +++
>  1 file changed, 3 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/video/fb.c b/drivers/video/fb.c
> index 004df1e604d6..599ac5b75e0a 100644
> --- a/drivers/video/fb.c
> +++ b/drivers/video/fb.c
> @@ -124,6 +124,9 @@ static int fb_enable_set(struct param_d *param, void *priv)
>  	struct fb_info *info = priv;
>  	int enable;
>  
> +	if (!info->mode)
> +		return -EINVAL;
> +
>  	enable = info->p_enable;
>  
>  	if (enable)
> -- 
> 2.16.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Sun Apr  8 23:57:15 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Apr 2018 08:57:15 +0200
Subject: [PATCH] video: IPUv3-LDB: demote dual-channel message to info
 level
In-Reply-To: <20180406154929.8604-1-l.stach@pengutronix.de>
References: <20180406154929.8604-1-l.stach@pengutronix.de>
Message-ID: <20180409065715.q5lmifctn2wpnlau@pengutronix.de>

On Fri, Apr 06, 2018 at 05:49:29PM +0200, Lucas Stach wrote:
> Dual channel mode is a valid mode of operation, so there is no reason to
> print this at the warning level.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> ---
>  drivers/video/imx-ipu-v3/imx-ldb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
> index 33dbade87007..9b4524274c4e 100644
> --- a/drivers/video/imx-ipu-v3/imx-ldb.c
> +++ b/drivers/video/imx-ipu-v3/imx-ldb.c
> @@ -347,7 +347,7 @@ static int imx_ldb_probe(struct device_d *dev)
>  			return -EINVAL;
>  
>  		if (dual && i > 0) {
> -			dev_warn(dev, "dual-channel mode, ignoring second output\n");
> +			dev_info(dev, "dual-channel mode, ignoring second output\n");
>  			continue;
>  		}
>  
> -- 
> 2.16.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From r.hieber at pengutronix.de  Mon Apr  9 01:59:33 2018
From: r.hieber at pengutronix.de (Roland Hieber)
Date: Mon,  9 Apr 2018 10:59:33 +0200
Subject: [RESEND] doc: bcm283x: update documentation for Raspberry Pi
In-Reply-To: <20180130112523.20258-1-r.hieber@pengutronix.de>
References: <20180130112523.20258-1-r.hieber@pengutronix.de>
Message-ID: <20180409085933.27413-1-r.hieber@pengutronix.de>

The old way does not seem to work for RPi 3, as the UART pins are
mapped differently and the NOOBS bootcode does not seem to read a
config.txt.

Signed-off-by: Roland Hieber <r.hieber at pengutronix.de>
---
 Documentation/boards/bcm2835.rst | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)
---
Although Sascha said he had applied the patch, I cannot find traces of
it in the current master. It probably got lost, so I'm resending it.
Note that this patch is independent of Lucas' RPi patch series and also
applies to the current state of RPi support.

 - Roland

diff --git a/Documentation/boards/bcm2835.rst b/Documentation/boards/bcm2835.rst
index 13cebb01c4..1a78cfba3c 100644
--- a/Documentation/boards/bcm2835.rst
+++ b/Documentation/boards/bcm2835.rst
@@ -1,17 +1,35 @@
-Broadcom BCM2835
+Broadcom BCM283x
 ================
 
 Raspberry Pi
 ------------
 
-  1. Prepare a card with a FAT filesystem. Download a tiny NOOBS LITE
-     zip archive and unpack it into FAT partition.
-     See http://www.raspberrypi.org/help/noobs-setup/ for details.
+  1. Prepare an SD or microSD card with a FAT filesystem of at least 30 MB in size.
+       
+  2. Download the `Raspberry Pi firmware`_ (120 MB), unzip it, and copy the
+     contents of the ``boot/`` folder to your card.
 
-  2. Compile ``barebox.bin`` image (use ``rpi_defconfig``).
-     Copy it to the SD/microSD card and name it ``recovery.img``.
+  3. Use ``make rpi_defconfig; make`` to build barebox. This will create the following images:
 
-  3. Connect to board's UART (115200 8N1);
+     - ``images/barebox-raspberry-pi-1.img`` for the BCM2835/ARM1176JZF-S (Raspberry Pi 1)
+     - ``images/barebox-raspberry-pi-2.img`` for the BCM2836/CORTEX-A7 (Raspberry Pi 2)
+     - ``images/barebox-raspberry-pi-3.img`` for the BCM2837/CORTEX-A53 (Raspberry Pi 3, Raspberry Pi Zero)
+    
+     Copy the respective image for your model to your SD card and name it
+     ``barebox.img``.
+
+  4. Create a text file ``config.txt`` on the SD card with the following content::
+
+         kernel=barebox.img
+         enable_uart=1
+         dtoverlay=pi3-miniuart-bt
+
+     (For more information, refer to the `documentation for config.txt`_.)
+
+  5. Connect to board's UART (115200 8N1);
      Use PIN6 (GND), PIN8 (UART_TX), PIN10 (UART_RX) pins.
 
-  4. Turn board's power on.
+  6. Turn board's power on.
+
+.. _Raspberry Pi firmware: https://codeload.github.com/raspberrypi/firmware/zip/80e1fbeb78f9df06701d28c0ed3a3060a3f557ef
+.. _documentation for config.txt: https://www.raspberrypi.org/documentation/configuration/config-txt/
-- 
2.11.0



From chf.fritz at googlemail.com  Mon Apr  9 04:43:19 2018
From: chf.fritz at googlemail.com (Christoph Fritz)
Date: Mon, 09 Apr 2018 13:43:19 +0200
Subject: [PATCH] ARM: Add Advantech imx6 board support
In-Reply-To: <20180406192134.bqnu3gpf2w33matc@pengutronix.de>
References: <1522934149.24545.3.camel@googlemail.com>
 <20180406192134.bqnu3gpf2w33matc@pengutronix.de>
Message-ID: <1523274199.3785.15.camel@googlemail.com>

Hi Sascha,

On Fri, 2018-04-06 at 21:21 +0200, Sascha Hauer wrote:
> Hi Christoph,
> 
> On Thu, Apr 05, 2018 at 03:15:49PM +0200, Christoph Fritz wrote:
> > +	phy_register_fixup_for_uid(0x004dd072, 0xffffffef, ar8035_phy_fixup);
> > +
> > +	switch (bootsource_get()) {
> > +	case BOOTSOURCE_MMC:
> > +		environment_path = basprintf("/chosen/environment-sd%d",
> > +					     bootsource_get_instance() + 1);
> > +		envdev = "MMC";
> > +		break;
> > +	case BOOTSOURCE_SPI:
> > +	default:
> > +		environment_path = basprintf("/chosen/environment-sd4");
> > +		envdev = "MMC";
> > +		break;
> > +	}
> > +
> > +	if (environment_path) {
> > +		ret = of_device_enable_path(environment_path);
> > +		if (ret < 0)
> > +			pr_warn("Failed to enable env partition '%s' (%d)\n",
> > +				environment_path, ret);
> > +		free(environment_path);
> > +	}
> > +
> > +	pr_notice("Using environment in %s\n", envdev);
> 
> This is always "MMC", not very informative. Maybe "eMMC" and "external
> SD"?

I'll fix that.

> 
> > +
> > +	imx6_bbu_internal_mmc_register_handler("mmc3", "/dev/mmc3",
> > +						BBU_HANDLER_FLAG_DEFAULT);
> 
> That would be the eMMC, right? For this I can recommend putting barebox
> into the boot partitions of the eMMC. Normally there are two of them
> and with imx6_bbu_internal_mmcboot_register_handler() you even get a
> robust barebox A/B update mechanism.

I'm currently using here a hybrid u-boot into barebox boot and can't use
the eMMC SLC boot-partitions without changes on the u-boot side. That's
why I kept this config.

If you really want me to go for the boot0 partition, I can adapt this in
this mainline barebox setup?

> > +
> > +	return 0;
> > +}
> > +device_initcall(advantech_mx6_devices_init);
> > diff --git a/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> > new file mode 100644
> > index 0000000..611e06b
> > --- /dev/null
> > +++ b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> > @@ -0,0 +1,73 @@
> > +soc imx6
> > +loadaddr 0x10000000
> > +dcdofs 0x400
> > +
> > +wm 32 0x020e0774 0x000C0000
> 
> [...]
> 
> > +wm 32 0x021b0004 0x0002556D
> > +wm 32 0x021b0404 0x00011006
> > +wm 32 0x021b001c 0x00000000
> 
> > +wm 32 0x020c4068 0x00C03F3F
> > +wm 32 0x020c406c 0x0030FC03
> > +wm 32 0x020c4070 0x0FFFC000
> > +wm 32 0x020c4074 0x3FF00000
> > +wm 32 0x020c4078 0x00FFF300
> > +wm 32 0x020c407c 0x0F0000C3
> > +wm 32 0x020c4080 0x000003FF
> 
> Please remove writing these clock registers here. The registers get
> overwritten in a few moments by barebox anyway. Often enough these gate
> settings disable the USB clocks and then booting this image from USB is
> no longer possible.

I'll fix that.

> 
> > +wm 32 0x020e0010 0xF00000CF
> > +wm 32 0x020e0018 0x007F007F
> > +wm 32 0x020e001c 0x007F007F
> > diff --git a/arch/arm/boards/advantech-mx6/lowlevel.c b/arch/arm/boards/advantech-mx6/lowlevel.c
> > new file mode 100644
> > index 0000000..5efb91a
> > --- /dev/null
> > +++ b/arch/arm/boards/advantech-mx6/lowlevel.c
> > @@ -0,0 +1,58 @@
> > +/*
> > + * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + *
> > + */
> > +
> > +#include <debug_ll.h>
> > +#include <common.h>
> > +#include <asm/barebox-arm-head.h>
> > +#include <asm/barebox-arm.h>
> > +#include <image-metadata.h>
> > +#include <mach/generic.h>
> > +#include <mach/esdctl.h>
> > +#include <linux/sizes.h>
> > +
> > +static inline void setup_uart(void)
> > +{
> > +	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
> > +
> > +	writel(0x3, iomuxbase + 0x4c);
> > +
> > +	imx6_ungate_all_peripherals();
> > +	imx6_uart_setup_ll();
> > +
> > +	putc_ll('>');
> > +}
> > +
> > +extern char __dtb_imx6dl_advantech_rom_7421_start[];
> > +
> > +BAREBOX_IMD_TAG_STRING(advantech_imx6dl_memsize_512M, IMD_TYPE_PARAMETER,
> > +		       "memsize=512", 0);
> > +
> > +ENTRY_FUNCTION(start_advantech_imx6dl_rom_7421, r0, r1, r2)
> > +{
> > +	void *fdt;
> > +
> > +	imx6_cpu_lowlevel_init();
> > +
> > +	arm_setup_stack(0x00920000 - 8);
> > +
> > +	IMD_USED(advantech_imx6dl_memsize_512M);
> > +
> > +	if (IS_ENABLED(CONFIG_DEBUG_LL))
> > +		setup_uart();
> > +
> > +	fdt = __dtb_imx6dl_advantech_rom_7421_start - get_runtime_offset();
> 
> Since "a43e2bbc46 ARM: return positive offset in get_runtime_offset()"
> this must be '+' get_runtime_offset();

I'll rework all that init and use imx6q_barebox_entry(fdt) instead.

> 
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include <arm/imx6dl.dtsi>
> > +#include "imx6dl.dtsi"
> > +
> > +/ {
> > +	model = "Advantech i.MX6 ROM-7421";
> > +	compatible = "advantech,imx6dl-rom-7421", "fsl,imx6dl";
> > +
> > +	chosen {
> > +		linux,stdout-path = &uart1;
> 
> just stdout-path. linux,stdout-path is the old binding.

I'll fix that.

> 
> > +
> > +		environment-sd2 {			/* Micro SD */
> > +			compatible = "barebox,environment";
> > +			device-path = &usdhc2, "partname:barebox-environment";
> > +			status = "disabled";
> > +		};
> > +
> > +		environment-sd4 {			/* eMMC */
> > +			compatible = "barebox,environment";
> > +			device-path = &usdhc4, "partname:barebox-environment";
> > +			status = "disabled";
> > +		};
> > +	};
> > +};
> > +
> > +&ecspi1 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_ecspi1>;
> > +	fsl,spi-num-chipselects = <1>;
> > +	cs-gpios = <&gpio3 19 0>;
> > +	status = "okay";
> > +
> > +	flash: m25p80 at 0 {
> > +		compatible = "m25p80";
> > +		spi-max-frequency = <20000000>;
> > +		reg = <0>;
> > +		status = "okay";
> > +
> > +		#address-cells = <1>;
> > +		#size-cells = <1>;
> > +
> > +		partition at 400 {
> > +			label = "SPL";
> > +			reg = <0x400 0xa0000>;
> > +		};
> > +
> > +		partition at d0000 {
> > +			label = "MAC";
> > +			reg = <0xd0000 0x1000>;
> > +		};
> 
> What's in the free space?

It is empty.

> If you can use the space up to 0xd0000 then
> you could put a full barebox before it instead of just a SPL (I guess
> this partitioning comes from the original vendor, right?)

Yes right.

Let me change the whole layout to a simple barebox mainline default.

> 
> > +	};
> > +};
> > +
> > +&usdhc4 {					/* eMMC */
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_usdhc4>;
> > +	bus-width = <8>;
> > +	non-removable;
> > +	no-1-8-v;
> > +	status = "okay";
> > +
> > +	#address-cells = <1>;
> > +	#size-cells = <1>;
> > +
> > +	partition at 400 {
> > +		label = "CRC";
> > +		reg = <0x200000 0x200>;
> > +	};
> > +
> > +	partition at 600 {
> > +		label = "barebox_CRCed";
> > +		reg = <0x200200 0x96000>;
> > +	};
> > +
> > +	partition at 96600 {
> > +		label = "barebox-environment";
> > +		reg = <0x296200 0x20000>;
> > +	};
> 
> the @adr in the partition names do not match the actual start of the
> partitions, this should be fixed. Overall the partitions look strange.
> Aren't barebox_CRCed and barebox-environment in somewhere in the middle
> of the device which is already occupied by the regular partitions?

In my local hybrid config regular partitions start with a big offset.

Let me change the whole layout to a simple barebox mainline default.

> 
> > +};
> > +
> > +&iomuxc {
> > +	pinctrl-names = "default";
> > +
> > +	imx6dl-advantech-rom-742 {
> 
> This additional subnode is obsolete, please remove and move the pinctrl
> nodes one level up.

I'll fix that.

> 
> > diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> > index eb135c3..e4de3d1 100644
> > --- a/arch/arm/mach-imx/Kconfig
> > +++ b/arch/arm/mach-imx/Kconfig
> > @@ -39,6 +39,7 @@ config ARCH_TEXT_BASE
> >  	default 0x4fc00000 if MACH_UDOO
> >  	default 0x4fc00000 if MACH_VARISCITE_MX6
> >  	default 0x4fc00000 if MACH_PHYTEC_SOM_IMX6
> > +	default 0x4fc00000 if MACH_ADVANTECH_ROM_742X
> 
> You shouldn't need this.

I'll fix that.

Thanks
 -- Christoph



From chf.fritz at googlemail.com  Mon Apr  9 04:45:02 2018
From: chf.fritz at googlemail.com (Christoph Fritz)
Date: Mon, 09 Apr 2018 13:45:02 +0200
Subject: [PATCH] ARM: Add Advantech imx6 board support
In-Reply-To: <CAHQ1cqFnNum_jgC_R-TxB3Y0+SU-68eny3Zq=YkSCmz9a=jFSw@mail.gmail.com>
References: <1522934149.24545.3.camel@googlemail.com>
 <CAHQ1cqFnNum_jgC_R-TxB3Y0+SU-68eny3Zq=YkSCmz9a=jFSw@mail.gmail.com>
Message-ID: <1523274302.3785.17.camel@googlemail.com>

Hi Andrey,

 thanks for your input, I'll integrate your suggestions and send a v2
patch.

Thanks
  -- Christoph



From chf.fritz at googlemail.com  Mon Apr  9 04:53:59 2018
From: chf.fritz at googlemail.com (Christoph Fritz)
Date: Mon, 09 Apr 2018 13:53:59 +0200
Subject: [PATCH v2] ARM: Add Advantech imx6 board support
In-Reply-To: <1522934149.24545.3.camel@googlemail.com>
References: <1522934149.24545.3.camel@googlemail.com>
Message-ID: <1523274839.3785.25.camel@googlemail.com>

Add support for Advantech i.MX6 SOM named ROM-7421.

Signed-off-by: Christoph Fritz <chf.fritz at googlemail.com>
---
Changes since v0:
 - distinguish between MMC environment names in pr_notice() board.c
 - rework eMMC partition layout and don't use its hw-bootpartition for now
 - purge writing clock registers
 - rework and simplify lowlevel.c init and use imx6q_barebox_entry(fdt)
 - s/linux,stdout-path/stdout-path in dts
 - rework and simplify spi nor partition layout
 - remove additional pinctrl subnode from dts
 - remove setting of explicit ARCH_TEXT_BASE in Kconfig
 - use bitop Macro for ar8035_phy_fixup()
 - use imx_setup_pad() for early debug uart
---
 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/advantech-mx6/Makefile             |   2 +
 arch/arm/boards/advantech-mx6/board.c              | 101 +++++++++
 .../flash-header-advantech-rom-7421.imxcfg         |  66 ++++++
 arch/arm/boards/advantech-mx6/lowlevel.c           |  56 +++++
 arch/arm/configs/imx_v7_defconfig                  |   1 +
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/imx6dl-advantech-rom-7421.dts         | 225 +++++++++++++++++++++
 arch/arm/mach-imx/Kconfig                          |   5 +
 images/Makefile.imx                                |   5 +
 10 files changed, 463 insertions(+)
 create mode 100644 arch/arm/boards/advantech-mx6/Makefile
 create mode 100644 arch/arm/boards/advantech-mx6/board.c
 create mode 100644 arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
 create mode 100644 arch/arm/boards/advantech-mx6/lowlevel.c
 create mode 100755 arch/arm/dts/imx6dl-advantech-rom-7421.dts

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index ca187cc..521f37d 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -1,4 +1,5 @@
 # keep sorted by CONFIG_* macro name.
+obj-$(CONFIG_MACH_ADVANTECH_ROM_742X)		+= advantech-mx6/
 obj-$(CONFIG_MACH_AFI_GF)			+= afi-gf/
 obj-$(CONFIG_MACH_ANIMEO_IP)			+= animeo_ip/
 obj-$(CONFIG_MACH_ARCHOSG9)			+= archosg9/
diff --git a/arch/arm/boards/advantech-mx6/Makefile b/arch/arm/boards/advantech-mx6/Makefile
new file mode 100644
index 0000000..01c7a25
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/Makefile
@@ -0,0 +1,2 @@
+obj-y += board.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/advantech-mx6/board.c b/arch/arm/boards/advantech-mx6/board.c
new file mode 100644
index 0000000..4a30a84
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/board.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <platform_data/eth-fec.h>
+#include <bootsource.h>
+#include <mach/bbu.h>
+
+static int ar8035_phy_fixup(struct phy_device *dev)
+{
+	u16 val;
+
+	/* Ar803x phy SmartEEE feature cause link status generates glitch,
+	 * which cause ethernet link down/up issue, so disable SmartEEE
+	 */
+	phy_write(dev, 0xd, 0x3);
+	phy_write(dev, 0xe, 0x805d);
+	phy_write(dev, 0xd, 0x4003);
+
+	val = phy_read(dev, 0xe);
+	phy_write(dev, 0xe, val & ~BIT(8));
+
+	/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+	phy_write(dev, 0xd, 0x7);
+	phy_write(dev, 0xe, 0x8016);
+	phy_write(dev, 0xd, 0x4007);
+
+	val = phy_read(dev, 0xe);
+	val &= 0xffe3;
+	val |= 0x18;
+	phy_write(dev, 0xe, val);
+
+	/* introduce tx clock delay */
+	phy_write(dev, 0x1d, 0x5);
+	val = phy_read(dev, 0x1e);
+	val |= 0x0100;
+	phy_write(dev, 0x1e, val);
+
+	return 0;
+}
+
+static int advantech_mx6_devices_init(void)
+{
+	int ret;
+	char *environment_path, *envdev;
+
+	if (!of_machine_is_compatible("advantech,imx6dl-rom-7421"))
+		return 0;
+
+	phy_register_fixup_for_uid(0x004dd072, 0xffffffef, ar8035_phy_fixup);
+
+	switch (bootsource_get()) {
+	case BOOTSOURCE_MMC:
+		environment_path = basprintf("/chosen/environment-sd%d",
+					     bootsource_get_instance() + 1);
+		if (bootsource_get_instance() + 1 == 4)
+			envdev = "eMMC";
+		else if (bootsource_get_instance() + 1 == 2)
+			envdev = "microSD";
+		else
+			envdev = "MMC";
+		break;
+	case BOOTSOURCE_SPI:
+		envdev = "SPI";
+		environment_path = basprintf("/chosen/environment-spi");
+		break;
+	default:
+		environment_path = basprintf("/chosen/environment-sd4");
+		envdev = "MMC";
+		break;
+	}
+
+	if (environment_path) {
+		ret = of_device_enable_path(environment_path);
+		if (ret < 0)
+			pr_warn("Failed to enable env partition '%s' (%d)\n",
+				environment_path, ret);
+		free(environment_path);
+	}
+
+	pr_notice("Using environment in %s\n", envdev);
+
+	imx6_bbu_internal_mmc_register_handler("mmc3", "/dev/mmc3",
+						BBU_HANDLER_FLAG_DEFAULT);
+
+	return 0;
+}
+device_initcall(advantech_mx6_devices_init);
diff --git a/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
new file mode 100644
index 0000000..996ecc7
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
@@ -0,0 +1,66 @@
+soc imx6
+loadaddr 0x10000000
+dcdofs 0x400
+
+wm 32 0x020e0774 0x000C0000
+wm 32 0x020e0754 0x00000000
+wm 32 0x020e04ac 0x00000030
+wm 32 0x020e04b0 0x00000030
+wm 32 0x020e0464 0x00000030
+wm 32 0x020e0490 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e0494 0x00000030
+wm 32 0x020e04a0 0x00000000
+wm 32 0x020e04b4 0x00000030
+wm 32 0x020e04b8 0x00000030
+wm 32 0x020e076c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e04bc 0x00000030
+wm 32 0x020e04c0 0x00000030
+wm 32 0x020e04c4 0x00000030
+wm 32 0x020e04c8 0x00000030
+wm 32 0x020e0760 0x00020000
+wm 32 0x020e0764 0x00000030
+wm 32 0x020e0770 0x00000030
+wm 32 0x020e0778 0x00000030
+wm 32 0x020e077c 0x00000030
+wm 32 0x020e0470 0x00000030
+wm 32 0x020e0474 0x00000030
+wm 32 0x020e0478 0x00000030
+wm 32 0x020e047c 0x00000030
+wm 32 0x021b0800 0xa1390003
+wm 32 0x021b080c 0x001F001F
+wm 32 0x021b0810 0x001F001F
+wm 32 0x021b083c 0x42480248
+wm 32 0x021b0840 0x022C0234
+wm 32 0x021b0848 0x3E404244
+wm 32 0x021b0850 0x30302C30
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+wm 32 0x021b0824 0x33333333
+wm 32 0x021b0828 0x33333333
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b0004 0x0002002D
+wm 32 0x021b0008 0x00333030
+wm 32 0x021b000c 0x3F435333
+wm 32 0x021b0010 0xB68E8B63
+wm 32 0x021b0014 0x01FF00DB
+wm 32 0x021b0018 0x00001740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b002c 0x000026d2
+wm 32 0x021b0030 0x00431023
+wm 32 0x021b0040 0x00000017
+wm 32 0x021b0000 0x83190000
+wm 32 0x021b001c 0x04008032
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x05208030
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b0020 0x00005800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b0004 0x0002556D
+wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
+wm 32 0x020e0010 0xF00000CF
+wm 32 0x020e0018 0x007F007F
+wm 32 0x020e001c 0x007F007F
diff --git a/arch/arm/boards/advantech-mx6/lowlevel.c b/arch/arm/boards/advantech-mx6/lowlevel.c
new file mode 100644
index 0000000..8921cd4
--- /dev/null
+++ b/arch/arm/boards/advantech-mx6/lowlevel.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <debug_ll.h>
+#include <common.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <image-metadata.h>
+#include <mach/generic.h>
+#include <mach/esdctl.h>
+#include <mach/iomux-mx6.h>
+#include <linux/sizes.h>
+
+#include <linux/sizes.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+static inline void setup_uart(void)
+{
+	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+	imx6_ungate_all_peripherals();
+
+	imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT10__UART1_TXD);
+
+	imx6_uart_setup_ll();
+
+	putc_ll('>');
+}
+
+extern char __dtb_imx6dl_advantech_rom_7421_start[];
+
+ENTRY_FUNCTION(start_advantech_imx6dl_rom_7421, r0, r1, r2)
+{
+	imx6_cpu_lowlevel_init();
+
+	relocate_to_current_adr();
+	setup_c();
+	barrier();
+
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+		setup_uart();
+
+	imx6q_barebox_entry(__dtb_imx6dl_advantech_rom_7421_start);
+}
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 62d6238..7a563a5 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -30,6 +30,7 @@ CONFIG_MACH_UDOO=y
 CONFIG_MACH_VARISCITE_MX6=y
 CONFIG_MACH_GW_VENTANA=y
 CONFIG_MACH_CM_FX6=y
+CONFIG_MACH_ADVANTECH_ROM_742X=y
 CONFIG_MACH_PHYTEC_PHYCORE_IMX7=y
 CONFIG_IMX_IIM=y
 CONFIG_IMX_IIM_FUSE_BLOW=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0526a6f..f094bdb 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -7,6 +7,7 @@ endif
 # created.
 obj- += dummy.o
 
+pbl-dtb-$(CONFIG_MACH_ADVANTECH_ROM_742X) += imx6dl-advantech-rom-7421.dtb.o
 pbl-dtb-$(CONFIG_MACH_AFI_GF) += am335x-afi-gf.dtb.o
 pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
 pbl-dtb-$(CONFIG_MACH_CM_FX6) += imx6dl-cm-fx6.dtb.o imx6q-cm-fx6.dtb.o imx6q-utilite.dtb.o
diff --git a/arch/arm/dts/imx6dl-advantech-rom-7421.dts b/arch/arm/dts/imx6dl-advantech-rom-7421.dts
new file mode 100755
index 0000000..1d5fd89
--- /dev/null
+++ b/arch/arm/dts/imx6dl-advantech-rom-7421.dts
@@ -0,0 +1,225 @@
+/*
+ * Copyright(c) 2018 Christoph Fritz <chf.fritz at googlemail.com>
+ *
+ * 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 <dt-bindings/gpio/gpio.h>
+#include <arm/imx6dl.dtsi>
+#include "imx6dl.dtsi"
+
+/ {
+	model = "Advantech i.MX6 ROM-7421";
+	compatible = "advantech,imx6dl-rom-7421", "fsl,imx6dl";
+
+	chosen {
+		stdout-path = &uart1;
+
+		environment-sd2 {			/* Micro SD */
+			compatible = "barebox,environment";
+			device-path = &usdhc2, "partname:barebox-environment";
+			status = "disabled";
+		};
+
+		environment-sd4 {			/* eMMC */
+			compatible = "barebox,environment";
+			device-path = &usdhc4, "partname:barebox-environment";
+			status = "disabled";
+		};
+
+		environment-spi {			/* spi nor */
+			compatible = "barebox,environment";
+			device-path = &ecspi1, "partname:barebox-environment";
+			status = "disabled";
+		};
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 0>;
+	status = "okay";
+
+	flash: m25p80 at 0 {
+		compatible = "m25p80";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+		status = "okay";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition at 0 {
+			label = "barebox";
+			reg = <0x0 0xe0000>;
+		};
+
+		partition at e0000 {
+			label = "barebox-environment";
+			reg = <0xe0000 0x20000>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+	fsl,magic-packet;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc2 {					/* Micro SD */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <8>;
+	cd-gpios = <&gpio2 0 0>;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition at 0 {
+		label = "barebox";
+		reg = <0x0 0xe0000>;
+	};
+
+	partition at e0000 {
+		label = "barebox-environment";
+		reg = <0xe0000 0x20000>;
+	};
+};
+
+&usdhc3 {					/* SD Card */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	bus-width = <4>;
+	cd-gpios = <&gpio2 1 0>;
+	en-gpios = <&gpio2 2 0>;
+	wp-gpios = <&gpio2 3 0>;
+	status = "okay";
+};
+
+&usdhc4 {					/* eMMC */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <8>;
+	non-removable;
+	no-1-8-v;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition at 0 {
+		label = "barebox";
+		reg = <0x0 0xe0000>;
+	};
+
+	partition at e0000 {
+		label = "barebox-environment";
+		reg = <0xe0000 0x20000>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x80000000
+		>;
+	};
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0A0B1
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25	0x80000000
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	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_NANDF_D0__GPIO2_IO00		0x1b0b0
+		>;
+	};
+
+	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
+			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+			MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
+		>;
+	};
+
+	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
+		>;
+	};
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index eb135c3..0902ba6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -383,6 +383,11 @@ config MACH_CM_FX6
 	bool "CM FX6"
 	select ARCH_IMX6
 
+config MACH_ADVANTECH_ROM_742X
+	bool "Advantech ROM 742X"
+	select ARCH_IMX6
+	select ARM_USE_COMPRESSED_DTB
+
 config MACH_WARP7
 	bool "NXP i.MX7: element 14 WaRP7 Board"
 	select ARCH_IMX7
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 5e0043f..131b3f2 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -465,6 +465,11 @@ CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-head
 FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
 image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
 
+pblx-$(CONFIG_MACH_ADVANTECH_ROM_742X) += start_advantech_imx6dl_rom_7421
+CFG_start_advantech_imx6dl_rom_7421.pblx.imximg = $(board)/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
+FILE_barebox-advantech-imx6dl-rom-7421.img = start_advantech_imx6dl_rom_7421.pblx.imximg
+image-$(CONFIG_MACH_ADVANTECH_ROM_742X) += barebox-advantech-imx6dl-rom-7421.img
+
 pblx-$(CONFIG_MACH_WARP7) += start_imx7s_element14_warp7
 CFG_start_imx7s_element14_warp7.pblx.imximg = $(board)/element14-warp7/flash-header-mx7-warp.imxcfg
 FILE_barebox-element14-imx7s-warp7.img = start_imx7s_element14_warp7.pblx.imximg
-- 
2.1.4



From andrew.smirnov at gmail.com  Mon Apr  9 09:00:52 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 9 Apr 2018 09:00:52 -0700
Subject: [PATCH 3/3] serial: Check result of console_unregister()
In-Reply-To: <20180403070427.terivivcpl2abuuf@pengutronix.de>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-4-andrew.smirnov@gmail.com>
 <20180403070427.terivivcpl2abuuf@pengutronix.de>
Message-ID: <CAHQ1cqHR2vmy4HRFaCLQnVgn=YCG+YOfBgBj_uzw4mn66T1nvA@mail.gmail.com>

On Tue, Apr 3, 2018 at 12:04 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Mon, Mar 26, 2018 at 06:09:15AM -0700, Andrey Smirnov wrote:
>> In order to allow 'serdev' devices to prevent parent console device
>> removal and correspondign memory deallocation add code to all serial
>> driver to check result of console_unregister() and bail out early if
>> it is unsuccessful.
>>
>> One example of a use-case for this would be a reset handler relying on
>> a serdev device for transport. Without this patch underlying console
>> device would be removed and de-allocated before reset handler is even
>> run thus leading to unpredictable behaviour and crashes.
>
> Can't we make this sure at driver core level?

I need to be able to prevent serial driver's "remove" function from
ever executing to prevent any de-initialization/memory freeing from
happening. The simplest way to solve this in driver core that comes to
my mind is implementing simple reference counting API that children
could use to force driver core to bail out on removing parents if they
are still in use. Does that sound like a reasonable idea?

> So if a device decides not
> to return -EBUSY in the remove callback then the parent devices won't be
> removed?

Remove callback currently returns void, we could change it to return
int and use it to implement a sort of implicit refcounting, but doing
so would result in quite a bit of code churn since all of the current
drivers would have to be converted to return int in their .remove
callbacks. Would you rather I do this or explicit refcounting?

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr  9 09:40:46 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 9 Apr 2018 09:40:46 -0700
Subject: [PATCH 2/3] console: Add simplified 'serdev' framework from Linux
 kernel
In-Reply-To: <20180403065436.p2vec7ntdja55hts@pengutronix.de>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-3-andrew.smirnov@gmail.com>
 <20180403065436.p2vec7ntdja55hts@pengutronix.de>
Message-ID: <CAHQ1cqHdhHiknrnzfU_9YLc_HiyNVDSPZyGNNsHcrAhgUoK_ig@mail.gmail.com>

On Mon, Apr 2, 2018 at 11:54 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> Hi Andrey,
>
> Some comments inside.
>
>
> On Mon, Mar 26, 2018 at 06:09:14AM -0700, Andrey Smirnov wrote:
>> Port 'serdev' UART-slave deivce framework found in recent Linux
>> kernels (post 4.13) in order to be able to port 'serdev' slave drivers
>> from Linux.
>>
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> @@ -323,6 +324,17 @@ int console_register(struct console_device *newcdev)
>>               dev->parent = newcdev->dev;
>>       platform_device_register(dev);
>>
>> +     newcdev->open_count = 0;
>> +
>> +     /*
>> +      * If our console deive is a serdev, we skip the creation of
>
> s/deive/device/

Will fix in v2.

>
>> +      * corresponding entry in /dev as well as registration in
>> +      * console_list and just go straigh to populating child
>
> s/straigh/straight/

Ditto.

>
>> +      * devices.
>> +      */
>> +     if (serdev_node)
>> +             return of_platform_populate(serdev_node, NULL, dev);
>
> How is this going to be used? A serdev driver binds to the serdev_node
> and then it probably needs to get a pointer to the console device,
> right? How does the driver accomplish this?
>

Serdev slave driver doesn't hold explicit pointer to console device,
instead accessing it via point to serdev_device. The latter could
obtained by calling to_serdev_device(dev->parent), where dev is
device_d given to slave driver's probe function.


>> +/**
>> + * struct serdev_device - Basic representation of an serdev device
>> + *
>> + * @dev:             Corresponding device
>> + * @fifo:            Circular buffer used for console draining
>> + * @buf:             Buffer used to pass Rx data to consumers
>> + * @poller           Async poller used to poll this serdev
>> + * @polling_interval:        Async poller periodicity
>> + * @polling_window:  Duration of a single busy loop poll
>> + * @receive_buf:     Function called with data received from device;
>> + *                   returns number of bytes accepted;
>> + */
>> +struct serdev_device {
>> +     struct device_d *dev;
>> +     struct kfifo *fifo;
>> +     unsigned char *buf;
>> +     struct poller_async poller;
>> +     uint64_t polling_interval;
>> +     uint64_t polling_window;
>> +
>> +     int (*receive_buf)(struct serdev_device *, const unsigned char *,
>> +                        size_t);
>> +};
>> +
>> +int serdev_device_open(struct serdev_device *);
>> +unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
>> +int serdev_device_write(struct serdev_device *, const unsigned char *,
>> +                     size_t, unsigned long);
>
> So a serdev driver uses serdev_device_write() to send characters out. To
> receive characters it has to implement serdev_device->receive_buf,
> right?

Right. I tried to implement exactly the same API that Linux's serdev
API provides.

> What kind of devices did you implement this for?

I ported serdev in support of porting the driver for RAVE SP which is
a small microcontroller device found many ZII board including RDU2. It
implement a whole bunch of various functionality including watchdog,
parameter EEPROM, sensor access, backlight control, button input event
generation, etc.

> For devices which send data without request (GPS?) this seems the way to go. For
> others a synchronous receive function might be good, no?
>

I didn't implement anything like that mostly because Linux serdev API
doesn't and any ported driver wouldn't have any need for those
functions. But in general, I am not sure how useful synchronous
receive function would be. In my experience, devices like that usually
implement some binary transport protocol with packetization/escape
sequences on top of UART, which usually requires a state machine
operating with byte granularity as the data comes in to parse
responses correctly and synchronous APIs are not extremely useful for
that kind of a use-case.

FWIW, since serdev API is integrated into poller infrastructure it is
pretty trivial to write blocking code with it. Here's how I use it in
my driver to implement request-response type of a function:

rave_sp_write(sp, data, data_size);
/*
* is_timeout will implicitly poll serdev via poller
* infrastructure
*/
while (!is_timeout(start, SECOND) && !reply.received)
   ;


Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr  9 18:36:36 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon,  9 Apr 2018 18:36:36 -0700
Subject: [PATCH 1/2] i.MX53/TX53: Adjust to latest get_runtime_offset()
Message-ID: <20180410013637.2513-1-andrew.smirnov@gmail.com>

Latest version of get_runtime_offset() returns positive offset that
needs to be added to rather than substracted from original pointer.

Cc: Michael Grzeschik <m.grzeschik at pengutronix.de>
Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---

Sascha:

This one obviously needs to go into master as well. Sorry for the
noise if this has already been fixed.

Thanks,
Andrey Smirnov

 arch/arm/boards/karo-tx53/lowlevel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boards/karo-tx53/lowlevel.c b/arch/arm/boards/karo-tx53/lowlevel.c
index cb324b200..a0bce8a78 100644
--- a/arch/arm/boards/karo-tx53/lowlevel.c
+++ b/arch/arm/boards/karo-tx53/lowlevel.c
@@ -47,7 +47,7 @@ static void __imx53_tx53_init(int is_xx30)
 	if (IS_ENABLED(CONFIG_DEBUG_LL))
 		setup_uart();
 
-	fdt = fdt_blob_fixed_offset - get_runtime_offset();
+	fdt = fdt_blob_fixed_offset + get_runtime_offset();
 
 	imx53_barebox_entry(fdt);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr  9 18:36:37 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon,  9 Apr 2018 18:36:37 -0700
Subject: [PATCH 2/2] boards: samx6: Adjust to latest get_runtime_offset()
In-Reply-To: <20180410013637.2513-1-andrew.smirnov@gmail.com>
References: <20180410013637.2513-1-andrew.smirnov@gmail.com>
Message-ID: <20180410013637.2513-2-andrew.smirnov@gmail.com>

Latest version of get_runtime_offset() returns positive offset that
needs to be added to rather than substracted from original pointer.

Cc: Michael Grzeschik <m.grzeschik at pengutronix.de>
Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---

Sascha:

This one obviously needs to go into master as well. Sorry for the
noise if this has already been fixed.

Thanks,
Andrey Smirnov

 arch/arm/boards/kontron-samx6i/lowlevel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boards/kontron-samx6i/lowlevel.c b/arch/arm/boards/kontron-samx6i/lowlevel.c
index 4113ddbb4..5c3500704 100644
--- a/arch/arm/boards/kontron-samx6i/lowlevel.c
+++ b/arch/arm/boards/kontron-samx6i/lowlevel.c
@@ -47,7 +47,7 @@ static void __noreturn start_imx6_samx6i_common(void *fdt_blob_fixed_offset)
 	if (IS_ENABLED(CONFIG_DEBUG_LL))
 		setup_uart();
 
-	fdt = fdt_blob_fixed_offset - get_runtime_offset();
+	fdt = fdt_blob_fixed_offset + get_runtime_offset();
 
 	barebox_arm_entry(0x10000000, size, fdt);
 }
-- 
2.14.3



From s.hauer at pengutronix.de  Tue Apr 10 00:06:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 10 Apr 2018 09:06:44 +0200
Subject: [PATCH 0/2] mfd: mc13xxx: ADC support
In-Reply-To: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>
References: <1523032404-7416-1-git-send-email-andrey.gusakov@cogentembedded.com>
Message-ID: <20180410070644.txdv22zpawbua2jf@pengutronix.de>

Hi Andrey,

On Fri, Apr 06, 2018 at 07:33:22PM +0300, Andrey Gusakov wrote:
> This set of pathces adds ADC support for MC13783 and MC13892 PMICs.

Applied, thanks. Out of curiosity, what do you use the ADCs for?

Sascha

> 
> Andrey Gusakov (2):
>   mfd: mc13xxx: add function returning mc13xxx type
>   aiodev: mc13xxx: add adc support
> 
>  drivers/aiodev/Kconfig       |   6 ++
>  drivers/aiodev/Makefile      |   1 +
>  drivers/aiodev/mc13xxx_adc.c | 234 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/mfd/mc13xxx.c        |  15 +++
>  include/mfd/mc13xxx.h        |  19 ++++
>  5 files changed, 275 insertions(+)
>  create mode 100644 drivers/aiodev/mc13xxx_adc.c
> 
> -- 
> 1.9.1
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 10 00:08:14 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 10 Apr 2018 09:08:14 +0200
Subject: [RESEND] doc: bcm283x: update documentation for Raspberry Pi
In-Reply-To: <20180409085933.27413-1-r.hieber@pengutronix.de>
References: <20180130112523.20258-1-r.hieber@pengutronix.de>
 <20180409085933.27413-1-r.hieber@pengutronix.de>
Message-ID: <20180410070814.y6meuwetfngkosvc@pengutronix.de>

On Mon, Apr 09, 2018 at 10:59:33AM +0200, Roland Hieber wrote:
> The old way does not seem to work for RPi 3, as the UART pins are
> mapped differently and the NOOBS bootcode does not seem to read a
> config.txt.
> 
> Signed-off-by: Roland Hieber <r.hieber at pengutronix.de>
> ---
>  Documentation/boards/bcm2835.rst | 34 ++++++++++++++++++++++++++--------
>  1 file changed, 26 insertions(+), 8 deletions(-)
> ---
> Although Sascha said he had applied the patch, I cannot find traces of
> it in the current master. It probably got lost, so I'm resending it.
> Note that this patch is independent of Lucas' RPi patch series and also
> applies to the current state of RPi support.

Applied, thanks. Yes, now I *really* did.

Sascha

> 
>  - Roland
> 
> diff --git a/Documentation/boards/bcm2835.rst b/Documentation/boards/bcm2835.rst
> index 13cebb01c4..1a78cfba3c 100644
> --- a/Documentation/boards/bcm2835.rst
> +++ b/Documentation/boards/bcm2835.rst
> @@ -1,17 +1,35 @@
> -Broadcom BCM2835
> +Broadcom BCM283x
>  ================
>  
>  Raspberry Pi
>  ------------
>  
> -  1. Prepare a card with a FAT filesystem. Download a tiny NOOBS LITE
> -     zip archive and unpack it into FAT partition.
> -     See http://www.raspberrypi.org/help/noobs-setup/ for details.
> +  1. Prepare an SD or microSD card with a FAT filesystem of at least 30 MB in size.
> +       
> +  2. Download the `Raspberry Pi firmware`_ (120 MB), unzip it, and copy the
> +     contents of the ``boot/`` folder to your card.
>  
> -  2. Compile ``barebox.bin`` image (use ``rpi_defconfig``).
> -     Copy it to the SD/microSD card and name it ``recovery.img``.
> +  3. Use ``make rpi_defconfig; make`` to build barebox. This will create the following images:
>  
> -  3. Connect to board's UART (115200 8N1);
> +     - ``images/barebox-raspberry-pi-1.img`` for the BCM2835/ARM1176JZF-S (Raspberry Pi 1)
> +     - ``images/barebox-raspberry-pi-2.img`` for the BCM2836/CORTEX-A7 (Raspberry Pi 2)
> +     - ``images/barebox-raspberry-pi-3.img`` for the BCM2837/CORTEX-A53 (Raspberry Pi 3, Raspberry Pi Zero)
> +    
> +     Copy the respective image for your model to your SD card and name it
> +     ``barebox.img``.
> +
> +  4. Create a text file ``config.txt`` on the SD card with the following content::
> +
> +         kernel=barebox.img
> +         enable_uart=1
> +         dtoverlay=pi3-miniuart-bt
> +
> +     (For more information, refer to the `documentation for config.txt`_.)
> +
> +  5. Connect to board's UART (115200 8N1);
>       Use PIN6 (GND), PIN8 (UART_TX), PIN10 (UART_RX) pins.
>  
> -  4. Turn board's power on.
> +  6. Turn board's power on.
> +
> +.. _Raspberry Pi firmware: https://codeload.github.com/raspberrypi/firmware/zip/80e1fbeb78f9df06701d28c0ed3a3060a3f557ef
> +.. _documentation for config.txt: https://www.raspberrypi.org/documentation/configuration/config-txt/
> -- 
> 2.11.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From l.stach at pengutronix.de  Tue Apr 10 03:34:54 2018
From: l.stach at pengutronix.de (Lucas Stach)
Date: Tue, 10 Apr 2018 12:34:54 +0200
Subject: [PATCH v3 07/10] ARM: install HYP vectors at PBL and Barebox entry
In-Reply-To: <20180405074224.mvjlnvmwfhgmn3m3@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-7-l.stach@pengutronix.de>
 <20180405074224.mvjlnvmwfhgmn3m3@pengutronix.de>
Message-ID: <1523356494.4981.3.camel@pengutronix.de>

Am Donnerstag, den 05.04.2018, 09:42 +0200 schrieb Sascha Hauer:
> On Mon, Mar 26, 2018 at 09:20:22PM +0200, Lucas Stach wrote:
> > If the CPU was already in HYP mode when entering the PBL, install a
> > simple trap handler to allow to get back from SVC to HYP before
> > switching to HYP mode.
> > 
> > As the vectors are part of the currently running binary, we need to
> > do the same setup when starting the real Barebox binary, as the PBL
> > setup vectors might get overwritten. To do this we trap into HYP mode
> > just before jumping to Barebox and then re-do the vector setup and
> > SVC switch as the first thing in Barebox proper.
> > 
> > > > Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> > > > Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> > ---
> > ?arch/arm/cpu/lowlevel.S???| 3 +++
> > ?arch/arm/cpu/start-pbl.c??| 4 ++++
> > ?arch/arm/cpu/start.c??????| 3 +++
> > ?arch/arm/cpu/uncompress.c | 4 ++++
> > ?4 files changed, 14 insertions(+)
> > 
> > diff --git a/arch/arm/cpu/lowlevel.S b/arch/arm/cpu/lowlevel.S
> > index 43665981e48b..13dfe496ad17 100644
> > --- a/arch/arm/cpu/lowlevel.S
> > +++ b/arch/arm/cpu/lowlevel.S
> > @@ -8,6 +8,9 @@ ENTRY(arm_cpu_lowlevel_init)
> > > > ?	/* save lr, since it may be banked away with a processor mode change */
> > > > > > ?	mov	r2, lr
> > ?
> > > > +	/* careful: the hyp install corrupts r0 and r1 */
> > > > > > +	bl	__hyp_install
> > +
> > > > ?	/* set the cpu to SVC32 mode, mask irq and fiq */
> > > > > > ?	mrs	r12, cpsr
> > > > > > ?	eor	r12, r12, #HYP_MODE
> > diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c
> > index e851b4a2da5e..e0793579e2e8 100644
> > --- a/arch/arm/cpu/start-pbl.c
> > +++ b/arch/arm/cpu/start-pbl.c
> > @@ -26,6 +26,7 @@
> > ?#include <asm/barebox-arm-head.h>
> > ?#include <asm-generic/memory_layout.h>
> > ?#include <asm/sections.h>
> > +#include <asm/secure.h>
> > ?#include <asm/pgtable.h>
> > ?#include <asm/cache.h>
> > ?#include <asm/unaligned.h>
> > @@ -100,5 +101,8 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
> > > > ?	else
> > > > ?		barebox = (void *)barebox_base;
> > ?
> > > > +	if (__boot_cpu_mode == HYP_MODE)
> > > > +		armv7_switch_to_hyp();
> > +
> > > > ?	barebox(membase, memsize, boarddata);
> > ?}
> > diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> > index 171e6ad0eb7a..a0db6436f387 100644
> > --- a/arch/arm/cpu/start.c
> > +++ b/arch/arm/cpu/start.c
> > @@ -24,6 +24,7 @@
> > ?#include <asm/barebox-arm-head.h>
> > ?#include <asm-generic/memory_layout.h>
> > ?#include <asm/sections.h>
> > +#include <asm/secure.h>
> > ?#include <asm/unaligned.h>
> > ?#include <asm/cache.h>
> > ?#include <memory.h>
> > @@ -145,6 +146,8 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
> > > > ?	unsigned long malloc_start, malloc_end;
> > > > ?	unsigned long barebox_size = barebox_image_size + MAX_BSS_SIZE;
> > ?
> > +	armv7_hyp_install();
> 
> Calling a armv7 specific function in a generic code path is not so nice.
> If this is really necessary then I suggest to #ifdef it here rather than
> in the header file (where armv7_hyp_install() expands to a noop for
> armv8. And what about the older architectures? A quick test revealed
> this works on armv5, but is this intentional or by accident?

Yep, it is coded to be a quick return on older < ARMv7 with the
executed instructions being compatible. I'll still change this to a
IS_ENABLED condition, as this might save some code size if only !ARMv7
arches are enabled in the config.

Thanks,
Lucas


From l.stach at pengutronix.de  Tue Apr 10 03:53:32 2018
From: l.stach at pengutronix.de (Lucas Stach)
Date: Tue, 10 Apr 2018 12:53:32 +0200
Subject: [PATCH v3 04/10] ARM: add file for HYP mode related setup
In-Reply-To: <20180405075402.gbplqqwoubu7cqpg@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-4-l.stach@pengutronix.de>
 <20180405075402.gbplqqwoubu7cqpg@pengutronix.de>
Message-ID: <1523357612.4981.5.camel@pengutronix.de>

Am Donnerstag, den 05.04.2018, 09:54 +0200 schrieb Sascha Hauer:
> On Mon, Mar 26, 2018 at 09:20:19PM +0200, Lucas Stach wrote:
> > This adds routines to add hyp mode vectors and switch back to HYP
> > mode from SVC. This is needed in both the PBL and Barebox proper.
> > 
> > > > Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> > > > Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> > ---
> > v3:
> > - fix whitespace
> > - use __BARE_INIT
> > ---
> > ?arch/arm/cpu/Makefile?????????|???4 ++
> > ?arch/arm/cpu/hyp.S????????????| 116 ++++++++++++++++++++++++++++++++++++++++++
> > ?arch/arm/cpu/sm_as.S??????????|??11 ----
> > ?arch/arm/include/asm/secure.h |???8 +++
> > ?4 files changed, 128 insertions(+), 11 deletions(-)
> > ?create mode 100644 arch/arm/cpu/hyp.S
> > 
> > diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
> > index 13fe12c31f6f..f86dff975bb4 100644
> > --- a/arch/arm/cpu/Makefile
> > +++ b/arch/arm/cpu/Makefile
> > @@ -9,6 +9,10 @@ obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o
> > ?obj-$(CONFIG_MMU) += mmu.o mmu-early.o
> > ?pbl-$(CONFIG_MMU) += mmu-early.o
> > ?lwl-y += lowlevel.o
> > +obj-y += hyp.o
> > +AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> > +pbl-y += hyp.o
> > +AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> > ?endif
> > ?
> > ?obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o
> > diff --git a/arch/arm/cpu/hyp.S b/arch/arm/cpu/hyp.S
> > new file mode 100644
> > index 000000000000..1314b56eab25
> > --- /dev/null
> > +++ b/arch/arm/cpu/hyp.S
> > @@ -0,0 +1,116 @@
> > +#include <linux/linkage.h>
> > +#include <asm/system.h>
> > +#include <asm/opcodes-virt.h>
> > +#include <init.h>
> > +
> > +.arch_extension sec
> > +.arch_extension virt
> > +
> > +__BARE_INIT
> > +
> > +.data
> > > > +	.align??2
> > +ENTRY(__boot_cpu_mode)
> > > > +	.long???0
> > +.text
> > +
> > +ENTRY(__hyp_install)
> > > > > > +	mrs	r12, cpsr
> > > > > > +	and	r12, r12, #MODE_MASK
> > +
> > > > +	@ Save the initial CPU state
> > > > > > +	adr	r0, .L__boot_cpu_mode_offset
> > > > > > +	ldr	r1, [r0]
> > +	str	r12, [r0, r1]
> 
> Naa, this won't work. You save the cpsr value in __boot_cpu_mode, but
> this variable exists both in PBL and regular barebox, __hyp_install
> is called multiple times and cpsr is modified right after saving it.

It does. ;)

I guess its non-obvious from the code flow, but what we do is to drop
down to SVC in the PBL, then jump back to HYP before starting barebox
proper and the dropping down to SVC again on barebox entry.
All in all this is less-than-pretty, but IMHO it's the lesser evil than
trying to implement some communication channel from PBL to barebox
proper to pass information like this.

So I guess this code needs some more comments...

Regards,
Lucas


From andrew.smirnov at gmail.com  Tue Apr 10 16:38:05 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:38:05 -0700
Subject: [PATCH] ARM: Make use of ALIGN_DOWN macro in barebox-arm.h
Message-ID: <20180410233805.4191-1-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/include/asm/barebox-arm.h | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index 4b270e7de..67e4d964d 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -114,8 +114,7 @@ static inline unsigned long arm_mem_ttb(unsigned long membase,
 					unsigned long endmem)
 {
 	endmem = arm_mem_stack(membase, endmem);
-	endmem &= ~(SZ_16K - 1);
-	endmem -= SZ_16K;
+	endmem = ALIGN_DOWN(endmem, SZ_16K) - SZ_16K;
 
 	return endmem;
 }
@@ -138,7 +137,7 @@ static inline unsigned long arm_mem_ramoops(unsigned long membase,
 	endmem = arm_mem_ttb(membase, endmem);
 #ifdef CONFIG_FS_PSTORE_RAMOOPS
 	endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
-	endmem &= ~(SZ_4K - 1); /* Align to 4K */
+	endmem = ALIGN_DOWN(endmem, SZ_4K);
 #endif
 
 	return endmem;
@@ -151,9 +150,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
 	endmem = arm_mem_ramoops(membase, endmem);
 
 	if (IS_ENABLED(CONFIG_RELOCATABLE)) {
-		endmem -= size;
-		endmem &= ~(SZ_1M - 1);
-		return endmem;
+		return ALIGN_DOWN(endmem - size, SZ_1M);
 	} else {
 		if (TEXT_BASE >= membase && TEXT_BASE < endmem)
 			return TEXT_BASE;
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:39:43 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:39:43 -0700
Subject: [PATCH] pinctrl-vf610: Make use of BIT macro
Message-ID: <20180410233943.4372-1-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 drivers/pinctrl/pinctrl-vf610.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
index 4234263d3..a46b0e2ca 100644
--- a/drivers/pinctrl/pinctrl-vf610.c
+++ b/drivers/pinctrl/pinctrl-vf610.c
@@ -29,9 +29,9 @@
 enum {
 	PINCTRL_VF610_MUX_LINE_SIZE = 20,
 
-	PINCTRL_VF610_IBE = 1 << 0,
-	PINCTRL_VF610_OBE = 1 << 1,
-	PINCTRL_VF610_xBE = 0b11,
+	PINCTRL_VF610_IBE = BIT(0),
+	PINCTRL_VF610_OBE = BIT(1),
+	PINCTRL_VF610_xBE = PINCTRL_VF610_OBE | PINCTRL_VF610_IBE,
 };
 
 struct pinctrl_vf610 {
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:40:37 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:40:37 -0700
Subject: [PATCH 1/2] i.MX: vf610-twr: Print '>' when DEBUG_LL is enabled
Message-ID: <20180410234038.4513-1-andrew.smirnov@gmail.com>

Majority of others boards prints '>' as soon as DEBUG_LL related
configuration is done, so do so for VF610-TWR as well.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/freescale-vf610-twr/lowlevel.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
index a043dd421..65956fdd2 100644
--- a/arch/arm/boards/freescale-vf610-twr/lowlevel.c
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -22,6 +22,8 @@ static inline void setup_uart(void)
 	writel(0, iomuxbase + 0x0380);
 
 	vf610_uart_setup_ll();
+
+	putc_ll('>');
 }
 
 extern char __dtb_vf610_twr_start[];
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:40:38 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:40:38 -0700
Subject: [PATCH 2/2] i.MX: vf610-twr: Convert to use vf610_setup_pad()
In-Reply-To: <20180410234038.4513-1-andrew.smirnov@gmail.com>
References: <20180410234038.4513-1-andrew.smirnov@gmail.com>
Message-ID: <20180410234038.4513-2-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/freescale-vf610-twr/lowlevel.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
index 65956fdd2..8fec9f4b9 100644
--- a/arch/arm/boards/freescale-vf610-twr/lowlevel.c
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -14,13 +14,7 @@ static inline void setup_uart(void)
 	void __iomem *iomuxbase = IOMEM(VF610_IOMUXC_BASE_ADDR);
 
 	vf610_ungate_all_peripherals();
-
-	/*
-	 * VF610_PAD_PTB4__UART1_TX
-	 */
-	writel(VF610_UART_PAD_CTRL | (2 << 20), iomuxbase + 0x0068);
-	writel(0, iomuxbase + 0x0380);
-
+	vf610_setup_pad(iomuxbase, VF610_PAD_PTB4__UART1_TX);
 	vf610_uart_setup_ll();
 
 	putc_ll('>');
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:45:36 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:45:36 -0700
Subject: [PATCH] ARM: start: Avoid calling arm_mem_barebox_image() twice
Message-ID: <20180410234536.4914-1-andrew.smirnov@gmail.com>

Avoid calling arm_mem_barebox_image() twice by making barebox_base
function-wide in scope

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/cpu/start.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 68fff892e..64bd942ad 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -144,13 +144,11 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
 	unsigned long endmem = membase + memsize;
 	unsigned long malloc_start, malloc_end;
 	unsigned long barebox_size = barebox_image_size + MAX_BSS_SIZE;
-
-	if (IS_ENABLED(CONFIG_RELOCATABLE)) {
-		unsigned long barebox_base = arm_mem_barebox_image(membase,
-								   endmem,
-								   barebox_size);
+	unsigned long barebox_base = arm_mem_barebox_image(membase,
+							   endmem,
+							   barebox_size);
+	if (IS_ENABLED(CONFIG_RELOCATABLE))
 		relocate_to_adr(barebox_base);
-	}
 
 	setup_c();
 
@@ -160,8 +158,7 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
 
 	arm_stack_top = arm_mem_stack_top(membase, endmem);
 	arm_barebox_size = barebox_size;
-	malloc_end = arm_mem_barebox_image(membase, endmem,
-						arm_barebox_size);
+	malloc_end = barebox_base;
 
 	if (IS_ENABLED(CONFIG_MMU_EARLY)) {
 		unsigned long ttb = arm_mem_ttb(membase, endmem);
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:14 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:14 -0700
Subject: [PATCH 01/10] ARM: i.MX: esdctl: Use IOMEM instead of (void *)
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-2-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/esdctl.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 1eebc77b6..895761e73 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -498,9 +498,9 @@ void __noreturn imx1_barebox_entry(void *boarddata)
 	unsigned long base, size;
 
 	upper_or_coalesced_range(MX1_CSD0_BASE_ADDR,
-			imx_v1_sdram_size((void *)MX1_SDRAMC_BASE_ADDR, 0),
+			imx_v1_sdram_size(IOMEM(MX1_SDRAMC_BASE_ADDR), 0),
 			MX1_CSD1_BASE_ADDR,
-			imx_v1_sdram_size((void *)MX1_SDRAMC_BASE_ADDR, 1),
+			imx_v1_sdram_size(IOMEM(MX1_SDRAMC_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -511,9 +511,9 @@ void __noreturn imx25_barebox_entry(void *boarddata)
 	unsigned long base, size;
 
 	upper_or_coalesced_range(MX25_CSD0_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX25_ESDCTL_BASE_ADDR, 0),
+			imx_v2_sdram_size(IOMEM(MX25_ESDCTL_BASE_ADDR), 0),
 			MX25_CSD1_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX25_ESDCTL_BASE_ADDR, 1),
+			imx_v2_sdram_size(IOMEM(MX25_ESDCTL_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -523,12 +523,12 @@ void __noreturn imx27_barebox_entry(void *boarddata)
 {
 	unsigned long base, size;
 
-	imx_esdctl_v2_disable_default((void *)MX27_ESDCTL_BASE_ADDR);
+	imx_esdctl_v2_disable_default(IOMEM(MX27_ESDCTL_BASE_ADDR));
 
 	upper_or_coalesced_range(MX27_CSD0_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX27_ESDCTL_BASE_ADDR, 0),
+			imx_v2_sdram_size(IOMEM(MX27_ESDCTL_BASE_ADDR), 0),
 			MX27_CSD1_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX27_ESDCTL_BASE_ADDR, 1),
+			imx_v2_sdram_size(IOMEM(MX27_ESDCTL_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -538,12 +538,12 @@ void __noreturn imx31_barebox_entry(void *boarddata)
 {
 	unsigned long base, size;
 
-	imx_esdctl_v2_disable_default((void *)MX31_ESDCTL_BASE_ADDR);
+	imx_esdctl_v2_disable_default(IOMEM(MX31_ESDCTL_BASE_ADDR));
 
 	upper_or_coalesced_range(MX31_CSD0_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX31_ESDCTL_BASE_ADDR, 0),
+			imx_v2_sdram_size(IOMEM(MX31_ESDCTL_BASE_ADDR), 0),
 			MX31_CSD1_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX31_ESDCTL_BASE_ADDR, 1),
+			imx_v2_sdram_size(IOMEM(MX31_ESDCTL_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -553,12 +553,12 @@ void __noreturn imx35_barebox_entry(void *boarddata)
 {
 	unsigned long base, size;
 
-	imx_esdctl_v2_disable_default((void *)MX35_ESDCTL_BASE_ADDR);
+	imx_esdctl_v2_disable_default(IOMEM(MX35_ESDCTL_BASE_ADDR));
 
 	upper_or_coalesced_range(MX35_CSD0_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX35_ESDCTL_BASE_ADDR, 0),
+			imx_v2_sdram_size(IOMEM(MX35_ESDCTL_BASE_ADDR), 0),
 			MX35_CSD1_BASE_ADDR,
-			imx_v2_sdram_size((void *)MX35_ESDCTL_BASE_ADDR, 1),
+			imx_v2_sdram_size(IOMEM(MX35_ESDCTL_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -569,9 +569,9 @@ void __noreturn imx51_barebox_entry(void *boarddata)
 	unsigned long base, size;
 
 	upper_or_coalesced_range(MX51_CSD0_BASE_ADDR,
-			imx_v3_sdram_size((void *)MX51_ESDCTL_BASE_ADDR, 0),
+			imx_v3_sdram_size(IOMEM(MX51_ESDCTL_BASE_ADDR), 0),
 			MX51_CSD1_BASE_ADDR,
-			imx_v3_sdram_size((void *)MX51_ESDCTL_BASE_ADDR, 1),
+			imx_v3_sdram_size(IOMEM(MX51_ESDCTL_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -582,9 +582,9 @@ void __noreturn imx53_barebox_entry(void *boarddata)
 	unsigned long base, size;
 
 	upper_or_coalesced_range(MX53_CSD0_BASE_ADDR,
-			imx_v4_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 0),
+			imx_v4_sdram_size(IOMEM(MX53_ESDCTL_BASE_ADDR), 0),
 			MX53_CSD1_BASE_ADDR,
-			imx_v4_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 1),
+			imx_v4_sdram_size(IOMEM(MX53_ESDCTL_BASE_ADDR), 1),
 			&base, &size);
 
 	barebox_arm_entry(base, size, boarddata);
@@ -592,8 +592,8 @@ void __noreturn imx53_barebox_entry(void *boarddata)
 
 void __noreturn imx6q_barebox_entry(void *boarddata)
 {
-	u64 size_cs0 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 0);
-	u64 size_cs1 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 1);
+	u64 size_cs0 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 0);
+	u64 size_cs1 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 1);
 	u64 total    = size_cs0 + size_cs1;
 
 	resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
@@ -603,8 +603,8 @@ void __noreturn imx6q_barebox_entry(void *boarddata)
 
 void __noreturn imx6ul_barebox_entry(void *boarddata)
 {
-	u64 size_cs0 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 0);
-	u64 size_cs1 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 1);
+	u64 size_cs0 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 0);
+	u64 size_cs1 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 1);
 	u64 total    = size_cs0 + size_cs1;
 
 	resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:15 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:15 -0700
Subject: [PATCH 02/10] ARM: i.MX51: esdctl: Replace magic value with
 ESDMISC_DDR2_8_BANK
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-3-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/esdctl.c              | 2 +-
 arch/arm/mach-imx/include/mach/esdctl.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 895761e73..1d6fa2995 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -120,7 +120,7 @@ static inline unsigned long imx_v3_sdram_size(void __iomem *esdctlbase, int num)
 
 	size = imx_v2_sdram_size(esdctlbase, num);
 
-	if (readl(esdctlbase + IMX_ESDMISC) & (1 << 6))
+	if (readl(esdctlbase + IMX_ESDMISC) & ESDMISC_DDR2_8_BANK)
 		size *= 2;
 
 	if (size > SZ_256M)
diff --git a/arch/arm/mach-imx/include/mach/esdctl.h b/arch/arm/mach-imx/include/mach/esdctl.h
index 66dcc8974..53710b0f2 100644
--- a/arch/arm/mach-imx/include/mach/esdctl.h
+++ b/arch/arm/mach-imx/include/mach/esdctl.h
@@ -48,6 +48,7 @@
 #define ESDMISC_MDDR_MDIS		0x00000010
 #define ESDMISC_LHD			0x00000020
 #define ESDMISC_SDRAMRDY		0x80000000
+#define ESDMISC_DDR2_8_BANK		BIT(6)
 
 #define	ESDCFGx_tXP_MASK 		0x00600000
 #define ESDCFGx_tXP_1			0x00000000
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:17 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:17 -0700
Subject: [PATCH 04/10] ARM: i.MX6: esdctl: Factor out common code in
 imx6*_barebox_entry()
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-5-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/esdctl.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index a7114effa..eda8184a0 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -595,16 +595,20 @@ void __noreturn imx53_barebox_entry(void *boarddata)
 	barebox_arm_entry(base, size, boarddata);
 }
 
-void __noreturn imx6q_barebox_entry(void *boarddata)
+static void __noreturn
+imx6_barebox_entry(unsigned long membase, void *boarddata)
 {
-	barebox_arm_entry(0x10000000,
+	barebox_arm_entry(membase,
 			  imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR)),
 			  boarddata);
 }
 
+void __noreturn imx6q_barebox_entry(void *boarddata)
+{
+	imx6_barebox_entry(0x10000000, boarddata);
+}
+
 void __noreturn imx6ul_barebox_entry(void *boarddata)
 {
-	barebox_arm_entry(0x80000000,
-			  imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR)),
-			  boarddata);
+	imx6_barebox_entry(0x80000000, boarddata);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:13 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:13 -0700
Subject: [PATCH 00/10] Vybrid MMDC support and misc ESDCTL fixes
Message-ID: <20180410235323.5440-1-andrew.smirnov@gmail.com>

Everyone:

This series is a bit of code I developed to support automatic
configured DRAM size detection on Vybrid platform as well as some
small fixes/cleanup I made while looking at esdctl.c.

All feedback is wellcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (10):
  ARM: i.MX: esdctl: Use IOMEM instead of (void *)
  ARM: i.MX51: esdctl: Replace magic value with ESDMISC_DDR2_8_BANK
  ARM: i.MX6: esdctl: Share memory size calculation code
  ARM: i.MX6: esdctl: Factor out common code in imx6*_barebox_entry()
  ARM: i.MX6: esdctl: Use symbolic constants for RAM base address
  ARM: i.MX: esdctl: Make use of min_t()
  ARM: i.MX: esdctl: Introduce memory_sdram_size()
  ARM: i.MX: esdctl: Add support for Vybrid's memory controller
  i.MX: vf610-twr: Make use of vf610_barebox_entry()
  i.MX: zii-vf610-dev: Make use of vf610_barebox_entry()

 arch/arm/boards/freescale-vf610-twr/lowlevel.c |   5 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c      |   2 +-
 arch/arm/boards/zii-vf610-dev/lowlevel.c       |   3 +-
 arch/arm/dts/vf610-ddrmc.dtsi                  |  15 +++
 arch/arm/dts/vf610-twr.dts                     |   1 +
 arch/arm/dts/vf610-zii-dev.dtsi                |   4 +-
 arch/arm/mach-imx/esdctl.c                     | 144 ++++++++++++++-----------
 arch/arm/mach-imx/include/mach/esdctl.h        |   2 +
 arch/arm/mach-imx/include/mach/imx6-regs.h     |   4 +-
 arch/arm/mach-imx/include/mach/vf610-ddrmc.h   |  18 ++++
 arch/arm/mach-imx/include/mach/vf610-regs.h    |   2 +
 include/memory.h                               |   8 ++
 12 files changed, 141 insertions(+), 67 deletions(-)
 create mode 100644 arch/arm/dts/vf610-ddrmc.dtsi
 create mode 100644 arch/arm/mach-imx/include/mach/vf610-ddrmc.h

-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:16 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:16 -0700
Subject: [PATCH 03/10] ARM: i.MX6: esdctl: Share memory size calculation code
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-4-andrew.smirnov@gmail.com>

Code for calculating total amount of memory found in
imx6_mmdc_add_mem(), imx6q_barebox_entry() and imx6ul_barebox_entry()
is exaclty the same, so refactor the code to avoid duplication.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/esdctl.c | 35 ++++++++++++++++-------------------
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 1d6fa2995..a7114effa 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -171,7 +171,7 @@ static inline unsigned long imx_v4_sdram_size(void __iomem *esdctlbase, int cs)
  * MMDC - found on i.MX6
  */
 
-static inline u64 imx6_mmdc_sdram_size(void __iomem *mmdcbase, int cs)
+static inline u64 __imx6_mmdc_sdram_size(void __iomem *mmdcbase, int cs)
 {
 	u32 ctlval = readl(mmdcbase + MDCTL);
 	u32 mdmisc = readl(mmdcbase + MDMISC);
@@ -286,7 +286,7 @@ static void imx_esdctl_v4_add_mem(void *esdctlbase, struct imx_esdctl_data *data
  */
 #define IMX6_MAX_SDRAM_SIZE 0xF0000000
 
-static void imx6_mmdc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
+static inline resource_size_t imx6_mmdc_sdram_size(void __iomem *mmdcbase)
 {
 	/*
 	 * It is possible to have a configuration in which both chip
@@ -296,14 +296,19 @@ static void imx6_mmdc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
 	 * IMX6_MAX_SDRAM_SIZE bytes of memory available.
 	 */
 
-	u64 size_cs0 = imx6_mmdc_sdram_size(mmdcbase, 0);
-	u64 size_cs1 = imx6_mmdc_sdram_size(mmdcbase, 1);
+	u64 size_cs0 = __imx6_mmdc_sdram_size(mmdcbase, 0);
+	u64 size_cs1 = __imx6_mmdc_sdram_size(mmdcbase, 1);
 	u64 total    = size_cs0 + size_cs1;
 
 	resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
 
+	return size;
+}
+
+static void imx6_mmdc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
+{
 	arm_add_mem_device("ram0", data->base0,
-			size);
+			   imx6_mmdc_sdram_size(mmdcbase));
 }
 
 static int imx_esdctl_probe(struct device_d *dev)
@@ -592,22 +597,14 @@ void __noreturn imx53_barebox_entry(void *boarddata)
 
 void __noreturn imx6q_barebox_entry(void *boarddata)
 {
-	u64 size_cs0 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 0);
-	u64 size_cs1 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 1);
-	u64 total    = size_cs0 + size_cs1;
-
-	resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
-
-	barebox_arm_entry(0x10000000, size, boarddata);
+	barebox_arm_entry(0x10000000,
+			  imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR)),
+			  boarddata);
 }
 
 void __noreturn imx6ul_barebox_entry(void *boarddata)
 {
-	u64 size_cs0 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 0);
-	u64 size_cs1 = imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR), 1);
-	u64 total    = size_cs0 + size_cs1;
-
-	resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
-
-	barebox_arm_entry(0x80000000, size, boarddata);
+	barebox_arm_entry(0x80000000,
+			  imx6_mmdc_sdram_size(IOMEM(MX6_MMDC_P0_BASE_ADDR)),
+			  boarddata);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:19 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:19 -0700
Subject: [PATCH 06/10] ARM: i.MX: esdctl: Make use of min_t()
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-7-andrew.smirnov@gmail.com>

Use min_t() instead of explicit if ().

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/esdctl.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 3cd7c5738..a4eb3f196 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -77,10 +77,7 @@ static inline unsigned long imx_v1_sdram_size(void __iomem *esdctlbase, int num)
 
 	size = (1 << cols) * (1 << rows) * banks * width;
 
-	if (size > SZ_64M)
-		size = SZ_64M;
-
-	return size;
+	return min_t(unsigned long, size, SZ_64M);
 }
 
 /*
@@ -105,10 +102,7 @@ static inline unsigned long imx_v2_sdram_size(void __iomem *esdctlbase, int num)
 
 	size = (1 << cols) * (1 << rows) * banks * width;
 
-	if (size > SZ_256M)
-		size = SZ_256M;
-
-	return size;
+	return min_t(unsigned long, size, SZ_256M);
 }
 
 /*
@@ -123,10 +117,7 @@ static inline unsigned long imx_v3_sdram_size(void __iomem *esdctlbase, int num)
 	if (readl(esdctlbase + IMX_ESDMISC) & ESDMISC_DDR2_8_BANK)
 		size *= 2;
 
-	if (size > SZ_256M)
-		size = SZ_256M;
-
-	return size;
+	return min_t(unsigned long, size, SZ_256M);
 }
 
 /*
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:18 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:18 -0700
Subject: [PATCH 05/10] ARM: i.MX6: esdctl: Use symbolic constants for RAM base
 address
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-6-andrew.smirnov@gmail.com>

Use symbolic constants for RAM base address, to do that rename
MX6_MMDC_PORT0_BASE_ADDR to MX6_MMDC_PORT01_BASE_ADDR to distinguish
it from SoCs with only one DDR controller (i.MX6UL) where port 0 will
always be at 0x80000000.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c  | 2 +-
 arch/arm/mach-imx/esdctl.c                 | 8 ++++----
 arch/arm/mach-imx/include/mach/imx6-regs.h | 4 +++-
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
index 22ffdf85e..c9ef16ae0 100644
--- a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
+++ b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
@@ -304,7 +304,7 @@ ENTRY_FUNCTION(start_imx6_zii_rdu2, r0, r1, r2)
 	 * When still running in SRAM, we need to setup the DRAM now and load
 	 * the remaining image.
 	 */
-	if (get_pc() < MX6_MMDC_PORT0_BASE_ADDR)
+	if (get_pc() < MX6_MMDC_PORT01_BASE_ADDR)
 		rdu2_sram_setup();
 
 	if (__imx6_cpu_revision() == IMX_CHIP_REV_2_0)
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index eda8184a0..3cd7c5738 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -378,12 +378,12 @@ static __maybe_unused struct imx_esdctl_data imx53_data = {
 };
 
 static __maybe_unused struct imx_esdctl_data imx6q_data = {
-	.base0 = MX6_MMDC_PORT0_BASE_ADDR,
+	.base0 = MX6_MMDC_PORT01_BASE_ADDR,
 	.add_mem = imx6_mmdc_add_mem,
 };
 
 static __maybe_unused struct imx_esdctl_data imx6ul_data = {
-	.base0 = 0x80000000,
+	.base0 = MX6_MMDC_PORT0_BASE_ADDR,
 	.add_mem = imx6_mmdc_add_mem,
 };
 
@@ -605,10 +605,10 @@ imx6_barebox_entry(unsigned long membase, void *boarddata)
 
 void __noreturn imx6q_barebox_entry(void *boarddata)
 {
-	imx6_barebox_entry(0x10000000, boarddata);
+	imx6_barebox_entry(MX6_MMDC_PORT01_BASE_ADDR, boarddata);
 }
 
 void __noreturn imx6ul_barebox_entry(void *boarddata)
 {
-	imx6_barebox_entry(0x80000000, boarddata);
+	imx6_barebox_entry(MX6_MMDC_PORT0_BASE_ADDR, boarddata);
 }
diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h
index ac2aa2109..1ba22b5bc 100644
--- a/arch/arm/mach-imx/include/mach/imx6-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx6-regs.h
@@ -117,6 +117,8 @@
 
 #define MX6_SATA_BASE_ADDR		0x02200000
 
-#define MX6_MMDC_PORT0_BASE_ADDR	0x10000000
+#define MX6_MMDC_PORT01_BASE_ADDR	0x10000000
+#define MX6_MMDC_PORT0_BASE_ADDR	0x80000000
+
 
 #endif /* __MACH_IMX6_REGS_H */
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:22 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:22 -0700
Subject: [PATCH 09/10] i.MX: vf610-twr: Make use of vf610_barebox_entry()
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-10-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/freescale-vf610-twr/lowlevel.c | 5 ++---
 arch/arm/dts/vf610-twr.dts                     | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
index deabe4e37..a043dd421 100644
--- a/arch/arm/boards/freescale-vf610-twr/lowlevel.c
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -3,6 +3,7 @@
 #include <mach/generic.h>
 #include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
+#include <mach/esdctl.h>
 #include <mach/vf610-regs.h>
 #include <mach/clock-vf610.h>
 #include <mach/iomux-vf610.h>
@@ -27,13 +28,11 @@ extern char __dtb_vf610_twr_start[];
 
 ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2)
 {
-	void *fdt;
 
 	vf610_cpu_lowlevel_init();
 
 	if (IS_ENABLED(CONFIG_DEBUG_LL))
 		setup_uart();
 
-	fdt = __dtb_vf610_twr_start + get_runtime_offset();
-	barebox_arm_entry(0x80000000, SZ_128M, fdt);
+	vf610_barebox_entry(__dtb_vf610_twr_start + get_runtime_offset());
 }
diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
index 5947fdbda..2456ade5f 100644
--- a/arch/arm/dts/vf610-twr.dts
+++ b/arch/arm/dts/vf610-twr.dts
@@ -8,6 +8,7 @@
  */
 
 #include <arm/vf610-twr.dts>
+#include "vf610-ddrmc.dtsi"
 
 &usbdev0 {
 	status = "disabled";
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:20 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:20 -0700
Subject: [PATCH 07/10] ARM: i.MX: esdctl: Introduce memory_sdram_size()
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-8-andrew.smirnov@gmail.com>

Introduce memory_sdram_size() - subroutine to calculate size of SDRAM
chip base on its parameters such as # or rows, columns, banks and bus
width.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/esdctl.c | 14 ++++----------
 include/memory.h           |  8 ++++++++
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index a4eb3f196..b8f048ee6 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -75,7 +75,7 @@ static inline unsigned long imx_v1_sdram_size(void __iomem *esdctlbase, int num)
 	if (ctlval & (1 << 17))
 		width = 4;
 
-	size = (1 << cols) * (1 << rows) * banks * width;
+	size = memory_sdram_size(cols, rows, banks, width);
 
 	return min_t(unsigned long, size, SZ_64M);
 }
@@ -100,7 +100,7 @@ static inline unsigned long imx_v2_sdram_size(void __iomem *esdctlbase, int num)
 	if ((ctlval & ESDCTL0_DSIZ_MASK) == ESDCTL0_DSIZ_31_0)
 		width = 4;
 
-	size = (1 << cols) * (1 << rows) * banks * width;
+	size = memory_sdram_size(cols, rows, banks, width);
 
 	return min_t(unsigned long, size, SZ_256M);
 }
@@ -127,7 +127,6 @@ static inline unsigned long imx_v4_sdram_size(void __iomem *esdctlbase, int cs)
 {
 	u32 ctlval = readl(esdctlbase + ESDCTL_V4_ESDCTL0);
 	u32 esdmisc = readl(esdctlbase + ESDCTL_V4_ESDMISC);
-	unsigned long size;
 	int rows, cols, width = 2, banks = 8;
 
 	if (cs == 0 && !(ctlval & ESDCTL_V4_ESDCTLx_SDE0))
@@ -153,9 +152,7 @@ static inline unsigned long imx_v4_sdram_size(void __iomem *esdctlbase, int cs)
 	if (esdmisc & ESDCTL_V4_ESDMISC_BANKS_4)
 		banks = 4;
 
-	size = (1 << cols) * (1 << rows) * banks * width;
-
-	return size;
+	return memory_sdram_size(cols, rows, banks, width);
 }
 
 /*
@@ -166,7 +163,6 @@ static inline u64 __imx6_mmdc_sdram_size(void __iomem *mmdcbase, int cs)
 {
 	u32 ctlval = readl(mmdcbase + MDCTL);
 	u32 mdmisc = readl(mmdcbase + MDMISC);
-	u64 size;
 	int rows, cols, width = 2, banks = 8;
 
 	if (cs == 0 && !(ctlval & MMDCx_MDCTL_SDE0))
@@ -192,9 +188,7 @@ static inline u64 __imx6_mmdc_sdram_size(void __iomem *mmdcbase, int cs)
 	if (mdmisc & MMDCx_MDMISC_DDR_4_BANKS)
 		banks = 4;
 
-	size = (u64)(1 << cols) * (1 << rows) * banks * width;
-
-	return size;
+	return memory_sdram_size(cols, rows, banks, width);
 }
 
 static void add_mem(unsigned long base0, unsigned long size0,
diff --git a/include/memory.h b/include/memory.h
index 56d16d20c..73ee7661e 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -32,4 +32,12 @@ void memory_bank_find_space(struct memory_bank *bank, resource_size_t *retstart,
 int memory_bank_first_find_space(resource_size_t *retstart,
 				 resource_size_t *retend);
 
+static inline u64 memory_sdram_size(unsigned int cols,
+				    unsigned int rows,
+				    unsigned int banks,
+				    unsigned int width)
+{
+	return (u64)banks * width << (rows + cols);
+}
+
 #endif
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:21 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:21 -0700
Subject: [PATCH 08/10] ARM: i.MX: esdctl: Add support for Vybrid's memory
 controller
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-9-andrew.smirnov@gmail.com>

Add code needed to dynamically detect the amount of RAM DDR controller
is configured to use as well as a simple entry function making use of
that functionality.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/dts/vf610-ddrmc.dtsi                | 15 +++++++++++
 arch/arm/mach-imx/esdctl.c                   | 38 ++++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/esdctl.h      |  1 +
 arch/arm/mach-imx/include/mach/vf610-ddrmc.h | 18 +++++++++++++
 arch/arm/mach-imx/include/mach/vf610-regs.h  |  2 ++
 5 files changed, 74 insertions(+)
 create mode 100644 arch/arm/dts/vf610-ddrmc.dtsi
 create mode 100644 arch/arm/mach-imx/include/mach/vf610-ddrmc.h

diff --git a/arch/arm/dts/vf610-ddrmc.dtsi b/arch/arm/dts/vf610-ddrmc.dtsi
new file mode 100644
index 000000000..772131ec2
--- /dev/null
+++ b/arch/arm/dts/vf610-ddrmc.dtsi
@@ -0,0 +1,15 @@
+/*
+ * Include file to switch board DTS form using hardcoded memory node
+ * to dynamic memory size detection based on DDR controller settings
+ */
+
+/ {
+	/delete-node/ memory;
+};
+
+&aips1 {
+	ddrmc at 400ae000 {
+		compatible = "fsl,vf610-ddrmc";
+		reg = <0x400ae000 0x1000>;
+	};
+};
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index b8f048ee6..c1680d5ff 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -37,6 +37,7 @@
 #include <mach/imx51-regs.h>
 #include <mach/imx53-regs.h>
 #include <mach/imx6-regs.h>
+#include <mach/vf610-ddrmc.h>
 
 struct imx_esdctl_data {
 	unsigned long base0;
@@ -296,6 +297,28 @@ static void imx6_mmdc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
 			   imx6_mmdc_sdram_size(mmdcbase));
 }
 
+static inline resource_size_t vf610_ddrmc_sdram_size(void __iomem *ddrmc)
+{
+	const u32 cr01 = readl(ddrmc + DDRMC_CR(1));
+	const u32 cr73 = readl(ddrmc + DDRMC_CR(73));
+	const u32 cr78 = readl(ddrmc + DDRMC_CR(78));
+
+	unsigned int rows, cols, width, banks;
+
+	rows  = DDRMC_CR01_MAX_ROW_REG(cr01) - DDRMC_CR73_ROW_DIFF(cr73);
+	cols  = DDRMC_CR01_MAX_COL_REG(cr01) - DDRMC_CR73_COL_DIFF(cr73);
+	banks = 1 << (3 - DDRMC_CR73_BANK_DIFF(cr73));
+	width = (cr78 & DDRMC_CR78_REDUC) ? sizeof(u8) : sizeof(u16);
+
+	return memory_sdram_size(cols, rows, banks, width);
+}
+
+static void vf610_ddrmc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
+{
+	arm_add_mem_device("ram0", data->base0,
+			   vf610_ddrmc_sdram_size(mmdcbase));
+}
+
 static int imx_esdctl_probe(struct device_d *dev)
 {
 	struct resource *iores;
@@ -372,6 +395,11 @@ static __maybe_unused struct imx_esdctl_data imx6ul_data = {
 	.add_mem = imx6_mmdc_add_mem,
 };
 
+static __maybe_unused struct imx_esdctl_data vf610_data = {
+	.base0 = VF610_RAM_BASE_ADDR,
+	.add_mem = vf610_ddrmc_add_mem,
+};
+
 static struct platform_device_id imx_esdctl_ids[] = {
 #ifdef CONFIG_ARCH_IMX1
 	{
@@ -430,6 +458,9 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
 	}, {
 		.compatible = "fsl,imx6q-mmdc",
 		.data = &imx6q_data
+	}, {
+		.compatible = "fsl,vf610-ddrmc",
+		.data = &vf610_data
 	}, {
 		/* sentinel */
 	}
@@ -597,3 +628,10 @@ void __noreturn imx6ul_barebox_entry(void *boarddata)
 {
 	imx6_barebox_entry(MX6_MMDC_PORT0_BASE_ADDR, boarddata);
 }
+
+void __noreturn vf610_barebox_entry(void *boarddata)
+{
+	barebox_arm_entry(VF610_RAM_BASE_ADDR,
+			  vf610_ddrmc_sdram_size(IOMEM(VF610_DDR_BASE_ADDR)),
+			  boarddata);
+}
diff --git a/arch/arm/mach-imx/include/mach/esdctl.h b/arch/arm/mach-imx/include/mach/esdctl.h
index 53710b0f2..117e2bbad 100644
--- a/arch/arm/mach-imx/include/mach/esdctl.h
+++ b/arch/arm/mach-imx/include/mach/esdctl.h
@@ -138,6 +138,7 @@ void __noreturn imx51_barebox_entry(void *boarddata);
 void __noreturn imx53_barebox_entry(void *boarddata);
 void __noreturn imx6q_barebox_entry(void *boarddata);
 void __noreturn imx6ul_barebox_entry(void *boarddata);
+void __noreturn vf610_barebox_entry(void *boarddata);
 void imx_esdctl_disable(void);
 #endif
 
diff --git a/arch/arm/mach-imx/include/mach/vf610-ddrmc.h b/arch/arm/mach-imx/include/mach/vf610-ddrmc.h
new file mode 100644
index 000000000..07feb036e
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/vf610-ddrmc.h
@@ -0,0 +1,18 @@
+#ifndef __MACH_DDRMC_H
+#define __MACH_DDRMC_H
+
+#include <mach/vf610-regs.h>
+
+
+#define DDRMC_CR(x)	((x) * 4)
+
+#define DDRMC_CR01_MAX_COL_REG(reg)	(((reg) >>  8) & 0b01111)
+#define DDRMC_CR01_MAX_ROW_REG(reg)	(((reg) >>  0) & 0b11111)
+#define DDRMC_CR73_COL_DIFF(reg)	(((reg) >> 16) & 0b00111)
+#define DDRMC_CR73_ROW_DIFF(reg)	(((reg) >>  8) & 0b00011)
+#define DDRMC_CR73_BANK_DIFF(reg)	(((reg) >>  0) & 0b00011)
+
+#define DDRMC_CR78_REDUC	BIT(8)
+
+
+#endif /* __MACH_MMDC_H */
diff --git a/arch/arm/mach-imx/include/mach/vf610-regs.h b/arch/arm/mach-imx/include/mach/vf610-regs.h
index 8be220b68..87772ee76 100644
--- a/arch/arm/mach-imx/include/mach/vf610-regs.h
+++ b/arch/arm/mach-imx/include/mach/vf610-regs.h
@@ -13,6 +13,8 @@
 #define VF610_AIPS0_BASE_ADDR		0x40000000
 #define VF610_AIPS1_BASE_ADDR		0x40080000
 
+#define VF610_RAM_BASE_ADDR		0x80000000
+
 /* AIPS 0 */
 #define VF610_MSCM_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00001000)
 #define VF610_MSCM_IR_BASE_ADDR		(VF610_AIPS0_BASE_ADDR + 0x00001800)
-- 
2.14.3



From andrew.smirnov at gmail.com  Tue Apr 10 16:53:23 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 10 Apr 2018 16:53:23 -0700
Subject: [PATCH 10/10] i.MX: zii-vf610-dev: Make use of vf610_barebox_entry()
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180410235323.5440-11-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/zii-vf610-dev/lowlevel.c | 3 ++-
 arch/arm/dts/vf610-zii-dev.dtsi          | 4 +++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boards/zii-vf610-dev/lowlevel.c b/arch/arm/boards/zii-vf610-dev/lowlevel.c
index c6663c141..f3d67501a 100644
--- a/arch/arm/boards/zii-vf610-dev/lowlevel.c
+++ b/arch/arm/boards/zii-vf610-dev/lowlevel.c
@@ -18,6 +18,7 @@
 #include <mach/generic.h>
 #include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
+#include <mach/esdctl.h>
 #include <mach/vf610-regs.h>
 #include <mach/clock-vf610.h>
 #include <mach/iomux-vf610.h>
@@ -133,5 +134,5 @@ ENTRY_FUNCTION(start_zii_vf610_dev, r0, r1, r2)
 		break;
 	}
 
-	barebox_arm_entry(0x80000000, SZ_512M, fdt + get_runtime_offset());
+	vf610_barebox_entry(fdt + get_runtime_offset());
 }
diff --git a/arch/arm/dts/vf610-zii-dev.dtsi b/arch/arm/dts/vf610-zii-dev.dtsi
index 4bf81451a..dc16280bc 100644
--- a/arch/arm/dts/vf610-zii-dev.dtsi
+++ b/arch/arm/dts/vf610-zii-dev.dtsi
@@ -40,7 +40,9 @@ n *     copy, modify, merge, publish, distribute, sublicense, and/or
  *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  *     OTHER DEALINGS IN THE SOFTWARE.
- */
+*/
+
+#include "vf610-ddrmc.dtsi"
 
 / {
 	audio_ext: mclk_osc {
-- 
2.14.3



From s.hauer at pengutronix.de  Wed Apr 11 01:12:40 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:12:40 +0200
Subject: [PATCH v2] ARM: Add Advantech imx6 board support
In-Reply-To: <1523274839.3785.25.camel@googlemail.com>
References: <1522934149.24545.3.camel@googlemail.com>
 <1523274839.3785.25.camel@googlemail.com>
Message-ID: <20180411081240.st6jjhg2vzq7g3gc@pengutronix.de>

On Mon, Apr 09, 2018 at 01:53:59PM +0200, Christoph Fritz wrote:
> Add support for Advantech i.MX6 SOM named ROM-7421.
> 
> Signed-off-by: Christoph Fritz <chf.fritz at googlemail.com>
> ---
> Changes since v0:
>  - distinguish between MMC environment names in pr_notice() board.c
>  - rework eMMC partition layout and don't use its hw-bootpartition for now
>  - purge writing clock registers
>  - rework and simplify lowlevel.c init and use imx6q_barebox_entry(fdt)
>  - s/linux,stdout-path/stdout-path in dts
>  - rework and simplify spi nor partition layout
>  - remove additional pinctrl subnode from dts
>  - remove setting of explicit ARCH_TEXT_BASE in Kconfig
>  - use bitop Macro for ar8035_phy_fixup()
>  - use imx_setup_pad() for early debug uart
> ---

Applied, thanks

Sascha

>  arch/arm/boards/Makefile                           |   1 +
>  arch/arm/boards/advantech-mx6/Makefile             |   2 +
>  arch/arm/boards/advantech-mx6/board.c              | 101 +++++++++
>  .../flash-header-advantech-rom-7421.imxcfg         |  66 ++++++
>  arch/arm/boards/advantech-mx6/lowlevel.c           |  56 +++++
>  arch/arm/configs/imx_v7_defconfig                  |   1 +
>  arch/arm/dts/Makefile                              |   1 +
>  arch/arm/dts/imx6dl-advantech-rom-7421.dts         | 225 +++++++++++++++++++++
>  arch/arm/mach-imx/Kconfig                          |   5 +
>  images/Makefile.imx                                |   5 +
>  10 files changed, 463 insertions(+)
>  create mode 100644 arch/arm/boards/advantech-mx6/Makefile
>  create mode 100644 arch/arm/boards/advantech-mx6/board.c
>  create mode 100644 arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
>  create mode 100644 arch/arm/boards/advantech-mx6/lowlevel.c
>  create mode 100755 arch/arm/dts/imx6dl-advantech-rom-7421.dts
> 
> diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
> index ca187cc..521f37d 100644
> --- a/arch/arm/boards/Makefile
> +++ b/arch/arm/boards/Makefile
> @@ -1,4 +1,5 @@
>  # keep sorted by CONFIG_* macro name.
> +obj-$(CONFIG_MACH_ADVANTECH_ROM_742X)		+= advantech-mx6/
>  obj-$(CONFIG_MACH_AFI_GF)			+= afi-gf/
>  obj-$(CONFIG_MACH_ANIMEO_IP)			+= animeo_ip/
>  obj-$(CONFIG_MACH_ARCHOSG9)			+= archosg9/
> diff --git a/arch/arm/boards/advantech-mx6/Makefile b/arch/arm/boards/advantech-mx6/Makefile
> new file mode 100644
> index 0000000..01c7a25
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/Makefile
> @@ -0,0 +1,2 @@
> +obj-y += board.o
> +lwl-y += lowlevel.o
> diff --git a/arch/arm/boards/advantech-mx6/board.c b/arch/arm/boards/advantech-mx6/board.c
> new file mode 100644
> index 0000000..4a30a84
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/board.c
> @@ -0,0 +1,101 @@
> +/*
> + * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <platform_data/eth-fec.h>
> +#include <bootsource.h>
> +#include <mach/bbu.h>
> +
> +static int ar8035_phy_fixup(struct phy_device *dev)
> +{
> +	u16 val;
> +
> +	/* Ar803x phy SmartEEE feature cause link status generates glitch,
> +	 * which cause ethernet link down/up issue, so disable SmartEEE
> +	 */
> +	phy_write(dev, 0xd, 0x3);
> +	phy_write(dev, 0xe, 0x805d);
> +	phy_write(dev, 0xd, 0x4003);
> +
> +	val = phy_read(dev, 0xe);
> +	phy_write(dev, 0xe, val & ~BIT(8));
> +
> +	/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
> +	phy_write(dev, 0xd, 0x7);
> +	phy_write(dev, 0xe, 0x8016);
> +	phy_write(dev, 0xd, 0x4007);
> +
> +	val = phy_read(dev, 0xe);
> +	val &= 0xffe3;
> +	val |= 0x18;
> +	phy_write(dev, 0xe, val);
> +
> +	/* introduce tx clock delay */
> +	phy_write(dev, 0x1d, 0x5);
> +	val = phy_read(dev, 0x1e);
> +	val |= 0x0100;
> +	phy_write(dev, 0x1e, val);
> +
> +	return 0;
> +}
> +
> +static int advantech_mx6_devices_init(void)
> +{
> +	int ret;
> +	char *environment_path, *envdev;
> +
> +	if (!of_machine_is_compatible("advantech,imx6dl-rom-7421"))
> +		return 0;
> +
> +	phy_register_fixup_for_uid(0x004dd072, 0xffffffef, ar8035_phy_fixup);
> +
> +	switch (bootsource_get()) {
> +	case BOOTSOURCE_MMC:
> +		environment_path = basprintf("/chosen/environment-sd%d",
> +					     bootsource_get_instance() + 1);
> +		if (bootsource_get_instance() + 1 == 4)
> +			envdev = "eMMC";
> +		else if (bootsource_get_instance() + 1 == 2)
> +			envdev = "microSD";
> +		else
> +			envdev = "MMC";
> +		break;
> +	case BOOTSOURCE_SPI:
> +		envdev = "SPI";
> +		environment_path = basprintf("/chosen/environment-spi");
> +		break;
> +	default:
> +		environment_path = basprintf("/chosen/environment-sd4");
> +		envdev = "MMC";
> +		break;
> +	}
> +
> +	if (environment_path) {
> +		ret = of_device_enable_path(environment_path);
> +		if (ret < 0)
> +			pr_warn("Failed to enable env partition '%s' (%d)\n",
> +				environment_path, ret);
> +		free(environment_path);
> +	}
> +
> +	pr_notice("Using environment in %s\n", envdev);
> +
> +	imx6_bbu_internal_mmc_register_handler("mmc3", "/dev/mmc3",
> +						BBU_HANDLER_FLAG_DEFAULT);
> +
> +	return 0;
> +}
> +device_initcall(advantech_mx6_devices_init);
> diff --git a/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> new file mode 100644
> index 0000000..996ecc7
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> @@ -0,0 +1,66 @@
> +soc imx6
> +loadaddr 0x10000000
> +dcdofs 0x400
> +
> +wm 32 0x020e0774 0x000C0000
> +wm 32 0x020e0754 0x00000000
> +wm 32 0x020e04ac 0x00000030
> +wm 32 0x020e04b0 0x00000030
> +wm 32 0x020e0464 0x00000030
> +wm 32 0x020e0490 0x00000030
> +wm 32 0x020e074c 0x00000030
> +wm 32 0x020e0494 0x00000030
> +wm 32 0x020e04a0 0x00000000
> +wm 32 0x020e04b4 0x00000030
> +wm 32 0x020e04b8 0x00000030
> +wm 32 0x020e076c 0x00000030
> +wm 32 0x020e0750 0x00020000
> +wm 32 0x020e04bc 0x00000030
> +wm 32 0x020e04c0 0x00000030
> +wm 32 0x020e04c4 0x00000030
> +wm 32 0x020e04c8 0x00000030
> +wm 32 0x020e0760 0x00020000
> +wm 32 0x020e0764 0x00000030
> +wm 32 0x020e0770 0x00000030
> +wm 32 0x020e0778 0x00000030
> +wm 32 0x020e077c 0x00000030
> +wm 32 0x020e0470 0x00000030
> +wm 32 0x020e0474 0x00000030
> +wm 32 0x020e0478 0x00000030
> +wm 32 0x020e047c 0x00000030
> +wm 32 0x021b0800 0xa1390003
> +wm 32 0x021b080c 0x001F001F
> +wm 32 0x021b0810 0x001F001F
> +wm 32 0x021b083c 0x42480248
> +wm 32 0x021b0840 0x022C0234
> +wm 32 0x021b0848 0x3E404244
> +wm 32 0x021b0850 0x30302C30
> +wm 32 0x021b081c 0x33333333
> +wm 32 0x021b0820 0x33333333
> +wm 32 0x021b0824 0x33333333
> +wm 32 0x021b0828 0x33333333
> +wm 32 0x021b08b8 0x00000800
> +wm 32 0x021b0004 0x0002002D
> +wm 32 0x021b0008 0x00333030
> +wm 32 0x021b000c 0x3F435333
> +wm 32 0x021b0010 0xB68E8B63
> +wm 32 0x021b0014 0x01FF00DB
> +wm 32 0x021b0018 0x00001740
> +wm 32 0x021b001c 0x00008000
> +wm 32 0x021b002c 0x000026d2
> +wm 32 0x021b0030 0x00431023
> +wm 32 0x021b0040 0x00000017
> +wm 32 0x021b0000 0x83190000
> +wm 32 0x021b001c 0x04008032
> +wm 32 0x021b001c 0x00008033
> +wm 32 0x021b001c 0x00048031
> +wm 32 0x021b001c 0x05208030
> +wm 32 0x021b001c 0x04008040
> +wm 32 0x021b0020 0x00005800
> +wm 32 0x021b0818 0x00011117
> +wm 32 0x021b0004 0x0002556D
> +wm 32 0x021b0404 0x00011006
> +wm 32 0x021b001c 0x00000000
> +wm 32 0x020e0010 0xF00000CF
> +wm 32 0x020e0018 0x007F007F
> +wm 32 0x020e001c 0x007F007F
> diff --git a/arch/arm/boards/advantech-mx6/lowlevel.c b/arch/arm/boards/advantech-mx6/lowlevel.c
> new file mode 100644
> index 0000000..8921cd4
> --- /dev/null
> +++ b/arch/arm/boards/advantech-mx6/lowlevel.c
> @@ -0,0 +1,56 @@
> +/*
> + * Copyright (C) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <debug_ll.h>
> +#include <common.h>
> +#include <asm/barebox-arm-head.h>
> +#include <asm/barebox-arm.h>
> +#include <image-metadata.h>
> +#include <mach/generic.h>
> +#include <mach/esdctl.h>
> +#include <mach/iomux-mx6.h>
> +#include <linux/sizes.h>
> +
> +#include <linux/sizes.h>
> +#include <asm/barebox-arm-head.h>
> +#include <asm/barebox-arm.h>
> +static inline void setup_uart(void)
> +{
> +	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
> +
> +	imx6_ungate_all_peripherals();
> +
> +	imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT10__UART1_TXD);
> +
> +	imx6_uart_setup_ll();
> +
> +	putc_ll('>');
> +}
> +
> +extern char __dtb_imx6dl_advantech_rom_7421_start[];
> +
> +ENTRY_FUNCTION(start_advantech_imx6dl_rom_7421, r0, r1, r2)
> +{
> +	imx6_cpu_lowlevel_init();
> +
> +	relocate_to_current_adr();
> +	setup_c();
> +	barrier();
> +
> +	if (IS_ENABLED(CONFIG_DEBUG_LL))
> +		setup_uart();
> +
> +	imx6q_barebox_entry(__dtb_imx6dl_advantech_rom_7421_start);
> +}
> diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
> index 62d6238..7a563a5 100644
> --- a/arch/arm/configs/imx_v7_defconfig
> +++ b/arch/arm/configs/imx_v7_defconfig
> @@ -30,6 +30,7 @@ CONFIG_MACH_UDOO=y
>  CONFIG_MACH_VARISCITE_MX6=y
>  CONFIG_MACH_GW_VENTANA=y
>  CONFIG_MACH_CM_FX6=y
> +CONFIG_MACH_ADVANTECH_ROM_742X=y
>  CONFIG_MACH_PHYTEC_PHYCORE_IMX7=y
>  CONFIG_IMX_IIM=y
>  CONFIG_IMX_IIM_FUSE_BLOW=y
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index 0526a6f..f094bdb 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -7,6 +7,7 @@ endif
>  # created.
>  obj- += dummy.o
>  
> +pbl-dtb-$(CONFIG_MACH_ADVANTECH_ROM_742X) += imx6dl-advantech-rom-7421.dtb.o
>  pbl-dtb-$(CONFIG_MACH_AFI_GF) += am335x-afi-gf.dtb.o
>  pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
>  pbl-dtb-$(CONFIG_MACH_CM_FX6) += imx6dl-cm-fx6.dtb.o imx6q-cm-fx6.dtb.o imx6q-utilite.dtb.o
> diff --git a/arch/arm/dts/imx6dl-advantech-rom-7421.dts b/arch/arm/dts/imx6dl-advantech-rom-7421.dts
> new file mode 100755
> index 0000000..1d5fd89
> --- /dev/null
> +++ b/arch/arm/dts/imx6dl-advantech-rom-7421.dts
> @@ -0,0 +1,225 @@
> +/*
> + * Copyright(c) 2018 Christoph Fritz <chf.fritz at googlemail.com>
> + *
> + * 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 <dt-bindings/gpio/gpio.h>
> +#include <arm/imx6dl.dtsi>
> +#include "imx6dl.dtsi"
> +
> +/ {
> +	model = "Advantech i.MX6 ROM-7421";
> +	compatible = "advantech,imx6dl-rom-7421", "fsl,imx6dl";
> +
> +	chosen {
> +		stdout-path = &uart1;
> +
> +		environment-sd2 {			/* Micro SD */
> +			compatible = "barebox,environment";
> +			device-path = &usdhc2, "partname:barebox-environment";
> +			status = "disabled";
> +		};
> +
> +		environment-sd4 {			/* eMMC */
> +			compatible = "barebox,environment";
> +			device-path = &usdhc4, "partname:barebox-environment";
> +			status = "disabled";
> +		};
> +
> +		environment-spi {			/* spi nor */
> +			compatible = "barebox,environment";
> +			device-path = &ecspi1, "partname:barebox-environment";
> +			status = "disabled";
> +		};
> +	};
> +};
> +
> +&ecspi1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_ecspi1>;
> +	fsl,spi-num-chipselects = <1>;
> +	cs-gpios = <&gpio3 19 0>;
> +	status = "okay";
> +
> +	flash: m25p80 at 0 {
> +		compatible = "m25p80";
> +		spi-max-frequency = <20000000>;
> +		reg = <0>;
> +		status = "okay";
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		partition at 0 {
> +			label = "barebox";
> +			reg = <0x0 0xe0000>;
> +		};
> +
> +		partition at e0000 {
> +			label = "barebox-environment";
> +			reg = <0xe0000 0x20000>;
> +		};
> +	};
> +};
> +
> +&fec {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_enet1>;
> +	phy-mode = "rgmii";
> +	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
> +	fsl,magic-packet;
> +	status = "okay";
> +};
> +
> +&uart1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_uart1>;
> +	status = "okay";
> +};
> +
> +&usbh1 {
> +	status = "okay";
> +};
> +
> +&usdhc2 {					/* Micro SD */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usdhc2>;
> +	bus-width = <8>;
> +	cd-gpios = <&gpio2 0 0>;
> +	status = "okay";
> +
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	partition at 0 {
> +		label = "barebox";
> +		reg = <0x0 0xe0000>;
> +	};
> +
> +	partition at e0000 {
> +		label = "barebox-environment";
> +		reg = <0xe0000 0x20000>;
> +	};
> +};
> +
> +&usdhc3 {					/* SD Card */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usdhc3>;
> +	bus-width = <4>;
> +	cd-gpios = <&gpio2 1 0>;
> +	en-gpios = <&gpio2 2 0>;
> +	wp-gpios = <&gpio2 3 0>;
> +	status = "okay";
> +};
> +
> +&usdhc4 {					/* eMMC */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usdhc4>;
> +	bus-width = <8>;
> +	non-removable;
> +	no-1-8-v;
> +	status = "okay";
> +
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	partition at 0 {
> +		label = "barebox";
> +		reg = <0x0 0xe0000>;
> +	};
> +
> +	partition at e0000 {
> +		label = "barebox-environment";
> +		reg = <0xe0000 0x20000>;
> +	};
> +};
> +
> +&iomuxc {
> +	pinctrl-names = "default";
> +
> +	pinctrl_ecspi1: ecspi1grp {
> +		fsl,pins = <
> +			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
> +			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
> +			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
> +			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x80000000
> +		>;
> +	};
> +
> +	pinctrl_enet1: enet1grp {
> +		fsl,pins = <
> +			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
> +			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
> +			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
> +			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
> +			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
> +			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
> +			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
> +			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
> +			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0A0B1
> +			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
> +			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
> +			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
> +			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
> +			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
> +			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
> +			MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25	0x80000000
> +		>;
> +	};
> +
> +	pinctrl_uart1: uart1grp {
> +		fsl,pins = <
> +			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
> +			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
> +		>;
> +	};
> +
> +	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_NANDF_D0__GPIO2_IO00		0x1b0b0
> +		>;
> +	};
> +
> +	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
> +			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
> +			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
> +			MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
> +		>;
> +	};
> +
> +	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
> +		>;
> +	};
> +};
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index eb135c3..0902ba6 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -383,6 +383,11 @@ config MACH_CM_FX6
>  	bool "CM FX6"
>  	select ARCH_IMX6
>  
> +config MACH_ADVANTECH_ROM_742X
> +	bool "Advantech ROM 742X"
> +	select ARCH_IMX6
> +	select ARM_USE_COMPRESSED_DTB
> +
>  config MACH_WARP7
>  	bool "NXP i.MX7: element 14 WaRP7 Board"
>  	select ARCH_IMX7
> diff --git a/images/Makefile.imx b/images/Makefile.imx
> index 5e0043f..131b3f2 100644
> --- a/images/Makefile.imx
> +++ b/images/Makefile.imx
> @@ -465,6 +465,11 @@ CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-head
>  FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
>  image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
>  
> +pblx-$(CONFIG_MACH_ADVANTECH_ROM_742X) += start_advantech_imx6dl_rom_7421
> +CFG_start_advantech_imx6dl_rom_7421.pblx.imximg = $(board)/advantech-mx6/flash-header-advantech-rom-7421.imxcfg
> +FILE_barebox-advantech-imx6dl-rom-7421.img = start_advantech_imx6dl_rom_7421.pblx.imximg
> +image-$(CONFIG_MACH_ADVANTECH_ROM_742X) += barebox-advantech-imx6dl-rom-7421.img
> +
>  pblx-$(CONFIG_MACH_WARP7) += start_imx7s_element14_warp7
>  CFG_start_imx7s_element14_warp7.pblx.imximg = $(board)/element14-warp7/flash-header-mx7-warp.imxcfg
>  FILE_barebox-element14-imx7s-warp7.img = start_imx7s_element14_warp7.pblx.imximg
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:13:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:13:44 +0200
Subject: [PATCH 1/2] i.MX53/TX53: Adjust to latest get_runtime_offset()
In-Reply-To: <20180410013637.2513-1-andrew.smirnov@gmail.com>
References: <20180410013637.2513-1-andrew.smirnov@gmail.com>
Message-ID: <20180411081344.blwrhrbzr4ftmefz@pengutronix.de>

On Mon, Apr 09, 2018 at 06:36:36PM -0700, Andrey Smirnov wrote:
> Latest version of get_runtime_offset() returns positive offset that
> needs to be added to rather than substracted from original pointer.
> 
> Cc: Michael Grzeschik <m.grzeschik at pengutronix.de>
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
> 
> Sascha:
> 
> This one obviously needs to go into master as well. Sorry for the
> noise if this has already been fixed.

Applied to master, thanks

Sascha

> 
> Thanks,
> Andrey Smirnov
> 
>  arch/arm/boards/karo-tx53/lowlevel.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boards/karo-tx53/lowlevel.c b/arch/arm/boards/karo-tx53/lowlevel.c
> index cb324b200..a0bce8a78 100644
> --- a/arch/arm/boards/karo-tx53/lowlevel.c
> +++ b/arch/arm/boards/karo-tx53/lowlevel.c
> @@ -47,7 +47,7 @@ static void __imx53_tx53_init(int is_xx30)
>  	if (IS_ENABLED(CONFIG_DEBUG_LL))
>  		setup_uart();
>  
> -	fdt = fdt_blob_fixed_offset - get_runtime_offset();
> +	fdt = fdt_blob_fixed_offset + get_runtime_offset();
>  
>  	imx53_barebox_entry(fdt);
>  }
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:34:08 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:34:08 +0200
Subject: [PATCH 3/3] serial: Check result of console_unregister()
In-Reply-To: <CAHQ1cqHR2vmy4HRFaCLQnVgn=YCG+YOfBgBj_uzw4mn66T1nvA@mail.gmail.com>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-4-andrew.smirnov@gmail.com>
 <20180403070427.terivivcpl2abuuf@pengutronix.de>
 <CAHQ1cqHR2vmy4HRFaCLQnVgn=YCG+YOfBgBj_uzw4mn66T1nvA@mail.gmail.com>
Message-ID: <20180411083408.lri4xpnpatno6qz6@pengutronix.de>

Hi Andrey,

On Mon, Apr 09, 2018 at 09:00:52AM -0700, Andrey Smirnov wrote:
> On Tue, Apr 3, 2018 at 12:04 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > On Mon, Mar 26, 2018 at 06:09:15AM -0700, Andrey Smirnov wrote:
> >> In order to allow 'serdev' devices to prevent parent console device
> >> removal and correspondign memory deallocation add code to all serial
> >> driver to check result of console_unregister() and bail out early if
> >> it is unsuccessful.
> >>
> >> One example of a use-case for this would be a reset handler relying on
> >> a serdev device for transport. Without this patch underlying console
> >> device would be removed and de-allocated before reset handler is even
> >> run thus leading to unpredictable behaviour and crashes.
> >
> > Can't we make this sure at driver core level?
> 
> I need to be able to prevent serial driver's "remove" function from
> ever executing to prevent any de-initialization/memory freeing from
> happening. The simplest way to solve this in driver core that comes to
> my mind is implementing simple reference counting API that children
> could use to force driver core to bail out on removing parents if they
> are still in use. Does that sound like a reasonable idea?
> 
> > So if a device decides not
> > to return -EBUSY in the remove callback then the parent devices won't be
> > removed?
> 
> Remove callback currently returns void, we could change it to return
> int and use it to implement a sort of implicit refcounting, but doing
> so would result in quite a bit of code churn since all of the current
> drivers would have to be converted to return int in their .remove
> callbacks. Would you rather I do this or explicit refcounting?

Normally it helps looking at the Linux kernel to see how a problem is
solved there. Not so this time it seems. Linux distinguishes between
"remove" and "shutdown". "shutdown" is what we want during barebox
shutdown. I found a Linux driver that is similar to your situation: It
registers a restart_handler while being a i2c device itself. There seems
to be no way to prevent a device from being shutdown, it's only that the
i2c bus drivers simply do not implement it.

Where do we go from here? I think reference counting is a bit over the
top.

At the moment I would opt for a *very* simple solution: Let's drop the
call to console_unregister() and the freeing of resources entirely as
it gives us nothing. The only console driver I can see where removing
is valid is drivers/usb/gadget/u_serial.c and you won't use this for
restarting a SoC ;)

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:39:57 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:39:57 +0200
Subject: [PATCH 2/3] console: Add simplified 'serdev' framework from
 Linux kernel
In-Reply-To: <CAHQ1cqHdhHiknrnzfU_9YLc_HiyNVDSPZyGNNsHcrAhgUoK_ig@mail.gmail.com>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-3-andrew.smirnov@gmail.com>
 <20180403065436.p2vec7ntdja55hts@pengutronix.de>
 <CAHQ1cqHdhHiknrnzfU_9YLc_HiyNVDSPZyGNNsHcrAhgUoK_ig@mail.gmail.com>
Message-ID: <20180411083957.pvagr7h4my4lyfpo@pengutronix.de>

On Mon, Apr 09, 2018 at 09:40:46AM -0700, Andrey Smirnov wrote:
> On Mon, Apr 2, 2018 at 11:54 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > Hi Andrey,
> >
> > Some comments inside.
> >
> >
> > On Mon, Mar 26, 2018 at 06:09:14AM -0700, Andrey Smirnov wrote:
> >> Port 'serdev' UART-slave deivce framework found in recent Linux
> >> kernels (post 4.13) in order to be able to port 'serdev' slave drivers
> >> from Linux.
> >>
> >> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> >> @@ -323,6 +324,17 @@ int console_register(struct console_device *newcdev)
> >>               dev->parent = newcdev->dev;
> >>       platform_device_register(dev);
> >>
> >> +     newcdev->open_count = 0;
> >> +
> >> +     /*
> >> +      * If our console deive is a serdev, we skip the creation of
> >
> > s/deive/device/
> 
> Will fix in v2.
> 
> >
> >> +      * corresponding entry in /dev as well as registration in
> >> +      * console_list and just go straigh to populating child
> >
> > s/straigh/straight/
> 
> Ditto.
> 
> >
> >> +      * devices.
> >> +      */
> >> +     if (serdev_node)
> >> +             return of_platform_populate(serdev_node, NULL, dev);
> >
> > How is this going to be used? A serdev driver binds to the serdev_node
> > and then it probably needs to get a pointer to the console device,
> > right? How does the driver accomplish this?
> >
> 
> Serdev slave driver doesn't hold explicit pointer to console device,
> instead accessing it via point to serdev_device. The latter could
> obtained by calling to_serdev_device(dev->parent), where dev is
> device_d given to slave driver's probe function.
> 
> 
> >> +/**
> >> + * struct serdev_device - Basic representation of an serdev device
> >> + *
> >> + * @dev:             Corresponding device
> >> + * @fifo:            Circular buffer used for console draining
> >> + * @buf:             Buffer used to pass Rx data to consumers
> >> + * @poller           Async poller used to poll this serdev
> >> + * @polling_interval:        Async poller periodicity
> >> + * @polling_window:  Duration of a single busy loop poll
> >> + * @receive_buf:     Function called with data received from device;
> >> + *                   returns number of bytes accepted;
> >> + */
> >> +struct serdev_device {
> >> +     struct device_d *dev;
> >> +     struct kfifo *fifo;
> >> +     unsigned char *buf;
> >> +     struct poller_async poller;
> >> +     uint64_t polling_interval;
> >> +     uint64_t polling_window;
> >> +
> >> +     int (*receive_buf)(struct serdev_device *, const unsigned char *,
> >> +                        size_t);
> >> +};
> >> +
> >> +int serdev_device_open(struct serdev_device *);
> >> +unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
> >> +int serdev_device_write(struct serdev_device *, const unsigned char *,
> >> +                     size_t, unsigned long);
> >
> > So a serdev driver uses serdev_device_write() to send characters out. To
> > receive characters it has to implement serdev_device->receive_buf,
> > right?
> 
> Right. I tried to implement exactly the same API that Linux's serdev
> API provides.
> 
> > What kind of devices did you implement this for?
> 
> I ported serdev in support of porting the driver for RAVE SP which is
> a small microcontroller device found many ZII board including RDU2. It
> implement a whole bunch of various functionality including watchdog,
> parameter EEPROM, sensor access, backlight control, button input event
> generation, etc.
> 
> > For devices which send data without request (GPS?) this seems the way to go. For
> > others a synchronous receive function might be good, no?
> >
> 
> I didn't implement anything like that mostly because Linux serdev API
> doesn't and any ported driver wouldn't have any need for those
> functions. But in general, I am not sure how useful synchronous
> receive function would be. In my experience, devices like that usually
> implement some binary transport protocol with packetization/escape
> sequences on top of UART, which usually requires a state machine
> operating with byte granularity as the data comes in to parse
> responses correctly and synchronous APIs are not extremely useful for
> that kind of a use-case.
> 
> FWIW, since serdev API is integrated into poller infrastructure it is
> pretty trivial to write blocking code with it. Here's how I use it in
> my driver to implement request-response type of a function:
> 
> rave_sp_write(sp, data, data_size);
> /*
> * is_timeout will implicitly poll serdev via poller
> * infrastructure
> */
> while (!is_timeout(start, SECOND) && !reply.received)
>    ;

I understand that synchronous receiving might not be that useful. Given
how simple it is we could add a synchronous receive wrapper function
just for the sake of completeness, even if it only provides an example
how the code can be used.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:41:20 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:41:20 +0200
Subject: [PATCH v3 04/10] ARM: add file for HYP mode related setup
In-Reply-To: <1523357612.4981.5.camel@pengutronix.de>
References: <20180326192025.28809-1-l.stach@pengutronix.de>
 <20180326192025.28809-4-l.stach@pengutronix.de>
 <20180405075402.gbplqqwoubu7cqpg@pengutronix.de>
 <1523357612.4981.5.camel@pengutronix.de>
Message-ID: <20180411084120.cxoyjrvp7f52aus2@pengutronix.de>

On Tue, Apr 10, 2018 at 12:53:32PM +0200, Lucas Stach wrote:
> Am Donnerstag, den 05.04.2018, 09:54 +0200 schrieb Sascha Hauer:
> > On Mon, Mar 26, 2018 at 09:20:19PM +0200, Lucas Stach wrote:
> > > This adds routines to add hyp mode vectors and switch back to HYP
> > > mode from SVC. This is needed in both the PBL and Barebox proper.
> > > 
> > > > > Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> > > > > Tested-by: Roland Hieber <r.hieber at pengutronix.de>
> > > ---
> > > v3:
> > > - fix whitespace
> > > - use __BARE_INIT
> > > ---
> > > ?arch/arm/cpu/Makefile?????????|???4 ++
> > > ?arch/arm/cpu/hyp.S????????????| 116 ++++++++++++++++++++++++++++++++++++++++++
> > > ?arch/arm/cpu/sm_as.S??????????|??11 ----
> > > ?arch/arm/include/asm/secure.h |???8 +++
> > > ?4 files changed, 128 insertions(+), 11 deletions(-)
> > > ?create mode 100644 arch/arm/cpu/hyp.S
> > > 
> > > diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
> > > index 13fe12c31f6f..f86dff975bb4 100644
> > > --- a/arch/arm/cpu/Makefile
> > > +++ b/arch/arm/cpu/Makefile
> > > @@ -9,6 +9,10 @@ obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o
> > > ?obj-$(CONFIG_MMU) += mmu.o mmu-early.o
> > > ?pbl-$(CONFIG_MMU) += mmu-early.o
> > > ?lwl-y += lowlevel.o
> > > +obj-y += hyp.o
> > > +AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> > > +pbl-y += hyp.o
> > > +AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all
> > > ?endif
> > > ?
> > > ?obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o
> > > diff --git a/arch/arm/cpu/hyp.S b/arch/arm/cpu/hyp.S
> > > new file mode 100644
> > > index 000000000000..1314b56eab25
> > > --- /dev/null
> > > +++ b/arch/arm/cpu/hyp.S
> > > @@ -0,0 +1,116 @@
> > > +#include <linux/linkage.h>
> > > +#include <asm/system.h>
> > > +#include <asm/opcodes-virt.h>
> > > +#include <init.h>
> > > +
> > > +.arch_extension sec
> > > +.arch_extension virt
> > > +
> > > +__BARE_INIT
> > > +
> > > +.data
> > > > > +	.align??2
> > > +ENTRY(__boot_cpu_mode)
> > > > > +	.long???0
> > > +.text
> > > +
> > > +ENTRY(__hyp_install)
> > > > > > > +	mrs	r12, cpsr
> > > > > > > +	and	r12, r12, #MODE_MASK
> > > +
> > > > > +	@ Save the initial CPU state
> > > > > > > +	adr	r0, .L__boot_cpu_mode_offset
> > > > > > > +	ldr	r1, [r0]
> > > +	str	r12, [r0, r1]
> > 
> > Naa, this won't work. You save the cpsr value in __boot_cpu_mode, but
> > this variable exists both in PBL and regular barebox, __hyp_install
> > is called multiple times and cpsr is modified right after saving it.
> 
> It does. ;)
> 
> I guess its non-obvious from the code flow, but what we do is to drop
> down to SVC in the PBL, then jump back to HYP before starting barebox
> proper and the dropping down to SVC again on barebox entry.
> All in all this is less-than-pretty, but IMHO it's the lesser evil than
> trying to implement some communication channel from PBL to barebox
> proper to pass information like this.
> 
> So I guess this code needs some more comments...

Yep ;)

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:43:10 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:43:10 +0200
Subject: [PATCH] ARM: Make use of ALIGN_DOWN macro in barebox-arm.h
In-Reply-To: <20180410233805.4191-1-andrew.smirnov@gmail.com>
References: <20180410233805.4191-1-andrew.smirnov@gmail.com>
Message-ID: <20180411084310.lox3beilymyxhvwb@pengutronix.de>

On Tue, Apr 10, 2018 at 04:38:05PM -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/include/asm/barebox-arm.h | 9 +++------
>  1 file changed, 3 insertions(+), 6 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
> index 4b270e7de..67e4d964d 100644
> --- a/arch/arm/include/asm/barebox-arm.h
> +++ b/arch/arm/include/asm/barebox-arm.h
> @@ -114,8 +114,7 @@ static inline unsigned long arm_mem_ttb(unsigned long membase,
>  					unsigned long endmem)
>  {
>  	endmem = arm_mem_stack(membase, endmem);
> -	endmem &= ~(SZ_16K - 1);
> -	endmem -= SZ_16K;
> +	endmem = ALIGN_DOWN(endmem, SZ_16K) - SZ_16K;
>  
>  	return endmem;
>  }
> @@ -138,7 +137,7 @@ static inline unsigned long arm_mem_ramoops(unsigned long membase,
>  	endmem = arm_mem_ttb(membase, endmem);
>  #ifdef CONFIG_FS_PSTORE_RAMOOPS
>  	endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE;
> -	endmem &= ~(SZ_4K - 1); /* Align to 4K */
> +	endmem = ALIGN_DOWN(endmem, SZ_4K);
>  #endif
>  
>  	return endmem;
> @@ -151,9 +150,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
>  	endmem = arm_mem_ramoops(membase, endmem);
>  
>  	if (IS_ENABLED(CONFIG_RELOCATABLE)) {
> -		endmem -= size;
> -		endmem &= ~(SZ_1M - 1);
> -		return endmem;
> +		return ALIGN_DOWN(endmem - size, SZ_1M);
>  	} else {
>  		if (TEXT_BASE >= membase && TEXT_BASE < endmem)
>  			return TEXT_BASE;
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:43:36 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:43:36 +0200
Subject: [PATCH] pinctrl-vf610: Make use of BIT macro
In-Reply-To: <20180410233943.4372-1-andrew.smirnov@gmail.com>
References: <20180410233943.4372-1-andrew.smirnov@gmail.com>
Message-ID: <20180411084336.rz2zfbufs642mooe@pengutronix.de>

On Tue, Apr 10, 2018 at 04:39:43PM -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  drivers/pinctrl/pinctrl-vf610.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
> index 4234263d3..a46b0e2ca 100644
> --- a/drivers/pinctrl/pinctrl-vf610.c
> +++ b/drivers/pinctrl/pinctrl-vf610.c
> @@ -29,9 +29,9 @@
>  enum {
>  	PINCTRL_VF610_MUX_LINE_SIZE = 20,
>  
> -	PINCTRL_VF610_IBE = 1 << 0,
> -	PINCTRL_VF610_OBE = 1 << 1,
> -	PINCTRL_VF610_xBE = 0b11,
> +	PINCTRL_VF610_IBE = BIT(0),
> +	PINCTRL_VF610_OBE = BIT(1),
> +	PINCTRL_VF610_xBE = PINCTRL_VF610_OBE | PINCTRL_VF610_IBE,
>  };
>  
>  struct pinctrl_vf610 {
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:44:09 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:44:09 +0200
Subject: [PATCH 1/2] i.MX: vf610-twr: Print '>' when DEBUG_LL is enabled
In-Reply-To: <20180410234038.4513-1-andrew.smirnov@gmail.com>
References: <20180410234038.4513-1-andrew.smirnov@gmail.com>
Message-ID: <20180411084409.b2nb2qz6aptr4an2@pengutronix.de>

On Tue, Apr 10, 2018 at 04:40:37PM -0700, Andrey Smirnov wrote:
> Majority of others boards prints '>' as soon as DEBUG_LL related
> configuration is done, so do so for VF610-TWR as well.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/boards/freescale-vf610-twr/lowlevel.c | 2 ++
>  1 file changed, 2 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
> index a043dd421..65956fdd2 100644
> --- a/arch/arm/boards/freescale-vf610-twr/lowlevel.c
> +++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
> @@ -22,6 +22,8 @@ static inline void setup_uart(void)
>  	writel(0, iomuxbase + 0x0380);
>  
>  	vf610_uart_setup_ll();
> +
> +	putc_ll('>');
>  }
>  
>  extern char __dtb_vf610_twr_start[];
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 01:45:53 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 10:45:53 +0200
Subject: [PATCH] ARM: start: Avoid calling arm_mem_barebox_image() twice
In-Reply-To: <20180410234536.4914-1-andrew.smirnov@gmail.com>
References: <20180410234536.4914-1-andrew.smirnov@gmail.com>
Message-ID: <20180411084553.cuiflcctaihesl7y@pengutronix.de>

On Tue, Apr 10, 2018 at 04:45:36PM -0700, Andrey Smirnov wrote:
> Avoid calling arm_mem_barebox_image() twice by making barebox_base
> function-wide in scope
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/cpu/start.c | 13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> index 68fff892e..64bd942ad 100644
> --- a/arch/arm/cpu/start.c
> +++ b/arch/arm/cpu/start.c
> @@ -144,13 +144,11 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
>  	unsigned long endmem = membase + memsize;
>  	unsigned long malloc_start, malloc_end;
>  	unsigned long barebox_size = barebox_image_size + MAX_BSS_SIZE;
> -
> -	if (IS_ENABLED(CONFIG_RELOCATABLE)) {
> -		unsigned long barebox_base = arm_mem_barebox_image(membase,
> -								   endmem,
> -								   barebox_size);
> +	unsigned long barebox_base = arm_mem_barebox_image(membase,
> +							   endmem,
> +							   barebox_size);
> +	if (IS_ENABLED(CONFIG_RELOCATABLE))
>  		relocate_to_adr(barebox_base);
> -	}
>  
>  	setup_c();
>  
> @@ -160,8 +158,7 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
>  
>  	arm_stack_top = arm_mem_stack_top(membase, endmem);
>  	arm_barebox_size = barebox_size;
> -	malloc_end = arm_mem_barebox_image(membase, endmem,
> -						arm_barebox_size);
> +	malloc_end = barebox_base;
>  
>  	if (IS_ENABLED(CONFIG_MMU_EARLY)) {
>  		unsigned long ttb = arm_mem_ttb(membase, endmem);
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 02:07:16 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 11:07:16 +0200
Subject: [PATCH 00/10] Vybrid MMDC support and misc ESDCTL fixes
In-Reply-To: <20180410235323.5440-1-andrew.smirnov@gmail.com>
References: <20180410235323.5440-1-andrew.smirnov@gmail.com>
Message-ID: <20180411090716.q4vhuxfrcbbko5bg@pengutronix.de>

On Tue, Apr 10, 2018 at 04:53:13PM -0700, Andrey Smirnov wrote:
> Everyone:
> 
> This series is a bit of code I developed to support automatic
> configured DRAM size detection on Vybrid platform as well as some
> small fixes/cleanup I made while looking at esdctl.c.
> 
> All feedback is wellcome!

Not much to comment, looks all good. Applied, thanks

Sascha

> 
> Thanks,
> Andrey Smirnov
> 
> Andrey Smirnov (10):
>   ARM: i.MX: esdctl: Use IOMEM instead of (void *)
>   ARM: i.MX51: esdctl: Replace magic value with ESDMISC_DDR2_8_BANK
>   ARM: i.MX6: esdctl: Share memory size calculation code
>   ARM: i.MX6: esdctl: Factor out common code in imx6*_barebox_entry()
>   ARM: i.MX6: esdctl: Use symbolic constants for RAM base address
>   ARM: i.MX: esdctl: Make use of min_t()
>   ARM: i.MX: esdctl: Introduce memory_sdram_size()
>   ARM: i.MX: esdctl: Add support for Vybrid's memory controller
>   i.MX: vf610-twr: Make use of vf610_barebox_entry()
>   i.MX: zii-vf610-dev: Make use of vf610_barebox_entry()
> 
>  arch/arm/boards/freescale-vf610-twr/lowlevel.c |   5 +-
>  arch/arm/boards/zii-imx6q-rdu2/lowlevel.c      |   2 +-
>  arch/arm/boards/zii-vf610-dev/lowlevel.c       |   3 +-
>  arch/arm/dts/vf610-ddrmc.dtsi                  |  15 +++
>  arch/arm/dts/vf610-twr.dts                     |   1 +
>  arch/arm/dts/vf610-zii-dev.dtsi                |   4 +-
>  arch/arm/mach-imx/esdctl.c                     | 144 ++++++++++++++-----------
>  arch/arm/mach-imx/include/mach/esdctl.h        |   2 +
>  arch/arm/mach-imx/include/mach/imx6-regs.h     |   4 +-
>  arch/arm/mach-imx/include/mach/vf610-ddrmc.h   |  18 ++++
>  arch/arm/mach-imx/include/mach/vf610-regs.h    |   2 +
>  include/memory.h                               |   8 ++
>  12 files changed, 141 insertions(+), 67 deletions(-)
>  create mode 100644 arch/arm/dts/vf610-ddrmc.dtsi
>  create mode 100644 arch/arm/mach-imx/include/mach/vf610-ddrmc.h
> 
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 11 02:29:47 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 11:29:47 +0200
Subject: [PATCH] clk: i.MX6: Adjust GPMI parent clock
Message-ID: <20180411092947.4302-1-s.hauer@pengutronix.de>

Based on the corresponding Kernel code:

The gpmi needs 100MHz frequency in the EDO/Sync mode, We can not get the
100MHz from the pll2_pfd0_352m. So choose pll2_pfd2_396m as enfc_sel's
parent.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/imx/clk-imx6.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/clk/imx/clk-imx6.c b/drivers/clk/imx/clk-imx6.c
index d0571bce5e..c48ab7f76a 100644
--- a/drivers/clk/imx/clk-imx6.c
+++ b/drivers/clk/imx/clk-imx6.c
@@ -514,6 +514,13 @@ static int imx6_ccm_probe(struct device_d *dev)
 
 	clk_set_parent(clks[IMX6QDL_CLK_LVDS1_SEL], clks[IMX6QDL_CLK_SATA_REF_100M]);
 
+	/*
+	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
+	 * We can not get the 100MHz from the pll2_pfd0_352m.
+	 * So choose pll2_pfd2_396m as enfc_sel's parent.
+	 */
+	clk_set_parent(clks[IMX6QDL_CLK_ENFC_SEL], clks[IMX6QDL_CLK_PLL2_PFD2_396M]);
+
 	return 0;
 }
 
-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 02:29:56 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 11:29:56 +0200
Subject: [PATCH] ARM: i.MX6: phycore: Enable usbotg
Message-ID: <20180411092956.8191-1-s.hauer@pengutronix.de>

The i.MX6 phyCORE boards have USBOTG support. Enable it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index b10530cbcf..2ce22b9880 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -252,6 +252,10 @@
 	status = "okay";
 };
 
+&usbotg {
+	status = "okay";
+};
+
 &usdhc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc1>;
-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 02:09:50 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 11:09:50 +0200
Subject: [PATCH] ARM: i.MX53 TX53: remove duplicate _imx53
Message-ID: <20180411090950.17924-1-s.hauer@pengutronix.de>

The pblx-y variables for the TX53 have _imx53 twice in their names. With
this the names do not match the names in the FILE_* variables. This
results in the make system removing the pblx files as intermediate
files. Fix the names.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 images/Makefile.imx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/images/Makefile.imx b/images/Makefile.imx
index ac46d51c59..90da95d4d0 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -139,17 +139,17 @@ CFG_start_imx53_mba53_1gib.pblx.imximg = $(board)/tqma53/flash-header-tq-tqma53-
 FILE_barebox-tq-mba53-1gib.img = start_imx53_mba53_1gib.pblx.imximg
 image-$(CONFIG_MACH_TQMA53) += barebox-tq-mba53-1gib.img
 
-pblx-$(CONFIG_MACH_TX53) += start_imx53_imx53_tx53_xx30_samsung
+pblx-$(CONFIG_MACH_TX53) += start_imx53_tx53_xx30_samsung
 CFG_start_imx53_tx53_xx30_samsung.pblx.imximg = $(board)/karo-tx53/flash-header-tx53-revxx30-samsung.imxcfg
 FILE_barebox-tx53-xx30-samsung.img = start_imx53_tx53_xx30_samsung.pblx.imximg
 image-$(CONFIG_MACH_TX53) += barebox-tx53-xx30-samsung.img
 
-pblx-$(CONFIG_MACH_TX53) += start_imx53_imx53_tx53_xx30
+pblx-$(CONFIG_MACH_TX53) += start_imx53_tx53_xx30
 CFG_start_imx53_tx53_xx30.pblx.imximg = $(board)/karo-tx53/flash-header-tx53-revxx30.imxcfg
 FILE_barebox-tx53-xx30.img = start_imx53_tx53_xx30.pblx.imximg
 image-$(CONFIG_MACH_TX53) += barebox-tx53-xx30.img
 
-pblx-$(CONFIG_MACH_TX53) += start_imx53_imx53_tx53_1011
+pblx-$(CONFIG_MACH_TX53) += start_imx53_tx53_1011
 CFG_start_imx53_tx53_1011.pblx.imximg = $(board)/karo-tx53/flash-header-tx53-rev1011.imxcfg
 FILE_barebox-tx53-1011.img = start_imx53_tx53_1011.pblx.imximg
 image-$(CONFIG_MACH_TX53) += barebox-tx53-1011.img
-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 06:26:50 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 15:26:50 +0200
Subject: [PATCH 0/4] Fix NAND controller clock for i.MX6plus
Message-ID: <20180411132654.10620-1-s.hauer@pengutronix.de>

The i.MX6 plus SoC variants have some changes in the clock controller,
start integrating them beginning with the NAND controller clock.
Before doing so we have to add proper detection code for the i.MX6 plus.

Sascha Hauer (4):
  ARM: i.MX6: de-inline i.MX6 type detection
  ARM: i.MX6: factor out function to read si_rev
  ARM: i.MX6: Add cpu type for 'plus' variants
  clk: i.MX6: Fix enfc_sel for i.MX6dqp

 arch/arm/boards/phytec-som-imx6/board.c   |  2 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c |  4 +-
 arch/arm/mach-imx/imx6.c                  | 42 +++++++++++++---
 arch/arm/mach-imx/include/mach/imx6.h     | 81 +++++++++++++++++--------------
 drivers/clk/imx/clk-imx6.c                | 19 +++++++-
 5 files changed, 99 insertions(+), 49 deletions(-)

-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 06:26:51 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 15:26:51 +0200
Subject: [PATCH 1/4] ARM: i.MX6: de-inline i.MX6 type detection
In-Reply-To: <20180411132654.10620-1-s.hauer@pengutronix.de>
References: <20180411132654.10620-1-s.hauer@pengutronix.de>
Message-ID: <20180411132654.10620-2-s.hauer@pengutronix.de>

Having the i.MX6 type detection completely inline is less then optimal
in terms of binary size. Make the detection functions non-inline. While
at it ask the registers only once and store the result in a variable as
the i.MX6 type is unlikely to change during runtime.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/mach-imx/imx6.c              | 26 ++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/imx6.h | 16 ++--------------
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 14a1cba5a4..5a7cb7f8bc 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -147,6 +147,32 @@ static void imx6ul_enet_clk_init(void)
 	writel(val, gprbase + IOMUXC_GPR1);
 }
 
+int imx6_cpu_type(void)
+{
+	static int cpu_type = -1;
+
+	if (!cpu_is_mx6())
+		return 0;
+
+	if (cpu_type < 0)
+		cpu_type = __imx6_cpu_type();
+
+	return cpu_type;
+}
+
+int imx6_cpu_revision(void)
+{
+	static int soc_revision = -1;
+
+	if (!cpu_is_mx6())
+		return 0;
+
+	if (soc_revision < 0)
+		soc_revision = __imx6_cpu_revision();
+
+	return soc_revision;
+}
+
 int imx6_init(void)
 {
 	const char *cputypestr;
diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index 6b08e6a521..436f8fc31b 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -55,13 +55,7 @@ static inline int __imx6_cpu_type(void)
 	return val;
 }
 
-static inline int imx6_cpu_type(void)
-{
-	if (!cpu_is_mx6())
-		return 0;
-
-	return __imx6_cpu_type();
-}
+int imx6_cpu_type(void);
 
 #define DEFINE_MX6_CPU_TYPE(str, type)					\
 	static inline int cpu_mx6_is_##str(void)			\
@@ -102,12 +96,6 @@ static inline int __imx6_cpu_revision(void)
 	return ((major_part + 1) << 4) | minor_part;
 }
 
-static inline int imx6_cpu_revision(void)
-{
-	if (!cpu_is_mx6())
-		return 0;
-
-	return __imx6_cpu_revision();
-}
+int imx6_cpu_revision(void);
 
 #endif /* __MACH_IMX6_H */
-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 06:26:52 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 15:26:52 +0200
Subject: [PATCH 2/4] ARM: i.MX6: factor out function to read si_rev
In-Reply-To: <20180411132654.10620-1-s.hauer@pengutronix.de>
References: <20180411132654.10620-1-s.hauer@pengutronix.de>
Message-ID: <20180411132654.10620-3-s.hauer@pengutronix.de>

The i.MX6sl has another silicon revision register offset than the
other i.MX6 SoCs. Finding the register is done twice. Factor out
a function to get a common place to find the register.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/mach-imx/include/mach/imx6.h | 61 +++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index 436f8fc31b..9b538db2ea 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -33,26 +33,43 @@ static inline int scu_get_core_count(void)
 	return (ncores & 0x03) + 1;
 }
 
+#define SI_REV_CPUTYPE(s)	(((s) >> 16) & 0xff)
+#define SI_REV_MAJOR(s)		(((s) >> 8) & 0xf)
+#define SI_REV_MINOR(s)		((s) & 0xf)
+
+static inline uint32_t __imx6_read_si_rev(void)
+{
+	uint32_t si_rev;
+	uint32_t cpu_type;
+
+	si_rev = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV);
+	cpu_type = SI_REV_CPUTYPE(si_rev);
+
+	if (cpu_type >= 0x61 && cpu_type <= 0x65)
+		return si_rev;
+
+	/* try non-MX6-standard SI_REV reg offset for MX6SL */
+	si_rev = readl(MX6_ANATOP_BASE_ADDR + IMX6SL_ANATOP_SI_REV);
+	cpu_type = SI_REV_CPUTYPE(si_rev);
+
+	if (si_rev == 0x60)
+		return si_rev;
+
+	return 0;
+}
+
 static inline int __imx6_cpu_type(void)
 {
-	uint32_t val;
-
-	val = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV);
-	val = (val >> 16) & 0xff;
-	/* non-MX6-standard SI_REV reg offset for MX6SL */
-	if (IS_ENABLED(CONFIG_ARCH_IMX6SL) &&
-	    val < (IMX6_CPUTYPE_IMX6S & 0xff)) {
-		uint32_t tmp;
-		tmp = readl(MX6_ANATOP_BASE_ADDR + IMX6SL_ANATOP_SI_REV);
-		tmp = (tmp >> 16) & 0xff;
-		if ((IMX6_CPUTYPE_IMX6SL & 0xff) == tmp)
-			/* intentionally skip scu_get_core_count() for MX6SL */
-			return IMX6_CPUTYPE_IMX6SL;
-	}
+	uint32_t si_rev = __imx6_read_si_rev();
+	uint32_t cpu_type = SI_REV_CPUTYPE(si_rev);
 
-	val |= scu_get_core_count() << 8;
+	/* intentionally skip scu_get_core_count() for MX6SL */
+	if (cpu_type == IMX6_CPUTYPE_IMX6SL)
+		return IMX6_CPUTYPE_IMX6SL;
 
-	return val;
+	cpu_type |= scu_get_core_count() << 8;
+
+	return cpu_type;
 }
 
 int imx6_cpu_type(void);
@@ -81,17 +98,11 @@ DEFINE_MX6_CPU_TYPE(mx6ull, IMX6_CPUTYPE_IMX6ULL);
 
 static inline int __imx6_cpu_revision(void)
 {
-	uint32_t rev;
-	uint32_t si_rev_offset = IMX6_ANATOP_SI_REV;
+	uint32_t si_rev = __imx6_read_si_rev();
 	u8 major_part, minor_part;
 
-	if (IS_ENABLED(CONFIG_ARCH_IMX6SL) && cpu_mx6_is_mx6sl())
-		si_rev_offset = IMX6SL_ANATOP_SI_REV;
-
-	rev = readl(MX6_ANATOP_BASE_ADDR + si_rev_offset);
-
-	major_part = (rev >> 8) & 0xf;
-	minor_part = rev & 0xf;
+	major_part = (si_rev >> 8) & 0xf;
+	minor_part = si_rev & 0xf;
 
 	return ((major_part + 1) << 4) | minor_part;
 }
-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 06:26:53 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 15:26:53 +0200
Subject: [PATCH 3/4] ARM: i.MX6: Add cpu type for 'plus' variants
In-Reply-To: <20180411132654.10620-1-s.hauer@pengutronix.de>
References: <20180411132654.10620-1-s.hauer@pengutronix.de>
Message-ID: <20180411132654.10620-4-s.hauer@pengutronix.de>

We need to distinguish between the i.MX6d/q and the i.MX6d/q plus SoC
variants. Add a cpu type for them to make that possible in the next
steps.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boards/phytec-som-imx6/board.c   |  2 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c |  4 ++--
 arch/arm/mach-imx/imx6.c                  | 16 ++++++++--------
 arch/arm/mach-imx/include/mach/imx6.h     |  8 ++++++++
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boards/phytec-som-imx6/board.c b/arch/arm/boards/phytec-som-imx6/board.c
index 717a22963a..7b63ee0e0c 100644
--- a/arch/arm/boards/phytec-som-imx6/board.c
+++ b/arch/arm/boards/phytec-som-imx6/board.c
@@ -66,7 +66,7 @@ static void phyflex_err006282_workaround(void)
 	mdelay(2);
 	gpio_set_value(MX6_PHYFLEX_ERR006282, 0);
 
-	if (cpu_is_mx6q() || cpu_is_mx6d())
+	if (cpu_is_mx6q() || cpu_is_mx6d() || cpu_is_mx6qp() || cpu_is_mx6dp())
 		mxc_iomux_v3_setup_pad(MX6Q_PAD_SD4_DAT3__GPIO_2_11_PD);
 	else if (cpu_is_mx6dl() || cpu_is_mx6s())
 		mxc_iomux_v3_setup_pad(MX6DL_PAD_SD4_DAT3__GPIO_2_11);
diff --git a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
index c9ef16ae05..48d02ce645 100644
--- a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
+++ b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
@@ -284,7 +284,7 @@ static noinline void rdu2_sram_setup(void)
 	relocate_to_current_adr();
 	setup_c();
 
-	if (__imx6_cpu_revision() == IMX_CHIP_REV_2_0)
+	if (__imx6_cpu_type() == IMX6_CPUTYPE_IMX6QP)
 		write_regs(imx6qp_dcd, ARRAY_SIZE(imx6qp_dcd));
 	else
 		write_regs(imx6q_dcd, ARRAY_SIZE(imx6q_dcd));
@@ -307,7 +307,7 @@ ENTRY_FUNCTION(start_imx6_zii_rdu2, r0, r1, r2)
 	if (get_pc() < MX6_MMDC_PORT01_BASE_ADDR)
 		rdu2_sram_setup();
 
-	if (__imx6_cpu_revision() == IMX_CHIP_REV_2_0)
+	if (__imx6_cpu_type() == IMX6_CPUTYPE_IMX6QP)
 		imx6q_barebox_entry(__dtb_imx6qp_zii_rdu2_start +
 				    get_runtime_offset());
 	else
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 5a7cb7f8bc..88165adee3 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -186,16 +186,16 @@ int imx6_init(void)
 
 	switch (imx6_cpu_type()) {
 	case IMX6_CPUTYPE_IMX6Q:
-		if (mx6_silicon_revision >= IMX_CHIP_REV_2_0)
-			cputypestr = "i.MX6 Quad Plus";
-		else
-			cputypestr = "i.MX6 Quad";
+		cputypestr = "i.MX6 Quad";
+		break;
+	case IMX6_CPUTYPE_IMX6QP:
+		cputypestr = "i.MX6 Quad Plus";
 		break;
 	case IMX6_CPUTYPE_IMX6D:
-		if (mx6_silicon_revision >= IMX_CHIP_REV_2_0)
-			cputypestr = "i.MX6 Dual Plus";
-		else
-			cputypestr = "i.MX6 Dual";
+		cputypestr = "i.MX6 Dual";
+		break;
+	case IMX6_CPUTYPE_IMX6DP:
+		cputypestr = "i.MX6 Dual Plus";
 		break;
 	case IMX6_CPUTYPE_IMX6DL:
 		cputypestr = "i.MX6 DualLite";
diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index 9b538db2ea..e06ca4e235 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -16,7 +16,9 @@ void __noreturn imx6_pm_stby_poweroff(void);
 #define IMX6_CPUTYPE_IMX6DL	0x261
 #define IMX6_CPUTYPE_IMX6SX	0x462
 #define IMX6_CPUTYPE_IMX6D	0x263
+#define IMX6_CPUTYPE_IMX6DP	0x1263
 #define IMX6_CPUTYPE_IMX6Q	0x463
+#define IMX6_CPUTYPE_IMX6QP	0x1463
 #define IMX6_CPUTYPE_IMX6UL	0x164
 #define IMX6_CPUTYPE_IMX6ULL	0x165
 
@@ -69,6 +71,10 @@ static inline int __imx6_cpu_type(void)
 
 	cpu_type |= scu_get_core_count() << 8;
 
+	if ((cpu_type == IMX6_CPUTYPE_IMX6D || cpu_type == IMX6_CPUTYPE_IMX6Q) &&
+	    SI_REV_MAJOR(si_rev) >= 1)
+		cpu_type |= 0x1000;
+
 	return cpu_type;
 }
 
@@ -90,7 +96,9 @@ int imx6_cpu_type(void);
 DEFINE_MX6_CPU_TYPE(mx6s, IMX6_CPUTYPE_IMX6S);
 DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL);
 DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q);
+DEFINE_MX6_CPU_TYPE(mx6qp, IMX6_CPUTYPE_IMX6QP);
 DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D);
+DEFINE_MX6_CPU_TYPE(mx6dp, IMX6_CPUTYPE_IMX6DP);
 DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX);
 DEFINE_MX6_CPU_TYPE(mx6sl, IMX6_CPUTYPE_IMX6SL);
 DEFINE_MX6_CPU_TYPE(mx6ul, IMX6_CPUTYPE_IMX6UL);
-- 
2.16.1



From s.hauer at pengutronix.de  Wed Apr 11 06:26:54 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 11 Apr 2018 15:26:54 +0200
Subject: [PATCH 4/4] clk: i.MX6: Fix enfc_sel for i.MX6dqp
In-Reply-To: <20180411132654.10620-1-s.hauer@pengutronix.de>
References: <20180411132654.10620-1-s.hauer@pengutronix.de>
Message-ID: <20180411132654.10620-5-s.hauer@pengutronix.de>

The plus SoC variants have some differences in the clock controller.
For now fix the NAND controller clock. There are more differences
that might be relevant, but for now are left for a future excercise.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/clk/imx/clk-imx6.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-imx6.c b/drivers/clk/imx/clk-imx6.c
index c48ab7f76a..7f1af12571 100644
--- a/drivers/clk/imx/clk-imx6.c
+++ b/drivers/clk/imx/clk-imx6.c
@@ -59,6 +59,11 @@
 static struct clk *clks[IMX6QDL_CLK_END];
 static struct clk_onecell_data clk_data;
 
+static inline int cpu_is_plus(void)
+{
+	return cpu_is_mx6qp() || cpu_is_mx6dp();
+}
+
 static const char *step_sels[] = {
 	"osc",
 	"pll2_pfd2_396m",
@@ -109,6 +114,15 @@ static const char *enfc_sels[]	= {
 	"pll2_pfd2_396m",
 };
 
+static const char *enfc_sels_plus[] = {
+	"pll2_pfd0_352m",
+	"pll2_bus",
+	"pll3_usb_otg",
+	"pll2_pfd2_396m",
+	"pll3_pfd3_454m",
+	"dummy",
+};
+
 static const char *eim_sels[] = {
 	"axi",
 	"pll3_usb_otg",
@@ -404,7 +418,10 @@ static int imx6_ccm_probe(struct device_d *dev)
 	clks[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel",       base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
 	clks[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_mux("usdhc3_sel",       base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
 	clks[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_mux("usdhc4_sel",       base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-	clks[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
+	if (cpu_is_plus())
+		clks[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
+	else
+		clks[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels_plus,    ARRAY_SIZE(enfc_sels_plus));
 	clks[IMX6QDL_CLK_EIM_SEL]          = imx_clk_mux("eim_sel",          base + 0x1c, 27, 2, eim_sels,          ARRAY_SIZE(eim_sels));
 	clks[IMX6QDL_CLK_EIM_SLOW_SEL]     = imx_clk_mux("eim_slow_sel",     base + 0x1c, 29, 2, eim_sels,          ARRAY_SIZE(eim_sels));
 	clks[IMX6QDL_CLK_VDO_AXI_SEL]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
-- 
2.16.1



From antonynpavlov at gmail.com  Wed Apr 11 22:35:55 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 12 Apr 2018 08:35:55 +0300
Subject: [PATCH 0/4] ARM: socfpga: misc fixes
Message-ID: <20180412053559.30687-1-antonynpavlov@gmail.com>

Antony Pavlov (4):
  net: make SoCFPGA-specific designware driver work again
  ARM: socfpga: boards: pll_config.h: remove duplicate macros
  ARM: socfpga: mach/pll_config.h: add guard macro
  ARM: socfpga_defconfig: enable Altera firmware stuff

 arch/arm/boards/ebv-socrates/pll_config.h       | 6 ------
 arch/arm/boards/terasic-sockit/pll_config.h     | 6 ------
 arch/arm/configs/socfpga_defconfig              | 3 +++
 arch/arm/mach-socfpga/include/mach/pll_config.h | 4 ++++
 drivers/net/Kconfig                             | 1 +
 5 files changed, 8 insertions(+), 12 deletions(-)

-- 
2.17.0



From antonynpavlov at gmail.com  Wed Apr 11 22:35:58 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 12 Apr 2018 08:35:58 +0300
Subject: [PATCH 3/4] ARM: socfpga: mach/pll_config.h: add guard macro
In-Reply-To: <20180412053559.30687-1-antonynpavlov@gmail.com>
References: <20180412053559.30687-1-antonynpavlov@gmail.com>
Message-ID: <20180412053559.30687-4-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/arm/mach-socfpga/include/mach/pll_config.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/mach-socfpga/include/mach/pll_config.h b/arch/arm/mach-socfpga/include/mach/pll_config.h
index 1a7e851eda..d6fb60dd24 100644
--- a/arch/arm/mach-socfpga/include/mach/pll_config.h
+++ b/arch/arm/mach-socfpga/include/mach/pll_config.h
@@ -1,3 +1,5 @@
+#ifndef _MACH_SOCFPGA_PRELOADER_PLL_CONFIG_H_
+#define _MACH_SOCFPGA_PRELOADER_PLL_CONFIG_H_
 
 #include <mach/cyclone5-clock-manager.h>
 
@@ -54,3 +56,5 @@ static struct socfpga_cm_config cm_default_cfg = {
 	.alteragrp_mpu = CONFIG_HPS_ALTERAGRP_MPUCLK,
 	.alteregrp_main = CONFIG_HPS_ALTERAGRP_MAINCLK,
 };
+
+#endif /* _MACH_SOCFPGA_PRELOADER_PLL_CONFIG_H_ */
-- 
2.17.0



From antonynpavlov at gmail.com  Wed Apr 11 22:35:57 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 12 Apr 2018 08:35:57 +0300
Subject: [PATCH 2/4] ARM: socfpga: boards: pll_config.h: remove duplicate
 macros
In-Reply-To: <20180412053559.30687-1-antonynpavlov@gmail.com>
References: <20180412053559.30687-1-antonynpavlov@gmail.com>
Message-ID: <20180412053559.30687-3-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/arm/boards/ebv-socrates/pll_config.h   | 6 ------
 arch/arm/boards/terasic-sockit/pll_config.h | 6 ------
 2 files changed, 12 deletions(-)

diff --git a/arch/arm/boards/ebv-socrates/pll_config.h b/arch/arm/boards/ebv-socrates/pll_config.h
index 083ebd4a87..e912912c9a 100644
--- a/arch/arm/boards/ebv-socrates/pll_config.h
+++ b/arch/arm/boards/ebv-socrates/pll_config.h
@@ -87,12 +87,6 @@
 #define CONFIG_HPS_CLK_MAINVCO_HZ (1600000000)
 #define CONFIG_HPS_CLK_PERVCO_HZ (1000000000)
 #define CONFIG_HPS_CLK_SDRVCO_HZ (666666666)
-#define CONFIG_HPS_CLK_OSC1_HZ (25000000)
-#define CONFIG_HPS_CLK_OSC2_HZ (25000000)
-#define CONFIG_HPS_CLK_F2S_SDR_REF_HZ (0)
-#define CONFIG_HPS_CLK_F2S_PER_REF_HZ (0)
-#define CONFIG_HPS_CLK_MAINVCO_HZ (1600000000)
-#define CONFIG_HPS_CLK_PERVCO_HZ (1000000000)
 #define CONFIG_HPS_CLK_EMAC0_HZ (1953125)
 #define CONFIG_HPS_CLK_EMAC1_HZ (250000000)
 #define CONFIG_HPS_CLK_USBCLK_HZ (200000000)
diff --git a/arch/arm/boards/terasic-sockit/pll_config.h b/arch/arm/boards/terasic-sockit/pll_config.h
index e064e2b2b2..ef4a59a611 100644
--- a/arch/arm/boards/terasic-sockit/pll_config.h
+++ b/arch/arm/boards/terasic-sockit/pll_config.h
@@ -87,12 +87,6 @@
 #define CONFIG_HPS_CLK_MAINVCO_HZ (1600000000)
 #define CONFIG_HPS_CLK_PERVCO_HZ (1000000000)
 #define CONFIG_HPS_CLK_SDRVCO_HZ (800000000)
-#define CONFIG_HPS_CLK_OSC1_HZ (25000000)
-#define CONFIG_HPS_CLK_OSC2_HZ (25000000)
-#define CONFIG_HPS_CLK_F2S_SDR_REF_HZ (0)
-#define CONFIG_HPS_CLK_F2S_PER_REF_HZ (0)
-#define CONFIG_HPS_CLK_MAINVCO_HZ (1600000000)
-#define CONFIG_HPS_CLK_PERVCO_HZ (1000000000)
 #define CONFIG_HPS_CLK_EMAC0_HZ (1953125)
 #define CONFIG_HPS_CLK_EMAC1_HZ (250000000)
 #define CONFIG_HPS_CLK_USBCLK_HZ (200000000)
-- 
2.17.0



From antonynpavlov at gmail.com  Wed Apr 11 22:35:56 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 12 Apr 2018 08:35:56 +0300
Subject: [PATCH 1/4] net: make SoCFPGA-specific designware driver work again
In-Reply-To: <20180412053559.30687-1-antonynpavlov@gmail.com>
References: <20180412053559.30687-1-antonynpavlov@gmail.com>
Message-ID: <20180412053559.30687-2-antonynpavlov@gmail.com>

If MFD_SYSCON is disabled in .config then socfpga_designware_eth probe
fails with this message:

  socfpga_designware_eth ff702000.ethernet: Could not get sysmgr-syscon node

Thanks to Steffen for hint!

Cc: Steffen Trumtrar <s.trumtrar at pengutronix.de>
Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/arm/configs/socfpga_defconfig | 1 +
 drivers/net/Kconfig                | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index dbc33f952f..6883b5f526 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -71,6 +71,7 @@ CONFIG_OF_BAREBOX_DRIVERS=y
 CONFIG_OF_BAREBOX_ENV_IN_FS=y
 CONFIG_DRIVER_SERIAL_NS16550=y
 CONFIG_DRIVER_NET_DESIGNWARE=y
+CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA=y
 CONFIG_MCI=y
 CONFIG_MCI_DW=y
 CONFIG_MFD_MC13XXX=y
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 09676b3d60..b633a3ac4d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -82,6 +82,7 @@ config DRIVER_NET_DESIGNWARE_GENERIC
 config DRIVER_NET_DESIGNWARE_SOCFPGA
 	bool "Designware Universal MAC ethernet driver for SoCFPGA platforms"
 	depends on ARCH_SOCFPGA
+	select MFD_SYSCON
 	help
 	  This option enables support for the Synopsys
 	  Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA.
-- 
2.17.0



From antonynpavlov at gmail.com  Wed Apr 11 22:35:59 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 12 Apr 2018 08:35:59 +0300
Subject: [PATCH 4/4] ARM: socfpga_defconfig: enable Altera firmware stuff
In-Reply-To: <20180412053559.30687-1-antonynpavlov@gmail.com>
References: <20180412053559.30687-1-antonynpavlov@gmail.com>
Message-ID: <20180412053559.30687-5-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/arm/configs/socfpga_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index 6883b5f526..3a50bae8f2 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -60,6 +60,7 @@ CONFIG_CMD_LED=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_LED_TRIGGER=y
 CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_FIRMWARELOAD=y
 CONFIG_CMD_OF_NODE=y
 CONFIG_CMD_OF_PROPERTY=y
 CONFIG_CMD_OFTREE=y
@@ -82,6 +83,7 @@ CONFIG_LED_TRIGGERS=y
 CONFIG_EEPROM_AT25=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_GPIO_DESIGNWARE=y
+CONFIG_FIRMWARE_ALTERA_SOCFPGA=y
 CONFIG_FS_EXT4=y
 CONFIG_FS_TFTP=y
 CONFIG_FS_NFS=y
-- 
2.17.0



From s.hauer at pengutronix.de  Thu Apr 12 00:09:27 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:09:27 +0200
Subject: [PATCH] mfd: da9063: Fix compilation
Message-ID: <20180412070927.6374-1-s.hauer@pengutronix.de>

Fixes: 1ef7cd07a3 watchdog: rename dev to hwdev

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/mfd/da9063.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index 4a335c9983..ac303611c0 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -126,7 +126,7 @@ static int da9063_probe(struct device_d *dev)
 	priv = xzalloc(sizeof(struct da9063));
 	priv->wd.priority = of_get_watchdog_priority(dev->device_node);
 	priv->wd.set_timeout = da9063_watchdog_set_timeout;
-	priv->wd.dev = dev;
+	priv->wd.hwdev = dev;
 	priv->client = to_i2c_client(dev);
 	priv->dev = dev;
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:30 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:30 +0200
Subject: [PATCH 8/9] ARM: i.MX: phycore-som: added and enabled DA9062 PMIC
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-9-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index b10530cbcf..c492b2ea47 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -138,6 +138,16 @@
 		compatible = "24c32";
 		reg = <0x50>;
 	};
+
+	pmic at 58 {
+		compatible = "dlg,da9062";
+		reg = <0x58>;
+		status = "okay";
+
+		watchdog-priority = <500>;
+		restart-priority = <500>;
+		reset-source-priority = <500>;
+	};
 };
 
 &iomuxc {
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:26 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:26 +0200
Subject: [PATCH 4/9] mfd: da9063: add device specific init function
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-5-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

Provide some more information about the used PMIC type; later patches
will add support for DA9062 which needs a custom init function.

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/da9063.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index 4f09bd384e..a1c748610a 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -52,6 +52,10 @@ struct da9063 {
 #define DA9063_WATCHDOG		0x01
 #define DA9063_SHUTDOWN		0x02
 
+struct da906x_device_data {
+	int	(*init)(struct da9063 *priv);
+};
+
 static int da906x_reg_update(struct da9063 *priv, unsigned int reg,
 			     uint8_t mask, uint8_t val)
 {
@@ -182,8 +186,13 @@ static void da9063_restart(struct restart_handler *rst)
 static int da9063_probe(struct device_d *dev)
 {
 	struct da9063 *priv = NULL;
+	struct da906x_device_data const *dev_data;
+	void const *dev_data_tmp;
 	int ret;
 
+	ret = dev_get_drvdata(dev, &dev_data_tmp);
+	dev_data = ret < 0 ? NULL : dev_data_tmp;
+
 	priv = xzalloc(sizeof(struct da9063));
 	priv->wd.priority = of_get_watchdog_priority(dev->device_node);
 	priv->wd.set_timeout = da9063_watchdog_set_timeout;
@@ -192,6 +201,12 @@ static int da9063_probe(struct device_d *dev)
 	priv->client = to_i2c_client(dev);
 	priv->dev = dev;
 
+	if (dev_data && dev_data->init) {
+		ret = dev_data->init(priv);
+		if (ret < 0)
+			goto on_error;
+	}
+
 	ret = watchdog_register(&priv->wd);
 	if (ret)
 		goto on_error;
@@ -213,7 +228,7 @@ on_error:
 }
 
 static struct platform_device_id da9063_id[] = {
-        { "da9063", },
+	{ "da9063", (uintptr_t)(NULL) },
 	{ }
 };
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:28 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:28 +0200
Subject: [PATCH 6/9] mfd: da9063: read out and report device id
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-7-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

just some kind of debugging atm...

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/da9063.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index 00a61279f3..0c27bf495f 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -45,6 +45,8 @@ struct da9063 {
 /* bank1: control register I */
 #define DA9063_REG1_CONFIG_I	0x10e
 
+#define DA9062AA_DEVICE_ID	0x181
+
 /* DA9063_REG_FAULT_LOG (addr=0x05) */
 #define DA9063_TWD_ERROR	0x01
 #define DA9063_POR		0x02
@@ -196,6 +198,7 @@ static void da9063_restart(struct restart_handler *rst)
 static int da9062_device_init(struct da9063 *priv)
 {
 	int ret;
+	uint8_t id[4];
 
 	priv->client1 = i2c_new_dummy(priv->client->adapter,
 				      priv->client->addr + 1);
@@ -206,6 +209,16 @@ static int da9062_device_init(struct da9063 *priv)
 		return -EINVAL;
 	}
 
+	ret = i2c_read_reg(priv->client1, DA9062AA_DEVICE_ID & 0xffu,
+			   id, sizeof id);
+	if (ret < 0) {
+		dev_warn(priv->dev, "failed to read ID: %d\n", ret);
+		return ret;
+	}
+
+	dev_info(priv->dev, "da9062 with id %02x.%02x.%02x.%02x detected\n",
+		 id[0], id[1], id[2], id[3]);
+
 	/* clear CONFIG_I[WATCHDOG_SD] */
 	ret = da906x_reg_update(priv, DA9063_REG1_CONFIG_I,
 				DA9062_WATCHDOG_SD, DA9062_WATCHDOG_SD);
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:22 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:22 +0200
Subject: [PATCH 0/9] Dialog da9063 updates
Message-ID: <20180412072231.31207-1-s.hauer@pengutronix.de>

Here are some patches found in the Phytec git repository.

Sascha

Enrico Scholz (8):
  mfd: da9063: reset watchdog timer
  mfd: da9063: added generic reg_update() function
  mfd: da9063: use da906x_reg_update()
  mfd: da9063: add device specific init function
  mfd: da9063: added of_device_id information
  mfd: da9063: read out and report device id
  ARM: i.MX: phycore-som: added and enabled DA9062 PMIC
  ARM: i.MX: pfla02: set priority of da9063 watchdog

Stefan Christ (1):
  mfd: da9063: update Kconfig for DA9062

 arch/arm/dts/imx6qdl-phytec-pfla02.dtsi      |   6 +
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi |  10 ++
 drivers/mfd/Kconfig                          |   2 +-
 drivers/mfd/da9063.c                         | 159 +++++++++++++++++++++++++--
 4 files changed, 165 insertions(+), 12 deletions(-)

-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:23 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:23 +0200
Subject: [PATCH 1/9] mfd: da9063: reset watchdog timer
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-2-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

Setting the new timeout does not suffice for restarting the watchdog;
the self-clearing bit in CONTROL_F must be set too.

barebox does not provide a ping function in its watchdog api to restart
the watchdog timer.  Detect ping vs. set_timeout() by comparing the
actual with the previous timeout value.

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/da9063.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index ac303611c0..74ad5bfdab 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -28,8 +28,13 @@ struct da9063 {
 	struct watchdog		wd;
 	struct i2c_client	*client;
 	struct device_d		*dev;
+	unsigned int		timeout;
 };
 
+/* forbidden/impossible value; timeout will be set to this value initially to
+ * detect ping vs. set_timeout() operations. */
+#define DA9063_INITIAL_TIMEOUT	(~0u)
+
 /* System Control and Event Registers */
 #define DA9063_REG_FAULT_LOG	0x05
 #define DA9063_REG_CONTROL_D	0x11
@@ -44,8 +49,25 @@ struct da9063 {
 #define DA9063_TWDSCALE_MASK	0x07
 
 /* DA9063_REG_CONTROL_F (addr=0x13) */
+#define DA9063_WATCHDOG		0x01
 #define DA9063_SHUTDOWN		0x02
 
+static int da9063_watchdog_ping(struct da9063 *priv)
+{
+	int ret;
+	u8 val;
+
+	dev_dbg(priv->dev, "ping\n");
+
+	/* reset watchdog timer; register is self clearing */
+	val = DA9063_WATCHDOG;
+	ret = i2c_write_reg(priv->client, DA9063_REG_CONTROL_F, &val, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
 {
 	struct da9063 *priv = container_of(wd, struct da9063, wd);
@@ -57,8 +79,14 @@ static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
 	if (timeout > 131)
 		return -EINVAL;
 
+	timeout *= 1000; /* convert to ms */
+
+	if (timeout == priv->timeout)
+		/* set_timeout called with previous parameter; just ping the
+		 * watchdog */
+		goto out;
+
 	if (timeout) {
-		timeout *= 1000; /* convert to ms */
 		scale = 0;
 		while (timeout > (2048 << scale) && scale <= 6)
 			scale++;
@@ -78,7 +106,10 @@ static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
 	if (ret < 0)
 		return ret;
 
-	return 0;
+	priv->timeout = timeout;
+
+out:
+	return da9063_watchdog_ping(priv);
 }
 
 static void da9063_detect_reset_source(struct da9063 *priv)
@@ -127,6 +158,7 @@ static int da9063_probe(struct device_d *dev)
 	priv->wd.priority = of_get_watchdog_priority(dev->device_node);
 	priv->wd.set_timeout = da9063_watchdog_set_timeout;
 	priv->wd.hwdev = dev;
+	priv->timeout = DA9063_INITIAL_TIMEOUT;
 	priv->client = to_i2c_client(dev);
 	priv->dev = dev;
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:24 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:24 +0200
Subject: [PATCH 2/9] mfd: da9063: added generic reg_update() function
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-3-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

Used to set or clear bits of a register.

The calculation of 'client' might look odd and unnecessary complicated.
But style prepares access to other register banks which is added in
following patches.

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/da9063.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index 74ad5bfdab..68b0723b61 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -52,6 +52,43 @@ struct da9063 {
 #define DA9063_WATCHDOG		0x01
 #define DA9063_SHUTDOWN		0x02
 
+static int da906x_reg_update(struct da9063 *priv, unsigned int reg,
+			     uint8_t mask, uint8_t val)
+{
+	struct i2c_client *client;
+	uint8_t tmp;
+	int ret;
+
+	if (reg < 0x100)
+		client = priv->client;
+	else
+		/* this should/can not happen because function is usually
+		 * called with a static register number; warn about it
+		 * below */
+		client = NULL;
+
+	if (WARN_ON(!client))
+		return -EINVAL;
+
+	ret = i2c_read_reg(client, reg & 0xffu, &tmp, 1);
+	if (ret < 0) {
+		dev_warn(priv->dev, "failed to read reg %02x\n", reg);
+		return ret;
+	}
+
+	tmp &= ~mask;
+	tmp |= val;
+
+	ret = i2c_write_reg(client, reg & 0xffu, &tmp, 1);
+	if (ret < 0) {
+		dev_warn(priv->dev, "failed to write %02x into reg %02x\n",
+			 tmp, reg);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int da9063_watchdog_ping(struct da9063 *priv)
 {
 	int ret;
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:25 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:25 +0200
Subject: [PATCH 3/9] mfd: da9063: use da906x_reg_update()
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-4-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

Use the previously added da906x_reg_update() function.

NOTE: patch depends on another patchset ("da9063: reset watchdog
timer"),

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/da9063.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index 68b0723b61..4f09bd384e 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -111,7 +111,6 @@ static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
 	struct device_d *dev = priv->dev;
 	unsigned int scale = 0;
 	int ret;
-	u8 val;
 
 	if (timeout > 131)
 		return -EINVAL;
@@ -132,14 +131,8 @@ static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
 		scale++; /* scale 0 disables the WD */
 	}
 
-	ret = i2c_read_reg(priv->client, DA9063_REG_CONTROL_D, &val, 1);
-	if (ret < 0)
-		return ret;
-
-	val &= ~DA9063_TWDSCALE_MASK;
-	val |= scale;
-
-	ret = i2c_write_reg(priv->client, DA9063_REG_CONTROL_D, &val, 1);
+	ret = da906x_reg_update(priv, DA9063_REG_CONTROL_D,
+				DA9063_TWDSCALE_MASK, scale);
 	if (ret < 0)
 		return ret;
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:31 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:31 +0200
Subject: [PATCH 9/9] ARM: i.MX: pfla02: set priority of da9063 watchdog
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-10-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

To win against the internal imx6 or other external watchdogs, increase
priority (default: 100) of the da9063 watchdog.

Ditto for the restart handler and reset source priority.

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-pfla02.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
index 9a8c7024a3..7cc8be1951 100644
--- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
@@ -200,4 +200,10 @@
 		pagesize = <32>;
 		reg = <0x50>;
 	};
+
+	pmic at 58 {
+		watchdog-priority = <500>;
+		restart-priority = <500>;
+		reset-source-priority = <500>;
+	};
 };
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:29 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:29 +0200
Subject: [PATCH 7/9] mfd: da9063: update Kconfig for DA9062
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-8-s.hauer@pengutronix.de>

From: Stefan Christ <s.christ at phytec.de>

Signed-off-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 417c9ce96c..521cf042ae 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -13,7 +13,7 @@ config MFD_DA9053
 
 config MFD_DA9063
 	depends on I2C
-	bool "DA9063 PMIC driver"
+	bool "DA9063/DA9062 PMIC driver"
 
 config MFD_LP3972
 	depends on I2C
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:22:27 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:22:27 +0200
Subject: [PATCH 5/9] mfd: da9063: added of_device_id information
In-Reply-To: <20180412072231.31207-1-s.hauer@pengutronix.de>
References: <20180412072231.31207-1-s.hauer@pengutronix.de>
Message-ID: <20180412072231.31207-6-s.hauer@pengutronix.de>

From: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Tested-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 drivers/mfd/da9063.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
index a1c748610a..00a61279f3 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -27,6 +27,8 @@ struct da9063 {
 	struct restart_handler	restart;
 	struct watchdog		wd;
 	struct i2c_client	*client;
+	/* dummy client for accessing bank #1 */
+	struct i2c_client	*client1;
 	struct device_d		*dev;
 	unsigned int		timeout;
 };
@@ -40,6 +42,9 @@ struct da9063 {
 #define DA9063_REG_CONTROL_D	0x11
 #define DA9063_REG_CONTROL_F	0x13
 
+/* bank1: control register I */
+#define DA9063_REG1_CONFIG_I	0x10e
+
 /* DA9063_REG_FAULT_LOG (addr=0x05) */
 #define DA9063_TWD_ERROR	0x01
 #define DA9063_POR		0x02
@@ -52,6 +57,9 @@ struct da9063 {
 #define DA9063_WATCHDOG		0x01
 #define DA9063_SHUTDOWN		0x02
 
+/* DA9063_REG_CONTROL_I (addr=0x10e) */
+#define DA9062_WATCHDOG_SD	BIT(3)
+
 struct da906x_device_data {
 	int	(*init)(struct da9063 *priv);
 };
@@ -65,6 +73,8 @@ static int da906x_reg_update(struct da9063 *priv, unsigned int reg,
 
 	if (reg < 0x100)
 		client = priv->client;
+	else if (reg < 0x200)
+		client = priv->client1;
 	else
 		/* this should/can not happen because function is usually
 		 * called with a static register number; warn about it
@@ -183,6 +193,30 @@ static void da9063_restart(struct restart_handler *rst)
 	i2c_write_reg(priv->client, DA9063_REG_CONTROL_F, &val, 1);
 }
 
+static int da9062_device_init(struct da9063 *priv)
+{
+	int ret;
+
+	priv->client1 = i2c_new_dummy(priv->client->adapter,
+				      priv->client->addr + 1);
+	if (!priv) {
+		dev_warn(priv->dev, "failed to create bank 1 device\n");
+		/* TODO: return -EINVAL; i2c api does not return more
+		 * details */
+		return -EINVAL;
+	}
+
+	/* clear CONFIG_I[WATCHDOG_SD] */
+	ret = da906x_reg_update(priv, DA9063_REG1_CONFIG_I,
+				DA9062_WATCHDOG_SD, DA9062_WATCHDOG_SD);
+
+	return ret;
+}
+
+static struct da906x_device_data const	da9062_device_data = {
+	.init	= da9062_device_init,
+};
+
 static int da9063_probe(struct device_d *dev)
 {
 	struct da9063 *priv = NULL;
@@ -229,13 +263,26 @@ on_error:
 
 static struct platform_device_id da9063_id[] = {
 	{ "da9063", (uintptr_t)(NULL) },
+	{ "da9062", (uintptr_t)(&da9062_device_data) },
 	{ }
 };
 
+static struct of_device_id const	da906x_dt_ids[] = {
+	{
+		.compatible	= "dlg,da9063",
+		.data		= NULL,
+	}, {
+		.compatible	= "dlg,da9062",
+		.data		= &da9062_device_data,
+	}, {
+	}
+};
+
 static struct driver_d da9063_driver = {
 	.name = "da9063",
 	.probe = da9063_probe,
 	.id_table = da9063_id,
+	.of_compatible  = DRV_OF_COMPAT(da906x_dt_ids),
 };
 
 static int da9063_init(void)
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:03 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:03 +0200
Subject: [PATCH 02/16] ARM: i.MX: phytec-som-imx: env: automount emmc if
 available
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-3-s.hauer@pengutronix.de>

From: Matthias Rabe <matthias.rabe at sigma-chemnitz.de>

added automount configuration for emmc, if available.
needed f.e. by the android boot.

Signed-off-by: Matthias Rabe <matthias.rabe at sigma-chemnitz.de>
Tested-by: Wadim Egorov <w.egorov at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 .../arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/automount | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/automount b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/automount
index 4b223d8037..fea64d627e 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/automount
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/automount
@@ -7,3 +7,8 @@ automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
 
 mkdir -p /mnt/mmc
 automount -d /mnt/mmc 'mmc2.probe=1 && [ -e /dev/mmc2.0 ] && mount /dev/mmc2.0 /mnt/mmc'
+
+if [ -e /dev/mmc3 ]; then
+  mkdir -p /mnt/mmc3
+  automount -d /mnt/mmc3 'mmc3.probe=1 && [ -e /dev/mmc3.0 ] && mount /dev/mmc3.0 /mnt/mmc3'
+fi
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:05 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:05 +0200
Subject: [PATCH 04/16] ARM: i.MX: phytec-som-imx: env: add android boot options
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-5-s.hauer@pengutronix.de>

From: Matthias Rabe <matthias.rabe at sigma-chemnitz.de>

Set needed bootargs for android in mmc, emmc and nand boot.

Signed-off-by: Matthias Rabe <matthias.rabe at sigma-chemnitz.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc | 5 +++++
 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc  | 5 +++++
 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand | 5 +++++
 3 files changed, 15 insertions(+)

diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
index 83924df5d7..4e286dc325 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
@@ -1,5 +1,10 @@
 #!/bin/sh
 
+if [ -f /mnt/mmc3/android ]; then
+	# configure here the android specific stuff
+	global linux.bootargs.sec="selinux=0 enforcing=0"
+fi
+
 global.bootm.image="/mnt/mmc3/linuximage"
 global.bootm.oftree="/mnt/mmc3/oftree"
 global.linux.bootargs.dyn.root="root=/dev/mmcblk3p2 rootwait rw"
diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc
index 332fc26ad0..df874f0a38 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc
@@ -1,5 +1,10 @@
 #!/bin/sh
 
+if [ -f /mnt/mmc/android ]; then
+	# configure here the android specific stuff
+	global linux.bootargs.sec="selinux=0 enforcing=0"
+fi
+
 global.bootm.image="/mnt/mmc/linuximage"
 global.bootm.oftree="/mnt/mmc/oftree"
 global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootwait rw"
diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand
index e4eded530d..0c2b1cbe4c 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand
@@ -2,6 +2,11 @@
 
 [ ! -e /dev/nand0.root.ubi ] && ubiattach /dev/nand0.root
 
+if [ -e /dev/nand0.root.ubi.system ]; then
+	# configure here the android specific stuff
+	global linux.bootargs.sec="selinux=0 enforcing=0"
+fi
+
 global.bootm.image="/dev/nand0.root.ubi.kernel"
 global.bootm.oftree="/dev/nand0.root.ubi.oftree"
 global.linux.bootargs.dyn.root="root=ubi0:root ubi.mtd=root rootfstype=ubifs rw"
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:02 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:02 +0200
Subject: [PATCH 01/16] ARM: i.MX: phytec-som-imx: Remove kernel and oftree
 partiton in NAND
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-2-s.hauer@pengutronix.de>

From: Christian Hemp <christian.hemp at gmail.com>

We store kernel and oftree in static UBI volumes now. No need
for separate partitions any more.

Signed-off-by: Christian Hemp <christian.hemp at gmail.com>
Acked-by: Stefan Lengfeld <s.lengfeld at phytec.de>
---
 .../boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand  |  6 ++++--
 arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi                       | 12 +-----------
 arch/arm/dts/imx6qdl-phytec-pfla02.dtsi                      | 12 +-----------
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi                 | 12 +-----------
 4 files changed, 7 insertions(+), 35 deletions(-)

diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand
index a23aa21cc7..e4eded530d 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/nand
@@ -1,5 +1,7 @@
 #!/bin/sh
 
-global.bootm.image="/dev/nand0.kernel.bb"
-global.bootm.oftree="/dev/nand0.oftree.bb"
+[ ! -e /dev/nand0.root.ubi ] && ubiattach /dev/nand0.root
+
+global.bootm.image="/dev/nand0.root.ubi.kernel"
+global.bootm.oftree="/dev/nand0.root.ubi.oftree"
 global.linux.bootargs.dyn.root="root=ubi0:root ubi.mtd=root rootfstype=ubifs rw"
diff --git a/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi b/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi
index a6ea7b5cce..63dd966b87 100644
--- a/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi
+++ b/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi
@@ -145,18 +145,8 @@
 	};
 
 	partition at 420000 {
-		label = "oftree";
-		reg = <0x420000 0x20000>;
-	};
-
-	partition at 440000 {
-		label = "kernel";
-		reg = <0x440000 0x800000>;
-	};
-
-	partition at C40000 {
 		label = "root";
-		reg = <0xC40000 0x0>;
+		reg = <0x420000 0x0>;
 	};
 };
 
diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
index 9a8c7024a3..862d856d00 100644
--- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
@@ -115,18 +115,8 @@
 	};
 
 	partition at 500000 {
-		label = "oftree";
-		reg = <0x500000 0x100000>;
-	};
-
-	partition at 600000 {
-		label = "kernel";
-		reg = <0x600000 0x800000>;
-	};
-
-	partition at e00000 {
 		label = "root";
-		reg = <0xe00000 0x0>;
+		reg = <0x500000 0x0>;
 	};
 };
 
diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index b10530cbcf..3a5b0dbf24 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -112,18 +112,8 @@
 	};
 
 	partition at 500000 {
-		label = "oftree";
-		reg = <0x500000 0x100000>;
-	};
-
-	partition at 600000 {
-		label = "kernel";
-		reg = <0x600000 0x800000>;
-	};
-
-	partition at e00000 {
 		label = "root";
-		reg = <0xe00000 0x0>;
+		reg = <0x500000 0x0>;
 	};
 };
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:01 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:01 +0200
Subject: [PATCH 00/16] ARM: i.MX: phyCORE/phyFLEX i.MX6 updates
Message-ID: <20180412073017.6750-1-s.hauer@pengutronix.de>

Some more patches from the Phytec barebox git repository only lacking
the final hit to the send button.

Sascha

Christian Hemp (4):
  ARM: i.MX: phytec-som-imx: Remove kernel and oftree partiton in NAND
  ARM: dts: imx6qdl: phycore: Sync muxing with kernel
  ARM: i.MX: phytec-som-imx6: phycore: Set BUCK mode to SYNC
  ARM: i.MX: phytec-som-imx6: add phyCORE-i.MX6 QuadPlus with 1GiB RAM

Matthias Rabe (3):
  ARM: i.MX: phytec-som-imx: env: automount emmc if available
  ARM: i.MX: phytec-som-imx: env: add boot script for emmc
  ARM: i.MX: phytec-som-imx: env: add android boot options

Stefan Christ (2):
  ARM: i.MX: phytec-som-imx6: add boot device emmc
  ARM: i.MX: phytec-som-imx6: add phyCORE-i.MX6 Solo with 1GiB RAM

Stefan Riedmueller (6):
  ARM: dts: phyCORE-imx6: Add SPINOR env node
  ARM: dts: imx6: phyboard-mira: Add usb support
  ARM: dts: imx6: phyboard-mira: Enable usb host and usb otg port
  ARM: dts: imx6: phyboard-mira: Remove unecessary iomuxc subnode
  ARM: dts: phycore-imx6: Use generic jedec spi nor compatible
  ARM: i.MX: phytec-som-imx6: Change kernel boot image to zImage

michael grassmann (1):
  ARM: i.MX: phyFLEX: Change Ram Timing for i.MX6 DualLite\Solo (400
    MHz)

 arch/arm/boards/phytec-som-imx6/board.c            |  55 ++++-
 .../defaultenv-physom-imx6-phycore/boot/emmc       |   5 +
 .../defaultenv-physom-imx6/boot/emmc               |  10 +
 .../defaultenv-physom-imx6/boot/mmc                |   7 +-
 .../defaultenv-physom-imx6/boot/nand               |  11 +-
 .../defaultenv-physom-imx6/init/automount          |   5 +
 .../flash-header-phytec-pcm058dl-1gib-32bit.imxcfg |   8 +
 .../flash-header-phytec-pcm058qp-1gib.imxcfg       |   8 +
 .../phytec-som-imx6/flash-header-phytec-pcm058qp.h | 112 +++++++++
 .../flash-header-phytec-pfla02dl-1gib-1bank.imxcfg |   2 +-
 .../flash-header-phytec-pfla02dl-1gib.imxcfg       |   2 +-
 .../phytec-som-imx6/flash-header-phytec-pfla02dl.h |   2 +-
 .../flash-header-phytec-pfla02s-128mb-1bank.imxcfg |   2 +-
 .../flash-header-phytec-pfla02s-256mb-1bank.imxcfg |   2 +-
 .../flash-header-phytec-pfla02s-512mb-1bank.imxcfg |   2 +-
 arch/arm/boards/phytec-som-imx6/lowlevel.c         |   2 +
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts    |   8 +
 arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts    |   8 +
 arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi             |  12 +-
 arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts     |   8 +
 arch/arm/dts/imx6q-phytec-phycore-som-nand.dts     |   8 +
 arch/arm/dts/imx6qdl-phytec-pfla02.dtsi            |  12 +-
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi       | 252 ++++++++++++---------
 arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts    |  69 ++++++
 images/Makefile.imx                                |  10 +
 26 files changed, 488 insertions(+), 135 deletions(-)
 create mode 100644 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/boot/emmc
 create mode 100644 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp.h
 create mode 100644 arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts

-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:13 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:13 +0200
Subject: [PATCH 12/16] ARM: dts: imx6: phyboard-mira: Add usb support
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-13-s.hauer@pengutronix.de>

From: Stefan Riedmueller <s.riedmueller at phytec.de>

This patch adds USB support for the phyBOARD-Mira for the host port and
the OTG port.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 54 ++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index a826a8b2ef..1dd88b5add 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -39,6 +39,28 @@
 			status = "disabled";
 		};
 	};
+
+	reg_usbh1_vbus: regulator-usbh1 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbh1_vbus>;
+		regulator-name = "usbh1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usbotg_vbus: regulator-usbotg {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbotg_vbus>;
+		regulator-name = "usbotg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
 };
 
 &ecspi1 {
@@ -209,6 +231,24 @@
 			>;
 		};
 
+		pinctrl_usbh1_vbus: usbh1vbusgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A20__GPIO2_IO18	0xb0b1
+				>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID	0x17059
+				>;
+		};
+
+		pinctrl_usbotg_vbus: usbotgvbusgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A19__GPIO2_IO19	0xb0b1
+				>;
+		};
+
 		pinctrl_usdhc1: usdhc1grp {
 			fsl,pins = <
 				MX6QDL_PAD_SD1_CMD__SD1_CMD		0x170f9
@@ -248,6 +288,20 @@
 	status = "okay";
 };
 
+&usbh1 {
+	vbus-supply = <&reg_usbh1_vbus>;
+	disable-over-current;
+	status = "disabled";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	vbus-supply = <&reg_usbotg_vbus>;
+	disable-over-current;
+	status = "disabled";
+};
+
 &usdhc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc1>;
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:04 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:04 +0200
Subject: [PATCH 03/16] ARM: i.MX: phytec-som-imx: env: add boot script for emmc
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-4-s.hauer@pengutronix.de>

From: Matthias Rabe <matthias.rabe at sigma-chemnitz.de>

add bootscript for emmc boot

Signed-off-by: Matthias Rabe <matthias.rabe at sigma-chemnitz.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc

diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
new file mode 100644
index 0000000000..83924df5d7
--- /dev/null
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+global.bootm.image="/mnt/mmc3/linuximage"
+global.bootm.oftree="/mnt/mmc3/oftree"
+global.linux.bootargs.dyn.root="root=/dev/mmcblk3p2 rootwait rw"
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:10 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:10 +0200
Subject: [PATCH 09/16] ARM: dts: phyCORE-imx6: Add SPINOR env node
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-10-s.hauer@pengutronix.de>

From: Stefan Riedmueller <s.riedmueller at phytec.de>

Add the SPI NOR barebox-environment node to the devicetree to make it
possible to use the barebox-environment from SPI NOR when booting barebox
from SPI NOR.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index 923c79c67b..a826a8b2ef 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -32,6 +32,12 @@
 			device-path = &gpmi, "partname:barebox-environment";
 			status = "disabled";
 		};
+
+		environment-spinor {
+			compatible = "barebox,environment";
+			device-path = &flash, "partname:barebox-environment";
+			status = "disabled";
+		};
 	};
 };
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:14 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:14 +0200
Subject: [PATCH 13/16] ARM: dts: imx6: phyboard-mira: Enable usb host and usb
 otg port
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-14-s.hauer@pengutronix.de>

From: Stefan Riedmueller <s.riedmueller at phytec.de>

Enable both USB ports (HOST and OTG) on the phyBOARD-Mira with i.MX
6Quad/Dual, i.MX 6Solo/DualLight and i.MX 6QuadPlus.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts | 8 ++++++++
 arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts | 8 ++++++++
 arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts  | 8 ++++++++
 arch/arm/dts/imx6q-phytec-phycore-som-nand.dts  | 8 ++++++++
 arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts | 8 ++++++++
 5 files changed, 40 insertions(+)

diff --git a/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts b/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts
index bffee5f154..7e4a5aba2a 100644
--- a/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts
+++ b/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts
@@ -41,6 +41,14 @@
 	status = "okay";
 };
 
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
 &usdhc1 {
 	status = "okay";
 
diff --git a/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts
index 1b66fdabc6..ffcbdc2134 100644
--- a/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts
+++ b/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts
@@ -36,6 +36,14 @@
 	status = "okay";
 };
 
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
 &usdhc1 {
 	status = "okay";
 
diff --git a/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts b/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts
index ecc5aa38e1..6e12b26d38 100644
--- a/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts
+++ b/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts
@@ -40,6 +40,14 @@
 	status = "okay";
 };
 
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
 &usdhc1 {
 	status = "okay";
 
diff --git a/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts
index 9ad7eda740..d9e37b7fca 100644
--- a/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts
+++ b/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts
@@ -45,6 +45,14 @@
 	status = "okay";
 };
 
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
 &usdhc1 {
 	status = "okay";
 
diff --git a/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts
index 031ee883ea..c2756142b5 100644
--- a/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts
+++ b/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts
@@ -43,6 +43,14 @@
 	status = "okay";
 };
 
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
 &usdhc1 {
 	status = "okay";
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:11 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:11 +0200
Subject: [PATCH 10/16] ARM: i.MX: phytec-som-imx6: add phyCORE-i.MX6 QuadPlus
 with 1GiB RAM
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-11-s.hauer@pengutronix.de>

From: Christian Hemp <c.hemp at phytec.de>

Add Phytec phyCORE-i.MX6 QuadPlus:
 - imx6qp-phytec-phycore-som-nand:
   - 1GiB RAM on 2 Banks with 64Bit
   - 1000Mbit Ethernet
   - NAND
   - SD
   - UART

Signed-off-by: Christian Hemp <c.hemp at phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/boards/phytec-som-imx6/board.c            |   4 +-
 .../flash-header-phytec-pcm058qp-1gib.imxcfg       |   8 ++
 .../phytec-som-imx6/flash-header-phytec-pcm058qp.h | 112 +++++++++++++++++++++
 arch/arm/boards/phytec-som-imx6/lowlevel.c         |   1 +
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts    |  61 +++++++++++
 images/Makefile.imx                                |   5 +
 7 files changed, 191 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp.h
 create mode 100644 arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts

diff --git a/arch/arm/boards/phytec-som-imx6/board.c b/arch/arm/boards/phytec-som-imx6/board.c
index f9b6cf55cd..1a2d45ec92 100644
--- a/arch/arm/boards/phytec-som-imx6/board.c
+++ b/arch/arm/boards/phytec-som-imx6/board.c
@@ -173,6 +173,7 @@ static int physom_imx6_devices_init(void)
 	} else if (of_machine_is_compatible("phytec,imx6q-pcm058-nand")
 		|| of_machine_is_compatible("phytec,imx6q-pcm058-emmc")
 		|| of_machine_is_compatible("phytec,imx6dl-pcm058-nand")
+		|| of_machine_is_compatible("phytec,imx6qp-pcm058-nand")
 		|| of_machine_is_compatible("phytec,imx6dl-pcm058-emmc")) {
 
 		if (phycore_da9062_setup_buck_mode())
@@ -235,7 +236,8 @@ static int physom_imx6_devices_init(void)
 	defaultenv_append_directory(defaultenv_physom_imx6);
 
 	/* Overwrite file /env/init/automount */
-	if (of_machine_is_compatible("phytec,imx6q-pcm058-nand")
+	if (of_machine_is_compatible("phytec,imx6qp-pcm058-nand")
+		|| of_machine_is_compatible("phytec,imx6q-pcm058-nand")
 		|| of_machine_is_compatible("phytec,imx6q-pcm058-emmc")
 		|| of_machine_is_compatible("phytec,imx6dl-pcm058-nand")
 		|| of_machine_is_compatible("phytec,imx6dl-pcm058-emmc")) {
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg
new file mode 100644
index 0000000000..bf85f0a19c
--- /dev/null
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg
@@ -0,0 +1,8 @@
+#define SETUP_MDCFG0			\
+	wm 32 0x021b000c 0x555A7955
+
+#define SETUP_MDASP_MDCTL		\
+	wm 32 0x021b0040 0x00000027;	\
+	wm 32 0x021b0000 0x831A0000
+
+#include "flash-header-phytec-pcm058qp.h"
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp.h b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp.h
new file mode 100644
index 0000000000..6e7b740a6f
--- /dev/null
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp.h
@@ -0,0 +1,112 @@
+soc imx6
+loadaddr 0x10000000
+dcdofs 0x400
+
+/* NOC setup */
+wm 32 0x00bb0008 0x00000000
+wm 32 0x00bb000c 0x2891E41A
+wm 32 0x00bb0038 0x00000564
+wm 32 0x00bb0014 0x00000040
+wm 32 0x00bb0028 0x00000020
+wm 32 0x00bb002c 0x00000020
+
+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 0x020e0590 0x00003000
+wm 32 0x020e0598 0x00003000
+wm 32 0x020e078c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e05a8 0x00000028
+wm 32 0x020e05b0 0x00000028
+wm 32 0x020e0524 0x00000028
+wm 32 0x020e051c 0x00000028
+wm 32 0x020e0518 0x00000028
+wm 32 0x020e050c 0x00000028
+wm 32 0x020e05b8 0x00000028
+wm 32 0x020e05c0 0x00000028
+wm 32 0x020e0774 0x00020000
+wm 32 0x020e0784 0x00000028
+wm 32 0x020e0788 0x00000028
+wm 32 0x020e0794 0x00000028
+wm 32 0x020e079c 0x00000028
+wm 32 0x020e07a0 0x00000028
+wm 32 0x020e07a4 0x00000028
+wm 32 0x020e07a8 0x00000028
+wm 32 0x020e0748 0x00000028
+wm 32 0x020e05ac 0x00000028
+wm 32 0x020e05b4 0x00000028
+wm 32 0x020e0528 0x00000028
+wm 32 0x020e0520 0x00000028
+wm 32 0x020e0514 0x00000028
+wm 32 0x020e0510 0x00000028
+wm 32 0x020e05bc 0x00000028
+wm 32 0x020e05c4 0x00000028
+wm 32 0x021b0800 0xa1390003
+wm 32 0x021b4800 0xa1380003
+wm 32 0x021b080c 0x00140014
+wm 32 0x021b0810 0x00230018
+wm 32 0x021b480c 0x000A001E
+wm 32 0x021b4810 0x000A0015
+wm 32 0x021b083c 0x43080314
+wm 32 0x021b0840 0x02680300
+wm 32 0x021b483c 0x430C0318
+wm 32 0x021b4840 0x03000254
+wm 32 0x021b0848 0x3A323234
+wm 32 0x021b4848 0x3E3C3242
+wm 32 0x021b0850 0x2A2E3632
+wm 32 0x021b4850 0x3C323E34
+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
+
+SETUP_MDCFG0
+
+wm 32 0x021b0010 0xFF328F64
+wm 32 0x021b0014 0x01FF00DB
+wm 32 0x021b0018 0x00011740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b002c 0x000026d2
+wm 32 0x021b0030 0x003F1023
+
+SETUP_MDASP_MDCTL
+
+wm 32 0x021b001c 0x04088032
+wm 32 0x021b001c 0x0408803a
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x0000803b
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x00048039
+wm 32 0x021b001c 0x09408030
+wm 32 0x021b001c 0x09408038
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b001c 0x04008048
+wm 32 0x021b0020 0x00007800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b4818 0x00011117
+wm 32 0x021b0890 0x00400c58
+wm 32 0x021b0400 0x14420000
+wm 32 0x021b0004 0x00025576
+wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
+wm 32 0x020e0010 0xf00000ff
+wm 32 0x020e0018 0x007F007F
+wm 32 0x020e001c 0x007F007F
+wm 32 0x020c8000 0x80002021
diff --git a/arch/arm/boards/phytec-som-imx6/lowlevel.c b/arch/arm/boards/phytec-som-imx6/lowlevel.c
index 12c3cfa642..9aa2104a3c 100644
--- a/arch/arm/boards/phytec-som-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-som-imx6/lowlevel.c
@@ -109,6 +109,7 @@ PHYTEC_ENTRY(start_phytec_phyboard_subra_1gib_1bank, imx6q_phytec_phyboard_subra
 PHYTEC_ENTRY(start_phytec_phycore_imx6dl_som_nand_256mb, imx6dl_phytec_phycore_som_nand, SZ_256M, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6dl_som_emmc_1gib, imx6dl_phytec_phycore_som_emmc, SZ_1G, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6q_som_nand_1gib, imx6q_phytec_phycore_som_nand, SZ_1G, true);
+PHYTEC_ENTRY(start_phytec_phycore_imx6qp_som_nand_1gib, imx6qp_phytec_phycore_som_nand, SZ_1G, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6q_som_emmc_1gib, imx6q_phytec_phycore_som_emmc, SZ_1G, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6q_som_emmc_2gib, imx6q_phytec_phycore_som_emmc, SZ_2G, true);
 
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0400c9349a..b69592e64e 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -58,6 +58,7 @@ pbl-dtb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += imx6q-phytec-pbaa03.dtb.o \
 				imx6dl-phytec-phyboard-subra.dtb.o \
 				imx6q-phytec-phycore-som-nand.dtb.o \
 				imx6q-phytec-phycore-som-emmc.dtb.o \
+				imx6qp-phytec-phycore-som-nand.dtb.o \
 				imx6dl-phytec-phycore-som-nand.dtb.o \
 				imx6dl-phytec-phycore-som-emmc.dtb.o \
 				imx6ul-phytec-phycore-som.dtb.o \
diff --git a/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts
new file mode 100644
index 0000000000..031ee883ea
--- /dev/null
+++ b/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 Phytec Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp at phytec.de>
+ *
+ * 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 <arm/imx6qp.dtsi>
+#include "imx6qdl-phytec-phycore-som.dtsi"
+
+/ {
+	model = "Phytec phyCORE-i.MX6 Quad with NAND";
+	compatible = "phytec,imx6qp-pcm058-nand", "fsl,imx6qp";
+};
+
+&ecspi1 {
+	status = "okay";
+};
+
+&eeprom {
+	status = "okay";
+};
+
+&ethphy {
+	max-speed = <1000>;
+};
+
+&fec {
+	status = "okay";
+};
+
+&flash {
+	status = "okay";
+};
+
+&gpmi {
+	status = "okay";
+};
+
+&usdhc1 {
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition at 0 {
+		label = "barebox";
+		reg = <0x0 0xe0000>;
+	};
+
+	partition at e0000 {
+		label = "barebox-environment";
+		reg = <0xe0000 0x20000>;
+	};
+};
diff --git a/images/Makefile.imx b/images/Makefile.imx
index ada828f644..5e10f4fbf3 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -440,6 +440,11 @@ CFG_start_phytec_phycore_imx6q_som_nand_1gib.pblx.imximg = $(board)/phytec-som-i
 FILE_barebox-phytec-phycore-imx6q-som-nand-1gib.img = start_phytec_phycore_imx6q_som_nand_1gib.pblx.imximg
 image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6q-som-nand-1gib.img
 
+pblx-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6qp_som_nand_1gib
+CFG_start_phytec_phycore_imx6qp_som_nand_1gib.pblx.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg
+FILE_barebox-phytec-phycore-imx6qp-som-nand-1gib.img = start_phytec_phycore_imx6qp_som_nand_1gib.pblx.imximg
+image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6qp-som-nand-1gib.img
+
 pblx-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6q_som_emmc_1gib
 CFG_start_phytec_phycore_imx6q_som_emmc_1gib.pblx.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg
 FILE_barebox-phytec-phycore-imx6q-som-emmc-1gib.img = start_phytec_phycore_imx6q_som_emmc_1gib.pblx.imximg
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:09 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:09 +0200
Subject: [PATCH 08/16] ARM: i.MX: phyFLEX: Change Ram Timing for i.MX6
 DualLite\Solo (400 MHz)
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-9-s.hauer@pengutronix.de>

From: michael grassmann <michael.grassmann at phytec.de>

The actual RAM timings in the phyFLEX BSP are generated for 528 MHz RAM clock
frequency, but the i.MX 6Solo/DualLite has only a 400 MHz RAM clock. These new
timings are accompanied by a speed increase of approx 10%.

Signed-off-by: michael grassmann <michael.grassmann at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 .../phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg      | 2 +-
 .../arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg | 2 +-
 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl.h          | 2 +-
 .../phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg      | 2 +-
 .../phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg      | 2 +-
 .../phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg      | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg
index 156eea971e..7b64e5d2fd 100644
--- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg
@@ -1,5 +1,5 @@
 #define SETUP_MDCFG0                    \
-	wm 32 0x021b000c 0x565c9b85
+	wm 32 0x021b000c 0x41447525
 
 #define SETUP_MDASP_MDCTL		\
 	wm 32 0x021b0040 0x00000027;	\
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
index e76867004a..04c489d7e8 100644
--- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
@@ -1,5 +1,5 @@
 #define SETUP_MDCFG0			\
-	wm 32 0x021b000c 0x8c929b85
+	wm 32 0x021b000c 0x2d307525
 
 #define SETUP_MDASP_MDCTL		\
 	wm 32 0x021b0040 0x00000017;	\
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl.h b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl.h
index 405529ddf8..b0f3faa0b7 100644
--- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl.h
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl.h
@@ -74,7 +74,7 @@ wm 32 MX6_MMDC_P0_MDOTC 0x09444040
 
 SETUP_MDCFG0
 
-wm 32 MX6_MMDC_P0_MDCFG1 0xff538f64
+wm 32 MX6_MMDC_P0_MDCFG1 0xb66e8b64
 wm 32 MX6_MMDC_P0_MDCFG2 0x01ff0124
 wm 32 MX6_MMDC_P0_MDMISC 0x00091740
 wm 32 MX6_MMDC_P0_MDSCR 0x00008000
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg
index 26fe2b2f7d..ebe5a968b1 100644
--- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg
@@ -1,5 +1,5 @@
 #define SETUP_MDCFG0                    \
-        wm 32 0x021b000c 0x3c409b85
+        wm 32 0x021b000c 0x2D307525
 
 #define SETUP_MDASP_MDCTL		\
         wm 32 0x021b0040 0x0000000B;    \
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg
index babb0dfe24..5f1585a40b 100644
--- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg
@@ -1,5 +1,5 @@
 #define SETUP_MDCFG0                    \
-        wm 32 0x021b000c 0x3c409b85
+        wm 32 0x021b000c 0x2D307525
 
 #define SETUP_MDASP_MDCTL		\
         wm 32 0x021b0040 0x0000000F;    \
diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg
index 6a46cd958f..5ff3ec69d7 100644
--- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg
@@ -1,5 +1,5 @@
 #define SETUP_MDCFG0			\
-	wm 32 0x021b000c 0x565c9b85
+	wm 32 0x021b000c 0x41447525
 
 #define SETUP_MDASP_MDCTL		\
 	wm 32 0x021b0040 0x00000017;	\
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:07 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:07 +0200
Subject: [PATCH 06/16] ARM: i.MX: phytec-som-imx6: add boot device emmc
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-7-s.hauer@pengutronix.de>

From: Stefan Christ <s.christ at phytec.de>

Add boot file 'emmc' for phyCORE-i.MX6.

Signed-off-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 .../boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/boot/emmc  | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/boot/emmc

diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/boot/emmc b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/boot/emmc
new file mode 100644
index 0000000000..7ba1d0d0cf
--- /dev/null
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/boot/emmc
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+global.bootm.image="/mnt/emmc/zImage"
+global.bootm.oftree="/mnt/emmc/oftree"
+global.linux.bootargs.dyn.root="root=/dev/mmcblk1p2 rootwait rw"
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:06 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:06 +0200
Subject: [PATCH 05/16] ARM: dts: imx6qdl: phycore: Sync muxing with kernel
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-6-s.hauer@pengutronix.de>

From: Christian Hemp <c.hemp at phytec.de>

Sync the USDCH drive strength muxing with kernel.
With this drive strength we saw no sd card errors.

Signed-off-by: Christian Hemp <c.hemp at phytec.de>
Acked-by: Stefan Lengfeld <s.lengfeld at phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index 3a5b0dbf24..923c79c67b 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -205,12 +205,12 @@
 
 		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
+				MX6QDL_PAD_SD1_CMD__SD1_CMD		0x170f9
+				MX6QDL_PAD_SD1_CLK__SD1_CLK		0x100f9
+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
 				MX6QDL_PAD_EIM_BCLK__GPIO6_IO31		0x80000000 /* CD */
 			>;
 		};
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:17 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:17 +0200
Subject: [PATCH 16/16] ARM: i.MX: phytec-som-imx6: Change kernel boot image to
 zImage
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-17-s.hauer@pengutronix.de>

From: Stefan Riedmueller <s.riedmueller at phytec.de>

Use zImage instead of linuximage as kernel boot image name for mmc and
emmc.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc | 2 +-
 arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
index 4e286dc325..f0d019c3ee 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/emmc
@@ -5,6 +5,6 @@ if [ -f /mnt/mmc3/android ]; then
 	global linux.bootargs.sec="selinux=0 enforcing=0"
 fi
 
-global.bootm.image="/mnt/mmc3/linuximage"
+global.bootm.image="/mnt/mmc3/zImage"
 global.bootm.oftree="/mnt/mmc3/oftree"
 global.linux.bootargs.dyn.root="root=/dev/mmcblk3p2 rootwait rw"
diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc
index df874f0a38..3e175122dd 100644
--- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc
+++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/boot/mmc
@@ -5,6 +5,6 @@ if [ -f /mnt/mmc/android ]; then
 	global linux.bootargs.sec="selinux=0 enforcing=0"
 fi
 
-global.bootm.image="/mnt/mmc/linuximage"
+global.bootm.image="/mnt/mmc/zImage"
 global.bootm.oftree="/mnt/mmc/oftree"
 global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootwait rw"
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:08 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:08 +0200
Subject: [PATCH 07/16] ARM: i.MX: phytec-som-imx6: phycore: Set BUCK mode to
 SYNC
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-8-s.hauer@pengutronix.de>

From: Christian Hemp <c.hemp at phytec.de>

Set the BUCK mode for all BUCKS (1-4) from BUCK_MODE_AUTO to
BUCK_MODE_SYNC.  If the BUCKs are in BUCK_MODE_AUTO in very rare cases
it is possible that the BUCK goes in power down mode.

Signed-off-by: Christian Hemp <c.hemp at phytec.de>
Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/boards/phytec-som-imx6/board.c | 51 +++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm/boards/phytec-som-imx6/board.c b/arch/arm/boards/phytec-som-imx6/board.c
index 7b63ee0e0c..f9b6cf55cd 100644
--- a/arch/arm/boards/phytec-som-imx6/board.c
+++ b/arch/arm/boards/phytec-som-imx6/board.c
@@ -28,6 +28,7 @@
 #include <gpio.h>
 #include <init.h>
 #include <of.h>
+#include <i2c/i2c.h>
 #include <mach/bbu.h>
 #include <platform_data/eth-fec.h>
 #include <mfd/imx6q-iomuxc-gpr.h>
@@ -51,6 +52,14 @@
 
 #define MX6_PHYFLEX_ERR006282	IMX_GPIO_NR(2, 11)
 
+#define DA9062_I2C_ADDRESS		0x58
+
+#define DA9062_BUCK1_CFG		0x9e
+#define DA9062_BUCK2_CFG		0x9d
+#define DA9062_BUCK3_CFG		0xa0
+#define DA9062_BUCK4_CFG		0x9f
+#define DA9062_BUCKx_MODE_SYNCHRONOUS	(2 << 6)
+
 static void phyflex_err006282_workaround(void)
 {
 	/*
@@ -96,6 +105,45 @@ int ksz8081_phy_fixup(struct phy_device *phydev)
 	return 0;
 }
 
+static int phycore_da9062_setup_buck_mode(void)
+{
+	struct i2c_adapter *adapter = NULL;
+	struct i2c_client client;
+	unsigned char value;
+	int bus = 0;
+	int ret;
+
+	adapter = i2c_get_adapter(bus);
+	if (!adapter)
+		return -ENODEV;
+
+	client.adapter = adapter;
+	client.addr = DA9062_I2C_ADDRESS;
+
+	value = DA9062_BUCKx_MODE_SYNCHRONOUS;
+
+	ret = i2c_write_reg(&client, DA9062_BUCK1_CFG, &value, 1);
+	if (ret != 1)
+		goto err_out;
+
+	ret = i2c_write_reg(&client, DA9062_BUCK2_CFG, &value, 1);
+	if (ret != 1)
+		goto err_out;
+
+	ret = i2c_write_reg(&client, DA9062_BUCK3_CFG, &value, 1);
+	if (ret != 1)
+		goto err_out;
+
+	ret = i2c_write_reg(&client, DA9062_BUCK4_CFG, &value, 1);
+	if (ret != 1)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	return ret;
+}
+
 static int physom_imx6_devices_init(void)
 {
 	int ret;
@@ -127,6 +175,9 @@ static int physom_imx6_devices_init(void)
 		|| of_machine_is_compatible("phytec,imx6dl-pcm058-nand")
 		|| of_machine_is_compatible("phytec,imx6dl-pcm058-emmc")) {
 
+		if (phycore_da9062_setup_buck_mode())
+			pr_err("Setting PMIC BUCK mode failed\n");
+
 		barebox_set_hostname("phyCORE-i.MX6");
 		default_environment_path = "/chosen/environment-spinor";
 		default_envdev = "SPI NOR flash";
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:16 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:16 +0200
Subject: [PATCH 15/16] ARM: dts: phycore-imx6: Use generic jedec spi nor
 compatible
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-16-s.hauer@pengutronix.de>

From: Stefan Riedmueller <s.riedmueller at phytec.de>

Use the generic jedec-spi-nor compatible for the SPI NOR node to make it
generic.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index c3cfa00ced..15fed812b0 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -70,8 +70,8 @@
 	cs-gpios = <&gpio3 19 0>;
 	status = "disabled";
 
-	flash: m25p80 at 0 {
-		compatible = "m25p80";
+	flash: flash at 0 {
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 		status = "disabled";
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:15 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:15 +0200
Subject: [PATCH 14/16] ARM: dts: imx6: phyboard-mira: Remove unecessary iomuxc
 subnode
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-15-s.hauer@pengutronix.de>

From: Stefan Riedmueller <s.riedmueller at phytec.de>

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi | 210 +++++++++++++--------------
 1 file changed, 103 insertions(+), 107 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
index 1dd88b5add..c3cfa00ced 100644
--- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -159,122 +159,118 @@
 };
 
 &iomuxc {
-	pinctrl-names = "default";
-
-	imx6qdl-phytec-phycore-som {
-		pinctrl_ecspi1: ecspi1grp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
-				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
-				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
-				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x80000000
-			>;
-		};
-
-		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_TX_EN__ENET_TX_EN	0x1b0b0
-				MX6QDL_PAD_SD2_DAT1__GPIO1_IO14		0x80000000
-			>;
-		};
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x80000000
+		>;
+	};
 
-		pinctrl_gpmi_nand: gpmigrp {
-			fsl,pins = <
-				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
-				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
-				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
-				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
-				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
-				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
-				MX6QDL_PAD_NANDF_CS2__NAND_CE2_B	0xb0b1
-				MX6QDL_PAD_NANDF_CS3__NAND_CE3_B	0xb0b1
-				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
-				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
-				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
-				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
-				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
-				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
-				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
-				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
-				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
-				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
-				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
-			>;
-		};
+	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_TX_EN__ENET_TX_EN	0x1b0b0
+			MX6QDL_PAD_SD2_DAT1__GPIO1_IO14		0x80000000
+		>;
+	};
 
-		pinctrl_i2c3: i2c3grp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
-				MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
-			>;
-		};
+	pinctrl_gpmi_nand: gpmigrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+			MX6QDL_PAD_NANDF_CS2__NAND_CE2_B	0xb0b1
+			MX6QDL_PAD_NANDF_CS3__NAND_CE3_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+			MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+		>;
+	};
 
-		pinctrl_uart2: uart2grp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
-				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
-			>;
-		};
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
+		>;
+	};
 
-		pinctrl_usbh1_vbus: usbh1vbusgrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_A20__GPIO2_IO18	0xb0b1
-				>;
-		};
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+		>;
+	};
 
-		pinctrl_usbotg: usbotggrp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_1__USB_OTG_ID	0x17059
-				>;
-		};
+	pinctrl_usbh1_vbus: usbh1vbusgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A20__GPIO2_IO18		0xb0b1
+		>;
+	};
 
-		pinctrl_usbotg_vbus: usbotgvbusgrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_A19__GPIO2_IO19	0xb0b1
-				>;
-		};
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+		>;
+	};
 
-		pinctrl_usdhc1: usdhc1grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD1_CMD__SD1_CMD		0x170f9
-				MX6QDL_PAD_SD1_CLK__SD1_CLK		0x100f9
-				MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
-				MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
-				MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
-				MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
-				MX6QDL_PAD_EIM_BCLK__GPIO6_IO31		0x80000000 /* CD */
+	pinctrl_usbotg_vbus: usbotgvbusgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A19__GPIO2_IO19		0xb0b1
 			>;
-		};
+	};
 
-		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
-			>;
-		};
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__SD1_CMD		0x170f9
+			MX6QDL_PAD_SD1_CLK__SD1_CLK		0x100f9
+			MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
+			MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
+			MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
+			MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
+			MX6QDL_PAD_EIM_BCLK__GPIO6_IO31		0x80000000 /* CD */
+		>;
+	};
+
+	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
+		>;
 	};
 };
 
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:30:12 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:30:12 +0200
Subject: [PATCH 11/16] ARM: i.MX: phytec-som-imx6: add phyCORE-i.MX6 Solo with
 1GiB RAM
In-Reply-To: <20180412073017.6750-1-s.hauer@pengutronix.de>
References: <20180412073017.6750-1-s.hauer@pengutronix.de>
Message-ID: <20180412073017.6750-12-s.hauer@pengutronix.de>

From: Stefan Christ <s.christ at phytec.de>

Add Phytec phyCORE-i.MX6 Solo:
  - imx6dl-phytec-phycore-som-nand:
    - 1GiB RAM on 1 Bank with 32Bit
    - 100Mbit Ethernet
    - NAND
    - SD
    - UART

Signed-off-by: Stefan Christ <s.christ at phytec.de>
Signed-off-by: Christian Hemp <c.hemp at phytec.de>
---
 .../flash-header-phytec-pcm058dl-1gib-32bit.imxcfg                | 8 ++++++++
 arch/arm/boards/phytec-som-imx6/lowlevel.c                        | 1 +
 images/Makefile.imx                                               | 5 +++++
 3 files changed, 14 insertions(+)
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg

diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg
new file mode 100644
index 0000000000..bf95d0f6ae
--- /dev/null
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg
@@ -0,0 +1,8 @@
+#define SETUP_MDCFG0			\
+	wm 32 0x021b000c 0x8c929b85
+
+#define SETUP_MDASP_MDCTL		\
+	wm 32 0x021b0040 0x00000027;	\
+	wm 32 0x021b0000 0x84190000
+
+#include "flash-header-phytec-pcm058dl.h"
diff --git a/arch/arm/boards/phytec-som-imx6/lowlevel.c b/arch/arm/boards/phytec-som-imx6/lowlevel.c
index 9aa2104a3c..f9d70c7450 100644
--- a/arch/arm/boards/phytec-som-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-som-imx6/lowlevel.c
@@ -107,6 +107,7 @@ PHYTEC_ENTRY(start_phytec_phyboard_subra_512mb_1bank, imx6dl_phytec_phyboard_sub
 PHYTEC_ENTRY(start_phytec_phyboard_subra_1gib_1bank, imx6q_phytec_phyboard_subra, SZ_1G, false);
 
 PHYTEC_ENTRY(start_phytec_phycore_imx6dl_som_nand_256mb, imx6dl_phytec_phycore_som_nand, SZ_256M, true);
+PHYTEC_ENTRY(start_phytec_phycore_imx6dl_som_nand_1gib, imx6dl_phytec_phycore_som_nand, SZ_1G, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6dl_som_emmc_1gib, imx6dl_phytec_phycore_som_emmc, SZ_1G, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6q_som_nand_1gib, imx6q_phytec_phycore_som_nand, SZ_1G, true);
 PHYTEC_ENTRY(start_phytec_phycore_imx6qp_som_nand_1gib, imx6qp_phytec_phycore_som_nand, SZ_1G, true);
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 5e10f4fbf3..8649c4919f 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -460,6 +460,11 @@ CFG_start_phytec_phycore_imx6dl_som_nand_256mb.pblx.imximg = $(board)/phytec-som
 FILE_barebox-phytec-phycore-imx6dl-som-nand-256mb.img = start_phytec_phycore_imx6dl_som_nand_256mb.pblx.imximg
 image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-nand-256mb.img
 
+pblx-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_nand_1gib
+CFG_start_phytec_phycore_imx6dl_som_nand_1gib.pblx.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg
+FILE_barebox-phytec-phycore-imx6dl-som-nand-1gib.img = start_phytec_phycore_imx6dl_som_nand_1gib.pblx.imximg
+image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-nand-1gib.img
+
 pblx-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_emmc_1gib
 CFG_start_phytec_phycore_imx6dl_som_emmc_1gib.pblx.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg
 FILE_barebox-phytec-phycore-imx6dl-som-emmc-1gib.img = start_phytec_phycore_imx6dl_som_emmc_1gib.pblx.imximg
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 00:34:28 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 09:34:28 +0200
Subject: [PATCH] net: phy: micrel: fix too late link up
Message-ID: <20180412073428.21094-1-s.hauer@pengutronix.de>

From: Christian Hemp <c.hemp at phytec.de>

Since commit a4cee7207a1 ("net: phy: micrel: Add workaround for bad
autoneg") by Philipp Zabel <p.zabel at pengutronix.de>:

    Based on kernel commit d2fd719bcb0e ("net/phy: micrel: Add workaround
    for bad autoneg") by Nathan Sullivan <nathan.sullivan at ni.com>:

        Very rarely, the KSZ9031 will appear to complete autonegotiation, but
        will drop all traffic afterwards.  When this happens, the idle error
        count will read 0xFF after autonegotiation completes. Reset the PHY
        when in that state.

is it possible that we get the link to late and  barebox reports "Network is
down". The problem is that ksz9031_config_init is called again in an
error case. In this case autoneg will restart but waiting for finish is
missing.

Signed-off-by: Christian Hemp <c.hemp at phytec.de>
Tested-by: Stefan M?ller-Klieser <s.mueller-klieser at phytec.de>
---
 drivers/net/phy/micrel.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 0ca359b0ba..fe71bfd1a6 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -293,6 +293,7 @@ static int ksz9031_read_status(struct phy_device *phydev)
 	if ((regval & 0xff) == 0xff) {
 		phy_init_hw(phydev);
 		phydev->link = 0;
+		phy_wait_aneg_done(phydev);
 	}
 
 	return 0;
-- 
2.16.1



From s.hauer at pengutronix.de  Thu Apr 12 01:00:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 12 Apr 2018 10:00:44 +0200
Subject: [PATCH 0/4] ARM: socfpga: misc fixes
In-Reply-To: <20180412053559.30687-1-antonynpavlov@gmail.com>
References: <20180412053559.30687-1-antonynpavlov@gmail.com>
Message-ID: <20180412080044.yt3uw3hzdjm7v5t4@pengutronix.de>

On Thu, Apr 12, 2018 at 08:35:55AM +0300, Antony Pavlov wrote:
> Antony Pavlov (4):
>   net: make SoCFPGA-specific designware driver work again
>   ARM: socfpga: boards: pll_config.h: remove duplicate macros
>   ARM: socfpga: mach/pll_config.h: add guard macro
>   ARM: socfpga_defconfig: enable Altera firmware stuff
> 

Applied all, thanks

Sascha

>  arch/arm/boards/ebv-socrates/pll_config.h       | 6 ------
>  arch/arm/boards/terasic-sockit/pll_config.h     | 6 ------
>  arch/arm/configs/socfpga_defconfig              | 3 +++
>  arch/arm/mach-socfpga/include/mach/pll_config.h | 4 ++++
>  drivers/net/Kconfig                             | 1 +
>  5 files changed, 8 insertions(+), 12 deletions(-)
> 
> -- 
> 2.17.0
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.tretter at pengutronix.de  Thu Apr 12 01:53:37 2018
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Thu, 12 Apr 2018 10:53:37 +0200
Subject: [PATCH] net: on ifup -a only detect devices when necessary
In-Reply-To: <20180406131639.14100-1-s.hauer@pengutronix.de>
References: <20180406131639.14100-1-s.hauer@pengutronix.de>
Message-ID: <20180412105337.751ab9ce@litschi.hi.pengutronix.de>

On Fri, 06 Apr 2018 15:16:39 +0200, Sascha Hauer wrote:
> For network boot we once used to hardcode eth0, but in latest changes
> this was changed to work with different network devices and the 'ifup
> eth0' was replaced with 'ifup -a' which lead to the result that we now
> detect all devices in order to eventually also bring up USB network
> adapters. In most of the cases this is not desired. When a board has
> internal network support this is likely to be used. With this patch
> we only detect all devices when we do not have a network device already.
> For the unusual case in which a USB network adapter shall be used
> even when an internal network interface is present we introduce the
> global variable "global.net.ifup_force_detect" which can be used to
> force detection of devices.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

Tested-by: Michael Tretter <m.tretter at pengutronix.de>

Michael

> ---
>  net/ifup.c | 21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/net/ifup.c b/net/ifup.c
> index 827c5c03d1..d550f82530 100644
> --- a/net/ifup.c
> +++ b/net/ifup.c
> @@ -28,6 +28,9 @@
>  #include <globalvar.h>
>  #include <string.h>
>  #include <driver.h>
> +#include <init.h>
> +#include <globalvar.h>
> +#include <magicvar.h>
>  #include <linux/stat.h>
>  
>  static int eth_discover(char *file)
> @@ -245,6 +248,8 @@ int ifup(const char *ethname, unsigned flags)
>  	return ifup_edev(edev, flags);
>  }
>  
> +static int net_ifup_force_detect;
> +
>  int ifup_all(unsigned flags)
>  {
>  	struct eth_device *edev;
> @@ -266,7 +271,9 @@ int ifup_all(unsigned flags)
>  
>  	closedir(dir);
>  
> -	device_detect_all();
> +	if ((flags & IFUP_FLAG_FORCE) || net_ifup_force_detect ||
> +	    list_empty(&netdev_list))
> +		device_detect_all();
>  
>  	for_each_netdev(edev)
>  		ifup_edev(edev, flags);
> @@ -274,6 +281,18 @@ int ifup_all(unsigned flags)
>  	return 0;
>  }
>  
> +static int ifup_all_init(void)
> +{
> +	globalvar_add_simple_bool("net.ifup_force_detect", &net_ifup_force_detect);
> +
> +	return 0;
> +}
> +late_initcall(ifup_all_init);
> +
> +BAREBOX_MAGICVAR_NAMED(global_net_ifup_force_detect,
> +                       global.net.ifup_force_detect,
> +                       "net: force detection of devices on ifup -a");
> +
>  #if IS_ENABLED(CONFIG_NET_CMD_IFUP)
>  
>  static int do_ifup(int argc, char *argv[])


From d.schultz at phytec.de  Thu Apr 12 02:13:02 2018
From: d.schultz at phytec.de (Daniel Schultz)
Date: Thu, 12 Apr 2018 11:13:02 +0200
Subject: [PATCH v2 2/2] ARM: dts: AM335x: Add keep-previous-content property
In-Reply-To: <1523524382-19217-1-git-send-email-d.schultz@phytec.de>
References: <1523524382-19217-1-git-send-email-d.schultz@phytec.de>
Message-ID: <1523524382-19217-2-git-send-email-d.schultz@phytec.de>

Some of our customers may have data in the EEPROM region, which we newly
have assigned as state partition. This property should prevent them of
data loses.

Signed-off-by: Daniel Schultz <d.schultz at phytec.de>
---
 arch/arm/dts/am335x-phytec-state.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/dts/am335x-phytec-state.dtsi b/arch/arm/dts/am335x-phytec-state.dtsi
index fbc35b9..6bca597 100644
--- a/arch/arm/dts/am335x-phytec-state.dtsi
+++ b/arch/arm/dts/am335x-phytec-state.dtsi
@@ -23,6 +23,7 @@
 		backend-type = "raw";
 		backend = <&backend_state_eeprom>;
 		backend-stridesize = <40>;
+		keep-previous-content;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
-- 
2.7.4



From d.schultz at phytec.de  Thu Apr 12 02:13:01 2018
From: d.schultz at phytec.de (Daniel Schultz)
Date: Thu, 12 Apr 2018 11:13:01 +0200
Subject: [PATCH v2 1/2] common: state: Add property to protect existing data
Message-ID: <1523524382-19217-1-git-send-email-d.schultz@phytec.de>

After an update to a newer barebox version with an enabled state
framework, existing data in storage memories could be overwritten.

Add a new property to check in front of every write task, if the meta
magic field only contains the magic number, zeros or ones.

Signed-off-by: Daniel Schultz <d.schultz at phytec.de>
---
Changes:
	v2: Added check for circular backend
	    Improved error message if content was found

 .../devicetree/bindings/barebox/barebox,state.rst     |  3 +++
 common/state/backend_bucket_circular.c                |  8 +++++---
 common/state/backend_bucket_direct.c                  |  2 ++
 common/state/state.c                                  | 19 ++++++++++++++++++-
 common/state/state.h                                  |  2 ++
 5 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
index 872bac0..2893937 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
@@ -55,6 +55,9 @@ Optional Properties
 * ``algo``: A HMAC algorithm used to detect manipulation of the data
   or header, sensible values follow this pattern ``hmac(<HASH>)``,
   e.g. ``hmac(sha256)``. Only available for the ``backend-type`` ``raw``.
+* ``keep-previous-content``: Check if a the bucket meta magic field contains
+  other data than the magic value. If so, the backend will not write the state
+  to prevent unconditionally overwrites of existing data.
 
 .. note:: For the ``backend-storage-type`` the keyword ``noncircular`` is still
    supported as a fall back to an old storage format. Recommendation is to not
diff --git a/common/state/backend_bucket_circular.c b/common/state/backend_bucket_circular.c
index 2324903..933493e 100644
--- a/common/state/backend_bucket_circular.c
+++ b/common/state/backend_bucket_circular.c
@@ -396,11 +396,13 @@ static int state_backend_bucket_circular_init(
 			meta = (struct state_backend_storage_bucket_circular_meta *)
 					(buf + sub_offset + circ->writesize - sizeof(*meta));
 
-			if (meta->magic != circular_magic)
+			if (meta->magic != circular_magic) {
 				written_length = 0;
-			else
+				if (meta->magic != ~0 && !!meta->magic)
+					bucket->wrong_magic = 1;
+			} else {
 				written_length = meta->written_length;
-
+			}
 			break;
 		}
 	}
diff --git a/common/state/backend_bucket_direct.c b/common/state/backend_bucket_direct.c
index 958696e..9d6a337 100644
--- a/common/state/backend_bucket_direct.c
+++ b/common/state/backend_bucket_direct.c
@@ -69,6 +69,8 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
 	if (meta.magic == direct_magic) {
 		read_len = meta.written_length;
 	} else {
+		if (meta.magic != ~0 && !!meta.magic)
+			bucket->wrong_magic = 1;
 		if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
 			dev_err(direct->dev, "No meta data header found\n");
 			dev_dbg(direct->dev, "Enable backward compatibility or increase stride size\n");
diff --git a/common/state/state.c b/common/state/state.c
index 73dfb58..25d9502 100644
--- a/common/state/state.c
+++ b/common/state/state.c
@@ -44,6 +44,8 @@ int state_save(struct state *state)
 	void *buf;
 	ssize_t len;
 	int ret;
+	struct state_backend_storage_bucket *bucket;
+	struct state_backend_storage *storage;
 
 	if (!state->dirty)
 		return 0;
@@ -55,7 +57,19 @@ int state_save(struct state *state)
 		return ret;
 	}
 
-	ret = state_storage_write(&state->storage, buf, len);
+	storage = &state->storage;
+	if (state->keep_prev_content) {
+		bool has_content = 0;
+		list_for_each_entry(bucket, &storage->buckets, bucket_list)
+			has_content |= bucket->wrong_magic;
+		if (has_content) {
+			dev_err(&state->dev, "Found foreign content on backend, won't overwrite.\n");
+			ret = -EPERM;
+			goto out;
+		}
+	}
+
+	ret = state_storage_write(storage, buf, len);
 	if (ret) {
 		dev_err(&state->dev, "Failed to write packed state, %d\n", ret);
 		goto out;
@@ -623,6 +637,9 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
 
 	of_property_read_string(node, "backend-storage-type", &storage_type);
 
+	state->keep_prev_content = of_property_read_bool(node,
+							"keep-previous-content");
+
 	ret = state_format_init(state, backend_type, node, alias);
 	if (ret)
 		goto out_release_state;
diff --git a/common/state/state.h b/common/state/state.h
index 6670523..3a0662f 100644
--- a/common/state/state.h
+++ b/common/state/state.h
@@ -46,6 +46,7 @@ struct state_backend_storage_bucket {
 	void *buf;
 	ssize_t len;
 	bool needs_refresh;
+	bool wrong_magic;
 };
 
 /**
@@ -105,6 +106,7 @@ struct state {
 	char *of_path;
 	const char *name;
 	uint32_t magic;
+	bool keep_prev_content;
 
 	struct list_head variables; /* Sorted list of variables */
 
-- 
2.7.4



From andrew.smirnov at gmail.com  Thu Apr 12 11:20:52 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 11:20:52 -0700
Subject: [PATCH 3/3] serial: Check result of console_unregister()
In-Reply-To: <20180411083408.lri4xpnpatno6qz6@pengutronix.de>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-4-andrew.smirnov@gmail.com>
 <20180403070427.terivivcpl2abuuf@pengutronix.de>
 <CAHQ1cqHR2vmy4HRFaCLQnVgn=YCG+YOfBgBj_uzw4mn66T1nvA@mail.gmail.com>
 <20180411083408.lri4xpnpatno6qz6@pengutronix.de>
Message-ID: <CAHQ1cqFV6_-sU+Qjtpa7+v7TKRK8RQzubw+8ct3BC9DHxgoDMQ@mail.gmail.com>

On Wed, Apr 11, 2018 at 1:34 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> Hi Andrey,
>
> On Mon, Apr 09, 2018 at 09:00:52AM -0700, Andrey Smirnov wrote:
>> On Tue, Apr 3, 2018 at 12:04 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
>> > On Mon, Mar 26, 2018 at 06:09:15AM -0700, Andrey Smirnov wrote:
>> >> In order to allow 'serdev' devices to prevent parent console device
>> >> removal and correspondign memory deallocation add code to all serial
>> >> driver to check result of console_unregister() and bail out early if
>> >> it is unsuccessful.
>> >>
>> >> One example of a use-case for this would be a reset handler relying on
>> >> a serdev device for transport. Without this patch underlying console
>> >> device would be removed and de-allocated before reset handler is even
>> >> run thus leading to unpredictable behaviour and crashes.
>> >
>> > Can't we make this sure at driver core level?
>>
>> I need to be able to prevent serial driver's "remove" function from
>> ever executing to prevent any de-initialization/memory freeing from
>> happening. The simplest way to solve this in driver core that comes to
>> my mind is implementing simple reference counting API that children
>> could use to force driver core to bail out on removing parents if they
>> are still in use. Does that sound like a reasonable idea?
>>
>> > So if a device decides not
>> > to return -EBUSY in the remove callback then the parent devices won't be
>> > removed?
>>
>> Remove callback currently returns void, we could change it to return
>> int and use it to implement a sort of implicit refcounting, but doing
>> so would result in quite a bit of code churn since all of the current
>> drivers would have to be converted to return int in their .remove
>> callbacks. Would you rather I do this or explicit refcounting?
>
> Normally it helps looking at the Linux kernel to see how a problem is
> solved there. Not so this time it seems. Linux distinguishes between
> "remove" and "shutdown". "shutdown" is what we want during barebox
> shutdown. I found a Linux driver that is similar to your situation: It
> registers a restart_handler while being a i2c device itself. There seems
> to be no way to prevent a device from being shutdown, it's only that the
> i2c bus drivers simply do not implement it.
>
> Where do we go from here? I think reference counting is a bit over the
> top.
>
> At the moment I would opt for a *very* simple solution: Let's drop the
> call to console_unregister() and the freeing of resources entirely as
> it gives us nothing. The only console driver I can see where removing
> is valid is drivers/usb/gadget/u_serial.c and you won't use this for
> restarting a SoC ;)
>

OK, makes sense and works for me. Will do in v2.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Thu Apr 12 11:22:18 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 11:22:18 -0700
Subject: [PATCH 2/3] console: Add simplified 'serdev' framework from Linux
 kernel
In-Reply-To: <20180411083957.pvagr7h4my4lyfpo@pengutronix.de>
References: <20180326130915.8726-1-andrew.smirnov@gmail.com>
 <20180326130915.8726-3-andrew.smirnov@gmail.com>
 <20180403065436.p2vec7ntdja55hts@pengutronix.de>
 <CAHQ1cqHdhHiknrnzfU_9YLc_HiyNVDSPZyGNNsHcrAhgUoK_ig@mail.gmail.com>
 <20180411083957.pvagr7h4my4lyfpo@pengutronix.de>
Message-ID: <CAHQ1cqHRuikPvLR+nNs6+=Nv0y3XvXdbkKjimCC=87uyi0HgNg@mail.gmail.com>

On Wed, Apr 11, 2018 at 1:39 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Mon, Apr 09, 2018 at 09:40:46AM -0700, Andrey Smirnov wrote:
>> On Mon, Apr 2, 2018 at 11:54 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
>> > Hi Andrey,
>> >
>> > Some comments inside.
>> >
>> >
>> > On Mon, Mar 26, 2018 at 06:09:14AM -0700, Andrey Smirnov wrote:
>> >> Port 'serdev' UART-slave deivce framework found in recent Linux
>> >> kernels (post 4.13) in order to be able to port 'serdev' slave drivers
>> >> from Linux.
>> >>
>> >> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> >> @@ -323,6 +324,17 @@ int console_register(struct console_device *newcdev)
>> >>               dev->parent = newcdev->dev;
>> >>       platform_device_register(dev);
>> >>
>> >> +     newcdev->open_count = 0;
>> >> +
>> >> +     /*
>> >> +      * If our console deive is a serdev, we skip the creation of
>> >
>> > s/deive/device/
>>
>> Will fix in v2.
>>
>> >
>> >> +      * corresponding entry in /dev as well as registration in
>> >> +      * console_list and just go straigh to populating child
>> >
>> > s/straigh/straight/
>>
>> Ditto.
>>
>> >
>> >> +      * devices.
>> >> +      */
>> >> +     if (serdev_node)
>> >> +             return of_platform_populate(serdev_node, NULL, dev);
>> >
>> > How is this going to be used? A serdev driver binds to the serdev_node
>> > and then it probably needs to get a pointer to the console device,
>> > right? How does the driver accomplish this?
>> >
>>
>> Serdev slave driver doesn't hold explicit pointer to console device,
>> instead accessing it via point to serdev_device. The latter could
>> obtained by calling to_serdev_device(dev->parent), where dev is
>> device_d given to slave driver's probe function.
>>
>>
>> >> +/**
>> >> + * struct serdev_device - Basic representation of an serdev device
>> >> + *
>> >> + * @dev:             Corresponding device
>> >> + * @fifo:            Circular buffer used for console draining
>> >> + * @buf:             Buffer used to pass Rx data to consumers
>> >> + * @poller           Async poller used to poll this serdev
>> >> + * @polling_interval:        Async poller periodicity
>> >> + * @polling_window:  Duration of a single busy loop poll
>> >> + * @receive_buf:     Function called with data received from device;
>> >> + *                   returns number of bytes accepted;
>> >> + */
>> >> +struct serdev_device {
>> >> +     struct device_d *dev;
>> >> +     struct kfifo *fifo;
>> >> +     unsigned char *buf;
>> >> +     struct poller_async poller;
>> >> +     uint64_t polling_interval;
>> >> +     uint64_t polling_window;
>> >> +
>> >> +     int (*receive_buf)(struct serdev_device *, const unsigned char *,
>> >> +                        size_t);
>> >> +};
>> >> +
>> >> +int serdev_device_open(struct serdev_device *);
>> >> +unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
>> >> +int serdev_device_write(struct serdev_device *, const unsigned char *,
>> >> +                     size_t, unsigned long);
>> >
>> > So a serdev driver uses serdev_device_write() to send characters out. To
>> > receive characters it has to implement serdev_device->receive_buf,
>> > right?
>>
>> Right. I tried to implement exactly the same API that Linux's serdev
>> API provides.
>>
>> > What kind of devices did you implement this for?
>>
>> I ported serdev in support of porting the driver for RAVE SP which is
>> a small microcontroller device found many ZII board including RDU2. It
>> implement a whole bunch of various functionality including watchdog,
>> parameter EEPROM, sensor access, backlight control, button input event
>> generation, etc.
>>
>> > For devices which send data without request (GPS?) this seems the way to go. For
>> > others a synchronous receive function might be good, no?
>> >
>>
>> I didn't implement anything like that mostly because Linux serdev API
>> doesn't and any ported driver wouldn't have any need for those
>> functions. But in general, I am not sure how useful synchronous
>> receive function would be. In my experience, devices like that usually
>> implement some binary transport protocol with packetization/escape
>> sequences on top of UART, which usually requires a state machine
>> operating with byte granularity as the data comes in to parse
>> responses correctly and synchronous APIs are not extremely useful for
>> that kind of a use-case.
>>
>> FWIW, since serdev API is integrated into poller infrastructure it is
>> pretty trivial to write blocking code with it. Here's how I use it in
>> my driver to implement request-response type of a function:
>>
>> rave_sp_write(sp, data, data_size);
>> /*
>> * is_timeout will implicitly poll serdev via poller
>> * infrastructure
>> */
>> while (!is_timeout(start, SECOND) && !reply.received)
>>    ;
>
> I understand that synchronous receiving might not be that useful. Given
> how simple it is we could add a synchronous receive wrapper function
> just for the sake of completeness, even if it only provides an example
> how the code can be used.

OK, will do in v2.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Thu Apr 12 14:33:13 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:33:13 -0700
Subject: [PATCH v2 1/5] console: Introduce console_drain()
In-Reply-To: <20180412213317.13199-1-andrew.smirnov@gmail.com>
References: <20180412213317.13199-1-andrew.smirnov@gmail.com>
Message-ID: <20180412213317.13199-2-andrew.smirnov@gmail.com>

Generalize high baud rate UART polling code found in lib/xmodem.c and
expose it as a generic function in console API.

The usecase for this -- besides X/Y-mode data transfers where the code
originated -- is command/reply type of serial exchages at high baud
rates (~1Mbaud) with payloads exceeding inernal UART FIFOs in
size. Such interactions are not uncommon in serdev device and this
patch is done in preparation for serdev support code that will follow.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 include/console.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/xymodem.c     | 30 ++++----------------
 2 files changed, 88 insertions(+), 25 deletions(-)

diff --git a/include/console.h b/include/console.h
index 3c14e3593..0f1fced93 100644
--- a/include/console.h
+++ b/include/console.h
@@ -23,6 +23,7 @@
 #include <param.h>
 #include <linux/list.h>
 #include <driver.h>
+#include <clock.h>
 
 #define CONSOLE_STDIN           (1 << 0)
 #define CONSOLE_STDOUT          (1 << 1)
@@ -88,6 +89,88 @@ unsigned console_get_active(struct console_device *cdev);
 int console_set_baudrate(struct console_device *cdev, unsigned baudrate);
 unsigned console_get_baudrate(struct console_device *cdev);
 
+
+/**
+ * console_fifo_fill - fill FIFO with as much console data as possible
+ *
+ * @cdev:	Console to poll for dat
+ * @fifo:	FIFO to store the data in
+ */
+static inline int console_fifo_fill(struct console_device *cdev,
+				    struct kfifo *fifo)
+{
+	size_t len = kfifo_len(fifo);
+	while (cdev->tstc(cdev) && len < fifo->size) {
+		kfifo_putc(fifo, (unsigned char)(cdev->getc(cdev)));
+		len++;
+	}
+
+	return len;
+}
+
+/**
+ * __console_drain - Drain console into a buffer via FIFO
+ *
+ * @__is_timeout	Callback used to determine timeout condition
+ * @cdev		Console to drain
+ * @fifo		FIFO to use as a transient buffer
+ * @buf			Buffer to drain console into
+ * @len			Size of the drain buffer
+ * @timeout		Console polling timeout in ns
+ *
+ * This function is optimized to :
+ * - maximize throughput (ie. read as much as is available in lower layer fifo)
+ * - minimize latencies (no delay or wait timeout if data available)
+ * - have a timeout
+ * This is why standard getc() is not used, and input_fifo_fill() exists.
+ */
+static inline int __console_drain(int (*__is_timeout)(uint64_t start_ns,
+						      uint64_t time_offset_ns),
+				  struct console_device *cdev,
+				  struct kfifo *fifo,
+				  unsigned char *buf,
+				  int len,
+				  uint64_t timeout)
+{
+	int i = 0;
+	uint64_t start = get_time_ns();
+
+	if (!len)
+		return -EINVAL;
+
+	do {
+		/*
+		 * To minimize wait time before we start polling Rx
+		 * (to potentially avoid overruning Rx FIFO) we call
+		 * console_fifo_fill first
+		 */
+		if (console_fifo_fill(cdev, fifo))
+			kfifo_getc(fifo, &buf[i++]);
+
+	} while (i < len && !__is_timeout(start, timeout));
+
+	return i;
+}
+
+static inline int console_drain_non_interruptible(struct console_device *cdev,
+						  struct kfifo *fifo,
+						  unsigned char *buf,
+						  int len,
+						  uint64_t timeout)
+{
+	return __console_drain(is_timeout_non_interruptible,
+			       cdev, fifo, buf, len, timeout);
+}
+
+static inline int console_drain(struct console_device *cdev,
+				struct kfifo *fifo,
+				unsigned char *buf,
+				int len,
+				uint64_t timeout)
+{
+	return __console_drain(is_timeout, cdev, fifo, buf, len, timeout);
+}
+
 #ifdef CONFIG_PBL_CONSOLE
 void pbl_set_putc(void (*putcf)(void *ctx, int c), void *ctx);
 #else
diff --git a/lib/xymodem.c b/lib/xymodem.c
index 37202e6ae..9e4ce58b6 100644
--- a/lib/xymodem.c
+++ b/lib/xymodem.c
@@ -144,36 +144,16 @@ static const char block_nack[MAX_PROTOS][MAX_CRCS] = {
 	{ 0, 0, 0 },		/* YMODEM-G */
 };
 
-static int input_fifo_fill(struct console_device *cdev, struct kfifo *fifo)
-{
-	while (cdev->tstc(cdev) && kfifo_len(fifo) < INPUT_FIFO_SIZE)
-		kfifo_putc(fifo, (unsigned char)(cdev->getc(cdev)));
-	return kfifo_len(fifo);
-}
-
-/*
- * This function is optimized to :
- * - maximize throughput (ie. read as much as is available in lower layer fifo)
- * - minimize latencies (no delay or wait timeout if data available)
- * - have a timeout
- * This is why standard getc() is not used, and input_fifo_fill() exists.
- */
 static int xy_gets(struct console_device *cdev, struct kfifo *fifo,
 		      unsigned char *buf, int len, uint64_t timeout)
 {
-	int i, rc;
-	uint64_t start = get_time_ns();
+	int rc;
 
-	for (i = 0, rc = 0; rc >= 0 && i < len; ) {
-		if (is_timeout(start, timeout)) {
-			rc = -ETIMEDOUT;
-			continue;
-		}
-		if (input_fifo_fill(cdev, fifo))
-			kfifo_getc(fifo, &buf[i++]);
-	}
+	rc = console_drain(cdev, fifo, buf, len, timeout);
+	if (rc != len)
+		return -ETIMEDOUT;
 
-	return rc < 0 ? rc : i;
+	return len;
 }
 
 static void xy_putc(struct console_device *cdev, unsigned char c)
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:33:12 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:33:12 -0700
Subject: [PATCH v2 0/5] Linux's serdev framwork port
Message-ID: <20180412213317.13199-1-andrew.smirnov@gmail.com>

Hi everyone:

In an effort to bring this kernel driver
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mfd/rave-sp.c?h=v4.16-rc7
to Barebox, I ended up creating a miniature and extremely simplified
version of 'serdev' subsystem which is presented in this patchset.

Changes since [v1]:

	- Blocking read function was added as example of API usage

	- "serial: Check result of console_unregister()" was converted
          to become "serial: Drop .remove functions from all drivers"

	- Minor spelling fixes

	- Original serdev framework patch modified to allow devices
          that do not require polling (I don't have such a usecase,
          but for the sake of being generic I added one line needed
          for that)

	- SERIAL_DEV_BUS Kconfig symbol moved into
          drivers/serial/Kconfig (where it, IMHO, fits much better)

	- Added a patch to dynamically adjust serdev's polling
          interval via device paramter. This was warranted by the
          problems that arose from real-life usage.

Feedback is wellcome!

Thanks,
Andrey Smirnov

[v1] https://www.spinics.net/lists/u-boot-v2/msg32322.html

Andrey Smirnov (5):
  console: Introduce console_drain()
  console: Add simplified 'serdev' framework from Linux kernel
  serdev: Add trivial blocking read function
  serial: Drop .remove functions from all drivers
  serdev: Allow polling interval to be adjusted at runtime

 common/Makefile                  |   1 +
 common/console.c                 |  24 ++++-
 common/serdev.c                  | 208 +++++++++++++++++++++++++++++++++++++++
 drivers/serial/Kconfig           |   6 ++
 drivers/serial/serial_auart.c    |  11 ---
 drivers/serial/serial_cadence.c  |   9 --
 drivers/serial/serial_clps711x.c |  10 --
 drivers/serial/serial_imx.c      |  10 --
 drivers/serial/serial_lpuart.c   |  13 ---
 drivers/serial/serial_pxa.c      |   9 --
 drivers/serial/serial_s3c.c      |  10 --
 drivers/serial/stm-serial.c      |  10 --
 include/console.h                | 110 +++++++++++++++++++++
 include/serdev.h                 |  44 +++++++++
 lib/xymodem.c                    |  30 +-----
 15 files changed, 395 insertions(+), 110 deletions(-)
 create mode 100644 common/serdev.c
 create mode 100644 include/serdev.h

-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:33:14 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:33:14 -0700
Subject: [PATCH v2 2/5] console: Add simplified 'serdev' framework from Linux
 kernel
In-Reply-To: <20180412213317.13199-1-andrew.smirnov@gmail.com>
References: <20180412213317.13199-1-andrew.smirnov@gmail.com>
Message-ID: <20180412213317.13199-3-andrew.smirnov@gmail.com>

Port 'serdev' UART-slave deivce framework found in recent Linux
kernels (post 4.13) in order to be able to port 'serdev' slave drivers
from Linux.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/Makefile        |  1 +
 common/console.c       | 24 ++++++++++++--
 common/serdev.c        | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/serial/Kconfig |  6 ++++
 include/console.h      | 27 +++++++++++++++
 include/serdev.h       | 36 ++++++++++++++++++++
 6 files changed, 180 insertions(+), 3 deletions(-)
 create mode 100644 common/serdev.c
 create mode 100644 include/serdev.h

diff --git a/common/Makefile b/common/Makefile
index 4e9681f20..1ff7d2370 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_FIRMWARE)		+= firmware.o
 obj-$(CONFIG_UBIFORMAT)		+= ubiformat.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
 obj-$(CONFIG_BOOT)		+= boot.o
+obj-$(CONFIG_SERIAL_DEV_BUS)	+= serdev.o
 
 ifdef CONFIG_PASSWORD
 
diff --git a/common/console.c b/common/console.c
index f4c799fa5..ab3d4d397 100644
--- a/common/console.c
+++ b/common/console.c
@@ -305,10 +305,11 @@ static ssize_t fops_write(struct cdev* dev, const void* buf, size_t count,
 
 int console_register(struct console_device *newcdev)
 {
+	struct device_node *serdev_node = console_is_serdev_node(newcdev);
 	struct device_d *dev = &newcdev->class_dev;
 	int activate = 0, ret;
 
-	if (initialized == CONSOLE_UNINITIALIZED)
+	if (!serdev_node && initialized == CONSOLE_UNINITIALIZED)
 		console_init_early();
 
 	if (newcdev->devname) {
@@ -323,6 +324,17 @@ int console_register(struct console_device *newcdev)
 		dev->parent = newcdev->dev;
 	platform_device_register(dev);
 
+	newcdev->open_count = 0;
+
+	/*
+	 * If our console device is a serdev, we skip the creation of
+	 * corresponding entry in /dev as well as registration in
+	 * console_list and just go straight to populating child
+	 * devices.
+	 */
+	if (serdev_node)
+		return of_platform_populate(serdev_node, NULL, dev);
+
 	if (newcdev->setbrg) {
 		ret = newcdev->setbrg(newcdev, CONFIG_BAUDRATE);
 		if (ret)
@@ -335,8 +347,6 @@ int console_register(struct console_device *newcdev)
 	if (newcdev->putc && !newcdev->puts)
 		newcdev->puts = __console_puts;
 
-	newcdev->open_count = 0;
-
 	dev_add_param_string(dev, "active", console_active_set, console_active_get,
 			     &newcdev->active_string, newcdev);
 
@@ -386,6 +396,14 @@ int console_unregister(struct console_device *cdev)
 	struct device_d *dev = &cdev->class_dev;
 	int status;
 
+	/*
+	 * We don't do any sophisticated serdev device de-population
+	 * and instead claim this console busy, preventing its
+	 * de-initialization, 'till the very end of our execution.
+	 */
+	if (console_is_serdev_node(cdev))
+		return -EBUSY;
+
 	devfs_remove(&cdev->devfs);
 
 	list_del(&cdev->list);
diff --git a/common/serdev.c b/common/serdev.c
new file mode 100644
index 000000000..32743738e
--- /dev/null
+++ b/common/serdev.c
@@ -0,0 +1,89 @@
+
+#include <common.h>
+#include <serdev.h>
+
+static void serdev_device_poller(void *context)
+{
+	struct serdev_device *serdev = context;
+	struct console_device *cdev = to_console_device(serdev);
+	unsigned char *buf = serdev->buf;
+	int ret, len;
+
+	/*
+	 * Since this callback is a part of poller infrastructure we
+	 * want to use _non_interruptible version of the function
+	 * below to prevent recursion from happening (regular
+	 * console_drain will call is_timeout, which might end up
+	 * calling this function again).
+	 */
+	len = console_drain_non_interruptible(cdev, serdev->fifo, buf,
+					      PAGE_SIZE,
+					      serdev->polling_window);
+	while (len > 0) {
+		ret = serdev->receive_buf(serdev, buf, len);
+		len -= ret;
+		buf += ret;
+	}
+
+	if (serdev->polling_interval) {
+		/*
+		 * Re-schedule ourselves in 'serdev->polling_interval'
+		 * nanoseconds
+		 */
+		poller_call_async(&serdev->poller,
+				  serdev->polling_interval,
+				  serdev_device_poller,
+				  serdev);
+	}
+}
+
+int serdev_device_open(struct serdev_device *serdev)
+{
+	struct console_device *cdev = to_console_device(serdev);
+	int ret;
+
+	if (!cdev->putc || !cdev->getc)
+		return -EINVAL;
+
+	if (!serdev->polling_window)
+		return -EINVAL;
+
+	serdev->buf = xzalloc(PAGE_SIZE);
+	serdev->fifo = kfifo_alloc(PAGE_SIZE);
+	if (!serdev->fifo)
+		return -ENOMEM;
+
+	ret = poller_async_register(&serdev->poller);
+	if (ret)
+		return ret;
+
+	return console_open(cdev);
+}
+
+unsigned int serdev_device_set_baudrate(struct serdev_device *serdev,
+					unsigned int speed)
+{
+	struct console_device *cdev = to_console_device(serdev);
+
+	if (console_set_baudrate(cdev, speed) < 0)
+		return 0;
+
+	return console_get_baudrate(cdev);
+}
+
+int serdev_device_write(struct serdev_device *serdev, const unsigned char *buf,
+			size_t count, unsigned long timeout)
+{
+	struct console_device *cdev = to_console_device(serdev);
+
+	while (count--)
+		cdev->putc(cdev, *buf++);
+	/*
+	 * Poll Rx once right after we just send some data in case our
+	 * serdev device implements command/response type of a
+	 * protocol and we need to start draining input as soon as
+	 * possible.
+	 */
+	serdev_device_poller(serdev);
+	return 0;
+}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index cfddc2ee9..8a56d39f7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1,6 +1,12 @@
 menu "serial drivers"
 	depends on !CONSOLE_NONE
 
+config SERIAL_DEV_BUS
+	bool "Serial device bus"
+	depends on CONSOLE_FULL
+	help
+	  Core support for devices connected via a serial port.
+
 config DRIVER_SERIAL_ARM_DCC
 	depends on ARM && !CPU_V8
 	bool "ARM Debug Communications Channel (DCC) serial driver"
diff --git a/include/console.h b/include/console.h
index 0f1fced93..6d3e6e123 100644
--- a/include/console.h
+++ b/include/console.h
@@ -23,6 +23,7 @@
 #include <param.h>
 #include <linux/list.h>
 #include <driver.h>
+#include <serdev.h>
 #include <clock.h>
 
 #define CONSOLE_STDIN           (1 << 0)
@@ -65,8 +66,34 @@ struct console_device {
 
 	struct cdev devfs;
 	struct cdev_operations fops;
+
+	struct serdev_device serdev;
 };
 
+static inline struct serdev_device *to_serdev_device(struct device_d *d)
+{
+	struct console_device *cdev =
+		container_of(d, struct console_device, class_dev);
+	return &cdev->serdev;
+}
+
+static inline struct console_device *
+to_console_device(struct serdev_device *serdev)
+{
+	return container_of(serdev, struct console_device, serdev);
+}
+
+static inline struct device_node *
+console_is_serdev_node(struct console_device *cdev)
+{
+	struct device_d *dev = cdev->dev;
+	if (dev && dev->device_node &&
+	    of_get_child_count(dev->device_node))
+		return dev->device_node;
+
+	return NULL;
+}
+
 int console_register(struct console_device *cdev);
 int console_unregister(struct console_device *cdev);
 
diff --git a/include/serdev.h b/include/serdev.h
new file mode 100644
index 000000000..efc735fed
--- /dev/null
+++ b/include/serdev.h
@@ -0,0 +1,36 @@
+#ifndef _SERDEV_H_
+#define _SERDEV_H_
+
+#include <driver.h>
+#include <poller.h>
+#include <kfifo.h>
+
+/**
+ * struct serdev_device - Basic representation of an serdev device
+ *
+ * @dev:		Corresponding device
+ * @fifo:		Circular buffer used for console draining
+ * @buf:		Buffer used to pass Rx data to consumers
+ * @poller		Async poller used to poll this serdev
+ * @polling_interval:	Async poller periodicity
+ * @polling_window:	Duration of a single busy loop poll
+ * @receive_buf:	Function called with data received from device;
+ *			returns number of bytes accepted;
+ */
+struct serdev_device {
+	struct device_d *dev;
+	struct kfifo *fifo;
+	unsigned char *buf;
+	struct poller_async poller;
+	uint64_t polling_interval;
+	uint64_t polling_window;
+
+	int (*receive_buf)(struct serdev_device *, const unsigned char *,
+			   size_t);
+};
+
+int serdev_device_open(struct serdev_device *);
+unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
+int serdev_device_write(struct serdev_device *, const unsigned char *,
+			size_t, unsigned long);
+#endif
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:33:15 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:33:15 -0700
Subject: [PATCH v2 3/5] serdev: Add trivial blocking read function
In-Reply-To: <20180412213317.13199-1-andrew.smirnov@gmail.com>
References: <20180412213317.13199-1-andrew.smirnov@gmail.com>
Message-ID: <20180412213317.13199-4-andrew.smirnov@gmail.com>

Add example implementation of a trivial blocking read function as a
part of Barebox's serdev API.

NOTE: This code has not been tested against real devices, so use it at
your own risk.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/serdev.c  | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/serdev.h |  8 +++++
 2 files changed, 103 insertions(+)

diff --git a/common/serdev.c b/common/serdev.c
index 32743738e..50eadc804 100644
--- a/common/serdev.c
+++ b/common/serdev.c
@@ -87,3 +87,98 @@ int serdev_device_write(struct serdev_device *serdev, const unsigned char *buf,
 	serdev_device_poller(serdev);
 	return 0;
 }
+
+/*
+ * NOTE: Code below is given primarily as an example of serdev API
+ * usage. It may or may not be as useful or work as well as the
+ * functions above.
+ */
+
+struct serdev_device_reader {
+	unsigned char *buf;
+	size_t len;
+	size_t capacity;
+};
+
+static int serdev_device_reader_receive_buf(struct serdev_device *serdev,
+					    const unsigned char *buf,
+					    size_t size)
+{
+	struct device_d *dev = serdev->dev;
+	struct serdev_device_reader *r = dev->priv;
+	const size_t room = min(r->capacity - r->len, size);
+
+	memcpy(r->buf + r->len, buf, room);
+	r->len += room;
+	/*
+	 * It's important we return 'size' even if we didn't trully
+	 * consume all of the data, since otherwise serdev will keep
+	 * re-executing us until we do. Given the logic above that
+	 * would mean infinite loop.
+	 */
+	return size;
+}
+
+/**
+ * serdev_device_reader_open - Open a reader serdev device
+ *
+ * @serdev:	Underlying serdev device
+ * @capacity:	Storage capacity of the reader
+ *
+ * This function is inteded for creating of reader serdev devices that
+ * can be used in conjunction with serdev_device_read() to perform
+ * trivial fixed length reads from a serdev device.
+ */
+int serdev_device_reader_open(struct serdev_device *serdev, size_t capacity)
+{
+	struct serdev_device_reader *r;
+
+	if (serdev->receive_buf)
+		return -EINVAL;
+
+	r = xzalloc(sizeof(*r));
+	r->capacity = capacity;
+	r->buf = xzalloc(capacity);
+
+	serdev->receive_buf = serdev_device_reader_receive_buf;
+	serdev->dev->priv   = r;
+
+	return 0;
+}
+
+/**
+ * serdev_device_read - Read data from serdev device
+ *
+ * @serdev:	Serdev device to read from (must be a serdev reader)
+ * @buf:	Buffer to read data into
+ * @count:	Number of bytes to read
+ * @timeout:	Read operation timeout
+ *
+ */
+int serdev_device_read(struct serdev_device *serdev, unsigned char *buf,
+		       size_t count, unsigned long timeout)
+{
+	struct device_d *dev = serdev->dev;
+	struct serdev_device_reader *r = dev->priv;
+	int ret;
+
+	uint64_t start = get_time_ns();
+
+	if (serdev->receive_buf != serdev_device_reader_receive_buf)
+		return -EINVAL;
+
+	/*
+	 * is_timeout will implicitly poll serdev via poller
+	 * infrastructure
+	 */
+	while (r->len < count) {
+		if (is_timeout(start, timeout))
+			return -ETIMEDOUT;
+	}
+
+	memcpy(buf, r->buf, count);
+	ret = (r->len == count) ? 0 : -EMSGSIZE;
+	r->len = 0;
+
+	return ret;
+}
diff --git a/include/serdev.h b/include/serdev.h
index efc735fed..f5d34f527 100644
--- a/include/serdev.h
+++ b/include/serdev.h
@@ -33,4 +33,12 @@ int serdev_device_open(struct serdev_device *);
 unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
 int serdev_device_write(struct serdev_device *, const unsigned char *,
 			size_t, unsigned long);
+
+/*
+ * The following two functions are not a part of original Linux API
+ */
+int serdev_device_reader_open(struct serdev_device *, size_t);
+int serdev_device_read(struct serdev_device *, unsigned char *,
+		       size_t, unsigned long);
+
 #endif
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:33:17 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:33:17 -0700
Subject: [PATCH v2 5/5] serdev: Allow polling interval to be adjusted at
 runtime
In-Reply-To: <20180412213317.13199-1-andrew.smirnov@gmail.com>
References: <20180412213317.13199-1-andrew.smirnov@gmail.com>
Message-ID: <20180412213317.13199-6-andrew.smirnov@gmail.com>

Due to blocking, synchronous, polling driven nature of Barebox's
serial communication handling trying to use two or more serial ports
at high (1Mbaud+) baudrates results in data loss and noticeable
perofmance degradation. This happens as soon as individual message
being sent around start exceeding HW Rx FIFO in size.

A good example of such a usecase would be using a system that has a
serdev driver (operating @ 1Mbaud+) and trying to do a X/YMODEM
transfer via serial console at comparable baudrates.

To at least partially ameliorate the problem, add code that will
expose "polling_interval" as a parameter, so that the user would have
an option of temporarily disabling (or significatly decreasing the
rate) of a given serdev's polling.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/serdev.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/common/serdev.c b/common/serdev.c
index 50eadc804..4a6dbefe6 100644
--- a/common/serdev.c
+++ b/common/serdev.c
@@ -34,12 +34,26 @@ static void serdev_device_poller(void *context)
 				  serdev->polling_interval,
 				  serdev_device_poller,
 				  serdev);
+	} else {
+		poller_async_cancel(&serdev->poller);
 	}
 }
 
+static int serdev_device_set_polling_interval(struct param_d *param, void *serdev)
+{
+	/*
+	 * We execute poller ever time polling_interval changes to get
+	 * any unprocessed immediate Rx data as well as to propagate
+	 * polling_interval chagnes to outstanging async pollers.
+	 */
+	serdev_device_poller(serdev);
+	return 0;
+}
+
 int serdev_device_open(struct serdev_device *serdev)
 {
 	struct console_device *cdev = to_console_device(serdev);
+	struct param_d *p;
 	int ret;
 
 	if (!cdev->putc || !cdev->getc)
@@ -57,7 +71,17 @@ int serdev_device_open(struct serdev_device *serdev)
 	if (ret)
 		return ret;
 
-	return console_open(cdev);
+	ret = console_open(cdev);
+	if (ret)
+		return ret;
+
+	p = dev_add_param_uint64(serdev->dev, "polling_interval",
+				 serdev_device_set_polling_interval, NULL,
+				 &serdev->polling_interval, "%llu", serdev);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	return 0;
 }
 
 unsigned int serdev_device_set_baudrate(struct serdev_device *serdev,
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:33:16 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:33:16 -0700
Subject: [PATCH v2 4/5] serial: Drop .remove functions from all drivers
In-Reply-To: <20180412213317.13199-1-andrew.smirnov@gmail.com>
References: <20180412213317.13199-1-andrew.smirnov@gmail.com>
Message-ID: <20180412213317.13199-5-andrew.smirnov@gmail.com>

Depending on specifics, some 'serdev' devices might need prevent
parent console device from being removed and corresponding memory
deallocated to properly function until the very end of Barebox's
execution. An example of such a use-case would be a reset handler
relying on a serdev device for transport.

To avoid having to develop complicatione reference counting/ownership
scheme drop all of the code that calls console_unregister() and frees
the memory effectively making the problem above impossible to arise.

All of the de-initialization that serial drivers were doing in their
.remove functions was somewhat superflous anyway, so this change
should be pretty harmless.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 drivers/serial/serial_auart.c    | 11 -----------
 drivers/serial/serial_cadence.c  |  9 ---------
 drivers/serial/serial_clps711x.c | 10 ----------
 drivers/serial/serial_imx.c      | 10 ----------
 drivers/serial/serial_lpuart.c   | 13 -------------
 drivers/serial/serial_pxa.c      |  9 ---------
 drivers/serial/serial_s3c.c      | 10 ----------
 drivers/serial/stm-serial.c      | 10 ----------
 8 files changed, 82 deletions(-)

diff --git a/drivers/serial/serial_auart.c b/drivers/serial/serial_auart.c
index c3b9a1995..05cc75797 100644
--- a/drivers/serial/serial_auart.c
+++ b/drivers/serial/serial_auart.c
@@ -220,16 +220,6 @@ static int auart_serial_probe(struct device_d *dev)
 	return 0;
 }
 
-
-static void auart_serial_remove(struct device_d *dev)
-{
-	struct auart_priv *priv = dev->priv;
-
-	auart_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
-	free(priv);
-}
-
 static const __maybe_unused struct of_device_id auart_serial_dt_ids[] = {
 	{
 		.compatible = "fsl,imx23-auart",
@@ -241,7 +231,6 @@ static const __maybe_unused struct of_device_id auart_serial_dt_ids[] = {
 static struct driver_d auart_serial_driver = {
 	.name = "auart_serial",
 	.probe = auart_serial_probe,
-	.remove = auart_serial_remove,
 	.of_compatible = DRV_OF_COMPAT(auart_serial_dt_ids),
 };
 console_platform_driver(auart_serial_driver);
diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
index 36dfa2084..0501c400b 100644
--- a/drivers/serial/serial_cadence.c
+++ b/drivers/serial/serial_cadence.c
@@ -267,14 +267,6 @@ err_free:
 	return ret;
 }
 
-static void cadence_serial_remove(struct device_d *dev)
-{
-	struct cadence_serial_priv *priv = dev->priv;
-
-	console_unregister(&priv->cdev);
-	free(priv);
-}
-
 static __maybe_unused struct of_device_id cadence_serial_dt_ids[] = {
 	{
 		.compatible = "xlnx,xuartps",
@@ -296,7 +288,6 @@ static struct platform_device_id cadence_serial_ids[] = {
 static struct driver_d cadence_serial_driver = {
 	.name   = "cadence_serial",
 	.probe  = cadence_serial_probe,
-	.remove = cadence_serial_remove,
 	.of_compatible = DRV_OF_COMPAT(cadence_serial_dt_ids),
 	.id_table = cadence_serial_ids,
 };
diff --git a/drivers/serial/serial_clps711x.c b/drivers/serial/serial_clps711x.c
index ad14373ac..fa6342346 100644
--- a/drivers/serial/serial_clps711x.c
+++ b/drivers/serial/serial_clps711x.c
@@ -181,15 +181,6 @@ out_err:
 	return err;
 }
 
-static void clps711x_remove(struct device_d *dev)
-{
-	struct clps711x_uart *s = dev->priv;
-
-	clps711x_flush(&s->cdev);
-	console_unregister(&s->cdev);
-	free(s);
-}
-
 static struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
 	{ .compatible = "cirrus,clps711x-uart", },
 };
@@ -197,7 +188,6 @@ static struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
 static struct driver_d clps711x_driver = {
 	.name		= "clps711x-uart",
 	.probe		= clps711x_probe,
-	.remove		= clps711x_remove,
 	.of_compatible	= DRV_OF_COMPAT(clps711x_uart_dt_ids),
 };
 console_platform_driver(clps711x_driver);
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index e8c3836a6..c8af995aa 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -271,15 +271,6 @@ err_free:
 	return ret;
 }
 
-static void imx_serial_remove(struct device_d *dev)
-{
-	struct imx_serial_priv *priv = dev->priv;
-
-	imx_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
-	free(priv);
-}
-
 static __maybe_unused struct of_device_id imx_serial_dt_ids[] = {
 	{
 		.compatible = "fsl,imx1-uart",
@@ -313,7 +304,6 @@ static struct platform_device_id imx_serial_ids[] = {
 static struct driver_d imx_serial_driver = {
 	.name   = "imx_serial",
 	.probe  = imx_serial_probe,
-	.remove = imx_serial_remove,
 	.of_compatible = DRV_OF_COMPAT(imx_serial_dt_ids),
 	.id_table = imx_serial_ids,
 };
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 8f87f7b9c..f28035a32 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -189,18 +189,6 @@ err_free:
 	return ret;
 }
 
-static void lpuart_serial_remove(struct device_d *dev)
-{
-	struct lpuart *lpuart = dev->priv;
-
-	lpuart_serial_flush(&lpuart->cdev);
-	console_unregister(&lpuart->cdev);
-	release_region(lpuart->io);
-	clk_put(lpuart->clk);
-
-	free(lpuart);
-}
-
 static struct of_device_id lpuart_serial_dt_ids[] = {
 	{ .compatible = "fsl,vf610-lpuart" },
 	{}
@@ -209,7 +197,6 @@ static struct of_device_id lpuart_serial_dt_ids[] = {
 static struct driver_d lpuart_serial_driver = {
 	.name   = "lpuart-serial",
 	.probe  = lpuart_serial_probe,
-	.remove = lpuart_serial_remove,
 	.of_compatible = DRV_OF_COMPAT(lpuart_serial_dt_ids),
 };
 console_platform_driver(lpuart_serial_driver);
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index 1a4d7b430..a427437b5 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -185,17 +185,8 @@ static int pxa_serial_probe(struct device_d *dev)
 	return 0;
 }
 
-static void pxa_serial_remove(struct device_d *dev)
-{
-	struct pxa_serial_priv *priv = dev->priv;
-
-	console_unregister(&priv->cdev);
-	free(priv);
-}
-
 static struct driver_d pxa_serial_driver = {
 	.name = "pxa_serial",
 	.probe = pxa_serial_probe,
-	.remove = pxa_serial_remove,
 };
 console_platform_driver(pxa_serial_driver);
diff --git a/drivers/serial/serial_s3c.c b/drivers/serial/serial_s3c.c
index 0a6e22d97..194556072 100644
--- a/drivers/serial/serial_s3c.c
+++ b/drivers/serial/serial_s3c.c
@@ -202,18 +202,8 @@ static int s3c_serial_probe(struct device_d *dev)
 	return 0;
 }
 
-static void s3c_serial_remove(struct device_d *dev)
-{
-	struct s3c_uart *priv= dev->priv;
-
-	s3c_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
-	free(priv);
-}
-
 static struct driver_d s3c_serial_driver = {
 	.name   = "s3c_serial",
 	.probe  = s3c_serial_probe,
-	.remove = s3c_serial_remove,
 };
 console_platform_driver(s3c_serial_driver);
diff --git a/drivers/serial/stm-serial.c b/drivers/serial/stm-serial.c
index 83328f455..ea482415c 100644
--- a/drivers/serial/stm-serial.c
+++ b/drivers/serial/stm-serial.c
@@ -182,15 +182,6 @@ static int stm_serial_probe(struct device_d *dev)
 	return 0;
 }
 
-static void stm_serial_remove(struct device_d *dev)
-{
-	struct stm_priv *priv = dev->priv;
-
-	stm_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
-	free(priv);
-}
-
 static __maybe_unused struct of_device_id stm_serial_dt_ids[] = {
 	{
 		.compatible = "arm,pl011",
@@ -202,7 +193,6 @@ static __maybe_unused struct of_device_id stm_serial_dt_ids[] = {
 static struct driver_d stm_serial_driver = {
         .name   = "stm_serial",
         .probe  = stm_serial_probe,
-	.remove = stm_serial_remove,
 	.of_compatible = DRV_OF_COMPAT(stm_serial_dt_ids),
 };
 console_platform_driver(stm_serial_driver);
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:38:59 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:38:59 -0700
Subject: [PATCH] gitignore: Add *.pblx files
Message-ID: <20180412213859.13742-1-andrew.smirnov@gmail.com>

Looks like *.pblx was accidentally dropped from ignored files list and
now my "git status" is clobbered by every *.pblx image that is being
built (that's quite a lot for imx_v7_defconfig). Re-add original rule
to prevent that.

Fixes eed8a41c5 ("gitignore: ignore pblx.simximg files")

Cc: Steffen Trumtrar <s.trumtrar at pengutronix.de>
Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 images/.gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/images/.gitignore b/images/.gitignore
index cce975f29..d6e85fa85 100644
--- a/images/.gitignore
+++ b/images/.gitignore
@@ -1,5 +1,6 @@
 *.pbl
 *.pblx.*
+*.pblx
 *.pblb
 *.img
 *.imximg
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 12 14:41:43 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 12 Apr 2018 14:41:43 -0700
Subject: [PATCH] serial/lpuart: Do not enable UART FIFO
Message-ID: <20180412214143.17074-1-andrew.smirnov@gmail.com>

Using FIFO in LPUART results in subtle serial input draining issues
which are quite difficult to reproduce and troubleshoot. Since the
change offered only moderate performance gain revert the code to
operate in no-FIFO mode to avoid FIFO-related problems alltogether.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 drivers/serial/serial_lpuart.c |  4 +---
 include/serial/lpuart.h        | 21 +++++----------------
 2 files changed, 6 insertions(+), 19 deletions(-)

diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 52fb6d39c..8f87f7b9c 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -170,9 +170,7 @@ static int lpuart_serial_probe(struct device_d *dev)
 
 	cdev->linux_console_name = "ttyLP";
 
-	lpuart_setup_with_fifo(lpuart->base,
-			       clk_get_rate(lpuart->clk),
-			       15);
+	lpuart_setup(lpuart->base, clk_get_rate(lpuart->clk));
 
 	ret = console_register(cdev);
 	if (!ret) {
diff --git a/include/serial/lpuart.h b/include/serial/lpuart.h
index 917f644a5..a920291de 100644
--- a/include/serial/lpuart.h
+++ b/include/serial/lpuart.h
@@ -238,22 +238,17 @@ static inline void lpuart_setbrg(void __iomem *base,
 	writeb(bfra, base + UARTCR4);
 }
 
-static inline void lpuart_setup_with_fifo(void __iomem *base,
-					  unsigned int refclock,
-					  unsigned int twfifo)
+static inline void lpuart_setup(void __iomem *base,
+				unsigned int refclock)
 {
 	/* Disable UART */
 	writeb(0, base + UARTCR2);
 	writeb(0, base + UARTMODEM);
 	writeb(0, base + UARTCR1);
 
-	if (twfifo) {
-		writeb(UARTPFIFO_TXFE | UARTPFIFO_RXFE, base + UARTPFIFO);
-		writeb((u8)twfifo, base + UARTTWFIFO);
-	} else {
-		writeb(0, base + UARTPFIFO);
-		writeb(0, base + UARTTWFIFO);
-	}
+	writeb(0, base + UARTPFIFO);
+	writeb(0, base + UARTTWFIFO);
+
 	writeb(1, base + UARTRWFIFO);
 	writeb(UARTCFIFO_RXFLUSH | UARTCFIFO_TXFLUSH, base + UARTCFIFO);
 
@@ -262,12 +257,6 @@ static inline void lpuart_setup_with_fifo(void __iomem *base,
 	writeb(UARTCR2_TE | UARTCR2_RE, base + UARTCR2);
 }
 
-static inline void lpuart_setup(void __iomem *base,
-				unsigned int refclock)
-{
-	lpuart_setup_with_fifo(base, refclock, 0x00);
-}
-
 static inline void lpuart_putc(void __iomem *base, int c)
 {
 	if (!(readb(base + UARTCR2) & UARTCR2_TE))
-- 
2.14.3



From u.kleine-koenig at pengutronix.de  Fri Apr 13 16:30:50 2018
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Sat, 14 Apr 2018 01:30:50 +0200
Subject: [PATCH 1/4] pci: rename variable mask -> barval
Message-ID: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>

The variable isn't really a mask. And it is irritating that this "mask"
value is passed as parameter "maxbase" to the function pci_size() which
also has a parameter "mask". So rename it to a more generic term.

The main reason for this patch is that the next patch introduces another
variable with name "mask" and so this original is in the way.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/pci/pci.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b2570eb15181..538903ee6607 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -170,25 +170,26 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 
 	for (bar = 0; bar < max_bar; bar++) {
 		resource_size_t last_addr;
-		u32 orig, mask, size;
+		u32 orig, barval, size;
 
 		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &orig);
 		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
-		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
+		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &barval);
 		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, orig);
 
-		if (mask == 0 || mask == 0xffffffff) {
+		if (barval == 0 || barval == 0xffffffff) {
 			pr_debug("pbar%d set bad mask\n", bar);
 			continue;
 		}
 
-		if (mask & 0x01) { /* IO */
-			size = pci_size(orig, mask, 0xfffffffe);
+		if (barval & 0x01) { /* IO */
+			size = pci_size(orig, barval, 0xfffffffe);
 			if (!size) {
 				pr_debug("pbar%d bad IO mask\n", bar);
 				continue;
 			}
-			pr_debug("pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
+			pr_debug("pbar%d: barval=%08x io %d bytes\n",
+				 bar, barval, size);
 			if (ALIGN(last_io, size) + size >
 			    dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
 				pr_debug("BAR does not fit within bus IO res\n");
@@ -200,15 +201,15 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			dev->resource[bar].flags = IORESOURCE_IO;
 			last_addr = last_io;
 			last_io += size;
-		} else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
+		} else if ((barval & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
 		           last_mem_pref) /* prefetchable MEM */ {
-			size = pci_size(orig, mask, 0xfffffff0);
+			size = pci_size(orig, barval, 0xfffffff0);
 			if (!size) {
 				pr_debug("pbar%d bad P-MEM mask\n", bar);
 				continue;
 			}
-			pr_debug("pbar%d: mask=%08x P memory %d bytes\n",
-			    bar, mask, size);
+			pr_debug("pbar%d: barval=%08x P memory %d bytes\n",
+				 bar, barval, size);
 			if (ALIGN(last_mem_pref, size) + size >
 			    dev->bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->end) {
 				pr_debug("BAR does not fit within bus p-mem res\n");
@@ -222,13 +223,13 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			last_addr = last_mem_pref;
 			last_mem_pref += size;
 		} else { /* non-prefetch MEM */
-			size = pci_size(orig, mask, 0xfffffff0);
+			size = pci_size(orig, barval, 0xfffffff0);
 			if (!size) {
 				pr_debug("pbar%d bad NP-MEM mask\n", bar);
 				continue;
 			}
-			pr_debug("pbar%d: mask=%08x NP memory %d bytes\n",
-			    bar, mask, size);
+			pr_debug("pbar%d: barval=%08x NP memory %d bytes\n",
+				 bar, barval, size);
 			if (ALIGN(last_mem, size) + size >
 			    dev->bus->resource[PCI_BUS_RESOURCE_MEM]->end) {
 				pr_debug("BAR does not fit within bus np-mem res\n");
@@ -245,7 +246,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 		dev->resource[bar].start = last_addr;
 		dev->resource[bar].end = last_addr + size - 1;
 
-		if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+		if ((barval & 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);
-- 
2.16.3



From u.kleine-koenig at pengutronix.de  Fri Apr 13 16:30:51 2018
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Sat, 14 Apr 2018 01:30:51 +0200
Subject: [PATCH 2/4] pci: refactor bar configuration
In-Reply-To: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20180413233053.15570-2-u.kleine-koenig@pengutronix.de>

Instead of doing nearly the same three times for the three different
memory types, use some helper variables and do the same in a more
generic way only once.

Apart from minor changes in the pr_debug output there is no semantic
change intended.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/pci/pci.c | 104 ++++++++++++++++++++++--------------------------------
 1 file changed, 43 insertions(+), 61 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 538903ee6607..87359b6de82c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -169,8 +169,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			      cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
 
 	for (bar = 0; bar < max_bar; bar++) {
-		resource_size_t last_addr;
-		u32 orig, barval, size;
+		u32 orig, barval, size, mask;
+		const char *type;
+		int restype;
+		unsigned long resflags;
+		resource_size_t *last;
 
 		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &orig);
 		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
@@ -183,68 +186,47 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 		}
 
 		if (barval & 0x01) { /* IO */
-			size = pci_size(orig, barval, 0xfffffffe);
-			if (!size) {
-				pr_debug("pbar%d bad IO mask\n", bar);
-				continue;
-			}
-			pr_debug("pbar%d: barval=%08x io %d bytes\n",
-				 bar, barval, size);
-			if (ALIGN(last_io, size) + size >
-			    dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
-				pr_debug("BAR does not fit within bus IO res\n");
-				return;
-			}
-			last_io = ALIGN(last_io, size);
-			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_io);
-			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;
+			mask = 0xfffffffe;
+			type = "IO";
+			restype = PCI_BUS_RESOURCE_IO;
+			resflags = IORESOURCE_IO;
+			last = &last_io;
 		} else if ((barval & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
-		           last_mem_pref) /* prefetchable MEM */ {
-			size = pci_size(orig, barval, 0xfffffff0);
-			if (!size) {
-				pr_debug("pbar%d bad P-MEM mask\n", bar);
-				continue;
-			}
-			pr_debug("pbar%d: barval=%08x P memory %d bytes\n",
-				 bar, barval, size);
-			if (ALIGN(last_mem_pref, size) + size >
-			    dev->bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->end) {
-				pr_debug("BAR does not fit within bus p-mem res\n");
-				return;
-			}
-			last_mem_pref = ALIGN(last_mem_pref, size);
-			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem_pref);
-			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem_pref);
-			dev->resource[bar].flags = IORESOURCE_MEM |
-			                           IORESOURCE_PREFETCH;
-			last_addr = last_mem_pref;
-			last_mem_pref += size;
-		} else { /* non-prefetch MEM */
-			size = pci_size(orig, barval, 0xfffffff0);
-			if (!size) {
-				pr_debug("pbar%d bad NP-MEM mask\n", bar);
-				continue;
-			}
-			pr_debug("pbar%d: barval=%08x NP memory %d bytes\n",
-				 bar, barval, size);
-			if (ALIGN(last_mem, size) + size >
-			    dev->bus->resource[PCI_BUS_RESOURCE_MEM]->end) {
-				pr_debug("BAR does not fit within bus np-mem res\n");
-				return;
-			}
-			last_mem = ALIGN(last_mem, size);
-			pr_debug("pbar%d: allocated at 0x%08x\n", bar, last_mem);
-			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;
+			   last_mem_pref) { /* prefetchable MEM */
+			mask = 0xfffffff0;
+			type = "P";
+			restype = PCI_BUS_RESOURCE_MEM_PREF;
+			resflags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+			last = &last_mem_pref;
+		} else { /* non-prefetchable MEM */
+			mask = 0xfffffff0;
+			type = "NP";
+			restype = PCI_BUS_RESOURCE_MEM;
+			resflags = IORESOURCE_MEM;
+			last = &last_mem;
 		}
 
-		dev->resource[bar].start = last_addr;
-		dev->resource[bar].end = last_addr + size - 1;
+		size = pci_size(orig, barval, mask);
+		if (!size) {
+			pr_debug("pbar%d bad %s mask\n", bar, type);
+			continue;
+		}
+
+		pr_debug("pbar%d: barval=%08x type=%s size=0x%x\n",
+			 bar, barval, type, size);
+
+		if (ALIGN(*last, size) + size > dev->bus->resource[restype]->end) {
+			pr_debug("BAR does not fit within bus %s res\n", type);
+			return;
+		}
+
+		*last = ALIGN(*last, size);
+		pr_debug("pbar%d: allocated at 0x%08x\n", bar, *last);
+		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, *last);
+		dev->resource[bar].flags = resflags;
+		dev->resource[bar].start = *last;
+		*last += size;
+		dev->resource[bar].end = *last - 1;
 
 		if ((barval & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
 			dev->resource[bar].flags |= IORESOURCE_MEM_64;
-- 
2.16.3



From u.kleine-koenig at pengutronix.de  Fri Apr 13 16:30:53 2018
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Sat, 14 Apr 2018 01:30:53 +0200
Subject: [PATCH 4/4] pci: don't hide hard to understand sanity check in size
 calculation
In-Reply-To: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20180413233053.15570-4-u.kleine-koenig@pengutronix.de>

pci_size() had a check that made it return 0 (i.e. an error) in some
cases. It took me a while to work out in which situations exactly this
check triggered: If writing 0xfffffffe to the BAR register doesn't
change it's value and the masked value isn't in the form 0b1....10...0.

This patch replaces the check in pci_size() by a similar check in
setup_device() where it is more expected to happen. This allows to
simplify pci_size() considerably.

The new check is a bit more strict as it doesn't consider the value the
BAR register holds initially and bails out iff the maximal base value
isn't in the expected format.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/pci/pci.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 837e17aa8397..72689560d598 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -144,18 +144,10 @@ static struct pci_dev *alloc_pci_dev(void)
 	return dev;
 }
 
-static u32 pci_size(u32 base, u32 maxbase, u32 mask)
+static u32 pci_size(u32 maxbase)
 {
-	u32 size = maxbase & mask;
-	if (!size)
-		return 0;
-
-	size = (size & ~(size-1)) - 1;
-
-	if (base == maxbase && ((base | size) & mask) != mask)
-		return 0;
-
-	return size + 1;
+	/* isolate right-most set bit */
+	return maxbase & ~(maxbase - 1);
 }
 
 
@@ -169,7 +161,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			      cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
 
 	for (bar = 0; bar < max_bar; bar++) {
-		u32 orig, barval, size, mask;
+		u32 orig, barval, maxbase, size, mask;
 		const char *type;
 		int restype;
 		unsigned long resflags;
@@ -206,13 +198,19 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			last = &last_mem;
 		}
 
-		size = pci_size(orig, barval, mask);
-		if (!size) {
-			pr_debug(" pbar%d: bad %s size (orig=%08x, barval=%08x, type=%s)\n",
-				 bar, type, orig, barval, type);
+		maxbase = barval & mask;
+
+		/*
+		 * if maxbase isn't in the form 0b1...10...0 there is something
+		 * fishy
+		 */
+		if ((maxbase | (maxbase - 1)) != (u32)-1 || maxbase == 0) {
+			pr_debug(" pbar%d: !! barval=%08x maxbase=0x%08x\n", bar, barval, maxbase);
 			continue;
 		}
 
+		size = pci_size(maxbase);
+
 		if (ALIGN(*last, size) + size > dev->bus->resource[restype]->end) {
 			pr_debug(" pbar%d: !! type=%s allocbase=0x%08x + size=0x%08x > resource_end=%pa (barval=%08x)\n",
 				 bar, type, ALIGN(*last, size), size, &dev->bus->resource[restype]->end, barval);
-- 
2.16.3



From u.kleine-koenig at pengutronix.de  Fri Apr 13 16:30:52 2018
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Sat, 14 Apr 2018 01:30:52 +0200
Subject: [PATCH 3/4] pci: improve debug output
In-Reply-To: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20180413233053.15570-3-u.kleine-koenig@pengutronix.de>

Print a single line per bar with all relevant information and indent it
by a space to group them together per device.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/pci/pci.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 87359b6de82c..837e17aa8397 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -181,7 +181,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, orig);
 
 		if (barval == 0 || barval == 0xffffffff) {
-			pr_debug("pbar%d set bad mask\n", bar);
+			pr_debug(" pbar%d: set bad mask (%08x)\n", bar, barval);
 			continue;
 		}
 
@@ -208,20 +208,21 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 
 		size = pci_size(orig, barval, mask);
 		if (!size) {
-			pr_debug("pbar%d bad %s mask\n", bar, type);
+			pr_debug(" pbar%d: bad %s size (orig=%08x, barval=%08x, type=%s)\n",
+				 bar, type, orig, barval, type);
 			continue;
 		}
 
-		pr_debug("pbar%d: barval=%08x type=%s size=0x%x\n",
-			 bar, barval, type, size);
-
 		if (ALIGN(*last, size) + size > dev->bus->resource[restype]->end) {
-			pr_debug("BAR does not fit within bus %s res\n", type);
+			pr_debug(" pbar%d: !! type=%s allocbase=0x%08x + size=0x%08x > resource_end=%pa (barval=%08x)\n",
+				 bar, type, ALIGN(*last, size), size, &dev->bus->resource[restype]->end, barval);
 			return;
 		}
 
 		*last = ALIGN(*last, size);
-		pr_debug("pbar%d: allocated at 0x%08x\n", bar, *last);
+		pr_debug(" pbar%d: type=%s allocbase=0x%08x size=0x%08x (barval=%08x)\n",
+			 bar, type, *last, size, barval);
+
 		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, *last);
 		dev->resource[bar].flags = resflags;
 		dev->resource[bar].start = *last;
-- 
2.16.3



From u.kleine-koenig at pengutronix.de  Fri Apr 13 16:58:15 2018
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Sat, 14 Apr 2018 01:58:15 +0200
Subject: [PATCH 3/4] pci: improve debug output
In-Reply-To: <20180413233053.15570-3-u.kleine-koenig@pengutronix.de>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
 <20180413233053.15570-3-u.kleine-koenig@pengutronix.de>
Message-ID: <20180413235815.h4zgmhhweqexqbcx@pengutronix.de>

Hello,

On Sat, Apr 14, 2018 at 01:30:52AM +0200, Uwe Kleine-K?nig wrote:
>  		if (ALIGN(*last, size) + size > dev->bus->resource[restype]->end) {
> -			pr_debug("BAR does not fit within bus %s res\n", type);
> +			pr_debug(" pbar%d: !! type=%s allocbase=0x%08x + size=0x%08x > resource_end=%pa (barval=%08x)\n",
> +				 bar, type, ALIGN(*last, size), size, &dev->bus->resource[restype]->end, barval);

slightly related: I have a machine where this new line results in:

	pci:  pbar0: !! type=NP allocbase=0x01800000 + size=0x00800000 > resource_end=0x01efffff (barval=ff800000)

This makes me wonder if the LHS of the check needs to read

	ALIGN(*last, size) + size - 1

. I will think about this after sleeping, and then probably send a patch
for that.

Best regards
Uwe


-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From andrew.smirnov at gmail.com  Sat Apr 14 09:25:59 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 09:25:59 -0700
Subject: [PATCH 4/4] pci: don't hide hard to understand sanity check in
 size calculation
In-Reply-To: <20180413233053.15570-4-u.kleine-koenig@pengutronix.de>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
 <20180413233053.15570-4-u.kleine-koenig@pengutronix.de>
Message-ID: <CAHQ1cqFkU=9aPg9xr3gbmApgx-rSfM3toH3m-Br3=PjN1Voqvw@mail.gmail.com>

On Fri, Apr 13, 2018 at 4:30 PM, Uwe Kleine-K?nig
<u.kleine-koenig at pengutronix.de> wrote:
> pci_size() had a check that made it return 0 (i.e. an error) in some
> cases. It took me a while to work out in which situations exactly this
> check triggered: If writing 0xfffffffe to the BAR register doesn't
> change it's value and the masked value isn't in the form 0b1....10...0.
>
> This patch replaces the check in pci_size() by a similar check in
> setup_device() where it is more expected to happen. This allows to
> simplify pci_size() considerably.
>
> The new check is a bit more strict as it doesn't consider the value the
> BAR register holds initially and bails out iff the maximal base value
> isn't in the expected format.
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---
>  drivers/pci/pci.c | 30 ++++++++++++++----------------
>  1 file changed, 14 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 837e17aa8397..72689560d598 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -144,18 +144,10 @@ static struct pci_dev *alloc_pci_dev(void)
>         return dev;
>  }
>
> -static u32 pci_size(u32 base, u32 maxbase, u32 mask)
> +static u32 pci_size(u32 maxbase)
>  {
> -       u32 size = maxbase & mask;
> -       if (!size)
> -               return 0;
> -
> -       size = (size & ~(size-1)) - 1;
> -
> -       if (base == maxbase && ((base | size) & mask) != mask)
> -               return 0;
> -
> -       return size + 1;
> +       /* isolate right-most set bit */
> +       return maxbase & ~(maxbase - 1);
>  }
>
>
> @@ -169,7 +161,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
>                               cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
>
>         for (bar = 0; bar < max_bar; bar++) {
> -               u32 orig, barval, size, mask;
> +               u32 orig, barval, maxbase, size, mask;
>                 const char *type;
>                 int restype;
>                 unsigned long resflags;
> @@ -206,13 +198,19 @@ static void setup_device(struct pci_dev *dev, int max_bar)
>                         last = &last_mem;
>                 }
>
> -               size = pci_size(orig, barval, mask);
> -               if (!size) {
> -                       pr_debug(" pbar%d: bad %s size (orig=%08x, barval=%08x, type=%s)\n",
> -                                bar, type, orig, barval, type);
> +               maxbase = barval & mask;
> +
> +               /*
> +                * if maxbase isn't in the form 0b1...10...0 there is something
> +                * fishy
> +                */
> +               if ((maxbase | (maxbase - 1)) != (u32)-1 || maxbase == 0) {

U32_MAX instead of (u32)-1 ?

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Sat Apr 14 10:50:15 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:15 -0700
Subject: [PATCH 01/10] common: reset_source: Add the notion of "reset source
 instance"
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-2-andrew.smirnov@gmail.com>

In order to accomodate SoCs that come with multiple watchdogs (or any
other reset sources of the same kind) add a notion of "reset source
instance", similar to what we already have for bootsource API.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/reset_source.c  | 17 +++++++++++++++++
 include/reset_source.h | 11 +++++++++++
 2 files changed, 28 insertions(+)

diff --git a/common/reset_source.c b/common/reset_source.c
index 06e2ca85f..6a6c4f5da 100644
--- a/common/reset_source.c
+++ b/common/reset_source.c
@@ -32,6 +32,7 @@ static const char * const reset_src_names[] = {
 
 static enum reset_src_type reset_source;
 static unsigned int reset_source_priority;
+static int reset_source_instance;
 
 enum reset_src_type reset_source_get(void)
 {
@@ -39,6 +40,12 @@ enum reset_src_type reset_source_get(void)
 }
 EXPORT_SYMBOL(reset_source_get);
 
+int reset_source_get_instance(void)
+{
+	return reset_source_instance;
+}
+EXPORT_SYMBOL(reset_source_get_instance);
+
 void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
 {
 	if (priority <= reset_source_priority)
@@ -46,17 +53,27 @@ void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
 
 	reset_source = st;
 	reset_source_priority = priority;
+	reset_source_instance = 0;
 
 	pr_debug("Setting reset source to %s with priority %d\n",
 			reset_src_names[reset_source], priority);
 }
 EXPORT_SYMBOL(reset_source_set_priority);
 
+void reset_source_set_instance(enum reset_src_type type, int instance)
+{
+	if (reset_source == type)
+		reset_source_instance = instance;
+}
+EXPORT_SYMBOL(reset_source_set_instance);
+
 static int reset_source_init(void)
 {
 	globalvar_add_simple_enum("system.reset", (unsigned int *)&reset_source,
 			reset_src_names, ARRAY_SIZE(reset_src_names));
 
+	globalvar_add_simple_int("system.reset_instance", &reset_source_instance,
+				 "%d");
 	return 0;
 }
 
diff --git a/include/reset_source.h b/include/reset_source.h
index 3ff06b70a..c9911c008 100644
--- a/include/reset_source.h
+++ b/include/reset_source.h
@@ -27,6 +27,8 @@ enum reset_src_type {
 #ifdef CONFIG_RESET_SOURCE
 void reset_source_set_priority(enum reset_src_type, unsigned int priority);
 enum reset_src_type reset_source_get(void);
+void reset_source_set_instance(enum reset_src_type type, int instance);
+int reset_source_get_instance(void);
 unsigned int of_get_reset_source_priority(struct device_node *node);
 #else
 static inline void reset_source_set_priority(enum reset_src_type type,
@@ -34,11 +36,20 @@ static inline void reset_source_set_priority(enum reset_src_type type,
 {
 }
 
+static inline void reset_source_set_instance(enum reset_src_type type, int instance)
+{
+}
+
 static inline enum reset_src_type reset_source_get(void)
 {
 	return RESET_UKWN;
 }
 
+static inline int reset_source_get_instance(void)
+{
+	return 0;
+}
+
 static inline unsigned int of_get_reset_source_priority(struct device_node *node)
 {
 	return 0;
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:17 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:17 -0700
Subject: [PATCH 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-4-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx6.c                      | 4 +++-
 arch/arm/mach-imx/include/mach/reset-reason.h | 2 ++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 14a1cba5a..3d81c2785 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -19,6 +19,7 @@
 #include <mach/imx6.h>
 #include <mach/generic.h>
 #include <mach/revision.h>
+#include <mach/reset-reason.h>
 #include <mach/imx6-anadig.h>
 #include <mach/imx6-regs.h>
 #include <mach/generic.h>
@@ -151,6 +152,7 @@ int imx6_init(void)
 {
 	const char *cputypestr;
 	u32 mx6_silicon_revision;
+	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
 
 	imx6_init_lowlevel();
 
@@ -195,7 +197,7 @@ int imx6_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
-
+	imx_set_reset_reason(src + IMX6_SRC_SRSR);
 	imx6_setup_ipu_qos();
 	imx6ul_enet_clk_init();
 
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index 96b905303..f65224a55 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -12,6 +12,8 @@
 #define IMX_SRC_SRSR_TEMPSENSE_RESET	BIT(9)
 #define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
 
+#define IMX6_SRC_SRSR	0x008
+
 void imx_set_reset_reason(void __iomem *srsr);
 
 #endif /* __MACH_RESET_REASON_H__ */
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:14 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:14 -0700
Subject: [PATCH 00/10] i.MX reset reason detection support
Message-ID: <20180414175024.9962-1-andrew.smirnov@gmail.com>

Everyone:

This patchset is the result of my work on adding support for detecting
and reporting reset reason as can be obtained from System Reset
Controller (to be more precise via SRSR register) on i.MX family of
SoC.

Currently list of supported SoC is as follows:

	  - i.MX6 (tested on i.MX6Q)
	  - i.MX7 (tested on i.MX7D)
	  - VFxxx (tested on VF610)

Feedback is wellcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (10):
  common: reset_source: Add the notion of "reset source instance"
  ARM: i.MX: Add infrastructure to record SoC reset reason
  ARM: i.MX6: Record reset reason as a part of startup
  ARM: i.MX7: Record reset reason as a part of startup
  common: reset_source: Introduce reset_source_name()
  ARM: i.MX: Log detected reset reason
  ARM: i.MX: Print "revision unknown" if that is the case
  ARM: VFxxx: Add code to detect reset reason
  ARM: VFxxx: Add code to detect cpu variant
  ARM: VFxxx: Detect cpu variant and reset source on start

 arch/arm/mach-imx/Makefile                    |  1 +
 arch/arm/mach-imx/imx.c                       | 83 ++++++++++++++++++++++++++-
 arch/arm/mach-imx/imx6.c                      |  4 +-
 arch/arm/mach-imx/imx7.c                      |  3 +
 arch/arm/mach-imx/include/mach/generic.h      |  1 +
 arch/arm/mach-imx/include/mach/reset-reason.h | 31 ++++++++++
 arch/arm/mach-imx/include/mach/vf610-regs.h   |  3 +
 arch/arm/mach-imx/include/mach/vf610.h        | 51 ++++++++++++++++
 arch/arm/mach-imx/vf610.c                     | 50 ++++++++++++++++
 common/reset_source.c                         | 23 ++++++++
 include/reset_source.h                        | 17 ++++++
 11 files changed, 264 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h
 create mode 100644 arch/arm/mach-imx/include/mach/vf610.h
 create mode 100644 arch/arm/mach-imx/vf610.c

-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:21 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:21 -0700
Subject: [PATCH 07/10] ARM: i.MX: Print "revision unknown" if that is the case
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-8-andrew.smirnov@gmail.com>

Printing "revision 16.16" if i.MX SoC's revision is unknown is a bit
confusing so modify the code to actually say "revision unknown" in
such a case.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index b7465875e..fb1160de9 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -31,7 +31,10 @@ void imx_set_silicon_revision(const char *soc, int revision)
 {
 	__imx_silicon_revision = revision;
 
-	pr_info("detected %s revision %d.%d\n", soc,
+	if (revision == IMX_CHIP_REV_UNKNOWN)
+		pr_info("detected %s revision unknown\n", soc);
+	else
+		pr_info("detected %s revision %d.%d\n", soc,
 			(revision >> 4) & 0xf,
 			revision & 0xf);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:16 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:16 -0700
Subject: [PATCH 02/10] ARM: i.MX: Add infrastructure to record SoC reset reason
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-3-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c                       | 49 +++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/reset-reason.h | 17 ++++++++++
 2 files changed, 66 insertions(+)
 create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 9400105c6..e860e298a 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -14,8 +14,11 @@
 #include <common.h>
 #include <of.h>
 #include <init.h>
+#include <io.h>
 #include <mach/revision.h>
+#include <mach/reset-reason.h>
 #include <mach/generic.h>
+#include <reset_source.h>
 
 static int __imx_silicon_revision = IMX_CHIP_REV_UNKNOWN;
 
@@ -147,3 +150,49 @@ static int imx_init(void)
 	return ret;
 }
 postcore_initcall(imx_init);
+
+void imx_set_reset_reason(void __iomem *srsr)
+{
+	enum reset_src_type type = RESET_UKWN;
+	const u32 reg = readl(srsr);
+
+	/*
+	 * SRSR register captures ALL reset event that occured since
+	 * POR, so we need to clear it to make sure we only caputre
+	 * the latest one.
+	 */
+	writel(reg, srsr);
+
+	switch (reg) {
+	case IMX_SRC_SRSR_IPP_RESET: /* FALLTHROUGH */
+	case IMX_SRC_SRSR_IPP_RESET | IMX_SRC_SRSR_WDOG1_RESET:
+		type = RESET_POR;
+		break;
+	case IMX_SRC_SRSR_WDOG3_RESET: /* FALLTHROUGH */
+	case IMX_SRC_SRSR_WDOG4_RESET: /* FALLTHROUGH */
+	case IMX_SRC_SRSR_WDOG1_RESET:
+		type = RESET_WDG;
+		break;
+	case IMX_SRC_SRSR_JTAG_RESET: /* FALLTHROUGH */
+	case IMX_SRC_SRSR_JTAG_SW_RESET:
+		type = RESET_JTAG;
+		break;
+	case IMX_SRC_SRSR_TEMPSENSE_RESET:
+		type = RESET_THERM;
+		break;
+	case IMX_SRC_SRSR_WARM_BOOT:
+		type = RESET_RST;
+		break;
+	}
+
+	reset_source_set(type);
+
+	switch (reg) {
+	case IMX_SRC_SRSR_WDOG3_RESET:
+		reset_source_set_instance(type, 1);
+		break;
+	case IMX_SRC_SRSR_WDOG4_RESET:
+		reset_source_set_instance(type, 2);
+		break;
+	}
+}
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
new file mode 100644
index 000000000..96b905303
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -0,0 +1,17 @@
+#ifndef __MACH_RESET_REASON_H__
+#define __MACH_RESET_REASON_H__
+
+#define IMX_SRC_SRSR_IPP_RESET		BIT(0)
+#define IMX_SRC_SRSR_CSU_RESET		BIT(1)
+#define IMX_SRC_SRSR_IPP_USER_RESET	BIT(3)
+#define IMX_SRC_SRSR_WDOG1_RESET	BIT(4)
+#define IMX_SRC_SRSR_JTAG_RESET		BIT(5)
+#define IMX_SRC_SRSR_JTAG_SW_RESET	BIT(6)
+#define IMX_SRC_SRSR_WDOG3_RESET	BIT(7)
+#define IMX_SRC_SRSR_WDOG4_RESET	BIT(8)
+#define IMX_SRC_SRSR_TEMPSENSE_RESET	BIT(9)
+#define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
+
+void imx_set_reset_reason(void __iomem *srsr);
+
+#endif /* __MACH_RESET_REASON_H__ */
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:20 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:20 -0700
Subject: [PATCH 06/10] ARM: i.MX: Log detected reset reason
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-7-andrew.smirnov@gmail.com>

Log detected reset reason as well as raw value of SRSR for better
clarity.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index e860e298a..b7465875e 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -195,4 +195,7 @@ void imx_set_reset_reason(void __iomem *srsr)
 		reset_source_set_instance(type, 2);
 		break;
 	}
+
+	pr_info("i.MX reset reason %s (SRSR: 0x%08x)\n",
+		reset_source_name(), reg);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:18 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:18 -0700
Subject: [PATCH 04/10] ARM: i.MX7: Record reset reason as a part of startup
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-5-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx7.c                      | 3 +++
 arch/arm/mach-imx/include/mach/reset-reason.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c
index 4eef99c87..a5debd06c 100644
--- a/arch/arm/mach-imx/imx7.c
+++ b/arch/arm/mach-imx/imx7.c
@@ -19,6 +19,7 @@
 #include <mach/imx7.h>
 #include <mach/generic.h>
 #include <mach/revision.h>
+#include <mach/reset-reason.h>
 #include <mach/imx7-regs.h>
 
 void imx7_init_lowlevel(void)
@@ -171,6 +172,7 @@ int imx7_init(void)
 {
 	const char *cputypestr;
 	u32 imx7_silicon_revision;
+	void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR);
 
 	imx7_init_lowlevel();
 
@@ -197,6 +199,7 @@ int imx7_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, imx7_silicon_revision);
+	imx_set_reset_reason(src + IMX7_SRC_SRSR);
 
 	return 0;
 }
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index f65224a55..a8a9dc682 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -13,6 +13,7 @@
 #define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
 
 #define IMX6_SRC_SRSR	0x008
+#define IMX7_SRC_SRSR	0x05c
 
 void imx_set_reset_reason(void __iomem *srsr);
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:23 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:23 -0700
Subject: [PATCH 09/10] ARM: VFxxx: Add code to detect cpu variant
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-10-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/include/mach/vf610-regs.h |  3 ++
 arch/arm/mach-imx/include/mach/vf610.h      | 51 +++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 arch/arm/mach-imx/include/mach/vf610.h

diff --git a/arch/arm/mach-imx/include/mach/vf610-regs.h b/arch/arm/mach-imx/include/mach/vf610-regs.h
index 8be220b68..2afdf7edc 100644
--- a/arch/arm/mach-imx/include/mach/vf610-regs.h
+++ b/arch/arm/mach-imx/include/mach/vf610-regs.h
@@ -107,4 +107,7 @@
 #define VF610_MSCM_IRSPRC_CP0_EN	1
 #define VF610_MSCM_IRSPRC_NUM		112
 
+#define VF610_MSCM_CPxCOUNT		0x00c
+#define VF610_MSCM_CPxCFG1		0x014
+
 #endif
diff --git a/arch/arm/mach-imx/include/mach/vf610.h b/arch/arm/mach-imx/include/mach/vf610.h
new file mode 100644
index 000000000..6d00d2e45
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/vf610.h
@@ -0,0 +1,51 @@
+#ifndef __MACH_VF610_H
+#define __MACH_VF610_H
+
+#include <io.h>
+#include <mach/generic.h>
+#include <mach/vf610-regs.h>
+#include <mach/revision.h>
+
+#define VF610_CPUTYPE_VFx10	0x010
+
+#define VF610_CPUTYPE_VF610	0x610
+#define VF610_CPUTYPE_VF600	0x600
+#define VF610_CPUTYPE_VF510	0x510
+#define VF610_CPUTYPE_VF500	0x500
+
+#define VF610_ROM_VERSION_OFFSET	0x80
+
+static inline int __vf610_cpu_type(void)
+{
+	void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
+	const u32 cpxcount = readl(mscm + VF610_MSCM_CPxCOUNT);
+	const u32 cpxcfg1  = readl(mscm + VF610_MSCM_CPxCFG1);
+	int cpu_type;
+
+	cpu_type = cpxcount ? VF610_CPUTYPE_VF600 : VF610_CPUTYPE_VF500;
+
+	return cpxcfg1 ? cpu_type | VF610_CPUTYPE_VFx10 : cpu_type;
+}
+
+static inline int vf610_cpu_type(void)
+{
+	if (!cpu_is_vf610())
+		return 0;
+
+	return __vf610_cpu_type();
+}
+
+static inline int vf610_cpu_revision(void)
+{
+	if (!cpu_is_vf610())
+		return IMX_CHIP_REV_UNKNOWN;
+
+	/*
+	 * There doesn't seem to be a documented way of retreiving
+	 * silicon revision on VFxxx cpus, so we just report Mask ROM
+	 * version instead
+	 */
+	return readl(VF610_ROM_VERSION_OFFSET) & 0xff;
+}
+
+#endif
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:22 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:22 -0700
Subject: [PATCH 08/10] ARM: VFxxx: Add code to detect reset reason
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-9-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c                       | 78 +++++++++++++++++----------
 arch/arm/mach-imx/include/mach/reset-reason.h | 11 ++++
 2 files changed, 62 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index fb1160de9..e84713766 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -158,6 +158,7 @@ void imx_set_reset_reason(void __iomem *srsr)
 {
 	enum reset_src_type type = RESET_UKWN;
 	const u32 reg = readl(srsr);
+	const bool is_vf610 = cpu_is_vf610();
 
 	/*
 	 * SRSR register captures ALL reset event that occured since
@@ -166,37 +167,60 @@ void imx_set_reset_reason(void __iomem *srsr)
 	 */
 	writel(reg, srsr);
 
-	switch (reg) {
-	case IMX_SRC_SRSR_IPP_RESET: /* FALLTHROUGH */
-	case IMX_SRC_SRSR_IPP_RESET | IMX_SRC_SRSR_WDOG1_RESET:
-		type = RESET_POR;
-		break;
-	case IMX_SRC_SRSR_WDOG3_RESET: /* FALLTHROUGH */
-	case IMX_SRC_SRSR_WDOG4_RESET: /* FALLTHROUGH */
-	case IMX_SRC_SRSR_WDOG1_RESET:
-		type = RESET_WDG;
-		break;
-	case IMX_SRC_SRSR_JTAG_RESET: /* FALLTHROUGH */
-	case IMX_SRC_SRSR_JTAG_SW_RESET:
-		type = RESET_JTAG;
-		break;
-	case IMX_SRC_SRSR_TEMPSENSE_RESET:
-		type = RESET_THERM;
-		break;
-	case IMX_SRC_SRSR_WARM_BOOT:
-		type = RESET_RST;
-		break;
+	if (is_vf610) {
+		/*
+		 * Layout of SRSR on Vybrid is quite different so we
+		 * handle it separately.
+		 */
+		if (reg & VF610_SRC_SRSR_POR_RST) {
+			type = RESET_POR;
+		} else if (reg & VF610_SRC_SRSR_WDOG_xx) {
+			type = RESET_WDG;
+		} else if (reg & VF610_SRC_SRSR_JTAG_RST) {
+			type = RESET_JTAG;
+		} else if (reg & VF610_SRC_SRSR_SW_RST) {
+			type = RESET_RST;
+		} else if (reg & VF610_SRC_SRSR_RESETB) {
+			type = RESET_EXT;
+		}
+	} else {
+		switch (reg) {
+		case IMX_SRC_SRSR_IPP_RESET: /* FALLTHROUGH */
+		case IMX_SRC_SRSR_IPP_RESET | IMX_SRC_SRSR_WDOG1_RESET:
+			type = RESET_POR;
+			break;
+		case IMX_SRC_SRSR_WDOG3_RESET: /* FALLTHROUGH */
+		case IMX_SRC_SRSR_WDOG4_RESET: /* FALLTHROUGH */
+		case IMX_SRC_SRSR_WDOG1_RESET:
+			type = RESET_WDG;
+			break;
+		case IMX_SRC_SRSR_JTAG_RESET: /* FALLTHROUGH */
+		case IMX_SRC_SRSR_JTAG_SW_RESET:
+			type = RESET_JTAG;
+			break;
+		case IMX_SRC_SRSR_TEMPSENSE_RESET:
+			type = RESET_THERM;
+			break;
+		case IMX_SRC_SRSR_WARM_BOOT:
+			type = RESET_RST;
+			break;
+		}
 	}
 
 	reset_source_set(type);
 
-	switch (reg) {
-	case IMX_SRC_SRSR_WDOG3_RESET:
-		reset_source_set_instance(type, 1);
-		break;
-	case IMX_SRC_SRSR_WDOG4_RESET:
-		reset_source_set_instance(type, 2);
-		break;
+	if (is_vf610) {
+		if (reg & VF610_SRC_SRSR_WDOG_M4)
+			reset_source_set_instance(type, 1);
+	} else {
+		switch (reg) {
+		case IMX_SRC_SRSR_WDOG3_RESET:
+			reset_source_set_instance(type, 1);
+			break;
+		case IMX_SRC_SRSR_WDOG4_RESET:
+			reset_source_set_instance(type, 2);
+			break;
+		}
 	}
 
 	pr_info("i.MX reset reason %s (SRSR: 0x%08x)\n",
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index a8a9dc682..543fec4a1 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -14,6 +14,17 @@
 
 #define IMX6_SRC_SRSR	0x008
 #define IMX7_SRC_SRSR	0x05c
+#define VF610_SRC_SRSR	0x008
+
+
+#define VF610_SRC_SRSR_SW_RST		BIT(18)
+#define VF610_SRC_SRSR_RESETB		BIT(7)
+#define VF610_SRC_SRSR_JTAG_RST		BIT(5)
+#define VF610_SRC_SRSR_WDOG_M4		BIT(4)
+#define VF610_SRC_SRSR_WDOG_A5		BIT(3)
+#define VF610_SRC_SRSR_WDOG_xx		(VF610_SRC_SRSR_WDOG_A5 | \
+					 VF610_SRC_SRSR_WDOG_M4)
+#define VF610_SRC_SRSR_POR_RST		BIT(0)
 
 void imx_set_reset_reason(void __iomem *srsr);
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:19 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:19 -0700
Subject: [PATCH 05/10] common: reset_source: Introduce reset_source_name()
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-6-andrew.smirnov@gmail.com>

Introduce reset_source_name() to get string representation of current
reset source.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/reset_source.c  | 6 ++++++
 include/reset_source.h | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/common/reset_source.c b/common/reset_source.c
index 6a6c4f5da..b2985ee85 100644
--- a/common/reset_source.c
+++ b/common/reset_source.c
@@ -60,6 +60,12 @@ void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
 }
 EXPORT_SYMBOL(reset_source_set_priority);
 
+const char *reset_source_name(void)
+{
+	return reset_src_names[reset_source];
+}
+EXPORT_SYMBOL(reset_source_name)
+
 void reset_source_set_instance(enum reset_src_type type, int instance)
 {
 	if (reset_source == type)
diff --git a/include/reset_source.h b/include/reset_source.h
index c9911c008..f9aed6a7a 100644
--- a/include/reset_source.h
+++ b/include/reset_source.h
@@ -30,6 +30,7 @@ enum reset_src_type reset_source_get(void);
 void reset_source_set_instance(enum reset_src_type type, int instance);
 int reset_source_get_instance(void);
 unsigned int of_get_reset_source_priority(struct device_node *node);
+const char *reset_source_name(void);
 #else
 static inline void reset_source_set_priority(enum reset_src_type type,
 		unsigned int priority)
@@ -54,6 +55,11 @@ static inline unsigned int of_get_reset_source_priority(struct device_node *node
 {
 	return 0;
 }
+
+const char *reset_source_name(void)
+{
+	return "unknown";
+}
 #endif
 
 #define RESET_SOURCE_DEFAULT_PRIORITY 100
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:24 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:24 -0700
Subject: [PATCH 10/10] ARM: VFxxx: Detect cpu variant and reset source on start
In-Reply-To: <20180414175024.9962-1-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175024.9962-11-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/Makefile               |  1 +
 arch/arm/mach-imx/imx.c                  |  2 +-
 arch/arm/mach-imx/include/mach/generic.h |  1 +
 arch/arm/mach-imx/vf610.c                | 50 ++++++++++++++++++++++++++++++++
 4 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/vf610.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 8ec846cce..160ed4b08 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o
 CFLAGS_imx6.o := -march=armv7-a
 lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
 obj-$(CONFIG_ARCH_IMX7) += imx7.o
+obj-$(CONFIG_ARCH_VF610) += vf610.o
 obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o
 obj-$(CONFIG_IMX_IIM)	+= iim.o
 obj-$(CONFIG_IMX_OCOTP)	+= ocotp.o
diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index e84713766..174eff037 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -120,7 +120,7 @@ static int imx_init(void)
 	else if (cpu_is_mx7())
 		ret = imx7_init();
 	else if (cpu_is_vf610())
-		ret = 0;
+		ret = vf610_init();
 	else
 		return -EINVAL;
 
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index f68dc875b..cb5675185 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -34,6 +34,7 @@ int imx51_init(void);
 int imx53_init(void);
 int imx6_init(void);
 int imx7_init(void);
+int vf610_init(void);
 
 int imx1_devices_init(void);
 int imx21_devices_init(void);
diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
new file mode 100644
index 000000000..0ef3e43af
--- /dev/null
+++ b/arch/arm/mach-imx/vf610.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <init.h>
+#include <common.h>
+#include <io.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <mach/revision.h>
+#include <mach/reset-reason.h>
+#include <mach/vf610.h>
+
+int vf610_init(void)
+{
+	const char *cputypestr;
+	void __iomem *src = IOMEM(VF610_SRC_BASE_ADDR);
+
+	switch (vf610_cpu_type()) {
+	case VF610_CPUTYPE_VF610:
+		cputypestr = "VF610";
+		break;
+	case VF610_CPUTYPE_VF600:
+		cputypestr = "VF600";
+		break;
+	case VF610_CPUTYPE_VF510:
+		cputypestr = "VF510";
+		break;
+	case VF610_CPUTYPE_VF500:
+		cputypestr = "VF500";
+		break;
+	default:
+		cputypestr = "unknown VFxxx";
+		break;
+	}
+
+	imx_set_silicon_revision(cputypestr, vf610_cpu_revision());
+	imx_set_reset_reason(src + VF610_SRC_SRSR);
+
+	return 0;
+}
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:46 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:46 -0700
Subject: [PATCH 00/17] i.MX bootsource bugfixes, refactoring and VFxxx support
Message-ID: <20180414175103.10125-1-andrew.smirnov@gmail.com>

Everyone:

This patchset is the result of my work on adding support for
bootsource detection of VFxxx as well as fixing a number of
bugs/unsupported corner cases in similar i.MX7 specific code.

NOTE: While VFxxx support is added in this series the code integrating
it into the SoC initalization sequnce is not included. Patch for that
is dependent on recently submitted "i.MX reset reason detection
support" and I didn't want to intertwine two otherwise independent
submissions.

Feedback is wellcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (17):
  ARM: i.MX: boot: Coalesce copy-pasted code
  ARM: i.MX: Add function to extract BMOD value
  ARM: i.MX: Simplify serial bootsource detection for i.MX6 and 7
  ARM: i.MX: Account for unprogrammed fuses on i.MX6 and i.MX7
  ARM: i.MX7: boot: Add code to handle SD/MMC manufacture mode
  ARM: i.MX7: boot: Remove incorrect NAND bootsource detection
  ARM: i.MX7: boot: Fix SPI-NOR/QSPI boot source mixup
  ARM: i.MX: boot: Remove unnecessary retruns
  ARM: i.MX: boot: Move magic values into small functions
  ARM: i.MX: boot: Share code to detect NAND as a boot source
  ARM: i.MX: boot: Check for NAND boot only if necessary on i.MX53, 6
  ARM: i.MX53: boot: Move magic numbers info utility functions
  ARM: i.MX6: boot: Move magic numbers into utility functions
  ARM: i.MX7: boot: Move magic numbers into utility functions
  bootsource: Add BOOTSOURCE_CAN
  ARM: VFxxx: Implement code to detect bootsource
  ARM: i.MX6: boot: Return BOOTSOURCE_SPI_NOR, not BOOTSOURCE_SPI

 arch/arm/boards/datamodul-edm-qmx6/board.c |   2 +-
 arch/arm/boards/dfi-fs700-m60/board.c      |   2 +-
 arch/arm/boards/phytec-som-imx6/board.c    |   2 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c  |   2 +-
 arch/arm/mach-imx/boot.c                   | 411 ++++++++++++++++++++---------
 arch/arm/mach-imx/include/mach/generic.h   |   2 +
 arch/arm/mach-imx/xload.c                  |   2 +-
 common/bootsource.c                        |   1 +
 include/bootsource.h                       |   1 +
 9 files changed, 289 insertions(+), 136 deletions(-)

-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:54 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:54 -0700
Subject: [PATCH 08/17] ARM: i.MX: boot: Remove unnecessary retruns
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-9-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 42ea2ccd6..cc54ea15a 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -299,8 +299,6 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 	/* BOOT_CFG1[7:0] */
 	if (sbmr1 & (1 << 7))
 		*src = BOOTSOURCE_NAND;
-
-	return;
 }
 
 #define IMX7_SRC_SBMR1	0x58
@@ -382,8 +380,6 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	default:
 		break;
 	}
-
-	return;
 }
 
 static void
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:47 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:47 -0700
Subject: [PATCH 01/17] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-2-andrew.smirnov@gmail.com>

All of the instances of imx*_boot_save_loc() do exactly the same thing with
the only difference being SoC-specific imx*_get_boot_source
call. Convert the code into a generic function taking function pointer
+ a macro to take care of the boilerplate.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 85 ++++++++++--------------------------------------
 1 file changed, 17 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 72597f5e2..4657fa017 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -89,17 +89,6 @@ void imx25_get_boot_source(enum bootsource *src, int *instance)
 				    (val >> MX25_CCM_RCSR_MEM_TYPE_SHIFT) & 0x3);
 }
 
-void imx25_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx25_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 void imx35_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *ccm_base = IOMEM(MX35_CCM_BASE_ADDR);
@@ -110,17 +99,6 @@ void imx35_get_boot_source(enum bootsource *src, int *instance)
 				    (val >> MX35_CCM_RCSR_MEM_TYPE_SHIFT) & 0x3);
 }
 
-void imx35_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx35_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX27_SYSCTRL_GPCR	0x18
 #define IMX27_GPCR_BOOT_SHIFT			16
 #define IMX27_GPCR_BOOT_MASK			(0xf << IMX27_GPCR_BOOT_SHIFT)
@@ -157,17 +135,6 @@ void imx27_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
-void imx27_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx27_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX51_SRC_SBMR			0x4
 #define IMX51_SBMR_BT_MEM_TYPE_SHIFT	7
 #define IMX51_SBMR_BT_MEM_CTL_SHIFT	0
@@ -201,17 +168,6 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
-void imx51_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx51_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX53_SRC_SBMR	0x4
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
@@ -260,17 +216,6 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
-void imx53_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx53_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX6_SRC_SBMR1	0x04
 #define IMX6_SRC_SBMR2	0x1c
 
@@ -337,17 +282,6 @@ internal_boot:
 	return;
 }
 
-void imx6_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx6_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX7_SRC_SBMR1	0x58
 #define IMX7_SRC_SBMR2	0x70
 
@@ -406,13 +340,28 @@ internal_boot:
 	return;
 }
 
-void imx7_boot_save_loc(void)
+static void
+imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
 {
 	enum bootsource src = BOOTSOURCE_UNKNOWN;
 	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
 
-	imx7_get_boot_source(&src, &instance);
+	get_boot_source(&src, &instance);
 
 	bootsource_set(src);
 	bootsource_set_instance(instance);
 }
+
+#define IMX_BOOT_SAVE_LOC(soc)					\
+	void soc##_boot_save_loc(void)				\
+	{							\
+		imx_boot_save_loc(soc##_get_boot_source);	\
+	}
+
+IMX_BOOT_SAVE_LOC(imx25)
+IMX_BOOT_SAVE_LOC(imx27)
+IMX_BOOT_SAVE_LOC(imx35)
+IMX_BOOT_SAVE_LOC(imx51)
+IMX_BOOT_SAVE_LOC(imx53)
+IMX_BOOT_SAVE_LOC(imx6)
+IMX_BOOT_SAVE_LOC(imx7)
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:51 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:51 -0700
Subject: [PATCH 05/17] ARM: i.MX7: boot: Add code to handle SD/MMC manufacture
 mode
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-6-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index a98c716fb..4082f46ae 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -306,6 +306,19 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 #define IMX7_SRC_SBMR1	0x58
 #define IMX7_SRC_SBMR2	0x70
 
+#define IMX_BOOT_SW_INFO_POINTER_ADDR	0x000001E8
+#define IMX_BOOT_SW_INFO_BDT_SD		0x1
+
+struct imx_boot_sw_info {
+	uint8_t  reserved_1;
+	uint8_t  boot_device_instance;
+	uint8_t  boot_device_type;
+	uint8_t  reserved_2;
+	uint32_t frequency_hz[4]; /* Various frequencies (ARM, AXI,
+				   * DDR, etc.). Not used */
+	uint32_t reserved_3[3];
+} __packed;
+
 void imx7_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR);
@@ -316,6 +329,33 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 		return;
 
 	if (imx6_bootsource_serial(sbmr2)) {
+		/*
+		 * On i.MX7 ROM code will try to bood from uSDHC1
+		 * before entering serial mode. It doesn't seem to be
+		 * reflected in the contents of SBMR1 in any way when
+		 * that happens, so we check "Boot_SW_Info" structure
+		 * (per 6.6.14 Boot information for software) to see
+		 * if that really happened.
+		 *
+		 * FIXME: This behaviour can be inhibited by
+		 * DISABLE_SDMMC_MFG, but location of that fuse
+		 * doesn't seem to be documented anywhere. Once that
+		 * is known it should be taken into account here.
+		 */
+		const struct imx_boot_sw_info *info;
+
+		info = (const void *)readl(IMX_BOOT_SW_INFO_POINTER_ADDR);
+
+		if (info->boot_device_type == IMX_BOOT_SW_INFO_BDT_SD) {
+			*src = BOOTSOURCE_MMC;
+			/*
+			 * We are expecting to only ever boot from
+			 * uSDHC1 here
+			 */
+			WARN_ON(*instance = info->boot_device_instance);
+			return;
+		}
+
 		*src = BOOTSOURCE_SERIAL;
 		return;
 	}
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:48 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:48 -0700
Subject: [PATCH 02/17] ARM: i.MX: Add function to extract BMOD value
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-3-andrew.smirnov@gmail.com>

The location of BMDO field in SBMR/SBMR2 registers is consistent
across all i.MX SoCs starting from i.MX53. Add simple helper function
imx53_get_bmod and use it to avoid code duplication.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 4657fa017..56f9fb5d4 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -169,12 +169,23 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 }
 
 #define IMX53_SRC_SBMR	0x4
+
+static unsigned int sbmr(uint32_t r, unsigned int msb, unsigned int lsb)
+{
+	return (r & GENMASK(msb, lsb)) >> lsb;
+}
+
+static unsigned int imx53_get_bmod(uint32_t r)
+{
+	return sbmr(r, 25, 24);
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
 	uint32_t cfg1 = readl(src_base + IMX53_SRC_SBMR);
 
-	if (((cfg1 >> 24) & 0x3) == 0x3) {
+	if (imx53_get_bmod(cfg1) == 0x3) {
 		*src = BOOTSOURCE_USB;
 		*instance = 0;
 		return;
@@ -225,12 +236,8 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
 	uint32_t boot_cfg_4_2_0;
-	int boot_mode;
 
-	/* BMOD[1:0] */
-	boot_mode = (sbmr2 >> 24) & 0x3;
-
-	switch (boot_mode) {
+	switch (imx53_get_bmod(sbmr2)) {
 	case 0: /* Fuses, fall through */
 	case 2: /* internal boot */
 		goto internal_boot;
@@ -290,12 +297,8 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR);
 	uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2);
-	int boot_mode;
-
-	/* BMOD[1:0] */
-	boot_mode = (sbmr2 >> 24) & 0x3;
 
-	switch (boot_mode) {
+	switch (imx53_get_bmod(sbmr2)) {
 	case 0: /* Fuses, fall through */
 	case 2: /* internal boot */
 		goto internal_boot;
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:57 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:57 -0700
Subject: [PATCH 11/17] ARM: i.MX: boot: Check for NAND boot only if necessary
 on i.MX53, 6
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-12-andrew.smirnov@gmail.com>

We don't need to check if the boot source is NAND in cases when we
already know for a fact that we booted from something else. To avoid
that, move the NAND check to be done inside of default branch of
the preceeding switch statement.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index c092dc827..8fbccb260 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -220,13 +220,11 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		*src = BOOTSOURCE_MMC;
 		break;
 	default:
+		if (imx53_bootsource_nand(cfg1))
+			*src = BOOTSOURCE_NAND;
 		break;
 	}
 
-	if (imx53_bootsource_nand(cfg1))
-		*src = BOOTSOURCE_NAND;
-
-
 	switch (*src) {
 	case BOOTSOURCE_MMC:
 	case BOOTSOURCE_SPI:
@@ -304,11 +302,10 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		*instance = (sbmr1 >> 11) & 0x3;
 		break;
 	default:
+		if (imx53_bootsource_nand(sbmr1))
+			*src = BOOTSOURCE_NAND;
 		break;
 	}
-
-	if (imx53_bootsource_nand(sbmr1))
-		*src = BOOTSOURCE_NAND;
 }
 
 #define IMX7_SRC_SBMR1	0x58
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:49 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:49 -0700
Subject: [PATCH 03/17] ARM: i.MX: Simplify serial bootsource detection for
 i.MX6 and 7
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-4-andrew.smirnov@gmail.com>

The algorithm to detect serial mode can be shared between i.M6 and
i.MX7 as wall as simplified a bit by replacing swich goto/break/return
termination logic with more trivial if statements.

This commit also sets the stage for additional improvements in the
commits that follow.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 50 +++++++++++++++++++++++-------------------------
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 56f9fb5d4..7eb7a16f3 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -229,6 +229,18 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 
 #define IMX6_SRC_SBMR1	0x04
 #define IMX6_SRC_SBMR2	0x1c
+#define IMX6_BMOD_SERIAL	0b01
+#define IMX6_BMOD_RESERVED	0b11
+
+static bool imx6_bootsource_reserved(uint32_t sbmr2)
+{
+	return imx53_get_bmod(sbmr2) == IMX6_BMOD_RESERVED;
+}
+
+static bool imx6_bootsource_serial(uint32_t sbmr2)
+{
+	return imx53_get_bmod(sbmr2) == IMX6_BMOD_SERIAL;
+}
 
 void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
@@ -237,20 +249,13 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
 	uint32_t boot_cfg_4_2_0;
 
-	switch (imx53_get_bmod(sbmr2)) {
-	case 0: /* Fuses, fall through */
-	case 2: /* internal boot */
-		goto internal_boot;
-	case 1: /* Serial Downloader */
-		*src = BOOTSOURCE_SERIAL;
-		break;
-	case 3: /* reserved */
-		break;
-	};
-
-	return;
+	if (imx6_bootsource_reserved(sbmr2))
+		return;
 
-internal_boot:
+	if (imx6_bootsource_serial(sbmr2)) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
 
 	/* BOOT_CFG1[7:4] */
 	switch ((sbmr1 >> 4) & 0xf) {
@@ -298,20 +303,13 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2);
 
-	switch (imx53_get_bmod(sbmr2)) {
-	case 0: /* Fuses, fall through */
-	case 2: /* internal boot */
-		goto internal_boot;
-	case 1: /* Serial Downloader */
-		*src = BOOTSOURCE_SERIAL;
-		break;
-	case 3: /* reserved */
-		break;
-	};
-
-	return;
+	if (imx6_bootsource_reserved(sbmr2))
+		return;
 
-internal_boot:
+	if (imx6_bootsource_serial(sbmr2)) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
 
 	switch ((sbmr1 >> 12) & 0xf) {
 	case 1:
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:50 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:50 -0700
Subject: [PATCH 04/17] ARM: i.MX: Account for unprogrammed fuses on i.MX6 and
 i.MX7
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-5-andrew.smirnov@gmail.com>

On both i.MX6 and i.MX7 (also true for VFxxx) there's an additional
path that leads mask ROM to switch into serial bootloader mode. Add
code to support it.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 7eb7a16f3..a98c716fb 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -231,6 +231,8 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 #define IMX6_SRC_SBMR2	0x1c
 #define IMX6_BMOD_SERIAL	0b01
 #define IMX6_BMOD_RESERVED	0b11
+#define IMX6_BMOD_FUSES		0b00
+#define BT_FUSE_SEL		BIT(4)
 
 static bool imx6_bootsource_reserved(uint32_t sbmr2)
 {
@@ -239,7 +241,14 @@ static bool imx6_bootsource_reserved(uint32_t sbmr2)
 
 static bool imx6_bootsource_serial(uint32_t sbmr2)
 {
-	return imx53_get_bmod(sbmr2) == IMX6_BMOD_SERIAL;
+	return imx53_get_bmod(sbmr2) == IMX6_BMOD_SERIAL ||
+		/*
+		 * If boot from fuses is selected and fuses are not
+		 * programmed by setting BT_FUSE_SEL, ROM code will
+		 * fallback to serial mode
+		 */
+	       (imx53_get_bmod(sbmr2) == IMX6_BMOD_FUSES &&
+		!(sbmr2 & BT_FUSE_SEL));
 }
 
 void imx6_get_boot_source(enum bootsource *src, int *instance)
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:58 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:58 -0700
Subject: [PATCH 12/17] ARM: i.MX53: boot: Move magic numbers info utility
 functions
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-13-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 8fbccb260..3cd79acfc 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -169,6 +169,7 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 }
 
 #define IMX53_SRC_SBMR	0x4
+#define IMX53_BMOD_SERIAL	0b11
 
 static unsigned int sbmr(uint32_t r, unsigned int msb, unsigned int lsb)
 {
@@ -187,17 +188,27 @@ static int imx53_bootsource_internal(uint32_t r)
 	return sbmr(r, 7, 4);	/* BOOT_CFG1[7:4] */
 }
 
+static int imx53_port_select(uint32_t r)
+{
+	return sbmr(r, 21, 20);	/* BOOT_CFG3[5:4] */
+}
+
 static bool imx53_bootsource_nand(uint32_t r)
 {
 	return BOOT_CFG1(r, 7);
 }
 
+static enum bootsource imx53_bootsource_serial_rom(uint32_t r)
+{
+	return BOOT_CFG1(r, 3) ? BOOTSOURCE_SPI : BOOTSOURCE_I2C;
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
 	uint32_t cfg1 = readl(src_base + IMX53_SRC_SBMR);
 
-	if (imx53_get_bmod(cfg1) == 0x3) {
+	if (imx53_get_bmod(cfg1) == IMX53_BMOD_SERIAL) {
 		*src = BOOTSOURCE_USB;
 		*instance = 0;
 		return;
@@ -208,10 +219,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		*src = BOOTSOURCE_HD;
 		break;
 	case 3:
-		if (cfg1 & (1 << 3))
-			*src = BOOTSOURCE_SPI;
-		else
-			*src = BOOTSOURCE_I2C;
+		*src = imx53_bootsource_serial_rom(cfg1);
 		break;
 	case 4:
 	case 5:
@@ -229,7 +237,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 	case BOOTSOURCE_MMC:
 	case BOOTSOURCE_SPI:
 	case BOOTSOURCE_I2C:
-		*instance = (cfg1 >> 20) & 0x3;
+		*instance = imx53_port_select(cfg1);
 		break;
 	default:
 		*instance = 0;
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:55 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:55 -0700
Subject: [PATCH 09/17] ARM: i.MX: boot: Move magic values into small functions
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-10-andrew.smirnov@gmail.com>

Move code to extract appropiate BOOT_CFG bits to decode booutsource on
i.MX53, 6, and 7 into small functions for clarity and to allow sharing
the code between i.MX53 and i.MX6.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index cc54ea15a..66e1a9254 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -180,6 +180,11 @@ static unsigned int imx53_get_bmod(uint32_t r)
 	return sbmr(r, 25, 24);
 }
 
+static int imx53_bootsource_internal(uint32_t r)
+{
+	return sbmr(r, 7, 4);	/* BOOT_CFG1[7:4] */
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
@@ -191,7 +196,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		return;
 	}
 
-	switch ((cfg1 & 0xff) >> 4) {
+	switch (imx53_bootsource_internal(cfg1)) {
 	case 2:
 		*src = BOOTSOURCE_HD;
 		break;
@@ -266,8 +271,7 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		return;
 	}
 
-	/* BOOT_CFG1[7:4] */
-	switch ((sbmr1 >> 4) & 0xf) {
+	switch (imx53_bootsource_internal(sbmr1)) {
 	case 2:
 		*src = BOOTSOURCE_HD;
 		break;
@@ -307,6 +311,11 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 #define IMX_BOOT_SW_INFO_POINTER_ADDR	0x000001E8
 #define IMX_BOOT_SW_INFO_BDT_SD		0x1
 
+static unsigned int imx7_bootsource_internal(uint32_t r)
+{
+	return sbmr(r, 15, 12);	/* BOOT_CFG[15:12] */
+}
+
 struct imx_boot_sw_info {
 	uint8_t  reserved_1;
 	uint8_t  boot_device_instance;
@@ -358,7 +367,7 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 		return;
 	}
 
-	switch ((sbmr1 >> 12) & 0xf) {
+	switch (imx7_bootsource_internal(sbmr1)) {
 	case 1:
 	case 2:
 		*src = BOOTSOURCE_MMC;
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:52 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:52 -0700
Subject: [PATCH 06/17] ARM: i.MX7: boot: Remove incorrect NAND bootsource
 detection
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-7-andrew.smirnov@gmail.com>

i.MX7 differs from i.MX6 and i.MX53 and bit 7 in SBMR is not used to
signify boot from NAND.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 4082f46ae..1c5a47f37 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -383,10 +383,6 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 		break;
 	}
 
-	/* BOOT_CFG1[7:0] */
-	if (sbmr1 & (1 << 7))
-		*src = BOOTSOURCE_NAND;
-
 	return;
 }
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:56 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:56 -0700
Subject: [PATCH 10/17] ARM: i.MX: boot: Share code to detect NAND as a boot
 source
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-11-andrew.smirnov@gmail.com>

Share code to detect NAND as a boot source between i.MX53 and i.MX6
which behave the same in that aspect.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 66e1a9254..c092dc827 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -175,6 +175,8 @@ static unsigned int sbmr(uint32_t r, unsigned int msb, unsigned int lsb)
 	return (r & GENMASK(msb, lsb)) >> lsb;
 }
 
+#define BOOT_CFG1(r, n)	sbmr(r, n, n)
+
 static unsigned int imx53_get_bmod(uint32_t r)
 {
 	return sbmr(r, 25, 24);
@@ -185,6 +187,11 @@ static int imx53_bootsource_internal(uint32_t r)
 	return sbmr(r, 7, 4);	/* BOOT_CFG1[7:4] */
 }
 
+static bool imx53_bootsource_nand(uint32_t r)
+{
+	return BOOT_CFG1(r, 7);
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
@@ -216,7 +223,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		break;
 	}
 
-	if (cfg1 & (1 << 7))
+	if (imx53_bootsource_nand(cfg1))
 		*src = BOOTSOURCE_NAND;
 
 
@@ -300,8 +307,7 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		break;
 	}
 
-	/* BOOT_CFG1[7:0] */
-	if (sbmr1 & (1 << 7))
+	if (imx53_bootsource_nand(sbmr1))
 		*src = BOOTSOURCE_NAND;
 }
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:53 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:53 -0700
Subject: [PATCH 07/17] ARM: i.MX7: boot: Fix SPI-NOR/QSPI boot source mixup
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-8-andrew.smirnov@gmail.com>

As per "Table 6-33. Boot device selection" from "i.MX 7Dual
Applications Processor Reference Manual, Rev. 1, 01/2018" QSPI is
encoded with 0b0100 and Serial ROM with 0b0110. Fix the original code
to use correct values.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 1c5a47f37..42ea2ccd6 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -369,11 +369,11 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	case 3:
 		*src = BOOTSOURCE_NAND;
 		break;
-	case 4:
+	case 6:
 		*src = BOOTSOURCE_SPI_NOR,
 		*instance = (sbmr1 >> 9 & 0x7);
 		break;
-	case 6:
+	case 4:
 		*src = BOOTSOURCE_SPI; /* Really: qspi */
 		break;
 	case 5:
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:50:59 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:50:59 -0700
Subject: [PATCH 13/17] ARM: i.MX6: boot: Move magic numbers into utility
 functions
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-14-andrew.smirnov@gmail.com>

Move magic numbers and algorithm for determining Serial ROM bootsource
and boot instance into utility functions. Add a comment on the logic
behing the latter while at it.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 63 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 49 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 3cd79acfc..cdfe3749d 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -269,12 +269,57 @@ static bool imx6_bootsource_serial(uint32_t sbmr2)
 		!(sbmr2 & BT_FUSE_SEL));
 }
 
+static int __imx6_bootsource_serial_rom(uint32_t r)
+{
+	return sbmr(r, 26, 24);	/* BOOT_CFG4[2:0] */
+}
+
+/*
+ * Serial ROM bootsource on i.MX6 are as follows:
+ *
+ *	000 - ECSPI-1
+ *	001 - ECSPI-2
+ *	010 - ECSPI-3
+ *	011 - ECSPI-4
+ *	100 - ECSPI-5
+ *	101 - I2C1
+ *	110 - I2C2
+ *	111 - I2C3
+ *
+ * There's no single bit that would tell us we are booting from I2C or
+ * SPI, so we just have to compare the "source" agains the value for
+ * I2C1 for both: calculating bootsource and boot instance.
+ */
+#define IMX6_BOOTSOURCE_SERIAL_ROM_I2C1	0b101
+
+static enum bootsource imx6_bootsource_serial_rom(uint32_t sbmr)
+{
+	const int source = __imx6_bootsource_serial_rom(sbmr);
+
+	return source < IMX6_BOOTSOURCE_SERIAL_ROM_I2C1 ?
+		BOOTSOURCE_SPI : BOOTSOURCE_I2C;
+}
+
+static int imx6_boot_instance_serial_rom(uint32_t sbmr)
+{
+	const int source = __imx6_bootsource_serial_rom(sbmr);
+
+	if (source < IMX6_BOOTSOURCE_SERIAL_ROM_I2C1)
+		return source;
+
+	return source - IMX6_BOOTSOURCE_SERIAL_ROM_I2C1;
+}
+
+static int imx6_boot_instance_mmc(uint32_t r)
+{
+	return sbmr(r, 13, 11);	/* BOOT_CFG2[4:3] */
+}
+
 void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
 	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
-	uint32_t boot_cfg_4_2_0;
 
 	if (imx6_bootsource_reserved(sbmr2))
 		return;
@@ -289,25 +334,15 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		*src = BOOTSOURCE_HD;
 		break;
 	case 3:
-		/* BOOT_CFG4[2:0] */
-		boot_cfg_4_2_0 = (sbmr1 >> 24) & 0x7;
-
-		if (boot_cfg_4_2_0 > 4) {
-			*src = BOOTSOURCE_I2C;
-			*instance = boot_cfg_4_2_0 - 5;
-		} else {
-			*src = BOOTSOURCE_SPI;
-			*instance = boot_cfg_4_2_0;
-		}
+		*src = imx6_bootsource_serial_rom(sbmr1);
+		*instance = imx6_boot_instance_serial_rom(sbmr1);
 		break;
 	case 4:
 	case 5:
 	case 6:
 	case 7:
 		*src = BOOTSOURCE_MMC;
-
-		/* BOOT_CFG2[4:3] */
-		*instance = (sbmr1 >> 11) & 0x3;
+		*instance = imx6_boot_instance_mmc(sbmr1);
 		break;
 	default:
 		if (imx53_bootsource_nand(sbmr1))
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:51:01 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:51:01 -0700
Subject: [PATCH 15/17] bootsource: Add BOOTSOURCE_CAN
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-16-andrew.smirnov@gmail.com>

Add BOOTSOURCE_CAN for SoCs that can boot from CAN interface.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/bootsource.c  | 1 +
 include/bootsource.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/common/bootsource.c b/common/bootsource.c
index 707b07924..78ecd8267 100644
--- a/common/bootsource.c
+++ b/common/bootsource.c
@@ -36,6 +36,7 @@ static const char *bootsource_str[] = {
 	[BOOTSOURCE_HD] = "harddisk",
 	[BOOTSOURCE_USB] = "usb",
 	[BOOTSOURCE_NET] = "net",
+	[BOOTSOURCE_CAN] = "can",
 };
 
 static enum bootsource bootsource = BOOTSOURCE_UNKNOWN;
diff --git a/include/bootsource.h b/include/bootsource.h
index c6d3b3a98..064f6b9a2 100644
--- a/include/bootsource.h
+++ b/include/bootsource.h
@@ -16,6 +16,7 @@ enum bootsource {
 	BOOTSOURCE_HD,
 	BOOTSOURCE_USB,
 	BOOTSOURCE_NET,
+	BOOTSOURCE_CAN,
 };
 
 #define BOOTSOURCE_INSTANCE_UNKNOWN	-1
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:51:00 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:51:00 -0700
Subject: [PATCH 14/17] ARM: i.MX7: boot: Move magic numbers into utility
 functions
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-15-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index cdfe3749d..0398804b0 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -362,6 +362,16 @@ static unsigned int imx7_bootsource_internal(uint32_t r)
 	return sbmr(r, 15, 12);	/* BOOT_CFG[15:12] */
 }
 
+static int imx7_boot_instance_spi_nor(uint32_t r)
+{
+	return sbmr(r, 11, 9);	/* BOOT_CFG[11:9] */
+}
+
+static int imx7_boot_instance_mmc(uint32_t r)
+{
+	return sbmr(r, 11, 10);	/* BOOT_CFG[11:10] */
+}
+
 struct imx_boot_sw_info {
 	uint8_t  reserved_1;
 	uint8_t  boot_device_instance;
@@ -417,14 +427,14 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	case 1:
 	case 2:
 		*src = BOOTSOURCE_MMC;
-		*instance = (sbmr1 >> 10 & 0x3);
+		*instance = imx7_boot_instance_mmc(sbmr1);
 		break;
 	case 3:
 		*src = BOOTSOURCE_NAND;
 		break;
 	case 6:
 		*src = BOOTSOURCE_SPI_NOR,
-		*instance = (sbmr1 >> 9 & 0x7);
+		*instance = imx7_boot_instance_spi_nor(sbmr1);
 		break;
 	case 4:
 		*src = BOOTSOURCE_SPI; /* Really: qspi */
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:51:02 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:51:02 -0700
Subject: [PATCH 16/17] ARM: VFxxx: Implement code to detect bootsource
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-17-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c                 | 93 ++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/generic.h |  2 +
 2 files changed, 95 insertions(+)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 0398804b0..24e2501e9 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -26,6 +26,7 @@
 #include <mach/imx53-regs.h>
 #include <mach/imx6-regs.h>
 #include <mach/imx7-regs.h>
+#include <mach/vf610-regs.h>
 
 /* [CTRL][TYPE] */
 static const enum bootsource locations[4][4] = {
@@ -177,6 +178,8 @@ static unsigned int sbmr(uint32_t r, unsigned int msb, unsigned int lsb)
 }
 
 #define BOOT_CFG1(r, n)	sbmr(r, n, n)
+#define BOOT_CFG2(r, n)	BOOT_CFG1(r, (n) + 8)
+#define BOOT_CFG4(r, n)	BOOT_CFG1(r, (n) + 24)
 
 static unsigned int imx53_get_bmod(uint32_t r)
 {
@@ -447,6 +450,95 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
+static int vf610_boot_instance_spi(uint32_t r)
+{
+	return BOOT_CFG1(r, 1);
+}
+
+static int vf610_boot_instance_nor(uint32_t r)
+{
+	return BOOT_CFG1(r, 3);
+}
+
+/*
+ * Vybrid's Serial ROM boot sources (BOOT_CFG4[2:0]) are as follows:
+ *
+ *	000 - SPI0
+ *	001 - SPI1
+ *	010 - SPI2
+ *	011 - SPI3
+ *	100 - I2C0
+ *	101 - I2C1
+ *	110 - I2C2
+ *	111 - I2C3
+ *
+ * Which we can neatly divide in two halves and use MSb to detect if
+ * bootsource is I2C or SPI EEPROM and 2 LSbs directly as boot
+ * insance.
+ */
+static enum bootsource vf610_bootsource_serial_rom(uint32_t r)
+{
+	return BOOT_CFG4(r, 2) ? BOOTSOURCE_I2C : BOOTSOURCE_SPI_NOR;
+}
+
+static int vf610_boot_instance_serial_rom(uint32_t r)
+{
+	return __imx6_bootsource_serial_rom(r) & 0b11;
+}
+
+static int vf610_boot_instance_can(uint32_t r)
+{
+	return BOOT_CFG1(r, 0);
+}
+
+static int vf610_boot_instance_mmc(uint32_t r)
+{
+	return BOOT_CFG2(r, 3);
+}
+
+void vf610_get_boot_source(enum bootsource *src, int *instance)
+{
+	void __iomem *src_base = IOMEM(VF610_SRC_BASE_ADDR);
+	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
+	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
+
+	if (imx6_bootsource_reserved(sbmr2))
+		return;
+
+	if (imx6_bootsource_serial(sbmr2)) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
+
+	switch (imx53_bootsource_internal(sbmr1)) {
+	case 0:
+		*src = BOOTSOURCE_SPI; /* Really: qspi */
+		*instance = vf610_boot_instance_spi(sbmr1);
+		break;
+	case 1:
+		*src = BOOTSOURCE_NOR;
+		*instance = vf610_boot_instance_nor(sbmr1);
+		break;
+	case 2:
+		*src = vf610_bootsource_serial_rom(sbmr1);
+		*instance = vf610_boot_instance_serial_rom(sbmr1);
+		break;
+	case 3:
+		*src = BOOTSOURCE_CAN;
+		*instance = vf610_boot_instance_can(sbmr1);
+		break;
+	case 6:
+	case 7:
+		*src = BOOTSOURCE_MMC;
+		*instance = vf610_boot_instance_mmc(sbmr1);
+		break;
+	default:
+		if (imx53_bootsource_nand(sbmr1))
+			*src = BOOTSOURCE_NAND;
+		break;
+	}
+}
+
 static void
 imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
 {
@@ -472,3 +564,4 @@ IMX_BOOT_SAVE_LOC(imx51)
 IMX_BOOT_SAVE_LOC(imx53)
 IMX_BOOT_SAVE_LOC(imx6)
 IMX_BOOT_SAVE_LOC(imx7)
+IMX_BOOT_SAVE_LOC(vf610)
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index cb5675185..ad9d9cb02 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -15,6 +15,7 @@ void imx51_boot_save_loc(void);
 void imx53_boot_save_loc(void);
 void imx6_boot_save_loc(void);
 void imx7_boot_save_loc(void);
+void vf610_boot_save_loc(void);
 
 void imx25_get_boot_source(enum bootsource *src, int *instance);
 void imx35_get_boot_source(enum bootsource *src, int *instance);
@@ -22,6 +23,7 @@ void imx51_get_boot_source(enum bootsource *src, int *instance);
 void imx53_get_boot_source(enum bootsource *src, int *instance);
 void imx6_get_boot_source(enum bootsource *src, int *instance);
 void imx7_get_boot_source(enum bootsource *src, int *instance);
+void vf610_get_boot_source(enum bootsource *src, int *instance);
 
 int imx1_init(void);
 int imx21_init(void);
-- 
2.14.3



From andrew.smirnov at gmail.com  Sat Apr 14 10:51:03 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Sat, 14 Apr 2018 10:51:03 -0700
Subject: [PATCH 17/17] ARM: i.MX6: boot: Return BOOTSOURCE_SPI_NOR,
 not BOOTSOURCE_SPI
In-Reply-To: <20180414175103.10125-1-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
Message-ID: <20180414175103.10125-18-andrew.smirnov@gmail.com>

We use BOOTSOURCE_SPI to denote, among other things, QSPI on i.MX7 and
VFxxx, whereas on i.MX6 it is used to mean SPI-NOR. To make functions
like imx_xload() work consistently across various i.MX platforms use
already existent BOOTSOURCE_SPI_NOR constant to mean booting from
SPI-NOR on i.MX6 as well.

Replace all in-tree code that relying on the old value as well.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/datamodul-edm-qmx6/board.c | 2 +-
 arch/arm/boards/dfi-fs700-m60/board.c      | 2 +-
 arch/arm/boards/phytec-som-imx6/board.c    | 2 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c  | 2 +-
 arch/arm/mach-imx/boot.c                   | 2 +-
 arch/arm/mach-imx/xload.c                  | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boards/datamodul-edm-qmx6/board.c b/arch/arm/boards/datamodul-edm-qmx6/board.c
index 043a93461..d93c940e3 100644
--- a/arch/arm/boards/datamodul-edm-qmx6/board.c
+++ b/arch/arm/boards/datamodul-edm-qmx6/board.c
@@ -132,7 +132,7 @@ static int realq7_device_init(void)
 		}
 		break;
 	default:
-	case BOOTSOURCE_SPI:
+	case BOOTSOURCE_SPI_NOR:
 		of_device_enable_path("/chosen/environment-spi");
 		break;
 	}
diff --git a/arch/arm/boards/dfi-fs700-m60/board.c b/arch/arm/boards/dfi-fs700-m60/board.c
index bef4612d9..2cb8e3106 100644
--- a/arch/arm/boards/dfi-fs700-m60/board.c
+++ b/arch/arm/boards/dfi-fs700-m60/board.c
@@ -105,7 +105,7 @@ static int dfi_fs700_m60_init(void)
 
 	phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, ar8031_phy_fixup);
 
-	if (bootsource_get() == BOOTSOURCE_SPI)
+	if (bootsource_get() == BOOTSOURCE_SPI_NOR)
 		flag_spi |= BBU_HANDLER_FLAG_DEFAULT;
 	else
 		flag_mmc |= BBU_HANDLER_FLAG_DEFAULT;
diff --git a/arch/arm/boards/phytec-som-imx6/board.c b/arch/arm/boards/phytec-som-imx6/board.c
index 717a22963..ecb22f956 100644
--- a/arch/arm/boards/phytec-som-imx6/board.c
+++ b/arch/arm/boards/phytec-som-imx6/board.c
@@ -152,7 +152,7 @@ static int physom_imx6_devices_init(void)
 		environment_path = basprintf("/chosen/environment-nand");
 		envdev = "NAND flash";
 		break;
-	case BOOTSOURCE_SPI:
+	case BOOTSOURCE_SPI_NOR:
 		environment_path = basprintf("/chosen/environment-spinor");
 		envdev = "SPI NOR flash";
 		break;
diff --git a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
index 22ffdf85e..3b4dbd212 100644
--- a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
+++ b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
@@ -290,7 +290,7 @@ static noinline void rdu2_sram_setup(void)
 		write_regs(imx6q_dcd, ARRAY_SIZE(imx6q_dcd));
 
 	imx6_get_boot_source(&bootsrc, &instance);
-	if (bootsrc == BOOTSOURCE_SPI)
+	if (bootsrc == BOOTSOURCE_SPI_NOR)
 		imx6_spi_start_image(0);
 	else
 		imx6_esdhc_start_image(instance);
diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 24e2501e9..bd2af2ef4 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -300,7 +300,7 @@ static enum bootsource imx6_bootsource_serial_rom(uint32_t sbmr)
 	const int source = __imx6_bootsource_serial_rom(sbmr);
 
 	return source < IMX6_BOOTSOURCE_SERIAL_ROM_I2C1 ?
-		BOOTSOURCE_SPI : BOOTSOURCE_I2C;
+		BOOTSOURCE_SPI_NOR : BOOTSOURCE_I2C;
 }
 
 static int imx6_boot_instance_serial_rom(uint32_t sbmr)
diff --git a/arch/arm/mach-imx/xload.c b/arch/arm/mach-imx/xload.c
index 16d56ab28..921e9ade2 100644
--- a/arch/arm/mach-imx/xload.c
+++ b/arch/arm/mach-imx/xload.c
@@ -24,7 +24,7 @@ static __noreturn int imx_xload(void)
 		pr_info("booting from MMC\n");
 		buf = bootstrap_read_disk("disk0.0", "fat");
 		break;
-	case BOOTSOURCE_SPI:
+	case BOOTSOURCE_SPI_NOR:
 		pr_info("booting from SPI\n");
 		buf = bootstrap_read_devfs("dataflash0", false,
 					   SZ_256K, SZ_1M, SZ_1M);
-- 
2.14.3



From marc at cpdesign.com.au  Sat Apr 14 19:22:41 2018
From: marc at cpdesign.com.au (Marc Reilly)
Date: Sun, 15 Apr 2018 12:22:41 +1000
Subject: [PATCH 08/17] ARM: i.MX: boot: Remove unnecessary retruns
In-Reply-To: <20180414175103.10125-9-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
 <20180414175103.10125-9-andrew.smirnov@gmail.com>
Message-ID: <2408243.jW0yOUZQgv@dev4>

Nitpick: in subject s/retruns/returns

On Sunday, April 15, 2018 3:50:54 AM AEST Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/boot.c | 4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> index 42ea2ccd6..cc54ea15a 100644
> --- a/arch/arm/mach-imx/boot.c
> +++ b/arch/arm/mach-imx/boot.c
> @@ -299,8 +299,6 @@ void imx6_get_boot_source(enum bootsource *src, int
> *instance) /* BOOT_CFG1[7:0] */
>  	if (sbmr1 & (1 << 7))
>  		*src = BOOTSOURCE_NAND;
> -
> -	return;
>  }
> 
>  #define IMX7_SRC_SBMR1	0x58
> @@ -382,8 +380,6 @@ void imx7_get_boot_source(enum bootsource *src, int
> *instance) default:
>  		break;
>  	}
> -
> -	return;
>  }
> 
>  static void






From marc at cpdesign.com.au  Sat Apr 14 19:24:37 2018
From: marc at cpdesign.com.au (Marc Reilly)
Date: Sun, 15 Apr 2018 12:24:37 +1000
Subject: [PATCH 09/17] ARM: i.MX: boot: Move magic values into small
 functions
In-Reply-To: <20180414175103.10125-10-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
 <20180414175103.10125-10-andrew.smirnov@gmail.com>
Message-ID: <2824671.pASI2u4fUC@dev4>

On Sunday, April 15, 2018 3:50:55 AM AEST Andrey Smirnov wrote:
> Move code to extract appropiate BOOT_CFG bits to decode booutsource on

s/booutsource/bootsource

> i.MX53, 6, and 7 into small functions for clarity and to allow sharing
> the code between i.MX53 and i.MX6.
> 

Cheers,
Marc




From antonynpavlov at gmail.com  Sun Apr 15 04:28:56 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:56 +0300
Subject: [PATCH 08/10] RISC-V: add erizo_generic_defconfig
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-9-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/configs/erizo_generic_defconfig | 53 ++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/arch/riscv/configs/erizo_generic_defconfig b/arch/riscv/configs/erizo_generic_defconfig
new file mode 100644
index 0000000000..e62b6ec719
--- /dev/null
+++ b/arch/riscv/configs/erizo_generic_defconfig
@@ -0,0 +1,53 @@
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="erizo_generic"
+# CONFIG_GLOBALVAR is not set
+CONFIG_TEXT_BASE=0x80000000
+CONFIG_MEMORY_LAYOUT_FIXED=y
+CONFIG_STACK_BASE=0x800e0000
+CONFIG_STACK_SIZE=0x20000
+CONFIG_MALLOC_BASE=0x80100000
+CONFIG_MALLOC_SIZE=0x100000
+CONFIG_MALLOC_TLSF=y
+CONFIG_PANIC_HANG=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_ERRNO_MESSAGES is not set
+# CONFIG_TIMESTAMP is not set
+# CONFIG_BOOTM is not set
+# CONFIG_ENV_HANDLING is not set
+CONFIG_POLLER=y
+CONFIG_DEBUG_LL=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_CMP=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_OF_DUMP=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_OFDEVICE=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_SPI_GPIO=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_MTD=y
+# CONFIG_MTD_OOB_DEVICE is not set
+CONFIG_MTD_M25P80=y
+CONFIG_CLOCKSOURCE_DUMMY_RATE=60000
+CONFIG_EEPROM_AT24=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_PINCTRL is not set
+CONFIG_DIGEST_CRC32_GENERIC=y
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:55 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:55 +0300
Subject: [PATCH 07/10] RISC-V: erizo: add nmon image creation
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-8-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Makefile      | 11 +++++++++++
 scripts/erizo-nmon-image |  3 +++
 2 files changed, 14 insertions(+)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 9a3921065c..c837d4e2e4 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -73,3 +73,14 @@ CFLAGS += $(cflags-y)
 lds-y	:= arch/riscv/lib/barebox.lds
 
 CLEAN_FILES += arch/riscv/lib/barebox.lds
+
+ifeq ($(CONFIG_MACH_ERIZO),y)
+KBUILD_IMAGE := barebox.erizo.nmon
+endif
+
+quiet_cmd_erizo_nmon_image = MKIMAGE $@
+      cmd_erizo_nmon_image = $(srctree)/scripts/erizo-nmon-image $< $@ || \
+	echo "WARNING: Couldn't create erizo nmon image due to previous errors."
+
+barebox.erizo.nmon: $(KBUILD_BINARY) FORCE
+	$(call if_changed,erizo_nmon_image)
diff --git a/scripts/erizo-nmon-image b/scripts/erizo-nmon-image
new file mode 100755
index 0000000000..4f0185b6de
--- /dev/null
+++ b/scripts/erizo-nmon-image
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+hexdump -v -e '/4 "%08x\n"' $1 | perl -e '$a = 0x80000000; while (<>) { chop; printf("expect \"nmon> \"\n"); printf("send \"w%08x$_\"\n", $a); $a = $a + 4; }' > $2
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:51 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:51 +0300
Subject: [PATCH 03/10] RISC-V: add low-level debug macros for ns16550
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-4-antonynpavlov@gmail.com>

This patch adds macros for ns16550 port initialization
and single char output. The macros can be used in
MIPS asm pbl code.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/include/asm/debug_ll_ns16550.h | 186 ++++++++++++++++++++++
 1 file changed, 186 insertions(+)

diff --git a/arch/riscv/include/asm/debug_ll_ns16550.h b/arch/riscv/include/asm/debug_ll_ns16550.h
new file mode 100644
index 0000000000..6929453b1e
--- /dev/null
+++ b/arch/riscv/include/asm/debug_ll_ns16550.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016, 2017 Antony Pavlov <antonynpavlov at 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.
+ *
+ */
+
+/** @file
+ *  This file contains declaration for early output support
+ */
+#ifndef __INCLUDE_RISCV_ASM_DEBUG_LL_NS16550_H__
+#define __INCLUDE_RISCV_ASM_DEBUG_LL_NS16550_H__
+
+#include <linux/kconfig.h>
+
+#ifdef CONFIG_DEBUG_LL
+
+#ifndef DEBUG_LL_UART_ADDR
+#error DEBUG_LL_UART_ADDR is undefined!
+#endif
+
+#ifndef DEBUG_LL_UART_SHIFT
+#error DEBUG_LL_UART_SHIFT is undefined!
+#endif
+
+#ifndef DEBUG_LL_UART_DIVISOR
+#error DEBUG_LL_UART_DIVISOR is undefined!
+#endif
+
+#endif /* CONFIG_DEBUG_LL */
+
+#define UART_THR	(0x0 << DEBUG_LL_UART_SHIFT)
+#define UART_RBR	(0x0 << DEBUG_LL_UART_SHIFT)
+#define UART_DLL	(0x0 << DEBUG_LL_UART_SHIFT)
+#define UART_DLM	(0x1 << DEBUG_LL_UART_SHIFT)
+#define UART_LCR	(0x3 << DEBUG_LL_UART_SHIFT)
+#define UART_LSR	(0x5 << DEBUG_LL_UART_SHIFT)
+
+#define UART_LCR_W	0x07	/* Set UART to 8,N,2 & DLAB = 0 */
+#define UART_LCR_DLAB	0x87	/* Set UART to 8,N,2 & DLAB = 1 */
+
+#define UART_LSR_DR	0x01    /* UART received data present */
+#define UART_LSR_THRE	0x20	/* Xmit holding register empty */
+
+#if defined(DEBUG_LL_UART_IOSIZE32)
+#define UART_REG_L	lw
+#define UART_REG_S	sw
+#elif defined(DEBUG_LL_UART_IOSIZE8)
+#define UART_REG_L	lbu
+#define UART_REG_S	sb
+#else
+#error "Please define DEBUG_LL_UART_IOSIZE{8,32}"
+#endif
+
+#ifndef __ASSEMBLY__
+/*
+ * C macros
+ */
+
+#include <asm/io.h>
+
+static inline void PUTC_LL(char ch)
+{
+#ifdef CONFIG_DEBUG_LL
+	while (!(__raw_readl((u8 *)DEBUG_LL_UART_ADDR + UART_LSR) & UART_LSR_THRE))
+		;
+	__raw_writel(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_THR);
+#endif /* CONFIG_DEBUG_LL */
+}
+
+static inline void debug_ll_ns16550_init(void)
+{
+#ifdef CONFIG_DEBUG_LL
+	__raw_writel(UART_LCR_DLAB, (u8 *)DEBUG_LL_UART_ADDR + UART_LCR);
+	__raw_writel(DEBUG_LL_UART_DIVISOR & 0xff, (u8 *)DEBUG_LL_UART_ADDR + UART_DLL);
+	__raw_writel((DEBUG_LL_UART_DIVISOR >> 8) & 0xff, (u8 *)DEBUG_LL_UART_ADDR + UART_DLM);
+	__raw_writel(UART_LCR_W, (u8 *)DEBUG_LL_UART_ADDR + UART_LCR);
+#endif /* CONFIG_DEBUG_LL */
+}
+#else /* __ASSEMBLY__ */
+/*
+ * Macros for use in assembly language code
+ */
+
+.macro	debug_ll_ns16550_init
+#ifdef CONFIG_DEBUG_LL
+	li	t0, DEBUG_LL_UART_ADDR
+
+	li	t1, UART_LCR_DLAB		/* DLAB on */
+	UART_REG_S	t1, UART_LCR(t0)		/* Write it out */
+
+	li	t1, DEBUG_LL_UART_DIVISOR
+	UART_REG_S	t1, UART_DLL(t0)		/* write low order byte */
+	srl	t1, t1, 8
+	UART_REG_S	t1, UART_DLM(t0)		/* write high order byte */
+
+	li	t1, UART_LCR_W			/* DLAB off */
+	UART_REG_S	t1, UART_LCR(t0)		/* Write it out */
+#endif /* CONFIG_DEBUG_LL */
+.endm
+
+/*
+ * output a character in a0
+ */
+.macro	debug_ll_outc_a0
+#ifdef CONFIG_DEBUG_LL
+
+	li	t0, DEBUG_LL_UART_ADDR
+
+201:
+	UART_REG_L	t1, UART_LSR(t0)	/* get line status */
+	andi	t1, t1, UART_LSR_THRE	/* check for transmitter empty */
+	beqz	t1, 201b			/* try again */
+
+	UART_REG_S	a0, UART_THR(t0)	/* write the character */
+
+#endif /* CONFIG_DEBUG_LL */
+.endm
+
+/*
+ * output a character
+ */
+.macro	debug_ll_outc chr
+#ifdef CONFIG_DEBUG_LL
+	li	a0, \chr
+	debug_ll_outc_a0
+#endif /* CONFIG_DEBUG_LL */
+.endm
+
+/*
+ * output CR + NL
+ */
+.macro	debug_ll_ns16550_outnl
+#ifdef CONFIG_DEBUG_LL
+	debug_ll_outc '\r'
+	debug_ll_outc '\n'
+#endif /* CONFIG_DEBUG_LL */
+.endm
+
+/*
+ * check character in input buffer
+ * return value:
+ *  v0 = 0   no character in input buffer
+ *  v0 != 0  character in input buffer
+ */
+.macro	debug_ll_tstc
+#ifdef CONFIG_DEBUG_LL
+	li      t0, DEBUG_LL_UART_ADDR
+
+	/* get line status and check for data present */
+	UART_REG_L	s0, UART_LSR(t0)
+	andi	s0, s0, UART_LSR_DR
+
+#endif /* CONFIG_DEBUG_LL */
+.endm
+
+/*
+ * get character to v0
+ */
+.macro	debug_ll_getc
+#ifdef CONFIG_DEBUG_LL
+
+204:
+	debug_ll_tstc
+
+	/* try again */
+	beqz	s0, 204b
+
+	/* read a character */
+	UART_REG_L	s0, UART_RBR(t0)
+
+#endif /* CONFIG_DEBUG_LL */
+.endm
+#endif /* __ASSEMBLY__ */
+
+#endif /* __INCLUDE_RISCV_ASM_DEBUG_LL_NS16550_H__ */
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:54 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:54 +0300
Subject: [PATCH 06/10] RISC-V: erizo: enable NMON
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-7-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ff3e6b96ab..915294c9cd 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -25,6 +25,7 @@ choice
 config MACH_ERIZO
 	bool "erizo family"
 	select HAS_DEBUG_LL
+	select HAS_NMON
 
 endchoice
 
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:48 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:48 +0300
Subject: [PATCH 00/10] Add initial RISC-V architecture support
Message-ID: <20180415112858.5163-1-antonynpavlov@gmail.com>

This patchseries adds initial RISC-V architecture support for barebox.

See Documentation/boards/riscv.rst for instructions.

You can obtain this patchseries from github:

    $ git clone -b 20180415.riscv https://github.com/frantony/barebox

Changes since RFC v4 (20170927)
(http://lists.infradead.org/pipermail/barebox/2017-September/031226.html)

    * drop 64-bit support;
    * sync with RISC-V linux;
    * RISC-V in barebox now is little endian only;
    * fix according to notes by Oleksij Rempel.

Changes since RFC v3 (20161212)
(http://lists.infradead.org/pipermail/barebox/2016-December/028716.html)

    * drop SiFive support, add support for custom Erizo SoC;
    * barebox runs on real hardware (e.g. DE0-Nano FPGA board,
      see https://github.com/miet-riscv-workgroup/rv32-simple-soc for
details);
    * introduce NMON for RISC-V;
    * add relocator to start.S.

Changes since RFC v2 (20161113)
(http://lists.infradead.org/pipermail/barebox/2016-November/028533.html):

    * add RV32 support.

Changes since RFC v1 (20161013)
(http://lists.infradead.org/pipermail/barebox/2016-October/028309.html):

    * drop spike pk support;
    * add qemu-sifive board support;
    * add Documentation/boards/riscv.rst;
    * fix guard macro names


Antony Pavlov (10):
  Add initial RISC-V architecture support
  RISC-V: add Erizo SoC support
  RISC-V: add low-level debug macros for ns16550
  RISC-V: add nmon nano-monitor
  RISC-V: erizo: add DEBUG_LL support
  RISC-V: erizo: enable NMON
  RISC-V: erizo: add nmon image creation
  RISC-V: add erizo_generic_defconfig
  scripts: add nmon-loader
  Documentation: add RISC-V docs

 Documentation/boards/riscv.rst                | 106 ++++++++
 arch/riscv/Kconfig                            |  99 ++++++++
 arch/riscv/Makefile                           |  86 +++++++
 arch/riscv/boards/erizo-generic/.gitignore    |   1 +
 arch/riscv/boards/erizo-generic/Makefile      |   1 +
 arch/riscv/boards/erizo-generic/board.c       |  28 +++
 arch/riscv/boot/Makefile                      |   2 +
 arch/riscv/boot/main_entry.c                  |  40 +++
 arch/riscv/boot/start.S                       |  76 ++++++
 arch/riscv/configs/erizo_generic_defconfig    |  53 ++++
 arch/riscv/dts/.gitignore                     |   1 +
 arch/riscv/dts/Makefile                       |   9 +
 arch/riscv/dts/erizo.dtsi                     |  46 ++++
 arch/riscv/dts/erizo_generic.dts              |  32 +++
 arch/riscv/dts/skeleton.dtsi                  |  13 +
 arch/riscv/include/asm/barebox.h              |   1 +
 arch/riscv/include/asm/bitops.h               |  35 +++
 arch/riscv/include/asm/bitsperlong.h          |  10 +
 arch/riscv/include/asm/byteorder.h            |   6 +
 arch/riscv/include/asm/common.h               |   6 +
 arch/riscv/include/asm/debug_ll_ns16550.h     | 186 ++++++++++++++
 arch/riscv/include/asm/elf.h                  |  11 +
 arch/riscv/include/asm/io.h                   |   8 +
 arch/riscv/include/asm/mmu.h                  |   6 +
 arch/riscv/include/asm/posix_types.h          |   1 +
 arch/riscv/include/asm/riscv_nmon.h           | 234 ++++++++++++++++++
 arch/riscv/include/asm/sections.h             |   1 +
 arch/riscv/include/asm/string.h               |   1 +
 arch/riscv/include/asm/swab.h                 |   6 +
 arch/riscv/include/asm/types.h                |  60 +++++
 arch/riscv/include/asm/unaligned.h            |  19 ++
 arch/riscv/lib/.gitignore                     |   1 +
 arch/riscv/lib/Makefile                       |   9 +
 arch/riscv/lib/ashldi3.c                      |  28 +++
 arch/riscv/lib/ashrdi3.c                      |  30 +++
 arch/riscv/lib/asm-offsets.c                  |  12 +
 arch/riscv/lib/barebox.lds.S                  |  89 +++++++
 arch/riscv/lib/dtb.c                          |  41 +++
 arch/riscv/lib/libgcc.h                       |  29 +++
 arch/riscv/lib/lshrdi3.c                      |  28 +++
 arch/riscv/lib/riscv_timer.c                  |  67 +++++
 arch/riscv/mach-erizo/Kconfig                 |  11 +
 arch/riscv/mach-erizo/Makefile                |   3 +
 arch/riscv/mach-erizo/include/mach/debug_ll.h |  37 +++
 drivers/of/Kconfig                            |   2 +-
 scripts/erizo-nmon-image                      |   3 +
 scripts/nmon-loader                           |  31 +++
 47 files changed, 1604 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/boards/riscv.rst
 create mode 100644 arch/riscv/Kconfig
 create mode 100644 arch/riscv/Makefile
 create mode 100644 arch/riscv/boards/erizo-generic/.gitignore
 create mode 100644 arch/riscv/boards/erizo-generic/Makefile
 create mode 100644 arch/riscv/boards/erizo-generic/board.c
 create mode 100644 arch/riscv/boot/Makefile
 create mode 100644 arch/riscv/boot/main_entry.c
 create mode 100644 arch/riscv/boot/start.S
 create mode 100644 arch/riscv/configs/erizo_generic_defconfig
 create mode 100644 arch/riscv/dts/.gitignore
 create mode 100644 arch/riscv/dts/Makefile
 create mode 100644 arch/riscv/dts/erizo.dtsi
 create mode 100644 arch/riscv/dts/erizo_generic.dts
 create mode 100644 arch/riscv/dts/skeleton.dtsi
 create mode 100644 arch/riscv/include/asm/barebox.h
 create mode 100644 arch/riscv/include/asm/bitops.h
 create mode 100644 arch/riscv/include/asm/bitsperlong.h
 create mode 100644 arch/riscv/include/asm/byteorder.h
 create mode 100644 arch/riscv/include/asm/common.h
 create mode 100644 arch/riscv/include/asm/debug_ll_ns16550.h
 create mode 100644 arch/riscv/include/asm/elf.h
 create mode 100644 arch/riscv/include/asm/io.h
 create mode 100644 arch/riscv/include/asm/mmu.h
 create mode 100644 arch/riscv/include/asm/posix_types.h
 create mode 100644 arch/riscv/include/asm/riscv_nmon.h
 create mode 100644 arch/riscv/include/asm/sections.h
 create mode 100644 arch/riscv/include/asm/string.h
 create mode 100644 arch/riscv/include/asm/swab.h
 create mode 100644 arch/riscv/include/asm/types.h
 create mode 100644 arch/riscv/include/asm/unaligned.h
 create mode 100644 arch/riscv/lib/.gitignore
 create mode 100644 arch/riscv/lib/Makefile
 create mode 100644 arch/riscv/lib/ashldi3.c
 create mode 100644 arch/riscv/lib/ashrdi3.c
 create mode 100644 arch/riscv/lib/asm-offsets.c
 create mode 100644 arch/riscv/lib/barebox.lds.S
 create mode 100644 arch/riscv/lib/dtb.c
 create mode 100644 arch/riscv/lib/libgcc.h
 create mode 100644 arch/riscv/lib/lshrdi3.c
 create mode 100644 arch/riscv/lib/riscv_timer.c
 create mode 100644 arch/riscv/mach-erizo/Kconfig
 create mode 100644 arch/riscv/mach-erizo/Makefile
 create mode 100644 arch/riscv/mach-erizo/include/mach/debug_ll.h
 create mode 100755 scripts/erizo-nmon-image
 create mode 100755 scripts/nmon-loader

-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:50 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:50 +0300
Subject: [PATCH 02/10] RISC-V: add Erizo SoC support
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-3-antonynpavlov@gmail.com>

Erizo is an opensource hardware SoC for FPGA.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig                         | 11 ++++++
 arch/riscv/Makefile                        |  3 ++
 arch/riscv/boards/erizo-generic/.gitignore |  1 +
 arch/riscv/boards/erizo-generic/Makefile   |  1 +
 arch/riscv/boards/erizo-generic/board.c    | 28 +++++++++++++
 arch/riscv/dts/erizo.dtsi                  | 46 ++++++++++++++++++++++
 arch/riscv/dts/erizo_generic.dts           | 32 +++++++++++++++
 arch/riscv/mach-erizo/Kconfig              | 11 ++++++
 arch/riscv/mach-erizo/Makefile             |  3 ++
 9 files changed, 136 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index d65e87acd8..fe79cb49b5 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -18,6 +18,15 @@ config GENERIC_LINKER_SCRIPT
 
 menu "Machine selection"
 
+choice
+	prompt "System type"
+	default MACH_ERIZO
+
+config MACH_ERIZO
+	bool "erizo family"
+
+endchoice
+
 choice
 	prompt "Base ISA"
 	default ARCH_RV32I
@@ -51,6 +60,8 @@ config BUILTIN_DTB_NAME
 	string "DTB to build into the barebox image"
 	depends on BUILTIN_DTB
 
+source arch/riscv/mach-erizo/Kconfig
+
 endmenu
 
 source common/Kconfig
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index e9c407354c..9a3921065c 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -11,6 +11,9 @@ cflags-y += -Wall -Wmissing-prototypes -Wstrict-prototypes \
 LDFLAGS += $(ldflags-y)
 LDFLAGS_barebox += -nostdlib
 
+machine-$(CONFIG_MACH_ERIZO)	:= erizo
+board-$(CONFIG_BOARD_ERIZO_GENERIC)	:= erizo-generic
+
 TEXT_BASE = $(CONFIG_TEXT_BASE)
 CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
 
diff --git a/arch/riscv/boards/erizo-generic/.gitignore b/arch/riscv/boards/erizo-generic/.gitignore
new file mode 100644
index 0000000000..d1165788c9
--- /dev/null
+++ b/arch/riscv/boards/erizo-generic/.gitignore
@@ -0,0 +1 @@
+barebox.lds
diff --git a/arch/riscv/boards/erizo-generic/Makefile b/arch/riscv/boards/erizo-generic/Makefile
new file mode 100644
index 0000000000..dcfc2937d3
--- /dev/null
+++ b/arch/riscv/boards/erizo-generic/Makefile
@@ -0,0 +1 @@
+obj-y += board.o
diff --git a/arch/riscv/boards/erizo-generic/board.c b/arch/riscv/boards/erizo-generic/board.c
new file mode 100644
index 0000000000..46c9ca34f0
--- /dev/null
+++ b/arch/riscv/boards/erizo-generic/board.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 Antony Pavlov <antonynpavlov at 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 <driver.h>
+#include <init.h>
+
+static int hostname_init(void)
+{
+	barebox_set_hostname("erizo-generic");
+
+	return 0;
+}
+postcore_initcall(hostname_init);
diff --git a/arch/riscv/dts/erizo.dtsi b/arch/riscv/dts/erizo.dtsi
new file mode 100644
index 0000000000..1660ad1040
--- /dev/null
+++ b/arch/riscv/dts/erizo.dtsi
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "miet-riscv-workgroup,erizo";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	clocks {
+		ref_clk: ref_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "cliffordwolf,picorv32";
+			clocks = <&ref_clk>;
+			reg = <0>;
+		};
+	};
+
+	uart0: uart at 90000000 {
+		compatible = "ns16550a";
+		reg = <0x90000000 0x20>;
+		reg-shift = <2>;
+		clocks = <&ref_clk>;
+	};
+
+	gpio0: gpio at 91000000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat", "dirout";
+		reg = <0x91000000 0x4>,
+			<0x91000004 0x4>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+};
diff --git a/arch/riscv/dts/erizo_generic.dts b/arch/riscv/dts/erizo_generic.dts
new file mode 100644
index 0000000000..a35983ab30
--- /dev/null
+++ b/arch/riscv/dts/erizo_generic.dts
@@ -0,0 +1,32 @@
+#include "erizo.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "generic Erizo SoC board";
+	compatible = "miet-riscv-workgroup,erizo-generic-board";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x00800000>;
+	};
+
+	spi0 {
+		compatible = "spi-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-sck  = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+		gpio-miso = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+		gpio-mosi = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+		cs-gpios  = <&gpio0 3 GPIO_ACTIVE_LOW>;
+		num-chipselects = <1>;
+
+		m25p128 at 0 {
+			compatible = "m25p128", "jedec,spi-nor";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0>;
+			spi-max-frequency = <1000000>;
+		};
+	};
+};
diff --git a/arch/riscv/mach-erizo/Kconfig b/arch/riscv/mach-erizo/Kconfig
new file mode 100644
index 0000000000..2400b4437b
--- /dev/null
+++ b/arch/riscv/mach-erizo/Kconfig
@@ -0,0 +1,11 @@
+if MACH_ERIZO
+
+choice
+	prompt "Board type"
+
+config BOARD_ERIZO_GENERIC
+	bool "erizo generic board"
+
+endchoice
+
+endif
diff --git a/arch/riscv/mach-erizo/Makefile b/arch/riscv/mach-erizo/Makefile
new file mode 100644
index 0000000000..d9c51e74c3
--- /dev/null
+++ b/arch/riscv/mach-erizo/Makefile
@@ -0,0 +1,3 @@
+# just to build a built-in.o. Otherwise compilation fails when no o-files is
+# created.
+obj- += dummy.o
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:57 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:57 +0300
Subject: [PATCH 09/10] scripts: add nmon-loader
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-10-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 scripts/nmon-loader | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/scripts/nmon-loader b/scripts/nmon-loader
new file mode 100755
index 0000000000..d80a53097a
--- /dev/null
+++ b/scripts/nmon-loader
@@ -0,0 +1,31 @@
+#!/usr/bin/expect -f
+
+# device
+set image [lindex $argv 0];
+set modem [lindex $argv 1];
+set speed [lindex $argv 2];
+
+if {$argc != 3} {
+    puts "Usage:"
+    puts "    nmon-loader.expect <file> <device> <speed>"
+    exit 2
+}
+
+# keep it open
+exec sh -c "sleep 3 < $modem" &
+
+# serial port parameters
+exec stty -F $modem $speed raw -clocal -echo -istrip -hup
+
+# connect
+send_user "connecting to $modem, exit with ~.\n"
+spawn -open [open $modem w+]
+send_user "connected\n"
+send "\r"
+
+source $image
+
+interact {
+    ~- exit
+    ~~ {send "\034"}
+}
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:53 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:53 +0300
Subject: [PATCH 05/10] RISC-V: erizo: add DEBUG_LL support
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-6-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig                            |  1 +
 arch/riscv/mach-erizo/include/mach/debug_ll.h | 37 +++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 9e7faf11d0..ff3e6b96ab 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -24,6 +24,7 @@ choice
 
 config MACH_ERIZO
 	bool "erizo family"
+	select HAS_DEBUG_LL
 
 endchoice
 
diff --git a/arch/riscv/mach-erizo/include/mach/debug_ll.h b/arch/riscv/mach-erizo/include/mach/debug_ll.h
new file mode 100644
index 0000000000..913b323d99
--- /dev/null
+++ b/arch/riscv/mach-erizo/include/mach/debug_ll.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 Antony Pavlov <antonynpavlov at 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_ERIZO_DEBUG_LL__
+#define __MACH_ERIZO_DEBUG_LL__
+
+/** @file
+ *  This File contains declaration for early output support
+ */
+
+#include <linux/kconfig.h>
+
+#define DEBUG_LL_UART_ADDR	0x90000000
+#define DEBUG_LL_UART_SHIFT	2
+#define DEBUG_LL_UART_IOSIZE32
+
+#define DEBUG_LL_UART_CLK       (24000000 / 16)
+#define DEBUG_LL_UART_BPS       CONFIG_BAUDRATE
+#define DEBUG_LL_UART_DIVISOR   (DEBUG_LL_UART_CLK / DEBUG_LL_UART_BPS)
+
+#include <asm/debug_ll_ns16550.h>
+
+#endif /* __MACH_ERIZO_DEBUG_LL__ */
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:52 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:52 +0300
Subject: [PATCH 04/10] RISC-V: add nmon nano-monitor
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-5-antonynpavlov@gmail.com>

nmon is a tiny (<1024 bytes) monitor program
for the RV32I processors.

It can operate with NO working RAM at all!

It uses only the processor registers and NS16550-compatible
UART port for operation, so it can be used for a memory
controller setup code debugging.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig                  |  24 +++
 arch/riscv/boot/start.S             |  13 ++
 arch/riscv/include/asm/riscv_nmon.h | 234 ++++++++++++++++++++++++++++
 3 files changed, 271 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index fe79cb49b5..9e7faf11d0 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -64,6 +64,30 @@ source arch/riscv/mach-erizo/Kconfig
 
 endmenu
 
+menu "RISC-V specific settings"
+
+config HAS_NMON
+	bool
+
+config NMON
+	bool "nmon"
+	depends on HAS_NMON
+	depends on DEBUG_LL
+	help
+	  Say yes here to add the nmon to pbl.
+	  nmon -- nano-monitor program for the RISC-V processors.
+	  It can operate with NO working RAM, using only
+	  the processor registers.
+
+config NMON_HELP
+	bool "nmon help message"
+	depends on NMON
+	help
+	  Say yes here to get the nmon commands message on
+	  every nmon start.
+
+endmenu
+
 source common/Kconfig
 source commands/Kconfig
 source net/Kconfig
diff --git a/arch/riscv/boot/start.S b/arch/riscv/boot/start.S
index be3aed1507..4ae2f77f9d 100644
--- a/arch/riscv/boot/start.S
+++ b/arch/riscv/boot/start.S
@@ -21,12 +21,20 @@
 
 #include <asm-generic/memory_layout.h>
 
+#include "mach/debug_ll.h"
+
+#include "asm/riscv_nmon.h"
+
 	.text
 	.section ".text_entry"
 	.align 2
 
 .globl _start
 _start:
+	debug_ll_ns16550_init
+
+	riscv_nmon
+
 	li	sp, STACK_BASE + STACK_SIZE
 
 	/* copy barebox to link location */
@@ -55,9 +63,14 @@ copy_loop:
 	addi	a1, a1, LONGSIZE * 4
 	bgeu	a2, a0, copy_loop
 
+	nmon_outs copy_loop_done_message
+
 	/* Alas! At the moment I can't load main_entry __link__ address
 	   into a0 with la. Use CONFIG_TEXT_BASE instead. This solution
 	   leads to extra cycles for repeat sp initialization. */
 
 	li	a0, CONFIG_TEXT_BASE
 	jalr	a0
+
+copy_loop_done_message:
+	.asciz "\r\ncopy loop done\r\nrestarting...\r\n"
diff --git a/arch/riscv/include/asm/riscv_nmon.h b/arch/riscv/include/asm/riscv_nmon.h
new file mode 100644
index 0000000000..717f613349
--- /dev/null
+++ b/arch/riscv/include/asm/riscv_nmon.h
@@ -0,0 +1,234 @@
+/*
+ * nano-monitor for RISC-V CPU
+ *
+ * Copyright (C) 2016, 2017 Antony Pavlov <antonynpavlov at 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 __ASM_RISCV_NMON_H
+#define __ASM_RISCV_NMON_H
+
+#define CODE_ESC	0x1b
+
+.macro nmon_outs msg
+
+	la	a1, \msg
+
+	jal	_nmon_outs
+
+.endm
+
+/*
+ * output a 32-bit value in hex
+ */
+.macro debug_ll_outhexw
+#ifdef CONFIG_DEBUG_LL
+	move	t6, a0
+	li	t5, 32
+
+202:
+	addi	t5, t5, -4
+	srl	a0, t6, t5
+
+	/* output one hex digit */
+	andi	a0, a0, 15
+	li	t4, 10
+	blt	a0, t4, 203f
+
+	addi	a0, a0, ('a' - '9' - 1)
+
+203:
+	addi	a0, a0, '0'
+
+	debug_ll_outc_a0
+
+	li	t4, 1
+	bge	t5, t4, 202b
+
+#endif /* CONFIG_DEBUG_LL */
+.endm
+
+.macro riscv_nmon
+
+nmon_main_help:
+#ifdef CONFIG_NMON_HELP
+	nmon_outs	msg_nmon_help
+#endif /* CONFIG_NMON_HELP */
+
+nmon_main:
+	nmon_outs	msg_prompt
+
+	debug_ll_getc
+
+	li	a0, 'q'
+	bne	s0, a0, 3f
+
+	jal	_nmon_outc_a0
+
+	j	nmon_exit
+
+3:
+	li	a0, 'd'
+	beq	s0, a0, nmon_cmd_d
+
+	li	a0, 'w'
+	beq	s0, a0, nmon_cmd_w
+
+	li	a0, 'g'
+	beq	s0, a0, nmon_cmd_g
+
+	j	nmon_main_help
+
+nmon_cmd_d:
+	jal	_nmon_outc_a0
+
+	li	a0, ' '
+	jal	_nmon_outc_a0
+
+	jal	_nmon_gethexw
+
+	nmon_outs	msg_nl
+
+	lw	a0, (s0)
+	debug_ll_outhexw
+
+	j	nmon_main
+
+nmon_cmd_w:
+	jal	_nmon_outc_a0
+
+	li	a0, ' '
+	jal	_nmon_outc_a0
+
+	jal	_nmon_gethexw
+	move	s2, s0
+
+	li	a0, ' '
+	jal	_nmon_outc_a0
+	jal	_nmon_gethexw
+
+	sw	s0, 0(s2)
+	j	nmon_main
+
+nmon_cmd_g:
+	jal	_nmon_outc_a0
+
+	li	a0, ' '
+	jal	_nmon_outc_a0
+
+	jal	_nmon_gethexw
+	move	s2, s0
+
+	nmon_outs	msg_nl
+
+	jalr	s2
+	j	nmon_main
+
+_nmon_outc_a0:
+	debug_ll_outc_a0
+	jr	ra
+
+_nmon_outs:
+
+	lb	a0, 0(a1)
+	addi	a1, a1, 1
+	beqz	a0, _nmon_jr_ra_exit
+
+	debug_ll_outc_a0
+
+	j	_nmon_outs
+
+_nmon_gethexw:
+
+	li	t3, 8
+	li	t2, 0
+
+_get_hex_digit:
+	debug_ll_getc
+
+	li	s1, CODE_ESC
+	beq	s0, s1, nmon_main
+
+	li	s1, '0'
+	bge	s0, s1, 0f
+	j	_get_hex_digit
+
+0:
+	li	s1, '9'
+	ble	s0, s1, 9f
+
+	li	s1, 'f'
+	ble	s0, s1, 1f
+	j	_get_hex_digit
+
+1:
+	li	s1, 'a'
+	bge	s0, s1, 8f
+
+	j	_get_hex_digit
+
+8: /* s0 \in {'a', 'b' ... 'f'} */
+	sub	a3, s0, s1
+	addi	a3, a3, 0xa
+	j	0f
+
+9: /* s0 \in {'0', '1' ... '9'} */
+	li	a3, '0'
+	sub	a3, s0, a3
+
+0:	move	a0, s0
+	debug_ll_outc_a0
+
+	sll	t2, t2, 4
+	or	t2, t2, a3
+	li	t0, 1
+	sub	t3, t3, t0
+
+	beqz	t3, 0f
+
+	j	_get_hex_digit
+
+0:
+	move	s0, t2
+
+_nmon_jr_ra_exit:
+	jr	ra
+
+msg_prompt:
+	.asciz "\r\nnmon> "
+
+msg_nl:
+	.asciz "\r\n"
+
+msg_bsp:
+	.asciz "\b \b"
+
+#ifdef CONFIG_NMON_HELP
+msg_nmon_help:
+	.ascii "\r\n\r\nnmon commands:\r\n"
+	.ascii " q - quit\r\n"
+	.ascii " d <addr> - read 32-bit word from <addr>\r\n"
+	.ascii " w <addr> <val> - write 32-bit word to <addr>\r\n"
+	.ascii " g <addr> - jump to <addr>\r\n"
+	.asciz "   use <ESC> key to interrupt current command\r\n"
+#endif /* CONFIG_NMON_HELP */
+
+	.align 2
+nmon_exit:
+	nmon_outs	msg_nl
+
+.endm
+
+#endif /* __ASM_RISCV_NMON_H */
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:49 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:49 +0300
Subject: [PATCH 01/10] Add initial RISC-V architecture support
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-2-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig                   | 62 +++++++++++++++++++
 arch/riscv/Makefile                  | 72 ++++++++++++++++++++++
 arch/riscv/boot/Makefile             |  2 +
 arch/riscv/boot/main_entry.c         | 40 +++++++++++++
 arch/riscv/boot/start.S              | 63 ++++++++++++++++++++
 arch/riscv/dts/.gitignore            |  1 +
 arch/riscv/dts/Makefile              |  9 +++
 arch/riscv/dts/skeleton.dtsi         | 13 ++++
 arch/riscv/include/asm/barebox.h     |  1 +
 arch/riscv/include/asm/bitops.h      | 35 +++++++++++
 arch/riscv/include/asm/bitsperlong.h | 10 ++++
 arch/riscv/include/asm/byteorder.h   |  6 ++
 arch/riscv/include/asm/common.h      |  6 ++
 arch/riscv/include/asm/elf.h         | 11 ++++
 arch/riscv/include/asm/io.h          |  8 +++
 arch/riscv/include/asm/mmu.h         |  6 ++
 arch/riscv/include/asm/posix_types.h |  1 +
 arch/riscv/include/asm/sections.h    |  1 +
 arch/riscv/include/asm/string.h      |  1 +
 arch/riscv/include/asm/swab.h        |  6 ++
 arch/riscv/include/asm/types.h       | 60 +++++++++++++++++++
 arch/riscv/include/asm/unaligned.h   | 19 ++++++
 arch/riscv/lib/.gitignore            |  1 +
 arch/riscv/lib/Makefile              |  9 +++
 arch/riscv/lib/ashldi3.c             | 28 +++++++++
 arch/riscv/lib/ashrdi3.c             | 30 ++++++++++
 arch/riscv/lib/asm-offsets.c         | 12 ++++
 arch/riscv/lib/barebox.lds.S         | 89 ++++++++++++++++++++++++++++
 arch/riscv/lib/dtb.c                 | 41 +++++++++++++
 arch/riscv/lib/libgcc.h              | 29 +++++++++
 arch/riscv/lib/lshrdi3.c             | 28 +++++++++
 arch/riscv/lib/riscv_timer.c         | 67 +++++++++++++++++++++
 drivers/of/Kconfig                   |  2 +-
 33 files changed, 768 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
new file mode 100644
index 0000000000..d65e87acd8
--- /dev/null
+++ b/arch/riscv/Kconfig
@@ -0,0 +1,62 @@
+config RISCV
+	def_bool y
+	select GENERIC_FIND_NEXT_BIT
+	select HAVE_CONFIGURABLE_MEMORY_LAYOUT
+	select HAVE_CONFIGURABLE_TEXT_BASE
+	select GPIOLIB
+	select OFTREE
+	select COMMON_CLK
+	select COMMON_CLK_OF_PROVIDER
+	select CLKDEV_LOOKUP
+
+config ARCH_TEXT_BASE
+	hex
+	default 0x0
+
+config GENERIC_LINKER_SCRIPT
+	def_bool y
+
+menu "Machine selection"
+
+choice
+	prompt "Base ISA"
+	default ARCH_RV32I
+
+config ARCH_RV32I
+	bool "RV32I"
+	select CPU_SUPPORTS_32BIT_KERNEL
+
+endchoice
+
+config CPU_SUPPORTS_32BIT_KERNEL
+	bool
+
+choice
+	prompt "barebox code model"
+	default 32BIT
+
+config 32BIT
+	bool "32-bit barebox"
+	depends on CPU_SUPPORTS_32BIT_KERNEL
+	help
+	  Select this option to build a 32-bit barebox.
+
+endchoice
+
+config BUILTIN_DTB
+	bool "link a DTB into the barebox image"
+	depends on OFTREE
+
+config BUILTIN_DTB_NAME
+	string "DTB to build into the barebox image"
+	depends on BUILTIN_DTB
+
+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/riscv/Makefile b/arch/riscv/Makefile
new file mode 100644
index 0000000000..e9c407354c
--- /dev/null
+++ b/arch/riscv/Makefile
@@ -0,0 +1,72 @@
+CPPFLAGS += -fno-strict-aliasing
+
+ifeq ($(CONFIG_ARCH_RV32I),y)
+	cflags-y += -march=rv32im
+endif
+
+cflags-y += -fno-pic -pipe
+cflags-y += -Wall -Wmissing-prototypes -Wstrict-prototypes \
+	-Wno-uninitialized -Wno-format -Wno-main -mcmodel=medany
+
+LDFLAGS += $(ldflags-y)
+LDFLAGS_barebox += -nostdlib
+
+TEXT_BASE = $(CONFIG_TEXT_BASE)
+CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
+
+ifndef CONFIG_MODULES
+# Add cleanup flags
+CPPFLAGS += -fdata-sections -ffunction-sections
+LDFLAGS_barebox += -static --gc-sections
+endif
+
+KBUILD_BINARY := barebox.bin
+
+machdirs := $(patsubst %,arch/riscv/mach-%/,$(machine-y))
+
+ifneq ($(board-y),)
+BOARD := arch/riscv/boards/$(board-y)/
+else
+BOARD :=
+endif
+
+ifeq ($(KBUILD_SRC),)
+CPPFLAGS += -I$(BOARD)/include
+else
+CPPFLAGS += -I$(srctree)/$(BOARD)/include
+endif
+
+ifeq ($(KBUILD_SRC),)
+CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
+else
+CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+endif
+
+archprepare: maketools
+
+PHONY += maketools
+
+ifneq ($(machine-y),)
+MACH  := arch/riscv/mach-$(machine-y)/
+else
+MACH  :=
+endif
+
+ifneq ($(board-y),)
+BOARD := arch/riscv/boards/$(board-y)/
+else
+BOARD :=
+endif
+
+common-y += $(BOARD) $(MACH)
+common-y += arch/riscv/lib/
+common-y += arch/riscv/boot/
+
+common-$(CONFIG_OFTREE) += arch/riscv/dts/
+
+CPPFLAGS += $(cflags-y)
+CFLAGS += $(cflags-y)
+
+lds-y	:= arch/riscv/lib/barebox.lds
+
+CLEAN_FILES += arch/riscv/lib/barebox.lds
diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile
new file mode 100644
index 0000000000..d6d28ce652
--- /dev/null
+++ b/arch/riscv/boot/Makefile
@@ -0,0 +1,2 @@
+obj-y += start.o
+obj-y += main_entry.o
diff --git a/arch/riscv/boot/main_entry.c b/arch/riscv/boot/main_entry.c
new file mode 100644
index 0000000000..18db86da58
--- /dev/null
+++ b/arch/riscv/boot/main_entry.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Antony Pavlov <antonynpavlov at 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 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 <memory.h>
+#include <asm-generic/memory_layout.h>
+#include <asm/sections.h>
+
+void main_entry(void);
+
+/**
+ * Called plainly from assembler code
+ *
+ * @note The C environment isn't initialized yet
+ */
+void main_entry(void)
+{
+	/* clear the BSS first */
+	memset(__bss_start, 0x00, __bss_stop - __bss_start);
+
+	mem_malloc_init((void *)MALLOC_BASE,
+			(void *)(MALLOC_BASE + MALLOC_SIZE - 1));
+
+	start_barebox();
+}
diff --git a/arch/riscv/boot/start.S b/arch/riscv/boot/start.S
new file mode 100644
index 0000000000..be3aed1507
--- /dev/null
+++ b/arch/riscv/boot/start.S
@@ -0,0 +1,63 @@
+/*
+ * Startup Code for RISC-V CPU
+ *
+ * based on coreboot/src/arch/riscv/bootblock.S
+ *
+ * Copyright (C) 2016 Antony Pavlov <antonynpavlov at 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 <asm-generic/memory_layout.h>
+
+	.text
+	.section ".text_entry"
+	.align 2
+
+.globl _start
+_start:
+	li	sp, STACK_BASE + STACK_SIZE
+
+	/* copy barebox to link location */
+
+	la	a0, _start	/* a0 <- _start actual address */
+	li	a1, CONFIG_TEXT_BASE	/* a1 <- _start link address */
+
+	beq	a0, a1, main_entry
+
+	la	a2, __bss_start
+
+#define LONGSIZE 4
+
+copy_loop:
+	/* copy from source address [a0] */
+	lw	t0, LONGSIZE * 0(a0)
+	lw	t1, LONGSIZE * 1(a0)
+	lw	t2, LONGSIZE * 2(a0)
+	lw	t3, LONGSIZE * 3(a0)
+	/* copy to target address [a1] */
+	sw	t0, LONGSIZE * 0(a1)
+	sw	t1, LONGSIZE * 1(a1)
+	sw	t2, LONGSIZE * 2(a1)
+	sw	t3, LONGSIZE * 3(a1)
+	addi	a0, a0, LONGSIZE * 4
+	addi	a1, a1, LONGSIZE * 4
+	bgeu	a2, a0, copy_loop
+
+	/* Alas! At the moment I can't load main_entry __link__ address
+	   into a0 with la. Use CONFIG_TEXT_BASE instead. This solution
+	   leads to extra cycles for repeat sp initialization. */
+
+	li	a0, CONFIG_TEXT_BASE
+	jalr	a0
diff --git a/arch/riscv/dts/.gitignore b/arch/riscv/dts/.gitignore
new file mode 100644
index 0000000000..077903c50a
--- /dev/null
+++ b/arch/riscv/dts/.gitignore
@@ -0,0 +1 @@
+*dtb*
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
new file mode 100644
index 0000000000..f8380b11c9
--- /dev/null
+++ b/arch/riscv/dts/Makefile
@@ -0,0 +1,9 @@
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME))
+obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
+
+# just to build a built-in.o. Otherwise compilation fails when no devicetree is
+# created.
+obj- += dummy.o
+
+always := $(dtb-y)
+clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
diff --git a/arch/riscv/dts/skeleton.dtsi b/arch/riscv/dts/skeleton.dtsi
new file mode 100644
index 0000000000..38ead821bb
--- /dev/null
+++ b/arch/riscv/dts/skeleton.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value.  The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	chosen { };
+	aliases { };
+	memory { device_type = "memory"; reg = <0 0 0>; };
+};
diff --git a/arch/riscv/include/asm/barebox.h b/arch/riscv/include/asm/barebox.h
new file mode 100644
index 0000000000..2997587d82
--- /dev/null
+++ b/arch/riscv/include/asm/barebox.h
@@ -0,0 +1 @@
+/* dummy */
diff --git a/arch/riscv/include/asm/bitops.h b/arch/riscv/include/asm/bitops.h
new file mode 100644
index 0000000000..e77ab83202
--- /dev/null
+++ b/arch/riscv/include/asm/bitops.h
@@ -0,0 +1,35 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+#ifndef _ASM_BITOPS_H_
+#define _ASM_BITOPS_H_
+
+#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/hweight.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.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 /* _ASM_BITOPS_H_ */
diff --git a/arch/riscv/include/asm/bitsperlong.h b/arch/riscv/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..4641e7e485
--- /dev/null
+++ b/arch/riscv/include/asm/bitsperlong.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_BITSPERLONG_H
+#define __ASM_BITSPERLONG_H
+
+#ifdef __riscv64
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif
+
+#endif /* __ASM_BITSPERLONG_H */
diff --git a/arch/riscv/include/asm/byteorder.h b/arch/riscv/include/asm/byteorder.h
new file mode 100644
index 0000000000..0be826927b
--- /dev/null
+++ b/arch/riscv/include/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_RISCV_BYTEORDER_H
+#define _ASM_RISCV_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_RISCV_BYTEORDER_H */
diff --git a/arch/riscv/include/asm/common.h b/arch/riscv/include/asm/common.h
new file mode 100644
index 0000000000..bc8a17e30b
--- /dev/null
+++ b/arch/riscv/include/asm/common.h
@@ -0,0 +1,6 @@
+#ifndef ASM_RISCV_COMMON_H
+#define ASM_RISCV_COMMON_H
+
+/* nothing special yet */
+
+#endif /* ASM_RISCV_COMMON_H */
diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
new file mode 100644
index 0000000000..7134fa0582
--- /dev/null
+++ b/arch/riscv/include/asm/elf.h
@@ -0,0 +1,11 @@
+#ifndef __ASM_RISCV_ELF_H__
+#define __ASM_RISCV_ELF_H__
+
+#if __SIZEOF_POINTER__ == 8
+#define ELF_CLASS	ELFCLASS64
+#define CONFIG_PHYS_ADDR_T_64BIT
+#else
+#define ELF_CLASS	ELFCLASS32
+#endif
+
+#endif /* __ASM_RISCV_ELF_H__ */
diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
new file mode 100644
index 0000000000..3cdea7fcac
--- /dev/null
+++ b/arch/riscv/include/asm/io.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_RISCV_IO_H
+#define __ASM_RISCV_IO_H
+
+#define IO_SPACE_LIMIT 0
+
+#include <asm-generic/io.h>
+
+#endif /* __ASM_RISCV_IO_H */
diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h
new file mode 100644
index 0000000000..95af871420
--- /dev/null
+++ b/arch/riscv/include/asm/mmu.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MMU_H
+#define __ASM_MMU_H
+
+#define MAP_ARCH_DEFAULT MAP_UNCACHED
+
+#endif /* __ASM_MMU_H */
diff --git a/arch/riscv/include/asm/posix_types.h b/arch/riscv/include/asm/posix_types.h
new file mode 100644
index 0000000000..22cae6230c
--- /dev/null
+++ b/arch/riscv/include/asm/posix_types.h
@@ -0,0 +1 @@
+#include <asm-generic/posix_types.h>
diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h
new file mode 100644
index 0000000000..2b8c516038
--- /dev/null
+++ b/arch/riscv/include/asm/sections.h
@@ -0,0 +1 @@
+#include <asm-generic/sections.h>
diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h
new file mode 100644
index 0000000000..2997587d82
--- /dev/null
+++ b/arch/riscv/include/asm/string.h
@@ -0,0 +1 @@
+/* dummy */
diff --git a/arch/riscv/include/asm/swab.h b/arch/riscv/include/asm/swab.h
new file mode 100644
index 0000000000..60a90120b6
--- /dev/null
+++ b/arch/riscv/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/riscv/include/asm/types.h b/arch/riscv/include/asm/types.h
new file mode 100644
index 0000000000..ba386ab4c5
--- /dev/null
+++ b/arch/riscv/include/asm/types.h
@@ -0,0 +1,60 @@
+#ifndef __ASM_RISCV_TYPES_H
+#define __ASM_RISCV_TYPES_H
+
+#ifdef __riscv64
+/*
+ * This is used in dlmalloc. On RISCV64 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;
+
+#include <asm/bitsperlong.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_RISCV_TYPES_H */
diff --git a/arch/riscv/include/asm/unaligned.h b/arch/riscv/include/asm/unaligned.h
new file mode 100644
index 0000000000..aaebc06411
--- /dev/null
+++ b/arch/riscv/include/asm/unaligned.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_RISCV_UNALIGNED_H
+#define _ASM_RISCV_UNALIGNED_H
+
+/*
+ * FIXME: this file is copy-n-pasted from sandbox's unaligned.h
+ */
+
+#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_RISCV_UNALIGNED_H */
diff --git a/arch/riscv/lib/.gitignore b/arch/riscv/lib/.gitignore
new file mode 100644
index 0000000000..d1165788c9
--- /dev/null
+++ b/arch/riscv/lib/.gitignore
@@ -0,0 +1 @@
+barebox.lds
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
new file mode 100644
index 0000000000..313363c1a5
--- /dev/null
+++ b/arch/riscv/lib/Makefile
@@ -0,0 +1,9 @@
+extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += barebox.lds
+
+obj-y += riscv_timer.o
+
+obj-$(CONFIG_32BIT) += lshrdi3.o
+obj-$(CONFIG_32BIT) += ashldi3.o
+obj-$(CONFIG_32BIT) += ashrdi3.o
+
+obj-$(CONFIG_BUILTIN_DTB) += dtb.o
diff --git a/arch/riscv/lib/ashldi3.c b/arch/riscv/lib/ashldi3.c
new file mode 100644
index 0000000000..cbdbcbb6a9
--- /dev/null
+++ b/arch/riscv/lib/ashldi3.c
@@ -0,0 +1,28 @@
+#include <module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (unsigned int) uu.s.low << -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+		w.s.low = (unsigned int) uu.s.low << b;
+		w.s.high = ((unsigned int) uu.s.high << b) | carries;
+	}
+
+	return w.ll;
+}
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/riscv/lib/ashrdi3.c b/arch/riscv/lib/ashrdi3.c
new file mode 100644
index 0000000000..928d6d97ce
--- /dev/null
+++ b/arch/riscv/lib/ashrdi3.c
@@ -0,0 +1,30 @@
+#include <module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high =
+		    uu.s.high >> 31;
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c
new file mode 100644
index 0000000000..22f382b71e
--- /dev/null
+++ b/arch/riscv/lib/asm-offsets.c
@@ -0,0 +1,12 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ */
+
+#include <linux/kbuild.h>
+
+int main(void)
+{
+	return 0;
+}
diff --git a/arch/riscv/lib/barebox.lds.S b/arch/riscv/lib/barebox.lds.S
new file mode 100644
index 0000000000..9468fb8b5e
--- /dev/null
+++ b/arch/riscv/lib/barebox.lds.S
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Antony Pavlov <antonynpavlov at 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 <asm-generic/barebox.lds.h>
+
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+SECTIONS
+{
+	. = TEXT_BASE;
+
+	. = ALIGN(8);
+	.text      :
+	{
+		_stext = .;
+		_start = .;
+		KEEP(*(.text_entry*))
+		_text = .;
+		__bare_init_start = .;
+		*(.text_bare_init*)
+		__bare_init_end = .;
+		*(.text*)
+	}
+	BAREBOX_BARE_INIT_SIZE
+
+	PRE_IMAGE
+
+	. = ALIGN(8);
+	.rodata : { *(.rodata*) }
+
+	_etext = .;			/* End of text and rodata section */
+	_sdata = .;
+
+	. = ALIGN(8);
+	.data : { *(.data*) }
+
+	.barebox_imd : { BAREBOX_IMD }
+
+	. = ALIGN(8);
+	.got : { *(.got*) }
+
+	. = .;
+	__barebox_cmd_start = .;
+	.barebox_cmd : { BAREBOX_CMDS }
+	__barebox_cmd_end = .;
+
+	__barebox_magicvar_start = .;
+	.barebox_magicvar : { BAREBOX_MAGICVARS }
+	__barebox_magicvar_end = .;
+
+	__barebox_initcalls_start = .;
+	.barebox_initcalls : { INITCALLS }
+	__barebox_initcalls_end = .;
+
+	__barebox_exitcalls_start = .;
+	.barebox_exitcalls : { EXITCALLS }
+	__barebox_exitcalls_end = .;
+
+	__usymtab_start = .;
+	__usymtab : { BAREBOX_SYMS }
+	__usymtab_end = .;
+
+	.rela.dyn : { *(.rela*) }
+
+	.oftables : { BAREBOX_CLK_TABLE() }
+
+	.dtb : { BAREBOX_DTB() }
+
+	_edata = .;
+	. = ALIGN(8);
+	__bss_start = .;
+	.bss : { *(.bss*) *(.sbss*) }
+	__bss_stop = .;
+	_end = .;
+}
diff --git a/arch/riscv/lib/dtb.c b/arch/riscv/lib/dtb.c
new file mode 100644
index 0000000000..09f519dcc2
--- /dev/null
+++ b/arch/riscv/lib/dtb.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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 <of.h>
+
+extern char __dtb_start[];
+
+static int of_riscv_init(void)
+{
+	struct device_node *root;
+
+	root = of_get_root_node();
+	if (root)
+		return 0;
+
+	root = of_unflatten_dtb(__dtb_start);
+	if (!IS_ERR(root)) {
+		pr_debug("using internal DTB\n");
+		of_set_root_node(root);
+		if (IS_ENABLED(CONFIG_OFDEVICE))
+			of_probe();
+	}
+
+	return 0;
+}
+core_initcall(of_riscv_init);
diff --git a/arch/riscv/lib/libgcc.h b/arch/riscv/lib/libgcc.h
new file mode 100644
index 0000000000..593e598022
--- /dev/null
+++ b/arch/riscv/lib/libgcc.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+	int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+	int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union {
+	struct DWstruct s;
+	long long ll;
+} DWunion;
+
+long long __lshrdi3(long long u, word_type b);
+long long __ashldi3(long long u, word_type b);
+long long __ashrdi3(long long u, word_type b);
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/riscv/lib/lshrdi3.c b/arch/riscv/lib/lshrdi3.c
new file mode 100644
index 0000000000..74a4846e97
--- /dev/null
+++ b/arch/riscv/lib/lshrdi3.c
@@ -0,0 +1,28 @@
+#include <module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (unsigned int) uu.s.high >> -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+		w.s.high = (unsigned int) uu.s.high >> b;
+		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/riscv/lib/riscv_timer.c b/arch/riscv/lib/riscv_timer.c
new file mode 100644
index 0000000000..0bae8e9a89
--- /dev/null
+++ b/arch/riscv/lib/riscv_timer.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 Antony Pavlov <antonynpavlov at 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.
+ *
+ */
+
+/**
+ * @file
+ * @brief Clocksource based on RISCV cycle CSR timer
+ */
+
+#include <init.h>
+#include <of.h>
+#include <linux/clk.h>
+#include <clock.h>
+
+static uint64_t rdcycle_read(void)
+{
+	register unsigned long __v;
+
+	__asm__ __volatile__ ("rdcycle %0" : "=r" (__v));
+
+	return __v;
+}
+
+static struct clocksource rdcycle_cs = {
+	.read	= rdcycle_read,
+	.mask	= CLOCKSOURCE_MASK(32),
+};
+
+static int rdcycle_cs_init(void)
+{
+	unsigned int cycle_frequency;
+
+	/* default rate: 100 MHz */
+	cycle_frequency = 100000000;
+
+	if (IS_ENABLED(CONFIG_OFTREE)) {
+		struct device_node *np;
+		struct clk *clk;
+
+		np = of_get_cpu_node(0, NULL);
+		if (np) {
+			clk = of_clk_get(np, 0);
+			if (!IS_ERR(clk)) {
+				cycle_frequency = clk_get_rate(clk);
+			}
+		}
+	}
+
+	clocks_calc_mult_shift(&rdcycle_cs.mult, &rdcycle_cs.shift,
+		cycle_frequency, NSEC_PER_SEC, 10);
+
+	return init_clock(&rdcycle_cs);
+}
+postcore_initcall(rdcycle_cs_init);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index a1fac0e613..24cf4465a8 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 || EFI_BOOTUP || OPENRISC || SANDBOX
+	depends on PPC || ARM || EFI_BOOTUP || OPENRISC || SANDBOX || RISCV
 	def_bool y
 
 config DTC
-- 
2.17.0



From antonynpavlov at gmail.com  Sun Apr 15 04:28:58 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Sun, 15 Apr 2018 14:28:58 +0300
Subject: [PATCH 10/10] Documentation: add RISC-V docs
In-Reply-To: <20180415112858.5163-1-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
Message-ID: <20180415112858.5163-11-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/boards/riscv.rst | 106 +++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/Documentation/boards/riscv.rst b/Documentation/boards/riscv.rst
new file mode 100644
index 0000000000..0cde02305e
--- /dev/null
+++ b/Documentation/boards/riscv.rst
@@ -0,0 +1,106 @@
+RISC-V
+======
+
+Running RISC-V barebox on qemu
+------------------------------
+
+Obtain RISC-V GCC/Newlib Toolchain,
+see https://github.com/riscv/riscv-tools/blob/master/README.md
+for details. The ``build.sh`` script from ``riscv-tools`` should
+create toolchain.
+
+Next compile qemu emulator::
+
+  $ git clone -b 20180409.erizo https://github.com/miet-riscv-workgroup/riscv-qemu
+  $ cd riscv-qemu
+  $ cap="no" ./configure \
+    --extra-cflags="-Wno-maybe-uninitialized" \
+    --audio-drv-list="" \
+    --disable-attr \
+    --disable-blobs \
+    --disable-bluez \
+    --disable-brlapi \
+    --disable-curl \
+    --disable-curses \
+    --disable-docs \
+    --disable-kvm \
+    --disable-spice \
+    --disable-sdl \
+    --disable-vde \
+    --disable-vnc-sasl \
+    --disable-werror \
+    --enable-trace-backend=simple \
+    --disable-stack-protector \
+    --target-list=riscv32-softmmu,riscv64-softmmu
+  $ make
+
+
+Next compile barebox::
+
+  $ make erizo_generic_defconfig ARCH=riscv
+  ...
+  $ make ARCH=riscv CROSS_COMPILE=<path to your riscv toolchain>/riscv32-unknown-elf-
+
+Run barebox::
+
+  $ <path to riscv-qemu source>/riscv32-softmmu/qemu-system-riscv32 \
+      -nographic -M erizo -bios <path to barebox sources >/barebox.bin \
+      -serial stdio -monitor none -trace file=/dev/null
+
+  nmon> q
+  
+  copy loop done
+  restarting...
+  
+  nmon> q
+  Switch to console [cs0]
+  
+  
+  barebox 2018.04.0-00140-gc717a0b017 #0 Sun Apr 15 11:30:42 MSK 2018
+  
+  
+  Board: generic Erizo SoC board
+  m25p80 m25p128 at 00: unrecognized JEDEC id bytes: 00,  0,  0
+  m25p80 m25p128 at 00: probe failed: error 2
+  malloc space: 0x80100000 -> 0x801fffff (size 1 MiB)
+  running /env/bin/init...
+  /env/bin/init not found
+  barebox:/
+
+
+Running RISC-V barebox on DE0-Nano FPGA board
+---------------------------------------------
+
+See https://github.com/open-design/riscv-soc-cores/ for instructions
+on DE0-Nano bitstream generation and loading.
+
+Connect to board's UART with your favorite serial communication software
+(e.g. minicom) and check 'nmon> ' prompt (nmon runs from onchip ROM).
+
+Next close your communication software and use ./scripts/nmon-loader
+to load barebox image into board's DRAM, e.g.
+
+  # ./scripts/nmon-loader barebox.erizo.nmon /dev/ttyUSB0 115200
+
+Wait several munutes for 'nmon> ' prompt.
+
+Next, start barebox from DRAM:
+
+  nmon> g 80000000
+
+You should see one more 'nmon> ' prompt (this nmon runs from DRAM).
+Exit nmon with 'q' command:
+
+  nmon> q
+  Switch to console [cs0]
+  
+  
+  barebox 2018.04.0-00140-gc717a0b017 #0 Sun Apr 15 11:30:42 MSK 2018
+  
+  
+  Board: generic Erizo SoC board
+  m25p80 m25p128 at 00: s25sl064p (8192 Kbytes)
+  malloc space: 0x80100000 -> 0x801fffff (size 1 MiB)
+  running /env/bin/init...
+  /env/bin/init not found
+  barebox:/ 
-- 
2.17.0



From u.kleine-koenig at pengutronix.de  Sun Apr 15 11:27:58 2018
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Sun, 15 Apr 2018 20:27:58 +0200
Subject: [PATCH 4/4] pci: don't hide hard to understand sanity check in
 size calculation
In-Reply-To: <CAHQ1cqFkU=9aPg9xr3gbmApgx-rSfM3toH3m-Br3=PjN1Voqvw@mail.gmail.com>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
 <20180413233053.15570-4-u.kleine-koenig@pengutronix.de>
 <CAHQ1cqFkU=9aPg9xr3gbmApgx-rSfM3toH3m-Br3=PjN1Voqvw@mail.gmail.com>
Message-ID: <20180415182758.2gvkmxp7e5zzxtev@pengutronix.de>

Hello Andrey,

On Sat, Apr 14, 2018 at 09:25:59AM -0700, Andrey Smirnov wrote:
> On Fri, Apr 13, 2018 at 4:30 PM, Uwe Kleine-K?nig
> <u.kleine-koenig at pengutronix.de> wrote:
> > +               /*
> > +                * if maxbase isn't in the form 0b1...10...0 there is something
> > +                * fishy
> > +                */
> > +               if ((maxbase | (maxbase - 1)) != (u32)-1 || maxbase == 0) {
> 
> U32_MAX instead of (u32)-1 ?

I don't feel strong here. Given that the LHS uses some characteristics
of the binary representation I slightly prefer (u32)-1, but I can change
it to U32_MAX, too.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From s.hauer at pengutronix.de  Mon Apr 16 00:00:59 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:00:59 +0200
Subject: [PATCH v2 0/5] Linux's serdev framwork port
In-Reply-To: <20180412213317.13199-1-andrew.smirnov@gmail.com>
References: <20180412213317.13199-1-andrew.smirnov@gmail.com>
Message-ID: <20180416070059.zxdebttdji7yi6rr@pengutronix.de>

On Thu, Apr 12, 2018 at 02:33:12PM -0700, Andrey Smirnov wrote:
> Hi everyone:
> 
> In an effort to bring this kernel driver
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mfd/rave-sp.c?h=v4.16-rc7
> to Barebox, I ended up creating a miniature and extremely simplified
> version of 'serdev' subsystem which is presented in this patchset.
> 
> Changes since [v1]:
> 
> 	- Blocking read function was added as example of API usage
> 
> 	- "serial: Check result of console_unregister()" was converted
>           to become "serial: Drop .remove functions from all drivers"
> 
> 	- Minor spelling fixes
> 
> 	- Original serdev framework patch modified to allow devices
>           that do not require polling (I don't have such a usecase,
>           but for the sake of being generic I added one line needed
>           for that)
> 
> 	- SERIAL_DEV_BUS Kconfig symbol moved into
>           drivers/serial/Kconfig (where it, IMHO, fits much better)
> 
> 	- Added a patch to dynamically adjust serdev's polling
>           interval via device paramter. This was warranted by the
>           problems that arose from real-life usage.
> 
> Feedback is wellcome!
> 
> Thanks,
> Andrey Smirnov
> 
> [v1] https://www.spinics.net/lists/u-boot-v2/msg32322.html

Applied, thanks

Sascha

> 
> Andrey Smirnov (5):
>   console: Introduce console_drain()
>   console: Add simplified 'serdev' framework from Linux kernel
>   serdev: Add trivial blocking read function
>   serial: Drop .remove functions from all drivers
>   serdev: Allow polling interval to be adjusted at runtime
> 
>  common/Makefile                  |   1 +
>  common/console.c                 |  24 ++++-
>  common/serdev.c                  | 208 +++++++++++++++++++++++++++++++++++++++
>  drivers/serial/Kconfig           |   6 ++
>  drivers/serial/serial_auart.c    |  11 ---
>  drivers/serial/serial_cadence.c  |   9 --
>  drivers/serial/serial_clps711x.c |  10 --
>  drivers/serial/serial_imx.c      |  10 --
>  drivers/serial/serial_lpuart.c   |  13 ---
>  drivers/serial/serial_pxa.c      |   9 --
>  drivers/serial/serial_s3c.c      |  10 --
>  drivers/serial/stm-serial.c      |  10 --
>  include/console.h                | 110 +++++++++++++++++++++
>  include/serdev.h                 |  44 +++++++++
>  lib/xymodem.c                    |  30 +-----
>  15 files changed, 395 insertions(+), 110 deletions(-)
>  create mode 100644 common/serdev.c
>  create mode 100644 include/serdev.h
> 
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:02:26 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:02:26 +0200
Subject: [PATCH] gitignore: Add *.pblx files
In-Reply-To: <20180412213859.13742-1-andrew.smirnov@gmail.com>
References: <20180412213859.13742-1-andrew.smirnov@gmail.com>
Message-ID: <20180416070226.eo7m73hutac5y2oj@pengutronix.de>

On Thu, Apr 12, 2018 at 02:38:59PM -0700, Andrey Smirnov wrote:
> Looks like *.pblx was accidentally dropped from ignored files list and
> now my "git status" is clobbered by every *.pblx image that is being
> built (that's quite a lot for imx_v7_defconfig). Re-add original rule
> to prevent that.
> 
> Fixes eed8a41c5 ("gitignore: ignore pblx.simximg files")
> 
> Cc: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>

Applied, thanks

I usually don't see these because I always build out of tree.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:03:58 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:03:58 +0200
Subject: [PATCH] serial/lpuart: Do not enable UART FIFO
In-Reply-To: <20180412214143.17074-1-andrew.smirnov@gmail.com>
References: <20180412214143.17074-1-andrew.smirnov@gmail.com>
Message-ID: <20180416070358.oaeekhxwsbuycafj@pengutronix.de>

On Thu, Apr 12, 2018 at 02:41:43PM -0700, Andrey Smirnov wrote:
> Using FIFO in LPUART results in subtle serial input draining issues
> which are quite difficult to reproduce and troubleshoot. Since the
> change offered only moderate performance gain revert the code to
> operate in no-FIFO mode to avoid FIFO-related problems alltogether.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>

Applied, thanks

Sascha

> ---
>  drivers/serial/serial_lpuart.c |  4 +---
>  include/serial/lpuart.h        | 21 +++++----------------
>  2 files changed, 6 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
> index 52fb6d39c..8f87f7b9c 100644
> --- a/drivers/serial/serial_lpuart.c
> +++ b/drivers/serial/serial_lpuart.c
> @@ -170,9 +170,7 @@ static int lpuart_serial_probe(struct device_d *dev)
>  
>  	cdev->linux_console_name = "ttyLP";
>  
> -	lpuart_setup_with_fifo(lpuart->base,
> -			       clk_get_rate(lpuart->clk),
> -			       15);
> +	lpuart_setup(lpuart->base, clk_get_rate(lpuart->clk));
>  
>  	ret = console_register(cdev);
>  	if (!ret) {
> diff --git a/include/serial/lpuart.h b/include/serial/lpuart.h
> index 917f644a5..a920291de 100644
> --- a/include/serial/lpuart.h
> +++ b/include/serial/lpuart.h
> @@ -238,22 +238,17 @@ static inline void lpuart_setbrg(void __iomem *base,
>  	writeb(bfra, base + UARTCR4);
>  }
>  
> -static inline void lpuart_setup_with_fifo(void __iomem *base,
> -					  unsigned int refclock,
> -					  unsigned int twfifo)
> +static inline void lpuart_setup(void __iomem *base,
> +				unsigned int refclock)
>  {
>  	/* Disable UART */
>  	writeb(0, base + UARTCR2);
>  	writeb(0, base + UARTMODEM);
>  	writeb(0, base + UARTCR1);
>  
> -	if (twfifo) {
> -		writeb(UARTPFIFO_TXFE | UARTPFIFO_RXFE, base + UARTPFIFO);
> -		writeb((u8)twfifo, base + UARTTWFIFO);
> -	} else {
> -		writeb(0, base + UARTPFIFO);
> -		writeb(0, base + UARTTWFIFO);
> -	}
> +	writeb(0, base + UARTPFIFO);
> +	writeb(0, base + UARTTWFIFO);
> +
>  	writeb(1, base + UARTRWFIFO);
>  	writeb(UARTCFIFO_RXFLUSH | UARTCFIFO_TXFLUSH, base + UARTCFIFO);
>  
> @@ -262,12 +257,6 @@ static inline void lpuart_setup_with_fifo(void __iomem *base,
>  	writeb(UARTCR2_TE | UARTCR2_RE, base + UARTCR2);
>  }
>  
> -static inline void lpuart_setup(void __iomem *base,
> -				unsigned int refclock)
> -{
> -	lpuart_setup_with_fifo(base, refclock, 0x00);
> -}
> -
>  static inline void lpuart_putc(void __iomem *base, int c)
>  {
>  	if (!(readb(base + UARTCR2) & UARTCR2_TE))
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:13:04 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:13:04 +0200
Subject: [PATCH 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <20180414175024.9962-4-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-4-andrew.smirnov@gmail.com>
Message-ID: <20180416071304.2gm2b6noqof3kokw@pengutronix.de>

Hi Andrey,

On Sat, Apr 14, 2018 at 10:50:17AM -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/imx6.c                      | 4 +++-
>  arch/arm/mach-imx/include/mach/reset-reason.h | 2 ++
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
> index 14a1cba5a..3d81c2785 100644
> --- a/arch/arm/mach-imx/imx6.c
> +++ b/arch/arm/mach-imx/imx6.c
> @@ -19,6 +19,7 @@
>  #include <mach/imx6.h>
>  #include <mach/generic.h>
>  #include <mach/revision.h>
> +#include <mach/reset-reason.h>
>  #include <mach/imx6-anadig.h>
>  #include <mach/imx6-regs.h>
>  #include <mach/generic.h>
> @@ -151,6 +152,7 @@ int imx6_init(void)
>  {
>  	const char *cputypestr;
>  	u32 mx6_silicon_revision;
> +	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
>  
>  	imx6_init_lowlevel();
>  
> @@ -195,7 +197,7 @@ int imx6_init(void)
>  	}
>  
>  	imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
> -
> +	imx_set_reset_reason(src + IMX6_SRC_SRSR);

This will get overwritten by the watchdog driver if enabled.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:13:31 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:13:31 +0200
Subject: [PATCH 04/10] ARM: i.MX7: Record reset reason as a part of startup
In-Reply-To: <20180414175024.9962-5-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-5-andrew.smirnov@gmail.com>
Message-ID: <20180416071331.fsoqfwgti36uyxc3@pengutronix.de>

On Sat, Apr 14, 2018 at 10:50:18AM -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/imx7.c                      | 3 +++
>  arch/arm/mach-imx/include/mach/reset-reason.h | 1 +
>  2 files changed, 4 insertions(+)
> 
> diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c
> index 4eef99c87..a5debd06c 100644
> --- a/arch/arm/mach-imx/imx7.c
> +++ b/arch/arm/mach-imx/imx7.c
> @@ -19,6 +19,7 @@
>  #include <mach/imx7.h>
>  #include <mach/generic.h>
>  #include <mach/revision.h>
> +#include <mach/reset-reason.h>
>  #include <mach/imx7-regs.h>
>  
>  void imx7_init_lowlevel(void)
> @@ -171,6 +172,7 @@ int imx7_init(void)
>  {
>  	const char *cputypestr;
>  	u32 imx7_silicon_revision;
> +	void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR);
>  
>  	imx7_init_lowlevel();
>  
> @@ -197,6 +199,7 @@ int imx7_init(void)
>  	}
>  
>  	imx_set_silicon_revision(cputypestr, imx7_silicon_revision);
> +	imx_set_reset_reason(src + IMX7_SRC_SRSR);

Same here.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:19:51 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:19:51 +0200
Subject: [PATCH 08/10] ARM: VFxxx: Add code to detect reset reason
In-Reply-To: <20180414175024.9962-9-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-9-andrew.smirnov@gmail.com>
Message-ID: <20180416071951.2is6xqlwlzju4wk2@pengutronix.de>

On Sat, Apr 14, 2018 at 10:50:22AM -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/imx.c                       | 78 +++++++++++++++++----------
>  arch/arm/mach-imx/include/mach/reset-reason.h | 11 ++++
>  2 files changed, 62 insertions(+), 27 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
> index fb1160de9..e84713766 100644
> --- a/arch/arm/mach-imx/imx.c
> +++ b/arch/arm/mach-imx/imx.c
> @@ -158,6 +158,7 @@ void imx_set_reset_reason(void __iomem *srsr)
>  {
>  	enum reset_src_type type = RESET_UKWN;
>  	const u32 reg = readl(srsr);
> +	const bool is_vf610 = cpu_is_vf610();
>  
>  	/*
>  	 * SRSR register captures ALL reset event that occured since
> @@ -166,37 +167,60 @@ void imx_set_reset_reason(void __iomem *srsr)
>  	 */
>  	writel(reg, srsr);
>  
> -	switch (reg) {
> -	case IMX_SRC_SRSR_IPP_RESET: /* FALLTHROUGH */
> -	case IMX_SRC_SRSR_IPP_RESET | IMX_SRC_SRSR_WDOG1_RESET:
> -		type = RESET_POR;
> -		break;
> -	case IMX_SRC_SRSR_WDOG3_RESET: /* FALLTHROUGH */
> -	case IMX_SRC_SRSR_WDOG4_RESET: /* FALLTHROUGH */
> -	case IMX_SRC_SRSR_WDOG1_RESET:
> -		type = RESET_WDG;
> -		break;
> -	case IMX_SRC_SRSR_JTAG_RESET: /* FALLTHROUGH */
> -	case IMX_SRC_SRSR_JTAG_SW_RESET:
> -		type = RESET_JTAG;
> -		break;
> -	case IMX_SRC_SRSR_TEMPSENSE_RESET:
> -		type = RESET_THERM;
> -		break;
> -	case IMX_SRC_SRSR_WARM_BOOT:
> -		type = RESET_RST;
> -		break;
> +	if (is_vf610) {

The caller already knows this is a vf610 and the code path for vf610 is
completely different. Please add a vf610_set_reset_reason() instead of
clobbering the i.MX function with this.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:37:27 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:37:27 +0200
Subject: [PATCH 02/17] ARM: i.MX: Add function to extract BMOD value
In-Reply-To: <20180414175103.10125-3-andrew.smirnov@gmail.com>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
 <20180414175103.10125-3-andrew.smirnov@gmail.com>
Message-ID: <20180416073727.z777ff4fuecb2anv@pengutronix.de>

On Sat, Apr 14, 2018 at 10:50:48AM -0700, Andrey Smirnov wrote:
> The location of BMDO field in SBMR/SBMR2 registers is consistent
> across all i.MX SoCs starting from i.MX53. Add simple helper function
> imx53_get_bmod and use it to avoid code duplication.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/boot.c | 25 ++++++++++++++-----------
>  1 file changed, 14 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> index 4657fa017..56f9fb5d4 100644
> --- a/arch/arm/mach-imx/boot.c
> +++ b/arch/arm/mach-imx/boot.c
> @@ -169,12 +169,23 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
>  }
>  
>  #define IMX53_SRC_SBMR	0x4
> +
> +static unsigned int sbmr(uint32_t r, unsigned int msb, unsigned int lsb)
> +{
> +	return (r & GENMASK(msb, lsb)) >> lsb;
> +}

If you like GENMASK then maybe the FIELD_GET and FIELD_PREP macros from
the Linux kernel are for you aswell.

#define SRC_SBMR_BMOD	GENMASK(25, 24)

> +
> +static unsigned int imx53_get_bmod(uint32_t r)
> +{
> +	return sbmr(r, 25, 24);

return FIELD_GET(SRC_SBMR_BMOD, r);

Sascha

> +}
> +
>  void imx53_get_boot_source(enum bootsource *src, int *instance)
>  {
>  	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
>  	uint32_t cfg1 = readl(src_base + IMX53_SRC_SBMR);
>  
> -	if (((cfg1 >> 24) & 0x3) == 0x3) {
> +	if (imx53_get_bmod(cfg1) == 0x3) {
>  		*src = BOOTSOURCE_USB;
>  		*instance = 0;
>  		return;
> @@ -225,12 +236,8 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
>  	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
>  	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
>  	uint32_t boot_cfg_4_2_0;
> -	int boot_mode;
>  
> -	/* BMOD[1:0] */
> -	boot_mode = (sbmr2 >> 24) & 0x3;
> -
> -	switch (boot_mode) {
> +	switch (imx53_get_bmod(sbmr2)) {
>  	case 0: /* Fuses, fall through */
>  	case 2: /* internal boot */
>  		goto internal_boot;
> @@ -290,12 +297,8 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
>  	void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR);
>  	uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1);
>  	uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2);
> -	int boot_mode;
> -
> -	/* BMOD[1:0] */
> -	boot_mode = (sbmr2 >> 24) & 0x3;
>  
> -	switch (boot_mode) {
> +	switch (imx53_get_bmod(sbmr2)) {
>  	case 0: /* Fuses, fall through */
>  	case 2: /* internal boot */
>  		goto internal_boot;
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 00:56:20 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 09:56:20 +0200
Subject: [PATCH v2 1/2] common: state: Add property to protect existing
 data
In-Reply-To: <1523524382-19217-1-git-send-email-d.schultz@phytec.de>
References: <1523524382-19217-1-git-send-email-d.schultz@phytec.de>
Message-ID: <20180416075620.plnlyaoppuazuy4r@pengutronix.de>

On Thu, Apr 12, 2018 at 11:13:01AM +0200, Daniel Schultz wrote:
> After an update to a newer barebox version with an enabled state
> framework, existing data in storage memories could be overwritten.
> 
> Add a new property to check in front of every write task, if the meta
> magic field only contains the magic number, zeros or ones.
> 
> Signed-off-by: Daniel Schultz <d.schultz at phytec.de>
> ---
> Changes:
> 	v2: Added check for circular backend
> 	    Improved error message if content was found
> 

Applied, thanks

Sascha

>  .../devicetree/bindings/barebox/barebox,state.rst     |  3 +++
>  common/state/backend_bucket_circular.c                |  8 +++++---
>  common/state/backend_bucket_direct.c                  |  2 ++
>  common/state/state.c                                  | 19 ++++++++++++++++++-
>  common/state/state.h                                  |  2 ++
>  5 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
> index 872bac0..2893937 100644
> --- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
> +++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
> @@ -55,6 +55,9 @@ Optional Properties
>  * ``algo``: A HMAC algorithm used to detect manipulation of the data
>    or header, sensible values follow this pattern ``hmac(<HASH>)``,
>    e.g. ``hmac(sha256)``. Only available for the ``backend-type`` ``raw``.
> +* ``keep-previous-content``: Check if a the bucket meta magic field contains
> +  other data than the magic value. If so, the backend will not write the state
> +  to prevent unconditionally overwrites of existing data.
>  
>  .. note:: For the ``backend-storage-type`` the keyword ``noncircular`` is still
>     supported as a fall back to an old storage format. Recommendation is to not
> diff --git a/common/state/backend_bucket_circular.c b/common/state/backend_bucket_circular.c
> index 2324903..933493e 100644
> --- a/common/state/backend_bucket_circular.c
> +++ b/common/state/backend_bucket_circular.c
> @@ -396,11 +396,13 @@ static int state_backend_bucket_circular_init(
>  			meta = (struct state_backend_storage_bucket_circular_meta *)
>  					(buf + sub_offset + circ->writesize - sizeof(*meta));
>  
> -			if (meta->magic != circular_magic)
> +			if (meta->magic != circular_magic) {
>  				written_length = 0;
> -			else
> +				if (meta->magic != ~0 && !!meta->magic)
> +					bucket->wrong_magic = 1;
> +			} else {
>  				written_length = meta->written_length;
> -
> +			}
>  			break;
>  		}
>  	}
> diff --git a/common/state/backend_bucket_direct.c b/common/state/backend_bucket_direct.c
> index 958696e..9d6a337 100644
> --- a/common/state/backend_bucket_direct.c
> +++ b/common/state/backend_bucket_direct.c
> @@ -69,6 +69,8 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
>  	if (meta.magic == direct_magic) {
>  		read_len = meta.written_length;
>  	} else {
> +		if (meta.magic != ~0 && !!meta.magic)
> +			bucket->wrong_magic = 1;
>  		if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
>  			dev_err(direct->dev, "No meta data header found\n");
>  			dev_dbg(direct->dev, "Enable backward compatibility or increase stride size\n");
> diff --git a/common/state/state.c b/common/state/state.c
> index 73dfb58..25d9502 100644
> --- a/common/state/state.c
> +++ b/common/state/state.c
> @@ -44,6 +44,8 @@ int state_save(struct state *state)
>  	void *buf;
>  	ssize_t len;
>  	int ret;
> +	struct state_backend_storage_bucket *bucket;
> +	struct state_backend_storage *storage;
>  
>  	if (!state->dirty)
>  		return 0;
> @@ -55,7 +57,19 @@ int state_save(struct state *state)
>  		return ret;
>  	}
>  
> -	ret = state_storage_write(&state->storage, buf, len);
> +	storage = &state->storage;
> +	if (state->keep_prev_content) {
> +		bool has_content = 0;
> +		list_for_each_entry(bucket, &storage->buckets, bucket_list)
> +			has_content |= bucket->wrong_magic;
> +		if (has_content) {
> +			dev_err(&state->dev, "Found foreign content on backend, won't overwrite.\n");
> +			ret = -EPERM;
> +			goto out;
> +		}
> +	}
> +
> +	ret = state_storage_write(storage, buf, len);
>  	if (ret) {
>  		dev_err(&state->dev, "Failed to write packed state, %d\n", ret);
>  		goto out;
> @@ -623,6 +637,9 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
>  
>  	of_property_read_string(node, "backend-storage-type", &storage_type);
>  
> +	state->keep_prev_content = of_property_read_bool(node,
> +							"keep-previous-content");
> +
>  	ret = state_format_init(state, backend_type, node, alias);
>  	if (ret)
>  		goto out_release_state;
> diff --git a/common/state/state.h b/common/state/state.h
> index 6670523..3a0662f 100644
> --- a/common/state/state.h
> +++ b/common/state/state.h
> @@ -46,6 +46,7 @@ struct state_backend_storage_bucket {
>  	void *buf;
>  	ssize_t len;
>  	bool needs_refresh;
> +	bool wrong_magic;
>  };
>  
>  /**
> @@ -105,6 +106,7 @@ struct state {
>  	char *of_path;
>  	const char *name;
>  	uint32_t magic;
> +	bool keep_prev_content;
>  
>  	struct list_head variables; /* Sorted list of variables */
>  
> -- 
> 2.7.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 01:00:14 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 16 Apr 2018 10:00:14 +0200
Subject: [PATCH 4/4] clk: i.MX6: Fix enfc_sel for i.MX6dqp
In-Reply-To: <20180411132654.10620-5-s.hauer@pengutronix.de>
References: <20180411132654.10620-1-s.hauer@pengutronix.de>
 <20180411132654.10620-5-s.hauer@pengutronix.de>
Message-ID: <20180416080014.fpl5mogcifb52r4w@pengutronix.de>

On Wed, Apr 11, 2018 at 03:26:54PM +0200, Sascha Hauer wrote:
> The plus SoC variants have some differences in the clock controller.
> For now fix the NAND controller clock. There are more differences
> that might be relevant, but for now are left for a future excercise.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/clk/imx/clk-imx6.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/imx/clk-imx6.c b/drivers/clk/imx/clk-imx6.c
> index c48ab7f76a..7f1af12571 100644
> --- a/drivers/clk/imx/clk-imx6.c
> +++ b/drivers/clk/imx/clk-imx6.c
> @@ -59,6 +59,11 @@
>  static struct clk *clks[IMX6QDL_CLK_END];
>  static struct clk_onecell_data clk_data;
>  
> +static inline int cpu_is_plus(void)
> +{
> +	return cpu_is_mx6qp() || cpu_is_mx6dp();
> +}
> +
>  static const char *step_sels[] = {
>  	"osc",
>  	"pll2_pfd2_396m",
> @@ -109,6 +114,15 @@ static const char *enfc_sels[]	= {
>  	"pll2_pfd2_396m",
>  };
>  
> +static const char *enfc_sels_plus[] = {
> +	"pll2_pfd0_352m",
> +	"pll2_bus",
> +	"pll3_usb_otg",
> +	"pll2_pfd2_396m",
> +	"pll3_pfd3_454m",
> +	"dummy",
> +};
> +
>  static const char *eim_sels[] = {
>  	"axi",
>  	"pll3_usb_otg",
> @@ -404,7 +418,10 @@ static int imx6_ccm_probe(struct device_d *dev)
>  	clks[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel",       base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
>  	clks[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_mux("usdhc3_sel",       base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
>  	clks[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_mux("usdhc4_sel",       base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
> -	clks[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
> +	if (cpu_is_plus())
> +		clks[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
> +	else
> +		clks[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels_plus,    ARRAY_SIZE(enfc_sels_plus));

The enfc_sels for plus and non plus version are swapped here. Fixed.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From baruch at tkos.co.il  Mon Apr 16 03:19:39 2018
From: baruch at tkos.co.il (Baruch Siach)
Date: Mon, 16 Apr 2018 13:19:39 +0300
Subject: Question about barebox*/drivers/mfd/mc34704.c and =?utf-8?Q?A?=
 =?utf-8?Q?CCURATE_I=C2=B2C?= mode ...
In-Reply-To: <38a86524d3ed4ff2b2306a3bb52fb312@eckelmann.de>
References: <38a86524d3ed4ff2b2306a3bb52fb312@eckelmann.de>
Message-ID: <20180416101939.yggybypgs3ahr76b@sapphire.tkos.co.il>

Hi Roland,

On Mon, Apr 16, 2018 at 09:52:14AM +0000, Mainz, Roland wrote:
> Two small questions about drivers/mfd/mc34704.c in the barebox codebase:
> 1. mc34704 has an ACCURATE bit (I2CSET1, see 
> https://www.nxp.com/docs/en/data-sheet/MC34704.pdf) which requires that all 
> read/write commands are send twice - does the barebox code have any support 
> for that in the current versions ?
> 2. Is this "accurate I?C communication mode" enabled by that bit a 
> vendor-specific protocol extension or is it part of the I?C standard ?

Please send your Barebox related questions to the barebox mailing list. I 
added the list to Cc.

To the best of my knowledge there is no "twice" mode in the I2C standard. The 
mc34704 driver does not seem to support this mode.

baruch

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -


From u.oelmann at pengutronix.de  Mon Apr 16 05:22:25 2018
From: u.oelmann at pengutronix.de (=?UTF-8?q?Ulrich=20=C3=96lmann?=)
Date: Mon, 16 Apr 2018 14:22:25 +0200
Subject: [PATCH 2/2] fs: remove shortcut in canonicalizing filenames
In-Reply-To: <20180416122225.6302-1-u.oelmann@pengutronix.de>
References: <20180416122225.6302-1-u.oelmann@pengutronix.de>
Message-ID: <20180416122225.6302-2-u.oelmann@pengutronix.de>

Only individually getting the file status for every part of the path tells us if
a symbolic link is involved or not. If this is the case the later call to
readlink will check if the filesystem supports symbolic links or not.

Hence this reverts commit d79a81736f64 ("fs: Don't bother filesystems without
link support with additional stat() calls").

Signed-off-by: Ulrich ?lmann <u.oelmann at pengutronix.de>
---
 fs/fs.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index 7c818eca024f..b2da0a62a29d 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -144,7 +144,6 @@ char *normalise_path(const char *pathname)
 EXPORT_SYMBOL(normalise_path);
 
 static int __lstat(const char *filename, struct stat *s);
-static struct fs_device_d *get_fsdevice_by_path(const char *path);
 
 static char *__canonicalize_path(const char *_pathname, int level)
 {
@@ -167,7 +166,6 @@ static char *__canonicalize_path(const char *_pathname, int level)
 		char *p = strsep(&path, "/");
 		char *tmp;
 		char link[PATH_MAX] = {};
-		struct fs_device_d *fsdev;
 
 		if (!p)
 			break;
@@ -186,14 +184,6 @@ static char *__canonicalize_path(const char *_pathname, int level)
 		free(outpath);
 		outpath = tmp;
 
-		/*
-		 * Don't bother filesystems without link support
-		 * with an additional stat() call.
-		 */
-		fsdev = get_fsdevice_by_path(outpath);
-		if (!fsdev || !fsdev->driver->readlink)
-			continue;
-
 		ret = __lstat(outpath, &s);
 		if (ret)
 			goto out;
-- 
2.16.3



From u.oelmann at pengutronix.de  Mon Apr 16 05:22:24 2018
From: u.oelmann at pengutronix.de (=?UTF-8?q?Ulrich=20=C3=96lmann?=)
Date: Mon, 16 Apr 2018 14:22:24 +0200
Subject: [PATCH 1/2] fs: fix error path in __canonicalize_path()
Message-ID: <20180416122225.6302-1-u.oelmann@pengutronix.de>

Report failure in resolving links to the caller and only clean up memory then.

Signed-off-by: Ulrich ?lmann <u.oelmann at pengutronix.de>
---
 fs/fs.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index 5135112c8b81..7c818eca024f 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -202,8 +202,11 @@ static char *__canonicalize_path(const char *_pathname, int level)
 			continue;
 
 		ret = readlink(outpath, link, PATH_MAX - 1);
-		if (ret < 0)
+		if (ret < 0) {
+			free(outpath);
+			outpath = ERR_PTR(ret);
 			goto out;
+		}
 
 		if (link[0] == '/') {
 			free(outpath);
@@ -218,14 +221,15 @@ static char *__canonicalize_path(const char *_pathname, int level)
 		if (IS_ERR(outpath))
 			goto out;
 	}
-out:
-	free(freep);
 
 	if (!*outpath) {
 		free(outpath);
 		outpath = xstrdup("/");
 	}
 
+out:
+	free(freep);
+
 	return outpath;
 }
 
-- 
2.16.3



From andrew.smirnov at gmail.com  Mon Apr 16 06:12:32 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 06:12:32 -0700
Subject: [PATCH 08/10] ARM: VFxxx: Add code to detect reset reason
In-Reply-To: <20180416071951.2is6xqlwlzju4wk2@pengutronix.de>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-9-andrew.smirnov@gmail.com>
 <20180416071951.2is6xqlwlzju4wk2@pengutronix.de>
Message-ID: <CAHQ1cqEvxmdTuEMPe-L-9puhNi_t_YvMxqY1RRVxQ6Uc96nZ=A@mail.gmail.com>

On Mon, Apr 16, 2018 at 12:19 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Sat, Apr 14, 2018 at 10:50:22AM -0700, Andrey Smirnov wrote:
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> ---
>>  arch/arm/mach-imx/imx.c                       | 78 +++++++++++++++++----------
>>  arch/arm/mach-imx/include/mach/reset-reason.h | 11 ++++
>>  2 files changed, 62 insertions(+), 27 deletions(-)
>>
>> diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
>> index fb1160de9..e84713766 100644
>> --- a/arch/arm/mach-imx/imx.c
>> +++ b/arch/arm/mach-imx/imx.c
>> @@ -158,6 +158,7 @@ void imx_set_reset_reason(void __iomem *srsr)
>>  {
>>       enum reset_src_type type = RESET_UKWN;
>>       const u32 reg = readl(srsr);
>> +     const bool is_vf610 = cpu_is_vf610();
>>
>>       /*
>>        * SRSR register captures ALL reset event that occured since
>> @@ -166,37 +167,60 @@ void imx_set_reset_reason(void __iomem *srsr)
>>        */
>>       writel(reg, srsr);
>>
>> -     switch (reg) {
>> -     case IMX_SRC_SRSR_IPP_RESET: /* FALLTHROUGH */
>> -     case IMX_SRC_SRSR_IPP_RESET | IMX_SRC_SRSR_WDOG1_RESET:
>> -             type = RESET_POR;
>> -             break;
>> -     case IMX_SRC_SRSR_WDOG3_RESET: /* FALLTHROUGH */
>> -     case IMX_SRC_SRSR_WDOG4_RESET: /* FALLTHROUGH */
>> -     case IMX_SRC_SRSR_WDOG1_RESET:
>> -             type = RESET_WDG;
>> -             break;
>> -     case IMX_SRC_SRSR_JTAG_RESET: /* FALLTHROUGH */
>> -     case IMX_SRC_SRSR_JTAG_SW_RESET:
>> -             type = RESET_JTAG;
>> -             break;
>> -     case IMX_SRC_SRSR_TEMPSENSE_RESET:
>> -             type = RESET_THERM;
>> -             break;
>> -     case IMX_SRC_SRSR_WARM_BOOT:
>> -             type = RESET_RST;
>> -             break;
>> +     if (is_vf610) {
>
> The caller already knows this is a vf610 and the code path for vf610 is
> completely different. Please add a vf610_set_reset_reason() instead of
> clobbering the i.MX function with this.
>

They do share code fore clearing RSRS register, but sure, will do in v2.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr 16 06:28:11 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 06:28:11 -0700
Subject: [PATCH 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <20180416071304.2gm2b6noqof3kokw@pengutronix.de>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-4-andrew.smirnov@gmail.com>
 <20180416071304.2gm2b6noqof3kokw@pengutronix.de>
Message-ID: <CAHQ1cqHjLt+UczgWu+_Pe3NLWZM6QWu_M07Odj_5++puaMNs3w@mail.gmail.com>

On Mon, Apr 16, 2018 at 12:13 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> Hi Andrey,
>
> On Sat, Apr 14, 2018 at 10:50:17AM -0700, Andrey Smirnov wrote:
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> ---
>>  arch/arm/mach-imx/imx6.c                      | 4 +++-
>>  arch/arm/mach-imx/include/mach/reset-reason.h | 2 ++
>>  2 files changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
>> index 14a1cba5a..3d81c2785 100644
>> --- a/arch/arm/mach-imx/imx6.c
>> +++ b/arch/arm/mach-imx/imx6.c
>> @@ -19,6 +19,7 @@
>>  #include <mach/imx6.h>
>>  #include <mach/generic.h>
>>  #include <mach/revision.h>
>> +#include <mach/reset-reason.h>
>>  #include <mach/imx6-anadig.h>
>>  #include <mach/imx6-regs.h>
>>  #include <mach/generic.h>
>> @@ -151,6 +152,7 @@ int imx6_init(void)
>>  {
>>       const char *cputypestr;
>>       u32 mx6_silicon_revision;
>> +     void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
>>
>>       imx6_init_lowlevel();
>>
>> @@ -195,7 +197,7 @@ int imx6_init(void)
>>       }
>>
>>       imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
>> -
>> +     imx_set_reset_reason(src + IMX6_SRC_SRSR);
>
> This will get overwritten by the watchdog driver if enabled.
>

I am not sure I see how. Imx_watchdog_detect_reset_source() reports
reset sources with the same priority as this code, so
reset_source_set_priority() should bail out early without changing
anything in that case.

Regardless, even if it were true, I think that behavior is perfectly
OK. First of all, startup log will still be present, which is IMHO
pretty useful. Second, the platforms that doen't use/rely on built-in
watchdog would benefit from this.

Another thing we can do is add code to respect "reset-source-priority"
to imxwd.c, so that people could ajdust what reset source info they
want to see via DT.

Let me know what you think.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr 16 06:36:50 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 06:36:50 -0700
Subject: [PATCH 02/17] ARM: i.MX: Add function to extract BMOD value
In-Reply-To: <20180416073727.z777ff4fuecb2anv@pengutronix.de>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
 <20180414175103.10125-3-andrew.smirnov@gmail.com>
 <20180416073727.z777ff4fuecb2anv@pengutronix.de>
Message-ID: <CAHQ1cqGu5HDLNF+g8WMXUZvLwHgd=89NCEEo=Nbn9KA_X5-DGw@mail.gmail.com>

On Mon, Apr 16, 2018 at 12:37 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Sat, Apr 14, 2018 at 10:50:48AM -0700, Andrey Smirnov wrote:
>> The location of BMDO field in SBMR/SBMR2 registers is consistent
>> across all i.MX SoCs starting from i.MX53. Add simple helper function
>> imx53_get_bmod and use it to avoid code duplication.
>>
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> ---
>>  arch/arm/mach-imx/boot.c | 25 ++++++++++++++-----------
>>  1 file changed, 14 insertions(+), 11 deletions(-)
>>
>> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
>> index 4657fa017..56f9fb5d4 100644
>> --- a/arch/arm/mach-imx/boot.c
>> +++ b/arch/arm/mach-imx/boot.c
>> @@ -169,12 +169,23 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
>>  }
>>
>>  #define IMX53_SRC_SBMR       0x4
>> +
>> +static unsigned int sbmr(uint32_t r, unsigned int msb, unsigned int lsb)
>> +{
>> +     return (r & GENMASK(msb, lsb)) >> lsb;
>> +}
>
> If you like GENMASK then maybe the FIELD_GET and FIELD_PREP macros from
> the Linux kernel are for you aswell.
>
> #define SRC_SBMR_BMOD   GENMASK(25, 24)
>

Definetly! I like it a lot! I was hoping that something like that
existed but didn't find anything in barebox's tree. Should've checked
the kernel one instead. Will add and use in v2 of the patch.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr 16 06:42:31 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 06:42:31 -0700
Subject: [PATCH 4/4] pci: don't hide hard to understand sanity check in
 size calculation
In-Reply-To: <20180415182758.2gvkmxp7e5zzxtev@pengutronix.de>
References: <20180413233053.15570-1-u.kleine-koenig@pengutronix.de>
 <20180413233053.15570-4-u.kleine-koenig@pengutronix.de>
 <CAHQ1cqFkU=9aPg9xr3gbmApgx-rSfM3toH3m-Br3=PjN1Voqvw@mail.gmail.com>
 <20180415182758.2gvkmxp7e5zzxtev@pengutronix.de>
Message-ID: <CAHQ1cqGaupXUAaBCsgKeA2Gby+xE85qxrXs1AE0PvBVsTUOayA@mail.gmail.com>

On Sun, Apr 15, 2018 at 11:27 AM, Uwe Kleine-K?nig
<u.kleine-koenig at pengutronix.de> wrote:
> Hello Andrey,
>
> On Sat, Apr 14, 2018 at 09:25:59AM -0700, Andrey Smirnov wrote:
>> On Fri, Apr 13, 2018 at 4:30 PM, Uwe Kleine-K?nig
>> <u.kleine-koenig at pengutronix.de> wrote:
>> > +               /*
>> > +                * if maxbase isn't in the form 0b1...10...0 there is something
>> > +                * fishy
>> > +                */
>> > +               if ((maxbase | (maxbase - 1)) != (u32)-1 || maxbase == 0) {
>>
>> U32_MAX instead of (u32)-1 ?
>
> I don't feel strong here.

Me neither. I just read (u32)-1 as a shortcut for 0xffffffff and we
already have a shortcut for that. But if you want to keep using
(u32)-1, then by all means.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr 16 09:33:32 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 09:33:32 -0700
Subject: [PATCH 09/17] ARM: i.MX: boot: Move magic values into small
 functions
In-Reply-To: <2824671.pASI2u4fUC@dev4>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
 <20180414175103.10125-10-andrew.smirnov@gmail.com> <2824671.pASI2u4fUC@dev4>
Message-ID: <CAHQ1cqGCV56U-98-v_6=M7XMdnC8R571AVc0UiWN+87Q=ifhqQ@mail.gmail.com>

On Sat, Apr 14, 2018 at 7:24 PM, Marc Reilly <marc at cpdesign.com.au> wrote:
> On Sunday, April 15, 2018 3:50:55 AM AEST Andrey Smirnov wrote:
>> Move code to extract appropiate BOOT_CFG bits to decode booutsource on
>
> s/booutsource/bootsource
>

Fixed in v2.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr 16 09:34:10 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 09:34:10 -0700
Subject: [PATCH 08/17] ARM: i.MX: boot: Remove unnecessary retruns
In-Reply-To: <2408243.jW0yOUZQgv@dev4>
References: <20180414175103.10125-1-andrew.smirnov@gmail.com>
 <20180414175103.10125-9-andrew.smirnov@gmail.com> <2408243.jW0yOUZQgv@dev4>
Message-ID: <CAHQ1cqHL+R54dXaRbPeM28tUOPiBT0DVbxbugS_+1JHXXCKPRA@mail.gmail.com>

On Sat, Apr 14, 2018 at 7:22 PM, Marc Reilly <marc at cpdesign.com.au> wrote:
> Nitpick: in subject s/retruns/returns
>

 Fixed in v2.

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Mon Apr 16 12:31:39 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:39 -0700
Subject: [PATCH v2 01/19] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-2-andrew.smirnov@gmail.com>

All of the instances of imx*_boot_save_loc() do exactly the same thing with
the only difference being SoC-specific imx*_get_boot_source
call. Convert the code into a generic function taking function pointer
+ a macro to take care of the boilerplate.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 85 ++++++++++--------------------------------------
 1 file changed, 17 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 72597f5e2..4657fa017 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -89,17 +89,6 @@ void imx25_get_boot_source(enum bootsource *src, int *instance)
 				    (val >> MX25_CCM_RCSR_MEM_TYPE_SHIFT) & 0x3);
 }
 
-void imx25_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx25_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 void imx35_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *ccm_base = IOMEM(MX35_CCM_BASE_ADDR);
@@ -110,17 +99,6 @@ void imx35_get_boot_source(enum bootsource *src, int *instance)
 				    (val >> MX35_CCM_RCSR_MEM_TYPE_SHIFT) & 0x3);
 }
 
-void imx35_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx35_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX27_SYSCTRL_GPCR	0x18
 #define IMX27_GPCR_BOOT_SHIFT			16
 #define IMX27_GPCR_BOOT_MASK			(0xf << IMX27_GPCR_BOOT_SHIFT)
@@ -157,17 +135,6 @@ void imx27_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
-void imx27_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx27_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX51_SRC_SBMR			0x4
 #define IMX51_SBMR_BT_MEM_TYPE_SHIFT	7
 #define IMX51_SBMR_BT_MEM_CTL_SHIFT	0
@@ -201,17 +168,6 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
-void imx51_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx51_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX53_SRC_SBMR	0x4
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
@@ -260,17 +216,6 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
-void imx53_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx53_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX6_SRC_SBMR1	0x04
 #define IMX6_SRC_SBMR2	0x1c
 
@@ -337,17 +282,6 @@ internal_boot:
 	return;
 }
 
-void imx6_boot_save_loc(void)
-{
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx6_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
-}
-
 #define IMX7_SRC_SBMR1	0x58
 #define IMX7_SRC_SBMR2	0x70
 
@@ -406,13 +340,28 @@ internal_boot:
 	return;
 }
 
-void imx7_boot_save_loc(void)
+static void
+imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
 {
 	enum bootsource src = BOOTSOURCE_UNKNOWN;
 	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
 
-	imx7_get_boot_source(&src, &instance);
+	get_boot_source(&src, &instance);
 
 	bootsource_set(src);
 	bootsource_set_instance(instance);
 }
+
+#define IMX_BOOT_SAVE_LOC(soc)					\
+	void soc##_boot_save_loc(void)				\
+	{							\
+		imx_boot_save_loc(soc##_get_boot_source);	\
+	}
+
+IMX_BOOT_SAVE_LOC(imx25)
+IMX_BOOT_SAVE_LOC(imx27)
+IMX_BOOT_SAVE_LOC(imx35)
+IMX_BOOT_SAVE_LOC(imx51)
+IMX_BOOT_SAVE_LOC(imx53)
+IMX_BOOT_SAVE_LOC(imx6)
+IMX_BOOT_SAVE_LOC(imx7)
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:38 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:38 -0700
Subject: [PATCH v2 00/19] i.MX bootsource bugfixes,
 refactoring and VFxxx support
Message-ID: <20180416193157.16094-1-andrew.smirnov@gmail.com>

Everyone:

This patchset is the result of my work on adding support for
bootsource detection of VFxxx as well as fixing a number of
bugs/unsupported corner cases in similar i.MX7 specific code.

NOTE: While VFxxx support is added in this series the code integrating
it into the SoC initalization sequnce is not included. Patch for that
is dependent on recently submitted "i.MX reset reason detection
support" and I didn't want to intertwine two otherwise independent
submissions.

Changes since [v1]:

	- Patchset converted to use FIELD_GET macro (which was ported
          from the kernel)

	- Spelling fixes

[v1] https://www.spinics.net/lists/u-boot-v2/msg32506.html

Feedback is wellcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (19):
  ARM: i.MX: boot: Coalesce copy-pasted code
  include: Port linux/build_bug.h from Linux kernel
  include: Port linux/bitfield.h from Linux kernel
  ARM: i.MX: Add a function to extract BMOD value
  ARM: i.MX: Simplify serial bootsource detection for i.MX6 and 7
  ARM: i.MX: Account for unprogrammed fuses on i.MX6 and i.MX7
  ARM: i.MX7: boot: Add code to handle SD/MMC manufacture mode
  ARM: i.MX7: boot: Remove incorrect NAND bootsource detection
  ARM: i.MX7: boot: Fix SPI-NOR/QSPI boot source mixup
  ARM: i.MX: boot: Remove unnecessary returns
  ARM: i.MX: boot: Move magic values into small functions
  ARM: i.MX: boot: Share code to detect NAND as a boot source
  ARM: i.MX: boot: Check for NAND boot only if necessary on i.MX53, 6
  ARM: i.MX53: boot: Move magic numbers info utility functions
  ARM: i.MX6: boot: Move magic numbers into utility functions
  ARM: i.MX7: boot: Move magic numbers into utility functions
  bootsource: Add BOOTSOURCE_CAN
  ARM: VFxxx: Implement code to detect bootsource
  ARM: i.MX6: boot: Return BOOTSOURCE_SPI_NOR, not BOOTSOURCE_SPI

 arch/arm/boards/datamodul-edm-qmx6/board.c |   2 +-
 arch/arm/boards/dfi-fs700-m60/board.c      |   2 +-
 arch/arm/boards/phytec-som-imx6/board.c    |   2 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c  |   2 +-
 arch/arm/mach-imx/boot.c                   | 436 ++++++++++++++++++++---------
 arch/arm/mach-imx/include/mach/generic.h   |   2 +
 arch/arm/mach-imx/xload.c                  |   2 +-
 common/bootsource.c                        |   1 +
 include/bootsource.h                       |   1 +
 include/linux/bitfield.h                   | 152 ++++++++++
 include/linux/bug.h                        |  25 +-
 include/linux/build_bug.h                  |  83 ++++++
 12 files changed, 550 insertions(+), 160 deletions(-)
 create mode 100644 include/linux/bitfield.h
 create mode 100644 include/linux/build_bug.h

-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:45 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:45 -0700
Subject: [PATCH v2 07/19] ARM: i.MX7: boot: Add code to handle SD/MMC
 manufacture mode
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-8-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 7c59c2181..e2696a934 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -303,6 +303,19 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 #define IMX7_SRC_SBMR1	0x58
 #define IMX7_SRC_SBMR2	0x70
 
+#define IMX_BOOT_SW_INFO_POINTER_ADDR	0x000001E8
+#define IMX_BOOT_SW_INFO_BDT_SD		0x1
+
+struct imx_boot_sw_info {
+	uint8_t  reserved_1;
+	uint8_t  boot_device_instance;
+	uint8_t  boot_device_type;
+	uint8_t  reserved_2;
+	uint32_t frequency_hz[4]; /* Various frequencies (ARM, AXI,
+				   * DDR, etc.). Not used */
+	uint32_t reserved_3[3];
+} __packed;
+
 void imx7_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR);
@@ -313,6 +326,33 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 		return;
 
 	if (imx6_bootsource_serial(sbmr2)) {
+		/*
+		 * On i.MX7 ROM code will try to bood from uSDHC1
+		 * before entering serial mode. It doesn't seem to be
+		 * reflected in the contents of SBMR1 in any way when
+		 * that happens, so we check "Boot_SW_Info" structure
+		 * (per 6.6.14 Boot information for software) to see
+		 * if that really happened.
+		 *
+		 * FIXME: This behaviour can be inhibited by
+		 * DISABLE_SDMMC_MFG, but location of that fuse
+		 * doesn't seem to be documented anywhere. Once that
+		 * is known it should be taken into account here.
+		 */
+		const struct imx_boot_sw_info *info;
+
+		info = (const void *)readl(IMX_BOOT_SW_INFO_POINTER_ADDR);
+
+		if (info->boot_device_type == IMX_BOOT_SW_INFO_BDT_SD) {
+			*src = BOOTSOURCE_MMC;
+			/*
+			 * We are expecting to only ever boot from
+			 * uSDHC1 here
+			 */
+			WARN_ON(*instance = info->boot_device_instance);
+			return;
+		}
+
 		*src = BOOTSOURCE_SERIAL;
 		return;
 	}
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:46 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:46 -0700
Subject: [PATCH v2 08/19] ARM: i.MX7: boot: Remove incorrect NAND bootsource
 detection
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-9-andrew.smirnov@gmail.com>

i.MX7 differs from i.MX6 and i.MX53 and bit 7 in SBMR is not used to
signify boot from NAND.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index e2696a934..5484812a6 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -380,10 +380,6 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 		break;
 	}
 
-	/* BOOT_CFG1[7:0] */
-	if (sbmr1 & (1 << 7))
-		*src = BOOTSOURCE_NAND;
-
 	return;
 }
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:40 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:40 -0700
Subject: [PATCH v2 02/19] include: Port linux/build_bug.h from Linux kernel
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-3-andrew.smirnov@gmail.com>

Port linux/build_bug.h needed by some of more recent kernel code.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 include/linux/bug.h       | 25 +-------------
 include/linux/build_bug.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 24 deletions(-)
 create mode 100644 include/linux/build_bug.h

diff --git a/include/linux/bug.h b/include/linux/bug.h
index 7295618c9..8367a11ec 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -2,29 +2,6 @@
 #define _LINUX_BUG_H
 
 #include <asm-generic/bug.h>
-
-#ifdef __CHECKER__
-#define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
-#define BUILD_BUG_ON_ZERO(e) (0)
-#define BUILD_BUG_ON_NULL(e) ((void*)0)
-#define BUILD_BUG_ON(condition) (0)
-#else /* __CHECKER__ */
-
-/* Force a compilation error if a constant expression is not a power of 2 */
-#define BUILD_BUG_ON_NOT_POWER_OF_2(n)			\
-	BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
-
-/* Force a compilation error if condition is true, but also produce a
-   result (of value 0 and type size_t), so the expression can be used
-   e.g. in a structure initializer (or where-ever else comma expressions
-   aren't permitted). */
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
-#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
-
-/* Force a compilation error if condition is true */
-#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
-
-#endif
-
+#include <linux/build_bug.h>
 
 #endif	/* _LINUX_BUG_H */
diff --git a/include/linux/build_bug.h b/include/linux/build_bug.h
new file mode 100644
index 000000000..43d1fd50d
--- /dev/null
+++ b/include/linux/build_bug.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BUILD_BUG_H
+#define _LINUX_BUILD_BUG_H
+
+#include <linux/compiler.h>
+
+#ifdef __CHECKER__
+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
+#define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
+#define BUILD_BUG_ON_ZERO(e) (0)
+#define BUILD_BUG_ON_INVALID(e) (0)
+#define BUILD_BUG_ON_MSG(cond, msg) (0)
+#define BUILD_BUG_ON(condition) (0)
+#define BUILD_BUG() (0)
+#else /* __CHECKER__ */
+
+/* Force a compilation error if a constant expression is not a power of 2 */
+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n)	\
+	BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
+#define BUILD_BUG_ON_NOT_POWER_OF_2(n)			\
+	BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
+
+/*
+ * Force a compilation error if condition is true, but also produce a
+ * result (of value 0 and type size_t), so the expression can be used
+ * e.g. in a structure initializer (or where-ever else comma expressions
+ * aren't permitted).
+ */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
+
+/*
+ * BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the
+ * expression but avoids the generation of any code, even if that expression
+ * has side-effects.
+ */
+#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
+
+/**
+ * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied
+ *		      error message.
+ * @condition: the condition which the compiler should know is false.
+ *
+ * See BUILD_BUG_ON for description.
+ */
+#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
+
+/**
+ * BUILD_BUG_ON - break compile if a condition is true.
+ * @condition: the condition which the compiler should know is false.
+ *
+ * If you have some code which relies on certain constants being equal, or
+ * some other compile-time-evaluated condition, you should use BUILD_BUG_ON to
+ * detect if someone changes it.
+ *
+ * The implementation uses gcc's reluctance to create a negative array, but gcc
+ * (as of 4.4) only emits that error for obvious cases (e.g. not arguments to
+ * inline functions).  Luckily, in 4.3 they added the "error" function
+ * attribute just for this type of case.  Thus, we use a negative sized array
+ * (should always create an error on gcc versions older than 4.4) and then call
+ * an undefined function with the error attribute (should always create an
+ * error on gcc 4.3 and later).  If for some reason, neither creates a
+ * compile-time error, we'll still have a link-time error, which is harder to
+ * track down.
+ */
+#ifndef __OPTIMIZE__
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#else
+#define BUILD_BUG_ON(condition) \
+	BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
+#endif
+
+/**
+ * BUILD_BUG - break compile if used.
+ *
+ * If you have some code that you expect the compiler to eliminate at
+ * build time, you should use BUILD_BUG to detect if it is
+ * unexpectedly used.
+ */
+#define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed")
+
+#endif	/* __CHECKER__ */
+
+#endif	/* _LINUX_BUILD_BUG_H */
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:47 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:47 -0700
Subject: [PATCH v2 09/19] ARM: i.MX7: boot: Fix SPI-NOR/QSPI boot source mixup
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-10-andrew.smirnov@gmail.com>

As per "Table 6-33. Boot device selection" from "i.MX 7Dual
Applications Processor Reference Manual, Rev. 1, 01/2018" QSPI is
encoded with 0b0100 and Serial ROM with 0b0110. Fix the original code
to use correct values.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 5484812a6..f9d730f6d 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -366,11 +366,11 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	case 3:
 		*src = BOOTSOURCE_NAND;
 		break;
-	case 4:
+	case 6:
 		*src = BOOTSOURCE_SPI_NOR,
 		*instance = (sbmr1 >> 9 & 0x7);
 		break;
-	case 6:
+	case 4:
 		*src = BOOTSOURCE_SPI; /* Really: qspi */
 		break;
 	case 5:
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:42 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:42 -0700
Subject: [PATCH v2 04/19] ARM: i.MX: Add a function to extract BMOD value
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-5-andrew.smirnov@gmail.com>

The location of BMDO field in SBMR/SBMR2 registers is consistent
across all i.MX SoCs starting from i.MX53. Add simple helper function
imx53_get_bmod and use it to avoid code duplication.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 4657fa017..9f5ddf629 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -15,6 +15,7 @@
 #include <bootsource.h>
 #include <environment.h>
 #include <init.h>
+#include <linux/bitfield.h>
 #include <magicvar.h>
 
 #include <io.h>
@@ -169,12 +170,19 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 }
 
 #define IMX53_SRC_SBMR	0x4
+#define SRC_SBMR_BMOD	GENMASK(25, 24)
+
+static unsigned int imx53_get_bmod(uint32_t r)
+{
+	return FIELD_GET(SRC_SBMR_BMOD, r);
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
 	uint32_t cfg1 = readl(src_base + IMX53_SRC_SBMR);
 
-	if (((cfg1 >> 24) & 0x3) == 0x3) {
+	if (imx53_get_bmod(cfg1) == 0x3) {
 		*src = BOOTSOURCE_USB;
 		*instance = 0;
 		return;
@@ -225,12 +233,8 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
 	uint32_t boot_cfg_4_2_0;
-	int boot_mode;
-
-	/* BMOD[1:0] */
-	boot_mode = (sbmr2 >> 24) & 0x3;
 
-	switch (boot_mode) {
+	switch (imx53_get_bmod(sbmr2)) {
 	case 0: /* Fuses, fall through */
 	case 2: /* internal boot */
 		goto internal_boot;
@@ -290,12 +294,8 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR);
 	uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2);
-	int boot_mode;
-
-	/* BMOD[1:0] */
-	boot_mode = (sbmr2 >> 24) & 0x3;
 
-	switch (boot_mode) {
+	switch (imx53_get_bmod(sbmr2)) {
 	case 0: /* Fuses, fall through */
 	case 2: /* internal boot */
 		goto internal_boot;
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:41 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:41 -0700
Subject: [PATCH v2 03/19] include: Port linux/bitfield.h from Linux kernel
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-4-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 include/linux/bitfield.h | 152 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)
 create mode 100644 include/linux/bitfield.h

diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
new file mode 100644
index 000000000..cf2588d81
--- /dev/null
+++ b/include/linux/bitfield.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_BITFIELD_H
+#define _LINUX_BITFIELD_H
+
+#include <linux/build_bug.h>
+#include <asm/byteorder.h>
+
+/*
+ * Bitfield access macros
+ *
+ * FIELD_{GET,PREP} macros take as first parameter shifted mask
+ * from which they extract the base mask and shift amount.
+ * Mask must be a compilation time constant.
+ *
+ * Example:
+ *
+ *  #define REG_FIELD_A  GENMASK(6, 0)
+ *  #define REG_FIELD_B  BIT(7)
+ *  #define REG_FIELD_C  GENMASK(15, 8)
+ *  #define REG_FIELD_D  GENMASK(31, 16)
+ *
+ * Get:
+ *  a = FIELD_GET(REG_FIELD_A, reg);
+ *  b = FIELD_GET(REG_FIELD_B, reg);
+ *
+ * Set:
+ *  reg = FIELD_PREP(REG_FIELD_A, 1) |
+ *	  FIELD_PREP(REG_FIELD_B, 0) |
+ *	  FIELD_PREP(REG_FIELD_C, c) |
+ *	  FIELD_PREP(REG_FIELD_D, 0x40);
+ *
+ * Modify:
+ *  reg &= ~REG_FIELD_C;
+ *  reg |= FIELD_PREP(REG_FIELD_C, c);
+ */
+
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+
+#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx)			\
+	({								\
+		BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask),		\
+				 _pfx "mask is not constant");		\
+		BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero");	\
+		BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?		\
+				 ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
+				 _pfx "value too large for the field"); \
+		BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,		\
+				 _pfx "type of reg too small for mask"); \
+		__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) +			\
+					      (1ULL << __bf_shf(_mask))); \
+	})
+
+/**
+ * FIELD_FIT() - check if value fits in the field
+ * @_mask: shifted mask defining the field's length and position
+ * @_val:  value to test against the field
+ *
+ * Return: true if @_val can fit inside @_mask, false if @_val is too big.
+ */
+#define FIELD_FIT(_mask, _val)						\
+	({								\
+		__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: ");	\
+		!((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
+	})
+
+/**
+ * FIELD_PREP() - prepare a bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_val:  value to put in the field
+ *
+ * FIELD_PREP() masks and shifts up the value.  The result should
+ * be combined with other fields of the bitfield using logical OR.
+ */
+#define FIELD_PREP(_mask, _val)						\
+	({								\
+		__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");	\
+		((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask);	\
+	})
+
+/**
+ * FIELD_GET() - extract a bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_reg:  value of entire bitfield
+ *
+ * FIELD_GET() extracts the field specified by @_mask from the
+ * bitfield passed in as @_reg by masking and shifting it down.
+ */
+#define FIELD_GET(_mask, _reg)						\
+	({								\
+		__BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: ");	\
+		(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask));	\
+	})
+
+extern void __compiletime_warning("value doesn't fit into mask")
+__field_overflow(void);
+extern void __compiletime_error("bad bitfield mask")
+__bad_mask(void);
+static __always_inline u64 field_multiplier(u64 field)
+{
+	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
+		__bad_mask();
+	return field & -field;
+}
+static __always_inline u64 field_mask(u64 field)
+{
+	return field / field_multiplier(field);
+}
+#define ____MAKE_OP(type,base,to,from)					\
+static __always_inline __##type type##_encode_bits(base v, base field)	\
+{									\
+        if (__builtin_constant_p(v) &&	(v & ~field_multiplier(field)))	\
+			    __field_overflow();				\
+	return to((v & field_mask(field)) * field_multiplier(field));	\
+}									\
+static __always_inline __##type type##_replace_bits(__##type old,	\
+					base val, base field)		\
+{									\
+	return (old & ~to(field)) | type##_encode_bits(val, field);	\
+}									\
+static __always_inline void type##p_replace_bits(__##type *p,		\
+					base val, base field)		\
+{									\
+	*p = (*p & ~to(field)) | type##_encode_bits(val, field);	\
+}									\
+static __always_inline base type##_get_bits(__##type v, base field)	\
+{									\
+	return (from(v) & field)/field_multiplier(field);		\
+}
+#define __MAKE_OP(size)							\
+	____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu)	\
+	____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu)	\
+	____MAKE_OP(u##size,u##size,,)
+__MAKE_OP(16)
+__MAKE_OP(32)
+__MAKE_OP(64)
+#undef __MAKE_OP
+#undef ____MAKE_OP
+
+#endif
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:49 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:49 -0700
Subject: [PATCH v2 11/19] ARM: i.MX: boot: Move magic values into small
 functions
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-12-andrew.smirnov@gmail.com>

Move code to extract appropiate BOOT_CFG bits to decode bootsource on
i.MX53, 6, and 7 into small functions for clarity and to allow sharing
the code between i.MX53 and i.MX6.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 4bb26d942..61ac8dadf 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -172,11 +172,38 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 #define IMX53_SRC_SBMR	0x4
 #define SRC_SBMR_BMOD	GENMASK(25, 24)
 
+#define __BOOT_CFG(n, m, l)	GENMASK((m) + ((n) - 1) * 8, \
+					(l) + ((n) - 1) * 8)
+#define BOOT_CFG1(m, l)		__BOOT_CFG(1, m, l)
+
+#define ___BOOT_CFG(n, i)	__BOOT_CFG(n, i, i)
+#define __MAKE_BOOT_CFG_BITS(idx)					\
+	enum {								\
+		BOOT_CFG##idx##_0 = ___BOOT_CFG(idx, 0),		\
+		BOOT_CFG##idx##_1 = ___BOOT_CFG(idx, 1),		\
+		BOOT_CFG##idx##_2 = ___BOOT_CFG(idx, 2),		\
+		BOOT_CFG##idx##_3 = ___BOOT_CFG(idx, 3),		\
+		BOOT_CFG##idx##_4 = ___BOOT_CFG(idx, 4),		\
+		BOOT_CFG##idx##_5 = ___BOOT_CFG(idx, 5),		\
+		BOOT_CFG##idx##_6 = ___BOOT_CFG(idx, 6),		\
+		BOOT_CFG##idx##_7 = ___BOOT_CFG(idx, 7),		\
+	};
+
+__MAKE_BOOT_CFG_BITS(1)
+#undef __MAKE_BOOT_CFG
+#undef ___BOOT_CFG
+
+
 static unsigned int imx53_get_bmod(uint32_t r)
 {
 	return FIELD_GET(SRC_SBMR_BMOD, r);
 }
 
+static int imx53_bootsource_internal(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG1(7, 4), r);
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
@@ -188,7 +215,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		return;
 	}
 
-	switch ((cfg1 & 0xff) >> 4) {
+	switch (imx53_bootsource_internal(cfg1)) {
 	case 2:
 		*src = BOOTSOURCE_HD;
 		break;
@@ -263,8 +290,7 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		return;
 	}
 
-	/* BOOT_CFG1[7:4] */
-	switch ((sbmr1 >> 4) & 0xf) {
+	switch (imx53_bootsource_internal(sbmr1)) {
 	case 2:
 		*src = BOOTSOURCE_HD;
 		break;
@@ -301,9 +327,19 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 #define IMX7_SRC_SBMR1	0x58
 #define IMX7_SRC_SBMR2	0x70
 
+/*
+ * Re-defined to match the naming in reference manual
+ */
+#define BOOT_CFG(m, l)	BOOT_CFG1(m, l)
+
 #define IMX_BOOT_SW_INFO_POINTER_ADDR	0x000001E8
 #define IMX_BOOT_SW_INFO_BDT_SD		0x1
 
+static unsigned int imx7_bootsource_internal(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG(15, 12), r);
+}
+
 struct imx_boot_sw_info {
 	uint8_t  reserved_1;
 	uint8_t  boot_device_instance;
@@ -355,7 +391,7 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 		return;
 	}
 
-	switch ((sbmr1 >> 12) & 0xf) {
+	switch (imx7_bootsource_internal(sbmr1)) {
 	case 1:
 	case 2:
 		*src = BOOTSOURCE_MMC;
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:43 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:43 -0700
Subject: [PATCH v2 05/19] ARM: i.MX: Simplify serial bootsource detection for
 i.MX6 and 7
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-6-andrew.smirnov@gmail.com>

The algorithm to detect serial mode can be shared between i.M6 and
i.MX7 as wall as simplified a bit by replacing swich goto/break/return
termination logic with more trivial if statements.

This commit also sets the stage for additional improvements in the
commits that follow.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 50 +++++++++++++++++++++++-------------------------
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 9f5ddf629..dc385ceae 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -226,6 +226,18 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 
 #define IMX6_SRC_SBMR1	0x04
 #define IMX6_SRC_SBMR2	0x1c
+#define IMX6_BMOD_SERIAL	0b01
+#define IMX6_BMOD_RESERVED	0b11
+
+static bool imx6_bootsource_reserved(uint32_t sbmr2)
+{
+	return imx53_get_bmod(sbmr2) == IMX6_BMOD_RESERVED;
+}
+
+static bool imx6_bootsource_serial(uint32_t sbmr2)
+{
+	return imx53_get_bmod(sbmr2) == IMX6_BMOD_SERIAL;
+}
 
 void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
@@ -234,20 +246,13 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
 	uint32_t boot_cfg_4_2_0;
 
-	switch (imx53_get_bmod(sbmr2)) {
-	case 0: /* Fuses, fall through */
-	case 2: /* internal boot */
-		goto internal_boot;
-	case 1: /* Serial Downloader */
-		*src = BOOTSOURCE_SERIAL;
-		break;
-	case 3: /* reserved */
-		break;
-	};
-
-	return;
+	if (imx6_bootsource_reserved(sbmr2))
+		return;
 
-internal_boot:
+	if (imx6_bootsource_serial(sbmr2)) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
 
 	/* BOOT_CFG1[7:4] */
 	switch ((sbmr1 >> 4) & 0xf) {
@@ -295,20 +300,13 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2);
 
-	switch (imx53_get_bmod(sbmr2)) {
-	case 0: /* Fuses, fall through */
-	case 2: /* internal boot */
-		goto internal_boot;
-	case 1: /* Serial Downloader */
-		*src = BOOTSOURCE_SERIAL;
-		break;
-	case 3: /* reserved */
-		break;
-	};
-
-	return;
+	if (imx6_bootsource_reserved(sbmr2))
+		return;
 
-internal_boot:
+	if (imx6_bootsource_serial(sbmr2)) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
 
 	switch ((sbmr1 >> 12) & 0xf) {
 	case 1:
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:44 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:44 -0700
Subject: [PATCH v2 06/19] ARM: i.MX: Account for unprogrammed fuses on i.MX6
 and i.MX7
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-7-andrew.smirnov@gmail.com>

On both i.MX6 and i.MX7 (also true for VFxxx) there's an additional
path that leads mask ROM to switch into serial bootloader mode. Add
code to support it.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index dc385ceae..7c59c2181 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -228,6 +228,8 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 #define IMX6_SRC_SBMR2	0x1c
 #define IMX6_BMOD_SERIAL	0b01
 #define IMX6_BMOD_RESERVED	0b11
+#define IMX6_BMOD_FUSES		0b00
+#define BT_FUSE_SEL		BIT(4)
 
 static bool imx6_bootsource_reserved(uint32_t sbmr2)
 {
@@ -236,7 +238,14 @@ static bool imx6_bootsource_reserved(uint32_t sbmr2)
 
 static bool imx6_bootsource_serial(uint32_t sbmr2)
 {
-	return imx53_get_bmod(sbmr2) == IMX6_BMOD_SERIAL;
+	return imx53_get_bmod(sbmr2) == IMX6_BMOD_SERIAL ||
+		/*
+		 * If boot from fuses is selected and fuses are not
+		 * programmed by setting BT_FUSE_SEL, ROM code will
+		 * fallback to serial mode
+		 */
+	       (imx53_get_bmod(sbmr2) == IMX6_BMOD_FUSES &&
+		!(sbmr2 & BT_FUSE_SEL));
 }
 
 void imx6_get_boot_source(enum bootsource *src, int *instance)
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:48 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:48 -0700
Subject: [PATCH v2 10/19] ARM: i.MX: boot: Remove unnecessary returns
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-11-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index f9d730f6d..4bb26d942 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -296,8 +296,6 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 	/* BOOT_CFG1[7:0] */
 	if (sbmr1 & (1 << 7))
 		*src = BOOTSOURCE_NAND;
-
-	return;
 }
 
 #define IMX7_SRC_SBMR1	0x58
@@ -379,8 +377,6 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	default:
 		break;
 	}
-
-	return;
 }
 
 static void
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:50 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:50 -0700
Subject: [PATCH v2 12/19] ARM: i.MX: boot: Share code to detect NAND as a boot
 source
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-13-andrew.smirnov@gmail.com>

Share code to detect NAND as a boot source between i.MX53 and i.MX6
which behave the same in that aspect.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 61ac8dadf..a5dff77df 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -204,6 +204,11 @@ static int imx53_bootsource_internal(uint32_t r)
 	return FIELD_GET(BOOT_CFG1(7, 4), r);
 }
 
+static bool imx53_bootsource_nand(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG1_7, r);
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
@@ -235,7 +240,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		break;
 	}
 
-	if (cfg1 & (1 << 7))
+	if (imx53_bootsource_nand(cfg1))
 		*src = BOOTSOURCE_NAND;
 
 
@@ -319,8 +324,7 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		break;
 	}
 
-	/* BOOT_CFG1[7:0] */
-	if (sbmr1 & (1 << 7))
+	if (imx53_bootsource_nand(sbmr1))
 		*src = BOOTSOURCE_NAND;
 }
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:52 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:52 -0700
Subject: [PATCH v2 14/19] ARM: i.MX53: boot: Move magic numbers info utility
 functions
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-15-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index f84be5c68..799d5ec93 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -171,10 +171,12 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 
 #define IMX53_SRC_SBMR	0x4
 #define SRC_SBMR_BMOD	GENMASK(25, 24)
+#define IMX53_BMOD_SERIAL	0b11
 
 #define __BOOT_CFG(n, m, l)	GENMASK((m) + ((n) - 1) * 8, \
 					(l) + ((n) - 1) * 8)
 #define BOOT_CFG1(m, l)		__BOOT_CFG(1, m, l)
+#define BOOT_CFG3(m, l)		__BOOT_CFG(3, m, l)
 
 #define ___BOOT_CFG(n, i)	__BOOT_CFG(n, i, i)
 #define __MAKE_BOOT_CFG_BITS(idx)					\
@@ -204,17 +206,27 @@ static int imx53_bootsource_internal(uint32_t r)
 	return FIELD_GET(BOOT_CFG1(7, 4), r);
 }
 
+static int imx53_port_select(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG3(5, 4), r);
+}
+
 static bool imx53_bootsource_nand(uint32_t r)
 {
 	return FIELD_GET(BOOT_CFG1_7, r);
 }
 
+static enum bootsource imx53_bootsource_serial_rom(uint32_t r)
+{
+	return BOOT_CFG1(r, 3) ? BOOTSOURCE_SPI : BOOTSOURCE_I2C;
+}
+
 void imx53_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX53_SRC_BASE_ADDR);
 	uint32_t cfg1 = readl(src_base + IMX53_SRC_SBMR);
 
-	if (imx53_get_bmod(cfg1) == 0x3) {
+	if (imx53_get_bmod(cfg1) == IMX53_BMOD_SERIAL) {
 		*src = BOOTSOURCE_USB;
 		*instance = 0;
 		return;
@@ -225,10 +237,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		*src = BOOTSOURCE_HD;
 		break;
 	case 3:
-		if (cfg1 & (1 << 3))
-			*src = BOOTSOURCE_SPI;
-		else
-			*src = BOOTSOURCE_I2C;
+		*src = imx53_bootsource_serial_rom(cfg1);
 		break;
 	case 4:
 	case 5:
@@ -246,7 +255,7 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 	case BOOTSOURCE_MMC:
 	case BOOTSOURCE_SPI:
 	case BOOTSOURCE_I2C:
-		*instance = (cfg1 >> 20) & 0x3;
+		*instance = imx53_port_select(cfg1);
 		break;
 	default:
 		*instance = 0;
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:51 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:51 -0700
Subject: [PATCH v2 13/19] ARM: i.MX: boot: Check for NAND boot only if
 necessary on i.MX53, 6
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-14-andrew.smirnov@gmail.com>

We don't need to check if the boot source is NAND in cases when we
already know for a fact that we booted from something else. To avoid
that, move the NAND check to be done inside of default branch of
the preceeding switch statement.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index a5dff77df..f84be5c68 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -237,13 +237,11 @@ void imx53_get_boot_source(enum bootsource *src, int *instance)
 		*src = BOOTSOURCE_MMC;
 		break;
 	default:
+		if (imx53_bootsource_nand(cfg1))
+			*src = BOOTSOURCE_NAND;
 		break;
 	}
 
-	if (imx53_bootsource_nand(cfg1))
-		*src = BOOTSOURCE_NAND;
-
-
 	switch (*src) {
 	case BOOTSOURCE_MMC:
 	case BOOTSOURCE_SPI:
@@ -321,11 +319,10 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		*instance = (sbmr1 >> 11) & 0x3;
 		break;
 	default:
+		if (imx53_bootsource_nand(sbmr1))
+			*src = BOOTSOURCE_NAND;
 		break;
 	}
-
-	if (imx53_bootsource_nand(sbmr1))
-		*src = BOOTSOURCE_NAND;
 }
 
 #define IMX7_SRC_SBMR1	0x58
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:57 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:57 -0700
Subject: [PATCH v2 19/19] ARM: i.MX6: boot: Return BOOTSOURCE_SPI_NOR,
 not BOOTSOURCE_SPI
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-20-andrew.smirnov@gmail.com>

We use BOOTSOURCE_SPI to denote, among other things, QSPI on i.MX7 and
VFxxx, whereas on i.MX6 it is used to mean SPI-NOR. To make functions
like imx_xload() work consistently across various i.MX platforms use
already existent BOOTSOURCE_SPI_NOR constant to mean booting from
SPI-NOR on i.MX6 as well.

Replace all in-tree code that relying on the old value as well.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/boards/datamodul-edm-qmx6/board.c | 2 +-
 arch/arm/boards/dfi-fs700-m60/board.c      | 2 +-
 arch/arm/boards/phytec-som-imx6/board.c    | 2 +-
 arch/arm/boards/zii-imx6q-rdu2/lowlevel.c  | 2 +-
 arch/arm/mach-imx/boot.c                   | 2 +-
 arch/arm/mach-imx/xload.c                  | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boards/datamodul-edm-qmx6/board.c b/arch/arm/boards/datamodul-edm-qmx6/board.c
index 043a93461..d93c940e3 100644
--- a/arch/arm/boards/datamodul-edm-qmx6/board.c
+++ b/arch/arm/boards/datamodul-edm-qmx6/board.c
@@ -132,7 +132,7 @@ static int realq7_device_init(void)
 		}
 		break;
 	default:
-	case BOOTSOURCE_SPI:
+	case BOOTSOURCE_SPI_NOR:
 		of_device_enable_path("/chosen/environment-spi");
 		break;
 	}
diff --git a/arch/arm/boards/dfi-fs700-m60/board.c b/arch/arm/boards/dfi-fs700-m60/board.c
index bef4612d9..2cb8e3106 100644
--- a/arch/arm/boards/dfi-fs700-m60/board.c
+++ b/arch/arm/boards/dfi-fs700-m60/board.c
@@ -105,7 +105,7 @@ static int dfi_fs700_m60_init(void)
 
 	phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, ar8031_phy_fixup);
 
-	if (bootsource_get() == BOOTSOURCE_SPI)
+	if (bootsource_get() == BOOTSOURCE_SPI_NOR)
 		flag_spi |= BBU_HANDLER_FLAG_DEFAULT;
 	else
 		flag_mmc |= BBU_HANDLER_FLAG_DEFAULT;
diff --git a/arch/arm/boards/phytec-som-imx6/board.c b/arch/arm/boards/phytec-som-imx6/board.c
index 717a22963..ecb22f956 100644
--- a/arch/arm/boards/phytec-som-imx6/board.c
+++ b/arch/arm/boards/phytec-som-imx6/board.c
@@ -152,7 +152,7 @@ static int physom_imx6_devices_init(void)
 		environment_path = basprintf("/chosen/environment-nand");
 		envdev = "NAND flash";
 		break;
-	case BOOTSOURCE_SPI:
+	case BOOTSOURCE_SPI_NOR:
 		environment_path = basprintf("/chosen/environment-spinor");
 		envdev = "SPI NOR flash";
 		break;
diff --git a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
index 22ffdf85e..3b4dbd212 100644
--- a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
+++ b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c
@@ -290,7 +290,7 @@ static noinline void rdu2_sram_setup(void)
 		write_regs(imx6q_dcd, ARRAY_SIZE(imx6q_dcd));
 
 	imx6_get_boot_source(&bootsrc, &instance);
-	if (bootsrc == BOOTSOURCE_SPI)
+	if (bootsrc == BOOTSOURCE_SPI_NOR)
 		imx6_spi_start_image(0);
 	else
 		imx6_esdhc_start_image(instance);
diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index f8a04d8f3..bb5318510 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -320,7 +320,7 @@ static enum bootsource imx6_bootsource_serial_rom(uint32_t sbmr)
 	const int source = __imx6_bootsource_serial_rom(sbmr);
 
 	return source < IMX6_BOOTSOURCE_SERIAL_ROM_I2C1 ?
-		BOOTSOURCE_SPI : BOOTSOURCE_I2C;
+		BOOTSOURCE_SPI_NOR : BOOTSOURCE_I2C;
 }
 
 static int imx6_boot_instance_serial_rom(uint32_t sbmr)
diff --git a/arch/arm/mach-imx/xload.c b/arch/arm/mach-imx/xload.c
index 16d56ab28..921e9ade2 100644
--- a/arch/arm/mach-imx/xload.c
+++ b/arch/arm/mach-imx/xload.c
@@ -24,7 +24,7 @@ static __noreturn int imx_xload(void)
 		pr_info("booting from MMC\n");
 		buf = bootstrap_read_disk("disk0.0", "fat");
 		break;
-	case BOOTSOURCE_SPI:
+	case BOOTSOURCE_SPI_NOR:
 		pr_info("booting from SPI\n");
 		buf = bootstrap_read_devfs("dataflash0", false,
 					   SZ_256K, SZ_1M, SZ_1M);
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:54 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:54 -0700
Subject: [PATCH v2 16/19] ARM: i.MX7: boot: Move magic numbers into utility
 functions
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-17-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 60307ffb6..3f67c2510 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -389,6 +389,16 @@ static unsigned int imx7_bootsource_internal(uint32_t r)
 	return FIELD_GET(BOOT_CFG(15, 12), r);
 }
 
+static int imx7_boot_instance_spi_nor(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG(11, 9), r);
+}
+
+static int imx7_boot_instance_mmc(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG(11, 10), r);
+}
+
 struct imx_boot_sw_info {
 	uint8_t  reserved_1;
 	uint8_t  boot_device_instance;
@@ -444,14 +454,14 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	case 1:
 	case 2:
 		*src = BOOTSOURCE_MMC;
-		*instance = (sbmr1 >> 10 & 0x3);
+		*instance = imx7_boot_instance_mmc(sbmr1);
 		break;
 	case 3:
 		*src = BOOTSOURCE_NAND;
 		break;
 	case 6:
 		*src = BOOTSOURCE_SPI_NOR,
-		*instance = (sbmr1 >> 9 & 0x7);
+		*instance = imx7_boot_instance_spi_nor(sbmr1);
 		break;
 	case 4:
 		*src = BOOTSOURCE_SPI; /* Really: qspi */
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:53 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:53 -0700
Subject: [PATCH v2 15/19] ARM: i.MX6: boot: Move magic numbers into utility
 functions
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-16-andrew.smirnov@gmail.com>

Move magic numbers and algorithm for determining Serial ROM bootsource
and boot instance into utility functions. Add a comment on the logic
behing the latter while at it.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c | 67 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 53 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 799d5ec93..60307ffb6 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -176,7 +176,9 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 #define __BOOT_CFG(n, m, l)	GENMASK((m) + ((n) - 1) * 8, \
 					(l) + ((n) - 1) * 8)
 #define BOOT_CFG1(m, l)		__BOOT_CFG(1, m, l)
+#define BOOT_CFG2(m, l)		__BOOT_CFG(2, m, l)
 #define BOOT_CFG3(m, l)		__BOOT_CFG(3, m, l)
+#define BOOT_CFG4(m, l)		__BOOT_CFG(4, m, l)
 
 #define ___BOOT_CFG(n, i)	__BOOT_CFG(n, i, i)
 #define __MAKE_BOOT_CFG_BITS(idx)					\
@@ -192,6 +194,8 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 	};
 
 __MAKE_BOOT_CFG_BITS(1)
+__MAKE_BOOT_CFG_BITS(2)
+__MAKE_BOOT_CFG_BITS(4)
 #undef __MAKE_BOOT_CFG
 #undef ___BOOT_CFG
 
@@ -287,12 +291,57 @@ static bool imx6_bootsource_serial(uint32_t sbmr2)
 		!(sbmr2 & BT_FUSE_SEL));
 }
 
+static int __imx6_bootsource_serial_rom(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG4(2, 0), r);
+}
+
+/*
+ * Serial ROM bootsource on i.MX6 are as follows:
+ *
+ *	000 - ECSPI-1
+ *	001 - ECSPI-2
+ *	010 - ECSPI-3
+ *	011 - ECSPI-4
+ *	100 - ECSPI-5
+ *	101 - I2C1
+ *	110 - I2C2
+ *	111 - I2C3
+ *
+ * There's no single bit that would tell us we are booting from I2C or
+ * SPI, so we just have to compare the "source" agains the value for
+ * I2C1 for both: calculating bootsource and boot instance.
+ */
+#define IMX6_BOOTSOURCE_SERIAL_ROM_I2C1	0b101
+
+static enum bootsource imx6_bootsource_serial_rom(uint32_t sbmr)
+{
+	const int source = __imx6_bootsource_serial_rom(sbmr);
+
+	return source < IMX6_BOOTSOURCE_SERIAL_ROM_I2C1 ?
+		BOOTSOURCE_SPI : BOOTSOURCE_I2C;
+}
+
+static int imx6_boot_instance_serial_rom(uint32_t sbmr)
+{
+	const int source = __imx6_bootsource_serial_rom(sbmr);
+
+	if (source < IMX6_BOOTSOURCE_SERIAL_ROM_I2C1)
+		return source;
+
+	return source - IMX6_BOOTSOURCE_SERIAL_ROM_I2C1;
+}
+
+static int imx6_boot_instance_mmc(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG2(4, 3), r);
+}
+
 void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
 	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
-	uint32_t boot_cfg_4_2_0;
 
 	if (imx6_bootsource_reserved(sbmr2))
 		return;
@@ -307,25 +356,15 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 		*src = BOOTSOURCE_HD;
 		break;
 	case 3:
-		/* BOOT_CFG4[2:0] */
-		boot_cfg_4_2_0 = (sbmr1 >> 24) & 0x7;
-
-		if (boot_cfg_4_2_0 > 4) {
-			*src = BOOTSOURCE_I2C;
-			*instance = boot_cfg_4_2_0 - 5;
-		} else {
-			*src = BOOTSOURCE_SPI;
-			*instance = boot_cfg_4_2_0;
-		}
+		*src = imx6_bootsource_serial_rom(sbmr1);
+		*instance = imx6_boot_instance_serial_rom(sbmr1);
 		break;
 	case 4:
 	case 5:
 	case 6:
 	case 7:
 		*src = BOOTSOURCE_MMC;
-
-		/* BOOT_CFG2[4:3] */
-		*instance = (sbmr1 >> 11) & 0x3;
+		*instance = imx6_boot_instance_mmc(sbmr1);
 		break;
 	default:
 		if (imx53_bootsource_nand(sbmr1))
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:55 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:55 -0700
Subject: [PATCH v2 17/19] bootsource: Add BOOTSOURCE_CAN
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-18-andrew.smirnov@gmail.com>

Add BOOTSOURCE_CAN for SoCs that can boot from CAN interface.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/bootsource.c  | 1 +
 include/bootsource.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/common/bootsource.c b/common/bootsource.c
index 707b07924..78ecd8267 100644
--- a/common/bootsource.c
+++ b/common/bootsource.c
@@ -36,6 +36,7 @@ static const char *bootsource_str[] = {
 	[BOOTSOURCE_HD] = "harddisk",
 	[BOOTSOURCE_USB] = "usb",
 	[BOOTSOURCE_NET] = "net",
+	[BOOTSOURCE_CAN] = "can",
 };
 
 static enum bootsource bootsource = BOOTSOURCE_UNKNOWN;
diff --git a/include/bootsource.h b/include/bootsource.h
index c6d3b3a98..064f6b9a2 100644
--- a/include/bootsource.h
+++ b/include/bootsource.h
@@ -16,6 +16,7 @@ enum bootsource {
 	BOOTSOURCE_HD,
 	BOOTSOURCE_USB,
 	BOOTSOURCE_NET,
+	BOOTSOURCE_CAN,
 };
 
 #define BOOTSOURCE_INSTANCE_UNKNOWN	-1
-- 
2.14.3



From andrew.smirnov at gmail.com  Mon Apr 16 12:31:56 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 16 Apr 2018 12:31:56 -0700
Subject: [PATCH v2 18/19] ARM: VFxxx: Implement code to detect bootsource
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180416193157.16094-19-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/boot.c                 | 91 ++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/generic.h |  2 +
 2 files changed, 93 insertions(+)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 3f67c2510..f8a04d8f3 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -27,6 +27,7 @@
 #include <mach/imx53-regs.h>
 #include <mach/imx6-regs.h>
 #include <mach/imx7-regs.h>
+#include <mach/vf610-regs.h>
 
 /* [CTRL][TYPE] */
 static const enum bootsource locations[4][4] = {
@@ -474,6 +475,95 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 	}
 }
 
+static int vf610_boot_instance_spi(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG1_1, r);
+}
+
+static int vf610_boot_instance_nor(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG1_3, r);
+}
+
+/*
+ * Vybrid's Serial ROM boot sources (BOOT_CFG4[2:0]) are as follows:
+ *
+ *	000 - SPI0
+ *	001 - SPI1
+ *	010 - SPI2
+ *	011 - SPI3
+ *	100 - I2C0
+ *	101 - I2C1
+ *	110 - I2C2
+ *	111 - I2C3
+ *
+ * Which we can neatly divide in two halves and use MSb to detect if
+ * bootsource is I2C or SPI EEPROM and 2 LSbs directly as boot
+ * insance.
+ */
+static enum bootsource vf610_bootsource_serial_rom(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG4_2, r) ? BOOTSOURCE_I2C : BOOTSOURCE_SPI_NOR;
+}
+
+static int vf610_boot_instance_serial_rom(uint32_t r)
+{
+	return __imx6_bootsource_serial_rom(r) & 0b11;
+}
+
+static int vf610_boot_instance_can(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG1_0, r);
+}
+
+static int vf610_boot_instance_mmc(uint32_t r)
+{
+	return FIELD_GET(BOOT_CFG2_3, r);
+}
+
+void vf610_get_boot_source(enum bootsource *src, int *instance)
+{
+	void __iomem *src_base = IOMEM(VF610_SRC_BASE_ADDR);
+	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
+	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
+
+	if (imx6_bootsource_reserved(sbmr2))
+		return;
+
+	if (imx6_bootsource_serial(sbmr2)) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
+
+	switch (imx53_bootsource_internal(sbmr1)) {
+	case 0:
+		*src = BOOTSOURCE_SPI; /* Really: qspi */
+		*instance = vf610_boot_instance_spi(sbmr1);
+		break;
+	case 1:
+		*src = BOOTSOURCE_NOR;
+		*instance = vf610_boot_instance_nor(sbmr1);
+		break;
+	case 2:
+		*src = vf610_bootsource_serial_rom(sbmr1);
+		*instance = vf610_boot_instance_serial_rom(sbmr1);
+		break;
+	case 3:
+		*src = BOOTSOURCE_CAN;
+		*instance = vf610_boot_instance_can(sbmr1);
+		break;
+	case 6:
+	case 7:
+		*src = BOOTSOURCE_MMC;
+		*instance = vf610_boot_instance_mmc(sbmr1);
+		break;
+	default:
+		if (imx53_bootsource_nand(sbmr1))
+			*src = BOOTSOURCE_NAND;
+		break;
+	}
+}
+
 static void
 imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
 {
@@ -499,3 +589,4 @@ IMX_BOOT_SAVE_LOC(imx51)
 IMX_BOOT_SAVE_LOC(imx53)
 IMX_BOOT_SAVE_LOC(imx6)
 IMX_BOOT_SAVE_LOC(imx7)
+IMX_BOOT_SAVE_LOC(vf610)
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index cb5675185..ad9d9cb02 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -15,6 +15,7 @@ void imx51_boot_save_loc(void);
 void imx53_boot_save_loc(void);
 void imx6_boot_save_loc(void);
 void imx7_boot_save_loc(void);
+void vf610_boot_save_loc(void);
 
 void imx25_get_boot_source(enum bootsource *src, int *instance);
 void imx35_get_boot_source(enum bootsource *src, int *instance);
@@ -22,6 +23,7 @@ void imx51_get_boot_source(enum bootsource *src, int *instance);
 void imx53_get_boot_source(enum bootsource *src, int *instance);
 void imx6_get_boot_source(enum bootsource *src, int *instance);
 void imx7_get_boot_source(enum bootsource *src, int *instance);
+void vf610_get_boot_source(enum bootsource *src, int *instance);
 
 int imx1_init(void);
 int imx21_init(void);
-- 
2.14.3



From antonynpavlov at gmail.com  Mon Apr 16 20:58:29 2018
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Apr 2018 06:58:29 +0300
Subject: [PATCH] commands: i2c_write: enable reg == 0 too
Message-ID: <20180417035829.11841-1-antonynpavlov@gmail.com>

This commit fixes the mistake introduced in the commit 34fadb685905
('commands: i2c_write: enable raw write to address').
The intended behaviour for i2c_write command is
"use raw i2c write only if reg address is not defined".
Before the commit 34fadb685905 reg address == 0
was acceptable. After the commit 34fadb685905 reg address == 0
became unacceptable ("undefined") and will lead to raw i2c write.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 commands/i2c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/commands/i2c.c b/commands/i2c.c
index 21c39fe5af..f0d16af0cb 100644
--- a/commands/i2c.c
+++ b/commands/i2c.c
@@ -131,7 +131,7 @@ static int do_i2c_write(int argc, char *argv[])
 	for (i = 0; i < count; i++)
 		*(buf + i) = (char) simple_strtol(argv[optind+i], NULL, 0);
 
-	if (reg > 0) {
+	if (reg >= 0) {
 		ret = i2c_write_reg(&client, reg | wide, buf, count);
 	} else {
 		ret = i2c_master_send(&client, buf, count);
-- 
2.17.0



From s.hauer at pengutronix.de  Mon Apr 16 23:22:55 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:22:55 +0200
Subject: [PATCH 01/10] Add initial RISC-V architecture support
In-Reply-To: <20180415112858.5163-2-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
 <20180415112858.5163-2-antonynpavlov@gmail.com>
Message-ID: <20180417062255.l62b3tldnqmydpjl@pengutronix.de>

Hi Antony,

On Sun, Apr 15, 2018 at 02:28:49PM +0300, Antony Pavlov wrote:
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> new file mode 100644
> index 0000000000..d65e87acd8
> --- /dev/null
> +++ b/arch/riscv/Kconfig
> @@ -0,0 +1,62 @@
> +config RISCV
> +	def_bool y
> +	select GENERIC_FIND_NEXT_BIT
> +	select HAVE_CONFIGURABLE_MEMORY_LAYOUT
> +	select HAVE_CONFIGURABLE_TEXT_BASE
> +	select GPIOLIB
> +	select OFTREE
> +	select COMMON_CLK
> +	select COMMON_CLK_OF_PROVIDER
> +	select CLKDEV_LOOKUP
> +
> +config ARCH_TEXT_BASE
> +	hex
> +	default 0x0
> +
> +config GENERIC_LINKER_SCRIPT
> +	def_bool y

Do we need this? The linker script should be universal enough to be used
by all boards.

> diff --git a/arch/riscv/dts/skeleton.dtsi b/arch/riscv/dts/skeleton.dtsi
> new file mode 100644
> index 0000000000..38ead821bb
> --- /dev/null
> +++ b/arch/riscv/dts/skeleton.dtsi
> @@ -0,0 +1,13 @@
> +/*
> + * Skeleton device tree; the bare minimum needed to boot; just include and
> + * add a compatible value.  The bootloader will typically populate the memory
> + * node.
> + */
> +
> +/ {
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	chosen { };
> +	aliases { };
> +	memory { device_type = "memory"; reg = <0 0 0>; };
> +};

skeleton.dtsi should no longer be used. For example we should now have
memory at adr {}; instead of memory {};. Since "adr" is board/SoC specific
we can't put it in a generic file.

> diff --git a/arch/riscv/lib/ashldi3.c b/arch/riscv/lib/ashldi3.c
> new file mode 100644
> index 0000000000..cbdbcbb6a9
> --- /dev/null
> +++ b/arch/riscv/lib/ashldi3.c
> @@ -0,0 +1,28 @@
> +#include <module.h>
> +
> +#include "libgcc.h"
> +
> +long long __ashldi3(long long u, word_type b)
> +{

Can we have generic C variants for these files? The Kernel has these
symbols in lib/ and they can be selected by "select GENERIC_ASHLDI3"

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 23:30:02 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:30:02 +0200
Subject: [PATCH 02/10] RISC-V: add Erizo SoC support
In-Reply-To: <20180415112858.5163-3-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
 <20180415112858.5163-3-antonynpavlov@gmail.com>
Message-ID: <20180417063002.jawxqh7252ndw3op@pengutronix.de>

On Sun, Apr 15, 2018 at 02:28:50PM +0300, Antony Pavlov wrote:
> Erizo is an opensource hardware SoC for FPGA.
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  arch/riscv/Kconfig                         | 11 ++++++
>  arch/riscv/Makefile                        |  3 ++
>  arch/riscv/boards/erizo-generic/.gitignore |  1 +
>  arch/riscv/boards/erizo-generic/Makefile   |  1 +
>  arch/riscv/boards/erizo-generic/board.c    | 28 +++++++++++++
>  arch/riscv/dts/erizo.dtsi                  | 46 ++++++++++++++++++++++
>  arch/riscv/dts/erizo_generic.dts           | 32 +++++++++++++++
>  arch/riscv/mach-erizo/Kconfig              | 11 ++++++
>  arch/riscv/mach-erizo/Makefile             |  3 ++
>  9 files changed, 136 insertions(+)
> 
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index d65e87acd8..fe79cb49b5 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -18,6 +18,15 @@ config GENERIC_LINKER_SCRIPT
>  
>  menu "Machine selection"
>  
> +choice
> +	prompt "System type"
> +	default MACH_ERIZO
> +
> +config MACH_ERIZO
> +	bool "erizo family"
> +
> +endchoice
> +
>  choice
>  	prompt "Base ISA"
>  	default ARCH_RV32I
> @@ -51,6 +60,8 @@ config BUILTIN_DTB_NAME
>  	string "DTB to build into the barebox image"
>  	depends on BUILTIN_DTB
>  
> +source arch/riscv/mach-erizo/Kconfig
> +
>  endmenu
>  
>  source common/Kconfig
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index e9c407354c..9a3921065c 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -11,6 +11,9 @@ cflags-y += -Wall -Wmissing-prototypes -Wstrict-prototypes \
>  LDFLAGS += $(ldflags-y)
>  LDFLAGS_barebox += -nostdlib
>  
> +machine-$(CONFIG_MACH_ERIZO)	:= erizo
> +board-$(CONFIG_BOARD_ERIZO_GENERIC)	:= erizo-generic
> +
>  TEXT_BASE = $(CONFIG_TEXT_BASE)
>  CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
>  
> diff --git a/arch/riscv/boards/erizo-generic/.gitignore b/arch/riscv/boards/erizo-generic/.gitignore
> new file mode 100644
> index 0000000000..d1165788c9
> --- /dev/null
> +++ b/arch/riscv/boards/erizo-generic/.gitignore
> @@ -0,0 +1 @@
> +barebox.lds
> diff --git a/arch/riscv/boards/erizo-generic/Makefile b/arch/riscv/boards/erizo-generic/Makefile
> new file mode 100644
> index 0000000000..dcfc2937d3
> --- /dev/null
> +++ b/arch/riscv/boards/erizo-generic/Makefile
> @@ -0,0 +1 @@
> +obj-y += board.o
> diff --git a/arch/riscv/boards/erizo-generic/board.c b/arch/riscv/boards/erizo-generic/board.c
> new file mode 100644
> index 0000000000..46c9ca34f0
> --- /dev/null
> +++ b/arch/riscv/boards/erizo-generic/board.c
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright (C) 2017 Antony Pavlov <antonynpavlov at 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 <driver.h>
> +#include <init.h>
> +
> +static int hostname_init(void)
> +{
> +	barebox_set_hostname("erizo-generic");
> +
> +	return 0;
> +}
> +postcore_initcall(hostname_init);
> diff --git a/arch/riscv/dts/erizo.dtsi b/arch/riscv/dts/erizo.dtsi
> new file mode 100644
> index 0000000000..1660ad1040
> --- /dev/null
> +++ b/arch/riscv/dts/erizo.dtsi
> @@ -0,0 +1,46 @@
> +/dts-v1/;
> +
> +#include "skeleton.dtsi"
> +
> +/ {
> +	compatible = "miet-riscv-workgroup,erizo";
> +
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	clocks {
> +		ref_clk: ref_clk {
> +			#clock-cells = <0>;
> +			compatible = "fixed-clock";
> +			clock-frequency = <24000000>;
> +		};
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu at 0 {
> +			device_type = "cpu";
> +			compatible = "cliffordwolf,picorv32";
> +			clocks = <&ref_clk>;
> +			reg = <0>;
> +		};
> +	};
> +
> +	uart0: uart at 90000000 {
> +		compatible = "ns16550a";
> +		reg = <0x90000000 0x20>;
> +		reg-shift = <2>;
> +		clocks = <&ref_clk>;
> +	};
> +
> +	gpio0: gpio at 91000000 {
> +		compatible = "wd,mbl-gpio";
> +		reg-names = "dat", "dirout";
> +		reg = <0x91000000 0x4>,
> +			<0x91000004 0x4>;
> +		#gpio-cells = <2>;
> +		gpio-controller;
> +	};
> +};
> diff --git a/arch/riscv/dts/erizo_generic.dts b/arch/riscv/dts/erizo_generic.dts
> new file mode 100644
> index 0000000000..a35983ab30
> --- /dev/null
> +++ b/arch/riscv/dts/erizo_generic.dts
> @@ -0,0 +1,32 @@
> +#include "erizo.dtsi"
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/ {
> +	model = "generic Erizo SoC board";
> +	compatible = "miet-riscv-workgroup,erizo-generic-board";
> +
> +	memory {
> +		device_type = "memory";
> +		reg = <0x80000000 0x00800000>;
> +	};
> +
> +	spi0 {
> +		compatible = "spi-gpio";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		gpio-sck  = <&gpio0 0 GPIO_ACTIVE_HIGH>;
> +		gpio-miso = <&gpio0 1 GPIO_ACTIVE_HIGH>;
> +		gpio-mosi = <&gpio0 2 GPIO_ACTIVE_HIGH>;
> +		cs-gpios  = <&gpio0 3 GPIO_ACTIVE_LOW>;
> +		num-chipselects = <1>;
> +
> +		m25p128 at 0 {
> +			compatible = "m25p128", "jedec,spi-nor";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0>;
> +			spi-max-frequency = <1000000>;
> +		};
> +	};
> +};

"generic" and GPIOs wired up for SPI do not go together very well. Are
there really more boards wired up like this?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 23:34:35 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:34:35 +0200
Subject: [PATCH 07/10] RISC-V: erizo: add nmon image creation
In-Reply-To: <20180415112858.5163-8-antonynpavlov@gmail.com>
References: <20180415112858.5163-1-antonynpavlov@gmail.com>
 <20180415112858.5163-8-antonynpavlov@gmail.com>
Message-ID: <20180417063435.zdrlh3grobf75kx7@pengutronix.de>

On Sun, Apr 15, 2018 at 02:28:55PM +0300, Antony Pavlov wrote:
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  arch/riscv/Makefile      | 11 +++++++++++
>  scripts/erizo-nmon-image |  3 +++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index 9a3921065c..c837d4e2e4 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -73,3 +73,14 @@ CFLAGS += $(cflags-y)
>  lds-y	:= arch/riscv/lib/barebox.lds
>  
>  CLEAN_FILES += arch/riscv/lib/barebox.lds
> +
> +ifeq ($(CONFIG_MACH_ERIZO),y)
> +KBUILD_IMAGE := barebox.erizo.nmon
> +endif
> +
> +quiet_cmd_erizo_nmon_image = MKIMAGE $@
> +      cmd_erizo_nmon_image = $(srctree)/scripts/erizo-nmon-image $< $@ || \
> +	echo "WARNING: Couldn't create erizo nmon image due to previous errors."
> +
> +barebox.erizo.nmon: $(KBUILD_BINARY) FORCE
> +	$(call if_changed,erizo_nmon_image)
> diff --git a/scripts/erizo-nmon-image b/scripts/erizo-nmon-image
> new file mode 100755
> index 0000000000..4f0185b6de
> --- /dev/null
> +++ b/scripts/erizo-nmon-image
> @@ -0,0 +1,3 @@
> +#!/bin/sh
> +
> +hexdump -v -e '/4 "%08x\n"' $1 | perl -e '$a = 0x80000000; while (<>) { chop; printf("expect \"nmon> \"\n"); printf("send \"w%08x$_\"\n", $a); $a = $a + 4; }' > $2
> -- 

Maybe add some

if [ $# != 2 ]; then echo "usage: ..."; exit 1; fi

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 23:37:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:37:44 +0200
Subject: MIPS parallel build breakage
In-Reply-To: <20180301110729.pvdxqjqul7klrjyr@pengutronix.de>
References: <20180301110729.pvdxqjqul7klrjyr@pengutronix.de>
Message-ID: <20180417063744.hnxitzm5psxbxfcc@pengutronix.de>

On Thu, Mar 01, 2018 at 12:07:29PM +0100, Sascha Hauer wrote:
> Hi Sam and Antony,
> 
> (Antony because you introduced this and Sam because you have intimate
> knowledge with our build system ;)
> 
> I am trying to solve a problem that annoys me for some years now. The
> problem is that the MIPS defconfigs regularly fail in my autobuilder.
> I usually help myself with trying it again and most of the time it
> then works, but doing this for years increases the pressure to do
> something.
> 
> What happens is that the MIPS builds use include/generated/compile.h:
> 
> > arch/mips/include/asm/pbl_macros.h:28:#include <generated/compile.h>
> 
> This often ends in:
> 
> > In file included from arch/mips/boot/start.S:20:0: arch/mips/include/asm/pbl_macros.h:28:31:
> > fatal error: generated/compile.h: No such file or directory
> > compilation terminated.
> 
> include/generated/compile.h is generated in common/Makefile:
> 
> > include/generated/compile.h: FORCE
> > 	@$($(quiet)chk_compile.h)
> > 	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
> > 	"$(UTS_MACHINE)" "$(CC) $(KBUILD_CFLAGS)"
> 
> Other users of this file add an explicit dependency on it:
> 
> > # dependencies on generated files need to be listed explicitly
> > $(obj)/version.o: include/generated/compile.h
> 
> This only seems to work though when the dependent file is in the same
> directory, but not when the file is in arch/mips/boot/.
> 
> I tried doing the include/generated/compile.h in Makefile instead of
> common/Makefile, but then the version counting gets confused and causes
> unnecessary rebuilds.
> 
> Any ideas how to solve this?

We still have no solution for this. I dropped MIPS from my autobuilder,
so we won't catch any build errors on MIPS anymore :(

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 23:43:20 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:43:20 +0200
Subject: Question about =?iso-8859-15?Q?barebox?=
 =?iso-8859-15?Q?*=2Fdrivers=2Fmfd=2Fmc34704=2Ec_and_ACCURATE_I=B2?=
 =?iso-8859-15?Q?C?= mode ...
In-Reply-To: <20180416101939.yggybypgs3ahr76b@sapphire.tkos.co.il>
References: <38a86524d3ed4ff2b2306a3bb52fb312@eckelmann.de>
 <20180416101939.yggybypgs3ahr76b@sapphire.tkos.co.il>
Message-ID: <20180417064320.hw3helj6mtr5a3v4@pengutronix.de>

Hi Roland,

On Mon, Apr 16, 2018 at 01:19:39PM +0300, Baruch Siach wrote:
> Hi Roland,
> 
> On Mon, Apr 16, 2018 at 09:52:14AM +0000, Mainz, Roland wrote:
> > Two small questions about drivers/mfd/mc34704.c in the barebox codebase:
> > 1. mc34704 has an ACCURATE bit (I2CSET1, see 
> > https://www.nxp.com/docs/en/data-sheet/MC34704.pdf) which requires that all 
> > read/write commands are send twice - does the barebox code have any support 
> > for that in the current versions ?
> > 2. Is this "accurate I?C communication mode" enabled by that bit a 
> > vendor-specific protocol extension or is it part of the I?C standard ?

I never heard of "accurate I?C", it must be something the chip designers
have invented. Also there is no support for it neither in the mc34704
driver nor in the generic I?C support.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 23:49:25 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:49:25 +0200
Subject: [PATCH 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <CAHQ1cqHjLt+UczgWu+_Pe3NLWZM6QWu_M07Odj_5++puaMNs3w@mail.gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-4-andrew.smirnov@gmail.com>
 <20180416071304.2gm2b6noqof3kokw@pengutronix.de>
 <CAHQ1cqHjLt+UczgWu+_Pe3NLWZM6QWu_M07Odj_5++puaMNs3w@mail.gmail.com>
Message-ID: <20180417064925.4uwscnbqgnw2zu27@pengutronix.de>

On Mon, Apr 16, 2018 at 06:28:11AM -0700, Andrey Smirnov wrote:
> On Mon, Apr 16, 2018 at 12:13 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > Hi Andrey,
> >
> > On Sat, Apr 14, 2018 at 10:50:17AM -0700, Andrey Smirnov wrote:
> >> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> >> ---
> >>  arch/arm/mach-imx/imx6.c                      | 4 +++-
> >>  arch/arm/mach-imx/include/mach/reset-reason.h | 2 ++
> >>  2 files changed, 5 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
> >> index 14a1cba5a..3d81c2785 100644
> >> --- a/arch/arm/mach-imx/imx6.c
> >> +++ b/arch/arm/mach-imx/imx6.c
> >> @@ -19,6 +19,7 @@
> >>  #include <mach/imx6.h>
> >>  #include <mach/generic.h>
> >>  #include <mach/revision.h>
> >> +#include <mach/reset-reason.h>
> >>  #include <mach/imx6-anadig.h>
> >>  #include <mach/imx6-regs.h>
> >>  #include <mach/generic.h>
> >> @@ -151,6 +152,7 @@ int imx6_init(void)
> >>  {
> >>       const char *cputypestr;
> >>       u32 mx6_silicon_revision;
> >> +     void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
> >>
> >>       imx6_init_lowlevel();
> >>
> >> @@ -195,7 +197,7 @@ int imx6_init(void)
> >>       }
> >>
> >>       imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
> >> -
> >> +     imx_set_reset_reason(src + IMX6_SRC_SRSR);
> >
> > This will get overwritten by the watchdog driver if enabled.
> >
> 
> I am not sure I see how. Imx_watchdog_detect_reset_source() reports
> reset sources with the same priority as this code, so
> reset_source_set_priority() should bail out early without changing
> anything in that case.

I wasn't aware there is a priority mechanism involved. Indeed the
behaviour seems to be correct. Maybe we should even higher the priority
of imx_set_reset_reason()? This information seems the more accurate one,
so it should be used, and we shouldn't depend on the order of execution.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Apr 16 23:55:47 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:55:47 +0200
Subject: [PATCH] ARM: i.MX6: Make cpu_is_mx6xy() greppable
Message-ID: <20180417065547.11810-1-s.hauer@pengutronix.de>

Grepping for cpu_is_mx6 will not find the definitions of this function
because it is hidden behind a macro. Add a comment containing all
functions defined here to make it greppable.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/mach-imx/include/mach/imx6.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index e06ca4e235..5701bd480c 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -93,6 +93,13 @@ int imx6_cpu_type(void);
 		return cpu_mx6_is_##str();				\
 	}
 
+/*
+ * Below are defined:
+ *
+ * cpu_is_mx6s(), cpu_is_mx6dl(), cpu_is_mx6q(), cpu_is_mx6qp(), cpu_is_mx6d(),
+ * cpu_is_mx6dp(), cpu_is_mx6sx(), cpu_is_mx6sl(), cpu_is_mx6ul(),
+ * cpu_is_mx6ull()
+ */
 DEFINE_MX6_CPU_TYPE(mx6s, IMX6_CPUTYPE_IMX6S);
 DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL);
 DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q);
-- 
2.16.3



From s.hauer at pengutronix.de  Mon Apr 16 23:58:55 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 08:58:55 +0200
Subject: [PATCH v2 01/19] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <20180416193157.16094-2-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
 <20180416193157.16094-2-andrew.smirnov@gmail.com>
Message-ID: <20180417065855.3o2lacq6j5sxzfr6@pengutronix.de>

On Mon, Apr 16, 2018 at 12:31:39PM -0700, Andrey Smirnov wrote:
> All of the instances of imx*_boot_save_loc() do exactly the same thing with
> the only difference being SoC-specific imx*_get_boot_source
> call. Convert the code into a generic function taking function pointer
> + a macro to take care of the boilerplate.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/boot.c | 85 ++++++++++--------------------------------------
>  1 file changed, 17 insertions(+), 68 deletions(-)
> 
> +imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
>  {
>  	enum bootsource src = BOOTSOURCE_UNKNOWN;
>  	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
>  
> -	imx7_get_boot_source(&src, &instance);
> +	get_boot_source(&src, &instance);
>  
>  	bootsource_set(src);
>  	bootsource_set_instance(instance);
>  }
> +
> +#define IMX_BOOT_SAVE_LOC(soc)					\
> +	void soc##_boot_save_loc(void)				\
> +	{							\
> +		imx_boot_save_loc(soc##_get_boot_source);	\
> +	}
> +
> +IMX_BOOT_SAVE_LOC(imx25)
> +IMX_BOOT_SAVE_LOC(imx27)
> +IMX_BOOT_SAVE_LOC(imx35)
> +IMX_BOOT_SAVE_LOC(imx51)
> +IMX_BOOT_SAVE_LOC(imx53)
> +IMX_BOOT_SAVE_LOC(imx6)
> +IMX_BOOT_SAVE_LOC(imx7)

I do not really like this patch. Yes, it saves a few lines of code, but
with the cost of making it less readable.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 17 00:24:19 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 09:24:19 +0200
Subject: [PATCH v2 00/19] i.MX bootsource bugfixes, refactoring and VFxxx
 support
In-Reply-To: <20180416193157.16094-1-andrew.smirnov@gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
Message-ID: <20180417072419.vqg5fmxmhdmrt3zq@pengutronix.de>

On Mon, Apr 16, 2018 at 12:31:38PM -0700, Andrey Smirnov wrote:
> Everyone:
> 
> This patchset is the result of my work on adding support for
> bootsource detection of VFxxx as well as fixing a number of
> bugs/unsupported corner cases in similar i.MX7 specific code.
> 
> NOTE: While VFxxx support is added in this series the code integrating
> it into the SoC initalization sequnce is not included. Patch for that
> is dependent on recently submitted "i.MX reset reason detection
> support" and I didn't want to intertwine two otherwise independent
> submissions.

Applied, thanks. Please send the missing vybrid patch so I can integrate
it here.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Tue Apr 17 00:25:22 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 17 Apr 2018 09:25:22 +0200
Subject: [PATCH] commands: i2c_write: enable reg == 0 too
In-Reply-To: <20180417035829.11841-1-antonynpavlov@gmail.com>
References: <20180417035829.11841-1-antonynpavlov@gmail.com>
Message-ID: <20180417072522.u3tvxjph5vehw4bt@pengutronix.de>

On Tue, Apr 17, 2018 at 06:58:29AM +0300, Antony Pavlov wrote:
> This commit fixes the mistake introduced in the commit 34fadb685905
> ('commands: i2c_write: enable raw write to address').
> The intended behaviour for i2c_write command is
> "use raw i2c write only if reg address is not defined".
> Before the commit 34fadb685905 reg address == 0
> was acceptable. After the commit 34fadb685905 reg address == 0
> became unacceptable ("undefined") and will lead to raw i2c write.
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  commands/i2c.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/commands/i2c.c b/commands/i2c.c
> index 21c39fe5af..f0d16af0cb 100644
> --- a/commands/i2c.c
> +++ b/commands/i2c.c
> @@ -131,7 +131,7 @@ static int do_i2c_write(int argc, char *argv[])
>  	for (i = 0; i < count; i++)
>  		*(buf + i) = (char) simple_strtol(argv[optind+i], NULL, 0);
>  
> -	if (reg > 0) {
> +	if (reg >= 0) {
>  		ret = i2c_write_reg(&client, reg | wide, buf, count);
>  	} else {
>  		ret = i2c_master_send(&client, buf, count);
> -- 
> 2.17.0
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From andrew.smirnov at gmail.com  Tue Apr 17 08:20:46 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 17 Apr 2018 08:20:46 -0700
Subject: [PATCH v2 01/19] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <20180417065855.3o2lacq6j5sxzfr6@pengutronix.de>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
 <20180416193157.16094-2-andrew.smirnov@gmail.com>
 <20180417065855.3o2lacq6j5sxzfr6@pengutronix.de>
Message-ID: <CAHQ1cqF3sXJ2-FiK8vHnMswns+fE=dad=xqaTONmC9z63Sr1cg@mail.gmail.com>

On Mon, Apr 16, 2018 at 11:58 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Mon, Apr 16, 2018 at 12:31:39PM -0700, Andrey Smirnov wrote:
>> All of the instances of imx*_boot_save_loc() do exactly the same thing with
>> the only difference being SoC-specific imx*_get_boot_source
>> call. Convert the code into a generic function taking function pointer
>> + a macro to take care of the boilerplate.
>>
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> ---
>>  arch/arm/mach-imx/boot.c | 85 ++++++++++--------------------------------------
>>  1 file changed, 17 insertions(+), 68 deletions(-)
>>
>> +imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
>>  {
>>       enum bootsource src = BOOTSOURCE_UNKNOWN;
>>       int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
>>
>> -     imx7_get_boot_source(&src, &instance);
>> +     get_boot_source(&src, &instance);
>>
>>       bootsource_set(src);
>>       bootsource_set_instance(instance);
>>  }
>> +
>> +#define IMX_BOOT_SAVE_LOC(soc)                                       \
>> +     void soc##_boot_save_loc(void)                          \
>> +     {                                                       \
>> +             imx_boot_save_loc(soc##_get_boot_source);       \
>> +     }
>> +
>> +IMX_BOOT_SAVE_LOC(imx25)
>> +IMX_BOOT_SAVE_LOC(imx27)
>> +IMX_BOOT_SAVE_LOC(imx35)
>> +IMX_BOOT_SAVE_LOC(imx51)
>> +IMX_BOOT_SAVE_LOC(imx53)
>> +IMX_BOOT_SAVE_LOC(imx6)
>> +IMX_BOOT_SAVE_LOC(imx7)
>
> I do not really like this patch. Yes, it saves a few lines of code, but
> with the cost of making it less readable.
>

Can you elaborate on what part is less readable? IMHO, replacing 68
line of mostly copy pasted code with 17 of a generic function is a bit
more than "saving a few lines of code", so I think it's worth trying
to find a solution that would be acceptable from both perspectives:
conciseness and readability.

Would replacing function pointer with a switch (imx_cpu_type) and
expanding IMX_BOOT_SAVE_LOC() make this patch readable enough to be
accepted?

Thanks,
Andrey Smirnov


From andrew.smirnov at gmail.com  Tue Apr 17 08:35:12 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Tue, 17 Apr 2018 08:35:12 -0700
Subject: [PATCH 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <20180417064925.4uwscnbqgnw2zu27@pengutronix.de>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-4-andrew.smirnov@gmail.com>
 <20180416071304.2gm2b6noqof3kokw@pengutronix.de>
 <CAHQ1cqHjLt+UczgWu+_Pe3NLWZM6QWu_M07Odj_5++puaMNs3w@mail.gmail.com>
 <20180417064925.4uwscnbqgnw2zu27@pengutronix.de>
Message-ID: <CAHQ1cqE+jzfOoFNkXpUX_eqjN=whM9EGYFA1OYo59gFbDiSYWQ@mail.gmail.com>

On Mon, Apr 16, 2018 at 11:49 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Mon, Apr 16, 2018 at 06:28:11AM -0700, Andrey Smirnov wrote:
>> On Mon, Apr 16, 2018 at 12:13 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
>> > Hi Andrey,
>> >
>> > On Sat, Apr 14, 2018 at 10:50:17AM -0700, Andrey Smirnov wrote:
>> >> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> >> ---
>> >>  arch/arm/mach-imx/imx6.c                      | 4 +++-
>> >>  arch/arm/mach-imx/include/mach/reset-reason.h | 2 ++
>> >>  2 files changed, 5 insertions(+), 1 deletion(-)
>> >>
>> >> diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
>> >> index 14a1cba5a..3d81c2785 100644
>> >> --- a/arch/arm/mach-imx/imx6.c
>> >> +++ b/arch/arm/mach-imx/imx6.c
>> >> @@ -19,6 +19,7 @@
>> >>  #include <mach/imx6.h>
>> >>  #include <mach/generic.h>
>> >>  #include <mach/revision.h>
>> >> +#include <mach/reset-reason.h>
>> >>  #include <mach/imx6-anadig.h>
>> >>  #include <mach/imx6-regs.h>
>> >>  #include <mach/generic.h>
>> >> @@ -151,6 +152,7 @@ int imx6_init(void)
>> >>  {
>> >>       const char *cputypestr;
>> >>       u32 mx6_silicon_revision;
>> >> +     void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
>> >>
>> >>       imx6_init_lowlevel();
>> >>
>> >> @@ -195,7 +197,7 @@ int imx6_init(void)
>> >>       }
>> >>
>> >>       imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
>> >> -
>> >> +     imx_set_reset_reason(src + IMX6_SRC_SRSR);
>> >
>> > This will get overwritten by the watchdog driver if enabled.
>> >
>>
>> I am not sure I see how. Imx_watchdog_detect_reset_source() reports
>> reset sources with the same priority as this code, so
>> reset_source_set_priority() should bail out early without changing
>> anything in that case.
>
> I wasn't aware there is a priority mechanism involved. Indeed the
> behaviour seems to be correct. Maybe we should even higher the priority
> of imx_set_reset_reason()? This information seems the more accurate one,
> so it should be used, and we shouldn't depend on the order of execution.
>

I think if I add support for "reset-source-priority" to imxwd.c and
set it up to use the value less then RESET_SOURCE_DEFAULT_PRIORITY by
default we can get both what you describe and allow users to override
the behavior and prioritize reset source provided by watchdog driver.

Let me know if this sounds like a bad idea.

Thanks,
Andrey Smirnov


From s.hauer at pengutronix.de  Wed Apr 18 01:15:15 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 18 Apr 2018 10:15:15 +0200
Subject: [PATCH v2 01/19] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <CAHQ1cqF3sXJ2-FiK8vHnMswns+fE=dad=xqaTONmC9z63Sr1cg@mail.gmail.com>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
 <20180416193157.16094-2-andrew.smirnov@gmail.com>
 <20180417065855.3o2lacq6j5sxzfr6@pengutronix.de>
 <CAHQ1cqF3sXJ2-FiK8vHnMswns+fE=dad=xqaTONmC9z63Sr1cg@mail.gmail.com>
Message-ID: <20180418081515.fdusp7fvycmq7kij@pengutronix.de>

On Tue, Apr 17, 2018 at 08:20:46AM -0700, Andrey Smirnov wrote:
> On Mon, Apr 16, 2018 at 11:58 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > On Mon, Apr 16, 2018 at 12:31:39PM -0700, Andrey Smirnov wrote:
> >> All of the instances of imx*_boot_save_loc() do exactly the same thing with
> >> the only difference being SoC-specific imx*_get_boot_source
> >> call. Convert the code into a generic function taking function pointer
> >> + a macro to take care of the boilerplate.
> >>
> >> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> >> ---
> >>  arch/arm/mach-imx/boot.c | 85 ++++++++++--------------------------------------
> >>  1 file changed, 17 insertions(+), 68 deletions(-)
> >>
> >> +imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
> >>  {
> >>       enum bootsource src = BOOTSOURCE_UNKNOWN;
> >>       int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> >>
> >> -     imx7_get_boot_source(&src, &instance);
> >> +     get_boot_source(&src, &instance);
> >>
> >>       bootsource_set(src);
> >>       bootsource_set_instance(instance);
> >>  }
> >> +
> >> +#define IMX_BOOT_SAVE_LOC(soc)                                       \
> >> +     void soc##_boot_save_loc(void)                          \
> >> +     {                                                       \
> >> +             imx_boot_save_loc(soc##_get_boot_source);       \
> >> +     }
> >> +
> >> +IMX_BOOT_SAVE_LOC(imx25)
> >> +IMX_BOOT_SAVE_LOC(imx27)
> >> +IMX_BOOT_SAVE_LOC(imx35)
> >> +IMX_BOOT_SAVE_LOC(imx51)
> >> +IMX_BOOT_SAVE_LOC(imx53)
> >> +IMX_BOOT_SAVE_LOC(imx6)
> >> +IMX_BOOT_SAVE_LOC(imx7)
> >
> > I do not really like this patch. Yes, it saves a few lines of code, but
> > with the cost of making it less readable.
> >
> 
> Can you elaborate on what part is less readable? IMHO, replacing 68
> line of mostly copy pasted code with 17 of a generic function is a bit
> more than "saving a few lines of code", so I think it's worth trying
> to find a solution that would be acceptable from both perspectives:
> conciseness and readability.

I think it's bad when grepping for a function name only reveals the
callers, maybe the declaraion, but not the definition of a function.
Using macros to define functions is sometimes very effective (and done
in barebox at other places), but not very nice to look at.

> 
> Would replacing function pointer with a switch (imx_cpu_type) and
> expanding IMX_BOOT_SAVE_LOC() make this patch readable enough to be
> accepted?

Not sure what exactly you mean, but the following should be fine. With
a bit of violating the coding style this is not longer than your solution,
but without hiding the function names behind a macro:

void vf610_boot_save_loc(void) { boot_save_loc(vf610_get_boot_source); }

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 18 01:23:21 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 18 Apr 2018 10:23:21 +0200
Subject: [PATCH 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <CAHQ1cqE+jzfOoFNkXpUX_eqjN=whM9EGYFA1OYo59gFbDiSYWQ@mail.gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-4-andrew.smirnov@gmail.com>
 <20180416071304.2gm2b6noqof3kokw@pengutronix.de>
 <CAHQ1cqHjLt+UczgWu+_Pe3NLWZM6QWu_M07Odj_5++puaMNs3w@mail.gmail.com>
 <20180417064925.4uwscnbqgnw2zu27@pengutronix.de>
 <CAHQ1cqE+jzfOoFNkXpUX_eqjN=whM9EGYFA1OYo59gFbDiSYWQ@mail.gmail.com>
Message-ID: <20180418082321.gvm5mhznphwqgl7y@pengutronix.de>

On Tue, Apr 17, 2018 at 08:35:12AM -0700, Andrey Smirnov wrote:
> On Mon, Apr 16, 2018 at 11:49 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > On Mon, Apr 16, 2018 at 06:28:11AM -0700, Andrey Smirnov wrote:
> >> On Mon, Apr 16, 2018 at 12:13 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> >> >> @@ -151,6 +152,7 @@ int imx6_init(void)
> >> >>  {
> >> >>       const char *cputypestr;
> >> >>       u32 mx6_silicon_revision;
> >> >> +     void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
> >> >>
> >> >>       imx6_init_lowlevel();
> >> >>
> >> >> @@ -195,7 +197,7 @@ int imx6_init(void)
> >> >>       }
> >> >>
> >> >>       imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
> >> >> -
> >> >> +     imx_set_reset_reason(src + IMX6_SRC_SRSR);
> >> >
> >> > This will get overwritten by the watchdog driver if enabled.
> >> >
> >>
> >> I am not sure I see how. Imx_watchdog_detect_reset_source() reports
> >> reset sources with the same priority as this code, so
> >> reset_source_set_priority() should bail out early without changing
> >> anything in that case.
> >
> > I wasn't aware there is a priority mechanism involved. Indeed the
> > behaviour seems to be correct. Maybe we should even higher the priority
> > of imx_set_reset_reason()? This information seems the more accurate one,
> > so it should be used, and we shouldn't depend on the order of execution.
> >
> 
> I think if I add support for "reset-source-priority" to imxwd.c and
> set it up to use the value less then RESET_SOURCE_DEFAULT_PRIORITY by
> default we can get both what you describe and allow users to override
> the behavior and prioritize reset source provided by watchdog driver.
> 
> Let me know if this sounds like a bad idea.

It doesn't sound like a bad idea, I'm just not convinced it's a good
idea ;)

Reading the SRC registers seems to give us more accurate informations
than reading the watchdog. Provided this is true I don't see a reason to
make the priority configurable. If it was only for i.MX6/7 I would say,
we could remove the reset source detection from the watchdog driver
entirely, but we need the informations from the driver on older SoCs.

Anyway, before making this configurable I think it's better to wait
until somebody to show up who really needs this (and thus can explain
the reasons), rather than to just add it in case it might be useful.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From p.zabel at pengutronix.de  Wed Apr 18 08:23:30 2018
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 18 Apr 2018 17:23:30 +0200
Subject: [PATCH 02/10] ARM: i.MX: Add infrastructure to record SoC reset
 reason
In-Reply-To: <20180414175024.9962-3-andrew.smirnov@gmail.com>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-3-andrew.smirnov@gmail.com>
Message-ID: <1524065010.3528.9.camel@pengutronix.de>

On Sat, 2018-04-14 at 10:50 -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/imx.c                       | 49 +++++++++++++++++++++++++++
>  arch/arm/mach-imx/include/mach/reset-reason.h | 17 ++++++++++
>  2 files changed, 66 insertions(+)
>  create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h
> 
> diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
> index 9400105c6..e860e298a 100644
> --- a/arch/arm/mach-imx/imx.c
> +++ b/arch/arm/mach-imx/imx.c
> @@ -14,8 +14,11 @@
>  #include <common.h>
>  #include <of.h>
>  #include <init.h>
> +#include <io.h>
>  #include <mach/revision.h>
> +#include <mach/reset-reason.h>
>  #include <mach/generic.h>
> +#include <reset_source.h>
>  
>  static int __imx_silicon_revision = IMX_CHIP_REV_UNKNOWN;
>  
> @@ -147,3 +150,49 @@ static int imx_init(void)
>  	return ret;
>  }
>  postcore_initcall(imx_init);
> +
> +void imx_set_reset_reason(void __iomem *srsr)
> +{
> +	enum reset_src_type type = RESET_UKWN;
> +	const u32 reg = readl(srsr);
> +
> +	/*
> +	 * SRSR register captures ALL reset event that occured since
> +	 * POR, so we need to clear it to make sure we only caputre
> +	 * the latest one.
> +	 */
> +	writel(reg, srsr);

What if, say, both a watchdog and the tempsense reset have triggered
since last POR (or since last clearing of SRSR)?
In that case we'll report RESET_UKWN *and* throw away the SRSR
information here.

regards
Philipp


From andrew.smirnov at gmail.com  Thu Apr 19 15:19:27 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 19 Apr 2018 15:19:27 -0700
Subject: [PATCH 02/10] ARM: i.MX: Add infrastructure to record SoC reset
 reason
In-Reply-To: <1524065010.3528.9.camel@pengutronix.de>
References: <20180414175024.9962-1-andrew.smirnov@gmail.com>
 <20180414175024.9962-3-andrew.smirnov@gmail.com>
 <1524065010.3528.9.camel@pengutronix.de>
Message-ID: <CAHQ1cqFpxiSpAVAyXZEp-UbXH39dHSzibzTfjpkHtNd-0bopnw@mail.gmail.com>

On Wed, Apr 18, 2018 at 8:23 AM, Philipp Zabel <p.zabel at pengutronix.de> wrote:
> On Sat, 2018-04-14 at 10:50 -0700, Andrey Smirnov wrote:
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> ---
>>  arch/arm/mach-imx/imx.c                       | 49 +++++++++++++++++++++++++++
>>  arch/arm/mach-imx/include/mach/reset-reason.h | 17 ++++++++++
>>  2 files changed, 66 insertions(+)
>>  create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h
>>
>> diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
>> index 9400105c6..e860e298a 100644
>> --- a/arch/arm/mach-imx/imx.c
>> +++ b/arch/arm/mach-imx/imx.c
>> @@ -14,8 +14,11 @@
>>  #include <common.h>
>>  #include <of.h>
>>  #include <init.h>
>> +#include <io.h>
>>  #include <mach/revision.h>
>> +#include <mach/reset-reason.h>
>>  #include <mach/generic.h>
>> +#include <reset_source.h>
>>
>>  static int __imx_silicon_revision = IMX_CHIP_REV_UNKNOWN;
>>
>> @@ -147,3 +150,49 @@ static int imx_init(void)
>>       return ret;
>>  }
>>  postcore_initcall(imx_init);
>> +
>> +void imx_set_reset_reason(void __iomem *srsr)
>> +{
>> +     enum reset_src_type type = RESET_UKWN;
>> +     const u32 reg = readl(srsr);
>> +
>> +     /*
>> +      * SRSR register captures ALL reset event that occured since
>> +      * POR, so we need to clear it to make sure we only caputre
>> +      * the latest one.
>> +      */
>> +     writel(reg, srsr);
>
> What if, say, both a watchdog and the tempsense reset have triggered
> since last POR (or since last clearing of SRSR)?
> In that case we'll report RESET_UKWN *and* throw away the SRSR
> information here.
>

I am assuming we are talking about the fact that "reg" is decoded
using switch statement, as opposed to doing bitmaksing (like VFxxx
code does). I got the code form U-Boot and that is how it's doing the
decoding, but you are right it is going to be problematic for use-case
you describe.

I'll switch the code to do bitmaksing instead.

Thanks,
Andrey Smrinov


From andrew.smirnov at gmail.com  Thu Apr 19 15:26:09 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 19 Apr 2018 15:26:09 -0700
Subject: [PATCH v2 01/19] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <20180418081515.fdusp7fvycmq7kij@pengutronix.de>
References: <20180416193157.16094-1-andrew.smirnov@gmail.com>
 <20180416193157.16094-2-andrew.smirnov@gmail.com>
 <20180417065855.3o2lacq6j5sxzfr6@pengutronix.de>
 <CAHQ1cqF3sXJ2-FiK8vHnMswns+fE=dad=xqaTONmC9z63Sr1cg@mail.gmail.com>
 <20180418081515.fdusp7fvycmq7kij@pengutronix.de>
Message-ID: <CAHQ1cqE3+HJaGgkSF7vH8mbOAErLWY+U-x-Un+YcP-ib5mOG5w@mail.gmail.com>

On Wed, Apr 18, 2018 at 1:15 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Tue, Apr 17, 2018 at 08:20:46AM -0700, Andrey Smirnov wrote:
>> On Mon, Apr 16, 2018 at 11:58 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
>> > On Mon, Apr 16, 2018 at 12:31:39PM -0700, Andrey Smirnov wrote:
>> >> All of the instances of imx*_boot_save_loc() do exactly the same thing with
>> >> the only difference being SoC-specific imx*_get_boot_source
>> >> call. Convert the code into a generic function taking function pointer
>> >> + a macro to take care of the boilerplate.
>> >>
>> >> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> >> ---
>> >>  arch/arm/mach-imx/boot.c | 85 ++++++++++--------------------------------------
>> >>  1 file changed, 17 insertions(+), 68 deletions(-)
>> >>
>> >> +imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
>> >>  {
>> >>       enum bootsource src = BOOTSOURCE_UNKNOWN;
>> >>       int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
>> >>
>> >> -     imx7_get_boot_source(&src, &instance);
>> >> +     get_boot_source(&src, &instance);
>> >>
>> >>       bootsource_set(src);
>> >>       bootsource_set_instance(instance);
>> >>  }
>> >> +
>> >> +#define IMX_BOOT_SAVE_LOC(soc)                                       \
>> >> +     void soc##_boot_save_loc(void)                          \
>> >> +     {                                                       \
>> >> +             imx_boot_save_loc(soc##_get_boot_source);       \
>> >> +     }
>> >> +
>> >> +IMX_BOOT_SAVE_LOC(imx25)
>> >> +IMX_BOOT_SAVE_LOC(imx27)
>> >> +IMX_BOOT_SAVE_LOC(imx35)
>> >> +IMX_BOOT_SAVE_LOC(imx51)
>> >> +IMX_BOOT_SAVE_LOC(imx53)
>> >> +IMX_BOOT_SAVE_LOC(imx6)
>> >> +IMX_BOOT_SAVE_LOC(imx7)
>> >
>> > I do not really like this patch. Yes, it saves a few lines of code, but
>> > with the cost of making it less readable.
>> >
>>
>> Can you elaborate on what part is less readable? IMHO, replacing 68
>> line of mostly copy pasted code with 17 of a generic function is a bit
>> more than "saving a few lines of code", so I think it's worth trying
>> to find a solution that would be acceptable from both perspectives:
>> conciseness and readability.
>
> I think it's bad when grepping for a function name only reveals the
> callers, maybe the declaraion, but not the definition of a function.
> Using macros to define functions is sometimes very effective (and done
> in barebox at other places), but not very nice to look at.
>
>>
>> Would replacing function pointer with a switch (imx_cpu_type) and
>> expanding IMX_BOOT_SAVE_LOC() make this patch readable enough to be
>> accepted?
>
> Not sure what exactly you mean, but the following should be fine. With
> a bit of violating the coding style this is not longer than your solution,
> but without hiding the function names behind a macro:
>
> void vf610_boot_save_loc(void) { boot_save_loc(vf610_get_boot_source); }
>

That's what I meant by "expanding IMX_BOOT_SAVE_LOC()". I'll update
the patch and re-submit it.

Thanks,
Andrey Smirnov


From gp at high-consulting.de  Fri Apr 20 01:01:14 2018
From: gp at high-consulting.de (Gerd Pauli)
Date: Fri, 20 Apr 2018 10:01:14 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
Message-ID: <20180420080114.9148-1-gp@high-consulting.de>

Adds ccryptlib library in crypto which implements a
stream cipher based on the block cipher Rijndael,
the candidate for the AES standard.
Compatible with the ccrypt tool in linux
from Peter Selinger.

Usage: ccrypt [-e|-d] -k KEYNAME_IN_KEYSTORE SRC DST

Signed-off-by: Gerd Pauli <gp at high-consulting.de>
---
 commands/Kconfig    |   17 +
 commands/Makefile   |    1 +
 commands/ccrypt.c   |  249 +++++++++
 crypto/Kconfig      |    7 +
 crypto/Makefile     |    1 +
 crypto/ccryptlib.c  | 1467 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/ccryptlib.h |  102 ++++
 7 files changed, 1844 insertions(+)
 create mode 100644 commands/ccrypt.c
 create mode 100644 crypto/ccryptlib.c
 create mode 100644 include/ccryptlib.h

diff --git a/commands/Kconfig b/commands/Kconfig
index 951a86963..b6911246a 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -2137,6 +2137,23 @@ config CMD_SEED
 	help
 	  Seed the pseudo random number generator (PRNG)
 
+config CMD_CCRYPT
+        tristate
+        prompt "ccrypt"
+        select CRYPTO_CCRYPTLIB
+        select CRYPTO_KEYSTORE
+        help
+          encrypting/decrypting a character stream
+          ccrypt implements a stream cipher based on the block cipher
+          Rijndael.
+
+          Usage: ccrypt [-ed] [-K name] srcfile dstfile
+
+          Options:
+                        -e            encrypt srcfile to dstfile
+                        -d            decrypt srcfile to dstfile
+                        -k name       use key with name from keystore
+
 # end Miscellaneous commands
 endmenu
 
diff --git a/commands/Makefile b/commands/Makefile
index eb4796389..3693bf553 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -123,3 +123,4 @@ obj-$(CONFIG_CMD_MMC_EXTCSD)	+= mmc_extcsd.o
 obj-$(CONFIG_CMD_NAND_BITFLIP)	+= nand-bitflip.o
 obj-$(CONFIG_CMD_SEED)		+= seed.o
 obj-$(CONFIG_CMD_IP_ROUTE_GET)  += ip-route-get.o
+obj-$(CONFIG_CMD_CCRYPT)        += ccrypt.o
diff --git a/commands/ccrypt.c b/commands/ccrypt.c
new file mode 100644
index 000000000..1b0ee9f1a
--- /dev/null
+++ b/commands/ccrypt.c
@@ -0,0 +1,249 @@
+/* -*- Mode:C; c-file-style:"linux"; -*- */
+
+/* Copyright (C) 2018 Gerd Pauli <gp at high-consulting.de */
+
+/* Copyright (C) 2000-2012 Peter Selinger. */
+
+/* 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.    
+ */
+
+/* ccrypt implements a stream cipher based on the block cipher
+   Rijndael  */
+
+/* needs library ccryptlib and keystore from barebox */
+
+#include <common.h>
+#include <command.h>
+#include <libfile.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <ccryptlib.h>
+#include <crypto/keystore.h>
+
+#define INBUFSIZE 1024  
+#define OUTBUFSIZE INBUFSIZE+32
+
+void ccrypt_error( int e ) {
+	if ( e == -1 ) {  
+		printf("ccrypt: %s\n",strerror(-errno));
+		return;
+	} 
+        if ( e == -2 ) {
+                switch (ccrypt_errno) {
+                case CCRYPT_EFORMAT:
+                        printf("ccrypt: %s\n","bad file format");
+                        break;
+                case CCRYPT_EMISMATCH:
+                        printf("ccrypt: %s\n","key does not match");
+                        break;
+                case CCRYPT_EBUFFER:
+                        printf("ccrypt: %s\n","buffer overflow");
+                        break;
+                default:
+                        /* do nothing */
+                        printf("ccrypt: %s %d\n","unknown ccrypt error: ",ccrypt_errno);
+                        break;
+		}
+		return;
+	}
+	if ( e == -3 ) {  
+		printf("ccrypt: %s\n","no key");
+		return;
+	} 
+	printf("ccrypt: %s: %d\n","unknown error",e);
+}
+
+static int do_ccrypt(int argc, char *argv[])
+{
+	int opt;
+	int ret=-EINVAL;
+	int encrypt=0;
+	int decrypt=0;
+	char *extract = NULL;
+	char *from = NULL;
+	char *to = NULL;
+	char *r_buf = NULL;
+	char *w_buf = NULL;
+	int from_fd = 0;
+	int to_fd = 0;
+	int r,w;
+	void *buf;
+	ccrypt_stream_t ccs;
+	ccrypt_stream_t *b = &ccs;
+	char *key;
+	int keylen;
+	int eof=0;
+
+	while ((opt = getopt(argc, argv, "dek:")) > 0) {
+		switch(opt) {
+		case 'e':
+			encrypt=1;
+			break;
+		case 'd':
+			decrypt=1;
+			break;
+		case 'k':
+			extract = optarg;
+			break;
+		}
+	}
+	if ( encrypt == 1 && decrypt == 1 ) 
+		return ret;
+	if ( extract == NULL )
+		return ret;
+
+	if ( optind != 4 ) 
+		return ret;
+
+	if ( argc != 6 )
+		return ret;
+
+	from = argv[optind];
+	to = argv[optind + 1];
+
+	r_buf=malloc(INBUFSIZE);
+        if ( r_buf == NULL ) {
+                ret = -1;
+                goto out;
+        }
+        
+	w_buf=malloc(OUTBUFSIZE);
+        if ( w_buf == NULL ) {
+                free(r_buf);
+                ret = -1;
+                goto out;
+        }
+  
+	ret=keystore_get_secret(extract, (const u8 **)&key, &keylen);
+
+#ifdef DEBUG
+        if ( key && keystore ) 
+                memory_display(key,0,keylen,1,0);
+#endif
+        
+        if ( ret ) {
+                ret=-3;
+		goto out;
+        }
+        
+	from_fd = open(from, O_RDONLY);
+	if (from_fd < 0) {
+		printf("could not open %s: %s\n", from, errno_str());
+		ret=-1;
+		goto out;
+	}
+
+	to_fd = open(to, O_WRONLY | O_CREAT | O_TRUNC);
+	if (to_fd < 0) {
+		printf("could not open %s: %s\n", to, errno_str());
+		ret=-1;
+		goto out;
+	}
+
+	ret=0;
+
+	if ( encrypt == 1 ) 
+		ret = ccencrypt_init(b, key, keylen);
+  
+	if ( decrypt == 1 ) 
+		ret = ccdecrypt_init(b, key, keylen);
+  
+	if ( ret != 0 ) {
+                printf("cc init error\n");
+		goto out;
+	}
+
+	b->avail_in = 0;
+  
+	while (1) {
+		/* fill input buffer */
+		if (b->avail_in == 0 && !eof) {
+			r = read(from_fd, r_buf, INBUFSIZE);
+			if (r < 0) {
+				perror("read");
+                                ret=-1;
+				goto out;
+			}
+			if (!r)
+				eof=1;
+			b->next_in = &r_buf[0];
+			b->avail_in = r;
+		}
+    
+		/* prepare output buffer */
+		b->next_out = &w_buf[0];
+		b->avail_out = OUTBUFSIZE;
+    
+		/* do some work */
+		if ( encrypt == 1 ) {
+			ret = ccencrypt(b);
+		}
+		if ( decrypt == 1 ) {
+			ret = ccdecrypt(b);
+			if (ret) {
+                                printf("cc dec err\n");
+				ret=-2;
+				goto out;
+			}
+		}
+    
+		r = OUTBUFSIZE-b->avail_out;
+		buf = &w_buf[0];
+
+		/* process output buffer */
+		while (r) {
+			w = write(to_fd, buf, r);
+			if (w < 0) {
+                                printf("write error\n");
+                                ret=-1;
+				goto out;
+			}
+			buf += w;
+			r -= w;
+		}
+
+		/* ready */ 
+		if (eof && b->avail_out != 0) {
+			break;
+		}
+	}
+	ret = 0;
+out:
+        free(r_buf);
+        free(w_buf);
+	if (from_fd > 0)
+		close(from_fd);
+	if (to_fd > 0)
+		close(to_fd);
+
+	return ret;
+}
+
+BAREBOX_CMD_HELP_START(ccrypt)
+BAREBOX_CMD_HELP_TEXT("Rijandel Crypt and Decrypt")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-e", "encrypt")
+BAREBOX_CMD_HELP_OPT("-d", "decrypt")
+BAREBOX_CMD_HELP_OPT("-k name", "Name of key in keystore")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(ccrypt)
+.cmd	= do_ccrypt,
+	BAREBOX_CMD_DESC("Crypt and Decrypt Files")
+	BAREBOX_CMD_OPTS("[-e|-d] -k NAME SRC DST")
+        BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+	BAREBOX_CMD_HELP(cmd_ccrypt_help)
+	BAREBOX_CMD_END
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 6d65c24d4..08669a2de 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -101,4 +101,11 @@ config CRYPTO_KEYSTORE
 	  This is a simple keystore, which can be used to pass keys
 	  between several components via simple interface.
 
+config CRYPTO_CCRYPTLIB
+        bool "ccryptlib"
+        help
+          This option provides functions implementing a stream cipher based
+          on the block cipher rijandel.
+          The cipher is based on Peter Selingers ccrypt implementation.
+
 endmenu
diff --git a/crypto/Makefile b/crypto/Makefile
index a7240d1d6..1231bc76d 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_DIGEST_SHA512_GENERIC)	+= sha4.o
 obj-$(CONFIG_CRYPTO_PBKDF2)	+= pbkdf2.o
 obj-$(CONFIG_CRYPTO_RSA)	+= rsa.o
 obj-$(CONFIG_CRYPTO_KEYSTORE)	+= keystore.o
+obj-$(CONFIG_CRYPTO_CCRYPTLIB)  += ccryptlib.o
diff --git a/crypto/ccryptlib.c b/crypto/ccryptlib.c
new file mode 100644
index 000000000..78f0ac843
--- /dev/null
+++ b/crypto/ccryptlib.c
@@ -0,0 +1,1467 @@
+/* -*- Mode:C; c-file-style:"linux"; -*- */
+
+/* Ported to barebox by Gerd Pauli <gp at high-consulting.de> 2018 */
+
+/* Copyright (C) 2000-2012 Peter Selinger.
+   This file is part of ccrypt. It is free software and it is covered
+   by the GNU general public license. See the file COPYING for details. */
+
+/* NOTE: this library is copyrighted under the GNU General Public
+   License, *not* under the GNU Library General Public License.  This
+   means, among other things, that you cannot use this library in
+   closed-source software. */
+
+/* ccryptlib implements a stream cipher based on the block cipher
+   Rijndael, the candidate for the AES standard. */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ccryptlib.h>
+#include <common.h>
+#include <malloc.h>
+
+/* ---------- rijandel.c ---------- */
+
+/* rijndael.c - optimized version of the Rijndeal cipher */
+/* derived from original source: rijndael-alg-ref.c   v2.0   August '99
+ * Reference ANSI C code for NIST competition
+ * authors: Paulo Barreto
+ *          Vincent Rijmen
+ */
+
+typedef unsigned char word8;
+
+#ifdef UINT32_TYPE
+typedef UINT32_TYPE word32;
+#else
+typedef int word32;		/* should be a 32-bit integer type */
+#endif
+
+/* a type to hold 32 bits accessible as 1 integer or 4 bytes */
+union word8x4_u {
+        word8 w8[4];
+        word32 w32;
+};
+typedef union word8x4_u word8x4;
+
+/* ---------- tables.c ------------ */
+
+word8x4 M0[4][256] = {
+        {
+                {{  0,   0,   0,   0}}, {{  2,   1,   1,   3}}, {{  4,   2,   2,   6}}, 
+                {{  6,   3,   3,   5}}, {{  8,   4,   4,  12}}, {{ 10,   5,   5,  15}}, 
+                {{ 12,   6,   6,  10}}, {{ 14,   7,   7,   9}}, {{ 16,   8,   8,  24}}, 
+                {{ 18,   9,   9,  27}}, {{ 20,  10,  10,  30}}, {{ 22,  11,  11,  29}}, 
+                {{ 24,  12,  12,  20}}, {{ 26,  13,  13,  23}}, {{ 28,  14,  14,  18}}, 
+                {{ 30,  15,  15,  17}}, {{ 32,  16,  16,  48}}, {{ 34,  17,  17,  51}}, 
+                {{ 36,  18,  18,  54}}, {{ 38,  19,  19,  53}}, {{ 40,  20,  20,  60}}, 
+                {{ 42,  21,  21,  63}}, {{ 44,  22,  22,  58}}, {{ 46,  23,  23,  57}}, 
+                {{ 48,  24,  24,  40}}, {{ 50,  25,  25,  43}}, {{ 52,  26,  26,  46}}, 
+                {{ 54,  27,  27,  45}}, {{ 56,  28,  28,  36}}, {{ 58,  29,  29,  39}}, 
+                {{ 60,  30,  30,  34}}, {{ 62,  31,  31,  33}}, {{ 64,  32,  32,  96}}, 
+                {{ 66,  33,  33,  99}}, {{ 68,  34,  34, 102}}, {{ 70,  35,  35, 101}}, 
+                {{ 72,  36,  36, 108}}, {{ 74,  37,  37, 111}}, {{ 76,  38,  38, 106}}, 
+                {{ 78,  39,  39, 105}}, {{ 80,  40,  40, 120}}, {{ 82,  41,  41, 123}}, 
+                {{ 84,  42,  42, 126}}, {{ 86,  43,  43, 125}}, {{ 88,  44,  44, 116}}, 
+                {{ 90,  45,  45, 119}}, {{ 92,  46,  46, 114}}, {{ 94,  47,  47, 113}}, 
+                {{ 96,  48,  48,  80}}, {{ 98,  49,  49,  83}}, {{100,  50,  50,  86}}, 
+                {{102,  51,  51,  85}}, {{104,  52,  52,  92}}, {{106,  53,  53,  95}}, 
+                {{108,  54,  54,  90}}, {{110,  55,  55,  89}}, {{112,  56,  56,  72}}, 
+                {{114,  57,  57,  75}}, {{116,  58,  58,  78}}, {{118,  59,  59,  77}}, 
+                {{120,  60,  60,  68}}, {{122,  61,  61,  71}}, {{124,  62,  62,  66}}, 
+                {{126,  63,  63,  65}}, {{128,  64,  64, 192}}, {{130,  65,  65, 195}}, 
+                {{132,  66,  66, 198}}, {{134,  67,  67, 197}}, {{136,  68,  68, 204}}, 
+                {{138,  69,  69, 207}}, {{140,  70,  70, 202}}, {{142,  71,  71, 201}}, 
+                {{144,  72,  72, 216}}, {{146,  73,  73, 219}}, {{148,  74,  74, 222}}, 
+                {{150,  75,  75, 221}}, {{152,  76,  76, 212}}, {{154,  77,  77, 215}}, 
+                {{156,  78,  78, 210}}, {{158,  79,  79, 209}}, {{160,  80,  80, 240}}, 
+                {{162,  81,  81, 243}}, {{164,  82,  82, 246}}, {{166,  83,  83, 245}}, 
+                {{168,  84,  84, 252}}, {{170,  85,  85, 255}}, {{172,  86,  86, 250}}, 
+                {{174,  87,  87, 249}}, {{176,  88,  88, 232}}, {{178,  89,  89, 235}}, 
+                {{180,  90,  90, 238}}, {{182,  91,  91, 237}}, {{184,  92,  92, 228}}, 
+                {{186,  93,  93, 231}}, {{188,  94,  94, 226}}, {{190,  95,  95, 225}}, 
+                {{192,  96,  96, 160}}, {{194,  97,  97, 163}}, {{196,  98,  98, 166}}, 
+                {{198,  99,  99, 165}}, {{200, 100, 100, 172}}, {{202, 101, 101, 175}}, 
+                {{204, 102, 102, 170}}, {{206, 103, 103, 169}}, {{208, 104, 104, 184}}, 
+                {{210, 105, 105, 187}}, {{212, 106, 106, 190}}, {{214, 107, 107, 189}}, 
+                {{216, 108, 108, 180}}, {{218, 109, 109, 183}}, {{220, 110, 110, 178}}, 
+                {{222, 111, 111, 177}}, {{224, 112, 112, 144}}, {{226, 113, 113, 147}}, 
+                {{228, 114, 114, 150}}, {{230, 115, 115, 149}}, {{232, 116, 116, 156}}, 
+                {{234, 117, 117, 159}}, {{236, 118, 118, 154}}, {{238, 119, 119, 153}}, 
+                {{240, 120, 120, 136}}, {{242, 121, 121, 139}}, {{244, 122, 122, 142}}, 
+                {{246, 123, 123, 141}}, {{248, 124, 124, 132}}, {{250, 125, 125, 135}}, 
+                {{252, 126, 126, 130}}, {{254, 127, 127, 129}}, {{ 27, 128, 128, 155}}, 
+                {{ 25, 129, 129, 152}}, {{ 31, 130, 130, 157}}, {{ 29, 131, 131, 158}}, 
+                {{ 19, 132, 132, 151}}, {{ 17, 133, 133, 148}}, {{ 23, 134, 134, 145}}, 
+                {{ 21, 135, 135, 146}}, {{ 11, 136, 136, 131}}, {{  9, 137, 137, 128}}, 
+                {{ 15, 138, 138, 133}}, {{ 13, 139, 139, 134}}, {{  3, 140, 140, 143}}, 
+                {{  1, 141, 141, 140}}, {{  7, 142, 142, 137}}, {{  5, 143, 143, 138}}, 
+                {{ 59, 144, 144, 171}}, {{ 57, 145, 145, 168}}, {{ 63, 146, 146, 173}}, 
+                {{ 61, 147, 147, 174}}, {{ 51, 148, 148, 167}}, {{ 49, 149, 149, 164}}, 
+                {{ 55, 150, 150, 161}}, {{ 53, 151, 151, 162}}, {{ 43, 152, 152, 179}}, 
+                {{ 41, 153, 153, 176}}, {{ 47, 154, 154, 181}}, {{ 45, 155, 155, 182}}, 
+                {{ 35, 156, 156, 191}}, {{ 33, 157, 157, 188}}, {{ 39, 158, 158, 185}}, 
+                {{ 37, 159, 159, 186}}, {{ 91, 160, 160, 251}}, {{ 89, 161, 161, 248}}, 
+                {{ 95, 162, 162, 253}}, {{ 93, 163, 163, 254}}, {{ 83, 164, 164, 247}}, 
+                {{ 81, 165, 165, 244}}, {{ 87, 166, 166, 241}}, {{ 85, 167, 167, 242}}, 
+                {{ 75, 168, 168, 227}}, {{ 73, 169, 169, 224}}, {{ 79, 170, 170, 229}}, 
+                {{ 77, 171, 171, 230}}, {{ 67, 172, 172, 239}}, {{ 65, 173, 173, 236}}, 
+                {{ 71, 174, 174, 233}}, {{ 69, 175, 175, 234}}, {{123, 176, 176, 203}}, 
+                {{121, 177, 177, 200}}, {{127, 178, 178, 205}}, {{125, 179, 179, 206}}, 
+                {{115, 180, 180, 199}}, {{113, 181, 181, 196}}, {{119, 182, 182, 193}}, 
+                {{117, 183, 183, 194}}, {{107, 184, 184, 211}}, {{105, 185, 185, 208}}, 
+                {{111, 186, 186, 213}}, {{109, 187, 187, 214}}, {{ 99, 188, 188, 223}}, 
+                {{ 97, 189, 189, 220}}, {{103, 190, 190, 217}}, {{101, 191, 191, 218}}, 
+                {{155, 192, 192,  91}}, {{153, 193, 193,  88}}, {{159, 194, 194,  93}}, 
+                {{157, 195, 195,  94}}, {{147, 196, 196,  87}}, {{145, 197, 197,  84}}, 
+                {{151, 198, 198,  81}}, {{149, 199, 199,  82}}, {{139, 200, 200,  67}}, 
+                {{137, 201, 201,  64}}, {{143, 202, 202,  69}}, {{141, 203, 203,  70}}, 
+                {{131, 204, 204,  79}}, {{129, 205, 205,  76}}, {{135, 206, 206,  73}}, 
+                {{133, 207, 207,  74}}, {{187, 208, 208, 107}}, {{185, 209, 209, 104}}, 
+                {{191, 210, 210, 109}}, {{189, 211, 211, 110}}, {{179, 212, 212, 103}}, 
+                {{177, 213, 213, 100}}, {{183, 214, 214,  97}}, {{181, 215, 215,  98}}, 
+                {{171, 216, 216, 115}}, {{169, 217, 217, 112}}, {{175, 218, 218, 117}}, 
+                {{173, 219, 219, 118}}, {{163, 220, 220, 127}}, {{161, 221, 221, 124}}, 
+                {{167, 222, 222, 121}}, {{165, 223, 223, 122}}, {{219, 224, 224,  59}}, 
+                {{217, 225, 225,  56}}, {{223, 226, 226,  61}}, {{221, 227, 227,  62}}, 
+                {{211, 228, 228,  55}}, {{209, 229, 229,  52}}, {{215, 230, 230,  49}}, 
+                {{213, 231, 231,  50}}, {{203, 232, 232,  35}}, {{201, 233, 233,  32}}, 
+                {{207, 234, 234,  37}}, {{205, 235, 235,  38}}, {{195, 236, 236,  47}}, 
+                {{193, 237, 237,  44}}, {{199, 238, 238,  41}}, {{197, 239, 239,  42}}, 
+                {{251, 240, 240,  11}}, {{249, 241, 241,   8}}, {{255, 242, 242,  13}}, 
+                {{253, 243, 243,  14}}, {{243, 244, 244,   7}}, {{241, 245, 245,   4}}, 
+                {{247, 246, 246,   1}}, {{245, 247, 247,   2}}, {{235, 248, 248,  19}}, 
+                {{233, 249, 249,  16}}, {{239, 250, 250,  21}}, {{237, 251, 251,  22}}, 
+                {{227, 252, 252,  31}}, {{225, 253, 253,  28}}, {{231, 254, 254,  25}}, 
+                {{229, 255, 255,  26}}, 
+        },
+        {
+                {{  0,   0,   0,   0}}, {{  3,   2,   1,   1}}, {{  6,   4,   2,   2}}, 
+                {{  5,   6,   3,   3}}, {{ 12,   8,   4,   4}}, {{ 15,  10,   5,   5}}, 
+                {{ 10,  12,   6,   6}}, {{  9,  14,   7,   7}}, {{ 24,  16,   8,   8}}, 
+                {{ 27,  18,   9,   9}}, {{ 30,  20,  10,  10}}, {{ 29,  22,  11,  11}}, 
+                {{ 20,  24,  12,  12}}, {{ 23,  26,  13,  13}}, {{ 18,  28,  14,  14}}, 
+                {{ 17,  30,  15,  15}}, {{ 48,  32,  16,  16}}, {{ 51,  34,  17,  17}}, 
+                {{ 54,  36,  18,  18}}, {{ 53,  38,  19,  19}}, {{ 60,  40,  20,  20}}, 
+                {{ 63,  42,  21,  21}}, {{ 58,  44,  22,  22}}, {{ 57,  46,  23,  23}}, 
+                {{ 40,  48,  24,  24}}, {{ 43,  50,  25,  25}}, {{ 46,  52,  26,  26}}, 
+                {{ 45,  54,  27,  27}}, {{ 36,  56,  28,  28}}, {{ 39,  58,  29,  29}}, 
+                {{ 34,  60,  30,  30}}, {{ 33,  62,  31,  31}}, {{ 96,  64,  32,  32}}, 
+                {{ 99,  66,  33,  33}}, {{102,  68,  34,  34}}, {{101,  70,  35,  35}}, 
+                {{108,  72,  36,  36}}, {{111,  74,  37,  37}}, {{106,  76,  38,  38}}, 
+                {{105,  78,  39,  39}}, {{120,  80,  40,  40}}, {{123,  82,  41,  41}}, 
+                {{126,  84,  42,  42}}, {{125,  86,  43,  43}}, {{116,  88,  44,  44}}, 
+                {{119,  90,  45,  45}}, {{114,  92,  46,  46}}, {{113,  94,  47,  47}}, 
+                {{ 80,  96,  48,  48}}, {{ 83,  98,  49,  49}}, {{ 86, 100,  50,  50}}, 
+                {{ 85, 102,  51,  51}}, {{ 92, 104,  52,  52}}, {{ 95, 106,  53,  53}}, 
+                {{ 90, 108,  54,  54}}, {{ 89, 110,  55,  55}}, {{ 72, 112,  56,  56}}, 
+                {{ 75, 114,  57,  57}}, {{ 78, 116,  58,  58}}, {{ 77, 118,  59,  59}}, 
+                {{ 68, 120,  60,  60}}, {{ 71, 122,  61,  61}}, {{ 66, 124,  62,  62}}, 
+                {{ 65, 126,  63,  63}}, {{192, 128,  64,  64}}, {{195, 130,  65,  65}}, 
+                {{198, 132,  66,  66}}, {{197, 134,  67,  67}}, {{204, 136,  68,  68}}, 
+                {{207, 138,  69,  69}}, {{202, 140,  70,  70}}, {{201, 142,  71,  71}}, 
+                {{216, 144,  72,  72}}, {{219, 146,  73,  73}}, {{222, 148,  74,  74}}, 
+                {{221, 150,  75,  75}}, {{212, 152,  76,  76}}, {{215, 154,  77,  77}}, 
+                {{210, 156,  78,  78}}, {{209, 158,  79,  79}}, {{240, 160,  80,  80}}, 
+                {{243, 162,  81,  81}}, {{246, 164,  82,  82}}, {{245, 166,  83,  83}}, 
+                {{252, 168,  84,  84}}, {{255, 170,  85,  85}}, {{250, 172,  86,  86}}, 
+                {{249, 174,  87,  87}}, {{232, 176,  88,  88}}, {{235, 178,  89,  89}}, 
+                {{238, 180,  90,  90}}, {{237, 182,  91,  91}}, {{228, 184,  92,  92}}, 
+                {{231, 186,  93,  93}}, {{226, 188,  94,  94}}, {{225, 190,  95,  95}}, 
+                {{160, 192,  96,  96}}, {{163, 194,  97,  97}}, {{166, 196,  98,  98}}, 
+                {{165, 198,  99,  99}}, {{172, 200, 100, 100}}, {{175, 202, 101, 101}}, 
+                {{170, 204, 102, 102}}, {{169, 206, 103, 103}}, {{184, 208, 104, 104}}, 
+                {{187, 210, 105, 105}}, {{190, 212, 106, 106}}, {{189, 214, 107, 107}}, 
+                {{180, 216, 108, 108}}, {{183, 218, 109, 109}}, {{178, 220, 110, 110}}, 
+                {{177, 222, 111, 111}}, {{144, 224, 112, 112}}, {{147, 226, 113, 113}}, 
+                {{150, 228, 114, 114}}, {{149, 230, 115, 115}}, {{156, 232, 116, 116}}, 
+                {{159, 234, 117, 117}}, {{154, 236, 118, 118}}, {{153, 238, 119, 119}}, 
+                {{136, 240, 120, 120}}, {{139, 242, 121, 121}}, {{142, 244, 122, 122}}, 
+                {{141, 246, 123, 123}}, {{132, 248, 124, 124}}, {{135, 250, 125, 125}}, 
+                {{130, 252, 126, 126}}, {{129, 254, 127, 127}}, {{155,  27, 128, 128}}, 
+                {{152,  25, 129, 129}}, {{157,  31, 130, 130}}, {{158,  29, 131, 131}}, 
+                {{151,  19, 132, 132}}, {{148,  17, 133, 133}}, {{145,  23, 134, 134}}, 
+                {{146,  21, 135, 135}}, {{131,  11, 136, 136}}, {{128,   9, 137, 137}}, 
+                {{133,  15, 138, 138}}, {{134,  13, 139, 139}}, {{143,   3, 140, 140}}, 
+                {{140,   1, 141, 141}}, {{137,   7, 142, 142}}, {{138,   5, 143, 143}}, 
+                {{171,  59, 144, 144}}, {{168,  57, 145, 145}}, {{173,  63, 146, 146}}, 
+                {{174,  61, 147, 147}}, {{167,  51, 148, 148}}, {{164,  49, 149, 149}}, 
+                {{161,  55, 150, 150}}, {{162,  53, 151, 151}}, {{179,  43, 152, 152}}, 
+                {{176,  41, 153, 153}}, {{181,  47, 154, 154}}, {{182,  45, 155, 155}}, 
+                {{191,  35, 156, 156}}, {{188,  33, 157, 157}}, {{185,  39, 158, 158}}, 
+                {{186,  37, 159, 159}}, {{251,  91, 160, 160}}, {{248,  89, 161, 161}}, 
+                {{253,  95, 162, 162}}, {{254,  93, 163, 163}}, {{247,  83, 164, 164}}, 
+                {{244,  81, 165, 165}}, {{241,  87, 166, 166}}, {{242,  85, 167, 167}}, 
+                {{227,  75, 168, 168}}, {{224,  73, 169, 169}}, {{229,  79, 170, 170}}, 
+                {{230,  77, 171, 171}}, {{239,  67, 172, 172}}, {{236,  65, 173, 173}}, 
+                {{233,  71, 174, 174}}, {{234,  69, 175, 175}}, {{203, 123, 176, 176}}, 
+                {{200, 121, 177, 177}}, {{205, 127, 178, 178}}, {{206, 125, 179, 179}}, 
+                {{199, 115, 180, 180}}, {{196, 113, 181, 181}}, {{193, 119, 182, 182}}, 
+                {{194, 117, 183, 183}}, {{211, 107, 184, 184}}, {{208, 105, 185, 185}}, 
+                {{213, 111, 186, 186}}, {{214, 109, 187, 187}}, {{223,  99, 188, 188}}, 
+                {{220,  97, 189, 189}}, {{217, 103, 190, 190}}, {{218, 101, 191, 191}}, 
+                {{ 91, 155, 192, 192}}, {{ 88, 153, 193, 193}}, {{ 93, 159, 194, 194}}, 
+                {{ 94, 157, 195, 195}}, {{ 87, 147, 196, 196}}, {{ 84, 145, 197, 197}}, 
+                {{ 81, 151, 198, 198}}, {{ 82, 149, 199, 199}}, {{ 67, 139, 200, 200}}, 
+                {{ 64, 137, 201, 201}}, {{ 69, 143, 202, 202}}, {{ 70, 141, 203, 203}}, 
+                {{ 79, 131, 204, 204}}, {{ 76, 129, 205, 205}}, {{ 73, 135, 206, 206}}, 
+                {{ 74, 133, 207, 207}}, {{107, 187, 208, 208}}, {{104, 185, 209, 209}}, 
+                {{109, 191, 210, 210}}, {{110, 189, 211, 211}}, {{103, 179, 212, 212}}, 
+                {{100, 177, 213, 213}}, {{ 97, 183, 214, 214}}, {{ 98, 181, 215, 215}}, 
+                {{115, 171, 216, 216}}, {{112, 169, 217, 217}}, {{117, 175, 218, 218}}, 
+                {{118, 173, 219, 219}}, {{127, 163, 220, 220}}, {{124, 161, 221, 221}}, 
+                {{121, 167, 222, 222}}, {{122, 165, 223, 223}}, {{ 59, 219, 224, 224}}, 
+                {{ 56, 217, 225, 225}}, {{ 61, 223, 226, 226}}, {{ 62, 221, 227, 227}}, 
+                {{ 55, 211, 228, 228}}, {{ 52, 209, 229, 229}}, {{ 49, 215, 230, 230}}, 
+                {{ 50, 213, 231, 231}}, {{ 35, 203, 232, 232}}, {{ 32, 201, 233, 233}}, 
+                {{ 37, 207, 234, 234}}, {{ 38, 205, 235, 235}}, {{ 47, 195, 236, 236}}, 
+                {{ 44, 193, 237, 237}}, {{ 41, 199, 238, 238}}, {{ 42, 197, 239, 239}}, 
+                {{ 11, 251, 240, 240}}, {{  8, 249, 241, 241}}, {{ 13, 255, 242, 242}}, 
+                {{ 14, 253, 243, 243}}, {{  7, 243, 244, 244}}, {{  4, 241, 245, 245}}, 
+                {{  1, 247, 246, 246}}, {{  2, 245, 247, 247}}, {{ 19, 235, 248, 248}}, 
+                {{ 16, 233, 249, 249}}, {{ 21, 239, 250, 250}}, {{ 22, 237, 251, 251}}, 
+                {{ 31, 227, 252, 252}}, {{ 28, 225, 253, 253}}, {{ 25, 231, 254, 254}}, 
+                {{ 26, 229, 255, 255}}, 
+        },
+        {
+                {{  0,   0,   0,   0}}, {{  1,   3,   2,   1}}, {{  2,   6,   4,   2}}, 
+                {{  3,   5,   6,   3}}, {{  4,  12,   8,   4}}, {{  5,  15,  10,   5}}, 
+                {{  6,  10,  12,   6}}, {{  7,   9,  14,   7}}, {{  8,  24,  16,   8}}, 
+                {{  9,  27,  18,   9}}, {{ 10,  30,  20,  10}}, {{ 11,  29,  22,  11}}, 
+                {{ 12,  20,  24,  12}}, {{ 13,  23,  26,  13}}, {{ 14,  18,  28,  14}}, 
+                {{ 15,  17,  30,  15}}, {{ 16,  48,  32,  16}}, {{ 17,  51,  34,  17}}, 
+                {{ 18,  54,  36,  18}}, {{ 19,  53,  38,  19}}, {{ 20,  60,  40,  20}}, 
+                {{ 21,  63,  42,  21}}, {{ 22,  58,  44,  22}}, {{ 23,  57,  46,  23}}, 
+                {{ 24,  40,  48,  24}}, {{ 25,  43,  50,  25}}, {{ 26,  46,  52,  26}}, 
+                {{ 27,  45,  54,  27}}, {{ 28,  36,  56,  28}}, {{ 29,  39,  58,  29}}, 
+                {{ 30,  34,  60,  30}}, {{ 31,  33,  62,  31}}, {{ 32,  96,  64,  32}}, 
+                {{ 33,  99,  66,  33}}, {{ 34, 102,  68,  34}}, {{ 35, 101,  70,  35}}, 
+                {{ 36, 108,  72,  36}}, {{ 37, 111,  74,  37}}, {{ 38, 106,  76,  38}}, 
+                {{ 39, 105,  78,  39}}, {{ 40, 120,  80,  40}}, {{ 41, 123,  82,  41}}, 
+                {{ 42, 126,  84,  42}}, {{ 43, 125,  86,  43}}, {{ 44, 116,  88,  44}}, 
+                {{ 45, 119,  90,  45}}, {{ 46, 114,  92,  46}}, {{ 47, 113,  94,  47}}, 
+                {{ 48,  80,  96,  48}}, {{ 49,  83,  98,  49}}, {{ 50,  86, 100,  50}}, 
+                {{ 51,  85, 102,  51}}, {{ 52,  92, 104,  52}}, {{ 53,  95, 106,  53}}, 
+                {{ 54,  90, 108,  54}}, {{ 55,  89, 110,  55}}, {{ 56,  72, 112,  56}}, 
+                {{ 57,  75, 114,  57}}, {{ 58,  78, 116,  58}}, {{ 59,  77, 118,  59}}, 
+                {{ 60,  68, 120,  60}}, {{ 61,  71, 122,  61}}, {{ 62,  66, 124,  62}}, 
+                {{ 63,  65, 126,  63}}, {{ 64, 192, 128,  64}}, {{ 65, 195, 130,  65}}, 
+                {{ 66, 198, 132,  66}}, {{ 67, 197, 134,  67}}, {{ 68, 204, 136,  68}}, 
+                {{ 69, 207, 138,  69}}, {{ 70, 202, 140,  70}}, {{ 71, 201, 142,  71}}, 
+                {{ 72, 216, 144,  72}}, {{ 73, 219, 146,  73}}, {{ 74, 222, 148,  74}}, 
+                {{ 75, 221, 150,  75}}, {{ 76, 212, 152,  76}}, {{ 77, 215, 154,  77}}, 
+                {{ 78, 210, 156,  78}}, {{ 79, 209, 158,  79}}, {{ 80, 240, 160,  80}}, 
+                {{ 81, 243, 162,  81}}, {{ 82, 246, 164,  82}}, {{ 83, 245, 166,  83}}, 
+                {{ 84, 252, 168,  84}}, {{ 85, 255, 170,  85}}, {{ 86, 250, 172,  86}}, 
+                {{ 87, 249, 174,  87}}, {{ 88, 232, 176,  88}}, {{ 89, 235, 178,  89}}, 
+                {{ 90, 238, 180,  90}}, {{ 91, 237, 182,  91}}, {{ 92, 228, 184,  92}}, 
+                {{ 93, 231, 186,  93}}, {{ 94, 226, 188,  94}}, {{ 95, 225, 190,  95}}, 
+                {{ 96, 160, 192,  96}}, {{ 97, 163, 194,  97}}, {{ 98, 166, 196,  98}}, 
+                {{ 99, 165, 198,  99}}, {{100, 172, 200, 100}}, {{101, 175, 202, 101}}, 
+                {{102, 170, 204, 102}}, {{103, 169, 206, 103}}, {{104, 184, 208, 104}}, 
+                {{105, 187, 210, 105}}, {{106, 190, 212, 106}}, {{107, 189, 214, 107}}, 
+                {{108, 180, 216, 108}}, {{109, 183, 218, 109}}, {{110, 178, 220, 110}}, 
+                {{111, 177, 222, 111}}, {{112, 144, 224, 112}}, {{113, 147, 226, 113}}, 
+                {{114, 150, 228, 114}}, {{115, 149, 230, 115}}, {{116, 156, 232, 116}}, 
+                {{117, 159, 234, 117}}, {{118, 154, 236, 118}}, {{119, 153, 238, 119}}, 
+                {{120, 136, 240, 120}}, {{121, 139, 242, 121}}, {{122, 142, 244, 122}}, 
+                {{123, 141, 246, 123}}, {{124, 132, 248, 124}}, {{125, 135, 250, 125}}, 
+                {{126, 130, 252, 126}}, {{127, 129, 254, 127}}, {{128, 155,  27, 128}}, 
+                {{129, 152,  25, 129}}, {{130, 157,  31, 130}}, {{131, 158,  29, 131}}, 
+                {{132, 151,  19, 132}}, {{133, 148,  17, 133}}, {{134, 145,  23, 134}}, 
+                {{135, 146,  21, 135}}, {{136, 131,  11, 136}}, {{137, 128,   9, 137}}, 
+                {{138, 133,  15, 138}}, {{139, 134,  13, 139}}, {{140, 143,   3, 140}}, 
+                {{141, 140,   1, 141}}, {{142, 137,   7, 142}}, {{143, 138,   5, 143}}, 
+                {{144, 171,  59, 144}}, {{145, 168,  57, 145}}, {{146, 173,  63, 146}}, 
+                {{147, 174,  61, 147}}, {{148, 167,  51, 148}}, {{149, 164,  49, 149}}, 
+                {{150, 161,  55, 150}}, {{151, 162,  53, 151}}, {{152, 179,  43, 152}}, 
+                {{153, 176,  41, 153}}, {{154, 181,  47, 154}}, {{155, 182,  45, 155}}, 
+                {{156, 191,  35, 156}}, {{157, 188,  33, 157}}, {{158, 185,  39, 158}}, 
+                {{159, 186,  37, 159}}, {{160, 251,  91, 160}}, {{161, 248,  89, 161}}, 
+                {{162, 253,  95, 162}}, {{163, 254,  93, 163}}, {{164, 247,  83, 164}}, 
+                {{165, 244,  81, 165}}, {{166, 241,  87, 166}}, {{167, 242,  85, 167}}, 
+                {{168, 227,  75, 168}}, {{169, 224,  73, 169}}, {{170, 229,  79, 170}}, 
+                {{171, 230,  77, 171}}, {{172, 239,  67, 172}}, {{173, 236,  65, 173}}, 
+                {{174, 233,  71, 174}}, {{175, 234,  69, 175}}, {{176, 203, 123, 176}}, 
+                {{177, 200, 121, 177}}, {{178, 205, 127, 178}}, {{179, 206, 125, 179}}, 
+                {{180, 199, 115, 180}}, {{181, 196, 113, 181}}, {{182, 193, 119, 182}}, 
+                {{183, 194, 117, 183}}, {{184, 211, 107, 184}}, {{185, 208, 105, 185}}, 
+                {{186, 213, 111, 186}}, {{187, 214, 109, 187}}, {{188, 223,  99, 188}}, 
+                {{189, 220,  97, 189}}, {{190, 217, 103, 190}}, {{191, 218, 101, 191}}, 
+                {{192,  91, 155, 192}}, {{193,  88, 153, 193}}, {{194,  93, 159, 194}}, 
+                {{195,  94, 157, 195}}, {{196,  87, 147, 196}}, {{197,  84, 145, 197}}, 
+                {{198,  81, 151, 198}}, {{199,  82, 149, 199}}, {{200,  67, 139, 200}}, 
+                {{201,  64, 137, 201}}, {{202,  69, 143, 202}}, {{203,  70, 141, 203}}, 
+                {{204,  79, 131, 204}}, {{205,  76, 129, 205}}, {{206,  73, 135, 206}}, 
+                {{207,  74, 133, 207}}, {{208, 107, 187, 208}}, {{209, 104, 185, 209}}, 
+                {{210, 109, 191, 210}}, {{211, 110, 189, 211}}, {{212, 103, 179, 212}}, 
+                {{213, 100, 177, 213}}, {{214,  97, 183, 214}}, {{215,  98, 181, 215}}, 
+                {{216, 115, 171, 216}}, {{217, 112, 169, 217}}, {{218, 117, 175, 218}}, 
+                {{219, 118, 173, 219}}, {{220, 127, 163, 220}}, {{221, 124, 161, 221}}, 
+                {{222, 121, 167, 222}}, {{223, 122, 165, 223}}, {{224,  59, 219, 224}}, 
+                {{225,  56, 217, 225}}, {{226,  61, 223, 226}}, {{227,  62, 221, 227}}, 
+                {{228,  55, 211, 228}}, {{229,  52, 209, 229}}, {{230,  49, 215, 230}}, 
+                {{231,  50, 213, 231}}, {{232,  35, 203, 232}}, {{233,  32, 201, 233}}, 
+                {{234,  37, 207, 234}}, {{235,  38, 205, 235}}, {{236,  47, 195, 236}}, 
+                {{237,  44, 193, 237}}, {{238,  41, 199, 238}}, {{239,  42, 197, 239}}, 
+                {{240,  11, 251, 240}}, {{241,   8, 249, 241}}, {{242,  13, 255, 242}}, 
+                {{243,  14, 253, 243}}, {{244,   7, 243, 244}}, {{245,   4, 241, 245}}, 
+                {{246,   1, 247, 246}}, {{247,   2, 245, 247}}, {{248,  19, 235, 248}}, 
+                {{249,  16, 233, 249}}, {{250,  21, 239, 250}}, {{251,  22, 237, 251}}, 
+                {{252,  31, 227, 252}}, {{253,  28, 225, 253}}, {{254,  25, 231, 254}}, 
+                {{255,  26, 229, 255}}, 
+        },
+        {
+                {{  0,   0,   0,   0}}, {{  1,   1,   3,   2}}, {{  2,   2,   6,   4}}, 
+                {{  3,   3,   5,   6}}, {{  4,   4,  12,   8}}, {{  5,   5,  15,  10}}, 
+                {{  6,   6,  10,  12}}, {{  7,   7,   9,  14}}, {{  8,   8,  24,  16}}, 
+                {{  9,   9,  27,  18}}, {{ 10,  10,  30,  20}}, {{ 11,  11,  29,  22}}, 
+                {{ 12,  12,  20,  24}}, {{ 13,  13,  23,  26}}, {{ 14,  14,  18,  28}}, 
+                {{ 15,  15,  17,  30}}, {{ 16,  16,  48,  32}}, {{ 17,  17,  51,  34}}, 
+                {{ 18,  18,  54,  36}}, {{ 19,  19,  53,  38}}, {{ 20,  20,  60,  40}}, 
+                {{ 21,  21,  63,  42}}, {{ 22,  22,  58,  44}}, {{ 23,  23,  57,  46}}, 
+                {{ 24,  24,  40,  48}}, {{ 25,  25,  43,  50}}, {{ 26,  26,  46,  52}}, 
+                {{ 27,  27,  45,  54}}, {{ 28,  28,  36,  56}}, {{ 29,  29,  39,  58}}, 
+                {{ 30,  30,  34,  60}}, {{ 31,  31,  33,  62}}, {{ 32,  32,  96,  64}}, 
+                {{ 33,  33,  99,  66}}, {{ 34,  34, 102,  68}}, {{ 35,  35, 101,  70}}, 
+                {{ 36,  36, 108,  72}}, {{ 37,  37, 111,  74}}, {{ 38,  38, 106,  76}}, 
+                {{ 39,  39, 105,  78}}, {{ 40,  40, 120,  80}}, {{ 41,  41, 123,  82}}, 
+                {{ 42,  42, 126,  84}}, {{ 43,  43, 125,  86}}, {{ 44,  44, 116,  88}}, 
+                {{ 45,  45, 119,  90}}, {{ 46,  46, 114,  92}}, {{ 47,  47, 113,  94}}, 
+                {{ 48,  48,  80,  96}}, {{ 49,  49,  83,  98}}, {{ 50,  50,  86, 100}}, 
+                {{ 51,  51,  85, 102}}, {{ 52,  52,  92, 104}}, {{ 53,  53,  95, 106}}, 
+                {{ 54,  54,  90, 108}}, {{ 55,  55,  89, 110}}, {{ 56,  56,  72, 112}}, 
+                {{ 57,  57,  75, 114}}, {{ 58,  58,  78, 116}}, {{ 59,  59,  77, 118}}, 
+                {{ 60,  60,  68, 120}}, {{ 61,  61,  71, 122}}, {{ 62,  62,  66, 124}}, 
+                {{ 63,  63,  65, 126}}, {{ 64,  64, 192, 128}}, {{ 65,  65, 195, 130}}, 
+                {{ 66,  66, 198, 132}}, {{ 67,  67, 197, 134}}, {{ 68,  68, 204, 136}}, 
+                {{ 69,  69, 207, 138}}, {{ 70,  70, 202, 140}}, {{ 71,  71, 201, 142}}, 
+                {{ 72,  72, 216, 144}}, {{ 73,  73, 219, 146}}, {{ 74,  74, 222, 148}}, 
+                {{ 75,  75, 221, 150}}, {{ 76,  76, 212, 152}}, {{ 77,  77, 215, 154}}, 
+                {{ 78,  78, 210, 156}}, {{ 79,  79, 209, 158}}, {{ 80,  80, 240, 160}}, 
+                {{ 81,  81, 243, 162}}, {{ 82,  82, 246, 164}}, {{ 83,  83, 245, 166}}, 
+                {{ 84,  84, 252, 168}}, {{ 85,  85, 255, 170}}, {{ 86,  86, 250, 172}}, 
+                {{ 87,  87, 249, 174}}, {{ 88,  88, 232, 176}}, {{ 89,  89, 235, 178}}, 
+                {{ 90,  90, 238, 180}}, {{ 91,  91, 237, 182}}, {{ 92,  92, 228, 184}}, 
+                {{ 93,  93, 231, 186}}, {{ 94,  94, 226, 188}}, {{ 95,  95, 225, 190}}, 
+                {{ 96,  96, 160, 192}}, {{ 97,  97, 163, 194}}, {{ 98,  98, 166, 196}}, 
+                {{ 99,  99, 165, 198}}, {{100, 100, 172, 200}}, {{101, 101, 175, 202}}, 
+                {{102, 102, 170, 204}}, {{103, 103, 169, 206}}, {{104, 104, 184, 208}}, 
+                {{105, 105, 187, 210}}, {{106, 106, 190, 212}}, {{107, 107, 189, 214}}, 
+                {{108, 108, 180, 216}}, {{109, 109, 183, 218}}, {{110, 110, 178, 220}}, 
+                {{111, 111, 177, 222}}, {{112, 112, 144, 224}}, {{113, 113, 147, 226}}, 
+                {{114, 114, 150, 228}}, {{115, 115, 149, 230}}, {{116, 116, 156, 232}}, 
+                {{117, 117, 159, 234}}, {{118, 118, 154, 236}}, {{119, 119, 153, 238}}, 
+                {{120, 120, 136, 240}}, {{121, 121, 139, 242}}, {{122, 122, 142, 244}}, 
+                {{123, 123, 141, 246}}, {{124, 124, 132, 248}}, {{125, 125, 135, 250}}, 
+                {{126, 126, 130, 252}}, {{127, 127, 129, 254}}, {{128, 128, 155,  27}}, 
+                {{129, 129, 152,  25}}, {{130, 130, 157,  31}}, {{131, 131, 158,  29}}, 
+                {{132, 132, 151,  19}}, {{133, 133, 148,  17}}, {{134, 134, 145,  23}}, 
+                {{135, 135, 146,  21}}, {{136, 136, 131,  11}}, {{137, 137, 128,   9}}, 
+                {{138, 138, 133,  15}}, {{139, 139, 134,  13}}, {{140, 140, 143,   3}}, 
+                {{141, 141, 140,   1}}, {{142, 142, 137,   7}}, {{143, 143, 138,   5}}, 
+                {{144, 144, 171,  59}}, {{145, 145, 168,  57}}, {{146, 146, 173,  63}}, 
+                {{147, 147, 174,  61}}, {{148, 148, 167,  51}}, {{149, 149, 164,  49}}, 
+                {{150, 150, 161,  55}}, {{151, 151, 162,  53}}, {{152, 152, 179,  43}}, 
+                {{153, 153, 176,  41}}, {{154, 154, 181,  47}}, {{155, 155, 182,  45}}, 
+                {{156, 156, 191,  35}}, {{157, 157, 188,  33}}, {{158, 158, 185,  39}}, 
+                {{159, 159, 186,  37}}, {{160, 160, 251,  91}}, {{161, 161, 248,  89}}, 
+                {{162, 162, 253,  95}}, {{163, 163, 254,  93}}, {{164, 164, 247,  83}}, 
+                {{165, 165, 244,  81}}, {{166, 166, 241,  87}}, {{167, 167, 242,  85}}, 
+                {{168, 168, 227,  75}}, {{169, 169, 224,  73}}, {{170, 170, 229,  79}}, 
+                {{171, 171, 230,  77}}, {{172, 172, 239,  67}}, {{173, 173, 236,  65}}, 
+                {{174, 174, 233,  71}}, {{175, 175, 234,  69}}, {{176, 176, 203, 123}}, 
+                {{177, 177, 200, 121}}, {{178, 178, 205, 127}}, {{179, 179, 206, 125}}, 
+                {{180, 180, 199, 115}}, {{181, 181, 196, 113}}, {{182, 182, 193, 119}}, 
+                {{183, 183, 194, 117}}, {{184, 184, 211, 107}}, {{185, 185, 208, 105}}, 
+                {{186, 186, 213, 111}}, {{187, 187, 214, 109}}, {{188, 188, 223,  99}}, 
+                {{189, 189, 220,  97}}, {{190, 190, 217, 103}}, {{191, 191, 218, 101}}, 
+                {{192, 192,  91, 155}}, {{193, 193,  88, 153}}, {{194, 194,  93, 159}}, 
+                {{195, 195,  94, 157}}, {{196, 196,  87, 147}}, {{197, 197,  84, 145}}, 
+                {{198, 198,  81, 151}}, {{199, 199,  82, 149}}, {{200, 200,  67, 139}}, 
+                {{201, 201,  64, 137}}, {{202, 202,  69, 143}}, {{203, 203,  70, 141}}, 
+                {{204, 204,  79, 131}}, {{205, 205,  76, 129}}, {{206, 206,  73, 135}}, 
+                {{207, 207,  74, 133}}, {{208, 208, 107, 187}}, {{209, 209, 104, 185}}, 
+                {{210, 210, 109, 191}}, {{211, 211, 110, 189}}, {{212, 212, 103, 179}}, 
+                {{213, 213, 100, 177}}, {{214, 214,  97, 183}}, {{215, 215,  98, 181}}, 
+                {{216, 216, 115, 171}}, {{217, 217, 112, 169}}, {{218, 218, 117, 175}}, 
+                {{219, 219, 118, 173}}, {{220, 220, 127, 163}}, {{221, 221, 124, 161}}, 
+                {{222, 222, 121, 167}}, {{223, 223, 122, 165}}, {{224, 224,  59, 219}}, 
+                {{225, 225,  56, 217}}, {{226, 226,  61, 223}}, {{227, 227,  62, 221}}, 
+                {{228, 228,  55, 211}}, {{229, 229,  52, 209}}, {{230, 230,  49, 215}}, 
+                {{231, 231,  50, 213}}, {{232, 232,  35, 203}}, {{233, 233,  32, 201}}, 
+                {{234, 234,  37, 207}}, {{235, 235,  38, 205}}, {{236, 236,  47, 195}}, 
+                {{237, 237,  44, 193}}, {{238, 238,  41, 199}}, {{239, 239,  42, 197}}, 
+                {{240, 240,  11, 251}}, {{241, 241,   8, 249}}, {{242, 242,  13, 255}}, 
+                {{243, 243,  14, 253}}, {{244, 244,   7, 243}}, {{245, 245,   4, 241}}, 
+                {{246, 246,   1, 247}}, {{247, 247,   2, 245}}, {{248, 248,  19, 235}}, 
+                {{249, 249,  16, 233}}, {{250, 250,  21, 239}}, {{251, 251,  22, 237}}, 
+                {{252, 252,  31, 227}}, {{253, 253,  28, 225}}, {{254, 254,  25, 231}}, 
+                {{255, 255,  26, 229}}, 
+        },
+};
+
+word8x4 M1[4][256] = {
+        {
+                {{  0,   0,   0,   0}}, {{ 14,   9,  13,  11}}, {{ 28,  18,  26,  22}}, 
+                {{ 18,  27,  23,  29}}, {{ 56,  36,  52,  44}}, {{ 54,  45,  57,  39}}, 
+                {{ 36,  54,  46,  58}}, {{ 42,  63,  35,  49}}, {{112,  72, 104,  88}}, 
+                {{126,  65, 101,  83}}, {{108,  90, 114,  78}}, {{ 98,  83, 127,  69}}, 
+                {{ 72, 108,  92, 116}}, {{ 70, 101,  81, 127}}, {{ 84, 126,  70,  98}}, 
+                {{ 90, 119,  75, 105}}, {{224, 144, 208, 176}}, {{238, 153, 221, 187}}, 
+                {{252, 130, 202, 166}}, {{242, 139, 199, 173}}, {{216, 180, 228, 156}}, 
+                {{214, 189, 233, 151}}, {{196, 166, 254, 138}}, {{202, 175, 243, 129}}, 
+                {{144, 216, 184, 232}}, {{158, 209, 181, 227}}, {{140, 202, 162, 254}}, 
+                {{130, 195, 175, 245}}, {{168, 252, 140, 196}}, {{166, 245, 129, 207}}, 
+                {{180, 238, 150, 210}}, {{186, 231, 155, 217}}, {{219,  59, 187, 123}}, 
+                {{213,  50, 182, 112}}, {{199,  41, 161, 109}}, {{201,  32, 172, 102}}, 
+                {{227,  31, 143,  87}}, {{237,  22, 130,  92}}, {{255,  13, 149,  65}}, 
+                {{241,   4, 152,  74}}, {{171, 115, 211,  35}}, {{165, 122, 222,  40}}, 
+                {{183,  97, 201,  53}}, {{185, 104, 196,  62}}, {{147,  87, 231,  15}}, 
+                {{157,  94, 234,   4}}, {{143,  69, 253,  25}}, {{129,  76, 240,  18}}, 
+                {{ 59, 171, 107, 203}}, {{ 53, 162, 102, 192}}, {{ 39, 185, 113, 221}}, 
+                {{ 41, 176, 124, 214}}, {{  3, 143,  95, 231}}, {{ 13, 134,  82, 236}}, 
+                {{ 31, 157,  69, 241}}, {{ 17, 148,  72, 250}}, {{ 75, 227,   3, 147}}, 
+                {{ 69, 234,  14, 152}}, {{ 87, 241,  25, 133}}, {{ 89, 248,  20, 142}}, 
+                {{115, 199,  55, 191}}, {{125, 206,  58, 180}}, {{111, 213,  45, 169}}, 
+                {{ 97, 220,  32, 162}}, {{173, 118, 109, 246}}, {{163, 127,  96, 253}}, 
+                {{177, 100, 119, 224}}, {{191, 109, 122, 235}}, {{149,  82,  89, 218}}, 
+                {{155,  91,  84, 209}}, {{137,  64,  67, 204}}, {{135,  73,  78, 199}}, 
+                {{221,  62,   5, 174}}, {{211,  55,   8, 165}}, {{193,  44,  31, 184}}, 
+                {{207,  37,  18, 179}}, {{229,  26,  49, 130}}, {{235,  19,  60, 137}}, 
+                {{249,   8,  43, 148}}, {{247,   1,  38, 159}}, {{ 77, 230, 189,  70}}, 
+                {{ 67, 239, 176,  77}}, {{ 81, 244, 167,  80}}, {{ 95, 253, 170,  91}}, 
+                {{117, 194, 137, 106}}, {{123, 203, 132,  97}}, {{105, 208, 147, 124}}, 
+                {{103, 217, 158, 119}}, {{ 61, 174, 213,  30}}, {{ 51, 167, 216,  21}}, 
+                {{ 33, 188, 207,   8}}, {{ 47, 181, 194,   3}}, {{  5, 138, 225,  50}}, 
+                {{ 11, 131, 236,  57}}, {{ 25, 152, 251,  36}}, {{ 23, 145, 246,  47}}, 
+                {{118,  77, 214, 141}}, {{120,  68, 219, 134}}, {{106,  95, 204, 155}}, 
+                {{100,  86, 193, 144}}, {{ 78, 105, 226, 161}}, {{ 64,  96, 239, 170}}, 
+                {{ 82, 123, 248, 183}}, {{ 92, 114, 245, 188}}, {{  6,   5, 190, 213}}, 
+                {{  8,  12, 179, 222}}, {{ 26,  23, 164, 195}}, {{ 20,  30, 169, 200}}, 
+                {{ 62,  33, 138, 249}}, {{ 48,  40, 135, 242}}, {{ 34,  51, 144, 239}}, 
+                {{ 44,  58, 157, 228}}, {{150, 221,   6,  61}}, {{152, 212,  11,  54}}, 
+                {{138, 207,  28,  43}}, {{132, 198,  17,  32}}, {{174, 249,  50,  17}}, 
+                {{160, 240,  63,  26}}, {{178, 235,  40,   7}}, {{188, 226,  37,  12}}, 
+                {{230, 149, 110, 101}}, {{232, 156,  99, 110}}, {{250, 135, 116, 115}}, 
+                {{244, 142, 121, 120}}, {{222, 177,  90,  73}}, {{208, 184,  87,  66}}, 
+                {{194, 163,  64,  95}}, {{204, 170,  77,  84}}, {{ 65, 236, 218, 247}}, 
+                {{ 79, 229, 215, 252}}, {{ 93, 254, 192, 225}}, {{ 83, 247, 205, 234}}, 
+                {{121, 200, 238, 219}}, {{119, 193, 227, 208}}, {{101, 218, 244, 205}}, 
+                {{107, 211, 249, 198}}, {{ 49, 164, 178, 175}}, {{ 63, 173, 191, 164}}, 
+                {{ 45, 182, 168, 185}}, {{ 35, 191, 165, 178}}, {{  9, 128, 134, 131}}, 
+                {{  7, 137, 139, 136}}, {{ 21, 146, 156, 149}}, {{ 27, 155, 145, 158}}, 
+                {{161, 124,  10,  71}}, {{175, 117,   7,  76}}, {{189, 110,  16,  81}}, 
+                {{179, 103,  29,  90}}, {{153,  88,  62, 107}}, {{151,  81,  51,  96}}, 
+                {{133,  74,  36, 125}}, {{139,  67,  41, 118}}, {{209,  52,  98,  31}}, 
+                {{223,  61, 111,  20}}, {{205,  38, 120,   9}}, {{195,  47, 117,   2}}, 
+                {{233,  16,  86,  51}}, {{231,  25,  91,  56}}, {{245,   2,  76,  37}}, 
+                {{251,  11,  65,  46}}, {{154, 215,  97, 140}}, {{148, 222, 108, 135}}, 
+                {{134, 197, 123, 154}}, {{136, 204, 118, 145}}, {{162, 243,  85, 160}}, 
+                {{172, 250,  88, 171}}, {{190, 225,  79, 182}}, {{176, 232,  66, 189}}, 
+                {{234, 159,   9, 212}}, {{228, 150,   4, 223}}, {{246, 141,  19, 194}}, 
+                {{248, 132,  30, 201}}, {{210, 187,  61, 248}}, {{220, 178,  48, 243}}, 
+                {{206, 169,  39, 238}}, {{192, 160,  42, 229}}, {{122,  71, 177,  60}}, 
+                {{116,  78, 188,  55}}, {{102,  85, 171,  42}}, {{104,  92, 166,  33}}, 
+                {{ 66,  99, 133,  16}}, {{ 76, 106, 136,  27}}, {{ 94, 113, 159,   6}}, 
+                {{ 80, 120, 146,  13}}, {{ 10,  15, 217, 100}}, {{  4,   6, 212, 111}}, 
+                {{ 22,  29, 195, 114}}, {{ 24,  20, 206, 121}}, {{ 50,  43, 237,  72}}, 
+                {{ 60,  34, 224,  67}}, {{ 46,  57, 247,  94}}, {{ 32,  48, 250,  85}}, 
+                {{236, 154, 183,   1}}, {{226, 147, 186,  10}}, {{240, 136, 173,  23}}, 
+                {{254, 129, 160,  28}}, {{212, 190, 131,  45}}, {{218, 183, 142,  38}}, 
+                {{200, 172, 153,  59}}, {{198, 165, 148,  48}}, {{156, 210, 223,  89}}, 
+                {{146, 219, 210,  82}}, {{128, 192, 197,  79}}, {{142, 201, 200,  68}}, 
+                {{164, 246, 235, 117}}, {{170, 255, 230, 126}}, {{184, 228, 241,  99}}, 
+                {{182, 237, 252, 104}}, {{ 12,  10, 103, 177}}, {{  2,   3, 106, 186}}, 
+                {{ 16,  24, 125, 167}}, {{ 30,  17, 112, 172}}, {{ 52,  46,  83, 157}}, 
+                {{ 58,  39,  94, 150}}, {{ 40,  60,  73, 139}}, {{ 38,  53,  68, 128}}, 
+                {{124,  66,  15, 233}}, {{114,  75,   2, 226}}, {{ 96,  80,  21, 255}}, 
+                {{110,  89,  24, 244}}, {{ 68, 102,  59, 197}}, {{ 74, 111,  54, 206}}, 
+                {{ 88, 116,  33, 211}}, {{ 86, 125,  44, 216}}, {{ 55, 161,  12, 122}}, 
+                {{ 57, 168,   1, 113}}, {{ 43, 179,  22, 108}}, {{ 37, 186,  27, 103}}, 
+                {{ 15, 133,  56,  86}}, {{  1, 140,  53,  93}}, {{ 19, 151,  34,  64}}, 
+                {{ 29, 158,  47,  75}}, {{ 71, 233, 100,  34}}, {{ 73, 224, 105,  41}}, 
+                {{ 91, 251, 126,  52}}, {{ 85, 242, 115,  63}}, {{127, 205,  80,  14}}, 
+                {{113, 196,  93,   5}}, {{ 99, 223,  74,  24}}, {{109, 214,  71,  19}}, 
+                {{215,  49, 220, 202}}, {{217,  56, 209, 193}}, {{203,  35, 198, 220}}, 
+                {{197,  42, 203, 215}}, {{239,  21, 232, 230}}, {{225,  28, 229, 237}}, 
+                {{243,   7, 242, 240}}, {{253,  14, 255, 251}}, {{167, 121, 180, 146}}, 
+                {{169, 112, 185, 153}}, {{187, 107, 174, 132}}, {{181,  98, 163, 143}}, 
+                {{159,  93, 128, 190}}, {{145,  84, 141, 181}}, {{131,  79, 154, 168}}, 
+                {{141,  70, 151, 163}}, 
+        },
+        {
+                {{  0,   0,   0,   0}}, {{ 11,  14,   9,  13}}, {{ 22,  28,  18,  26}}, 
+                {{ 29,  18,  27,  23}}, {{ 44,  56,  36,  52}}, {{ 39,  54,  45,  57}}, 
+                {{ 58,  36,  54,  46}}, {{ 49,  42,  63,  35}}, {{ 88, 112,  72, 104}}, 
+                {{ 83, 126,  65, 101}}, {{ 78, 108,  90, 114}}, {{ 69,  98,  83, 127}}, 
+                {{116,  72, 108,  92}}, {{127,  70, 101,  81}}, {{ 98,  84, 126,  70}}, 
+                {{105,  90, 119,  75}}, {{176, 224, 144, 208}}, {{187, 238, 153, 221}}, 
+                {{166, 252, 130, 202}}, {{173, 242, 139, 199}}, {{156, 216, 180, 228}}, 
+                {{151, 214, 189, 233}}, {{138, 196, 166, 254}}, {{129, 202, 175, 243}}, 
+                {{232, 144, 216, 184}}, {{227, 158, 209, 181}}, {{254, 140, 202, 162}}, 
+                {{245, 130, 195, 175}}, {{196, 168, 252, 140}}, {{207, 166, 245, 129}}, 
+                {{210, 180, 238, 150}}, {{217, 186, 231, 155}}, {{123, 219,  59, 187}}, 
+                {{112, 213,  50, 182}}, {{109, 199,  41, 161}}, {{102, 201,  32, 172}}, 
+                {{ 87, 227,  31, 143}}, {{ 92, 237,  22, 130}}, {{ 65, 255,  13, 149}}, 
+                {{ 74, 241,   4, 152}}, {{ 35, 171, 115, 211}}, {{ 40, 165, 122, 222}}, 
+                {{ 53, 183,  97, 201}}, {{ 62, 185, 104, 196}}, {{ 15, 147,  87, 231}}, 
+                {{  4, 157,  94, 234}}, {{ 25, 143,  69, 253}}, {{ 18, 129,  76, 240}}, 
+                {{203,  59, 171, 107}}, {{192,  53, 162, 102}}, {{221,  39, 185, 113}}, 
+                {{214,  41, 176, 124}}, {{231,   3, 143,  95}}, {{236,  13, 134,  82}}, 
+                {{241,  31, 157,  69}}, {{250,  17, 148,  72}}, {{147,  75, 227,   3}}, 
+                {{152,  69, 234,  14}}, {{133,  87, 241,  25}}, {{142,  89, 248,  20}}, 
+                {{191, 115, 199,  55}}, {{180, 125, 206,  58}}, {{169, 111, 213,  45}}, 
+                {{162,  97, 220,  32}}, {{246, 173, 118, 109}}, {{253, 163, 127,  96}}, 
+                {{224, 177, 100, 119}}, {{235, 191, 109, 122}}, {{218, 149,  82,  89}}, 
+                {{209, 155,  91,  84}}, {{204, 137,  64,  67}}, {{199, 135,  73,  78}}, 
+                {{174, 221,  62,   5}}, {{165, 211,  55,   8}}, {{184, 193,  44,  31}}, 
+                {{179, 207,  37,  18}}, {{130, 229,  26,  49}}, {{137, 235,  19,  60}}, 
+                {{148, 249,   8,  43}}, {{159, 247,   1,  38}}, {{ 70,  77, 230, 189}}, 
+                {{ 77,  67, 239, 176}}, {{ 80,  81, 244, 167}}, {{ 91,  95, 253, 170}}, 
+                {{106, 117, 194, 137}}, {{ 97, 123, 203, 132}}, {{124, 105, 208, 147}}, 
+                {{119, 103, 217, 158}}, {{ 30,  61, 174, 213}}, {{ 21,  51, 167, 216}}, 
+                {{  8,  33, 188, 207}}, {{  3,  47, 181, 194}}, {{ 50,   5, 138, 225}}, 
+                {{ 57,  11, 131, 236}}, {{ 36,  25, 152, 251}}, {{ 47,  23, 145, 246}}, 
+                {{141, 118,  77, 214}}, {{134, 120,  68, 219}}, {{155, 106,  95, 204}}, 
+                {{144, 100,  86, 193}}, {{161,  78, 105, 226}}, {{170,  64,  96, 239}}, 
+                {{183,  82, 123, 248}}, {{188,  92, 114, 245}}, {{213,   6,   5, 190}}, 
+                {{222,   8,  12, 179}}, {{195,  26,  23, 164}}, {{200,  20,  30, 169}}, 
+                {{249,  62,  33, 138}}, {{242,  48,  40, 135}}, {{239,  34,  51, 144}}, 
+                {{228,  44,  58, 157}}, {{ 61, 150, 221,   6}}, {{ 54, 152, 212,  11}}, 
+                {{ 43, 138, 207,  28}}, {{ 32, 132, 198,  17}}, {{ 17, 174, 249,  50}}, 
+                {{ 26, 160, 240,  63}}, {{  7, 178, 235,  40}}, {{ 12, 188, 226,  37}}, 
+                {{101, 230, 149, 110}}, {{110, 232, 156,  99}}, {{115, 250, 135, 116}}, 
+                {{120, 244, 142, 121}}, {{ 73, 222, 177,  90}}, {{ 66, 208, 184,  87}}, 
+                {{ 95, 194, 163,  64}}, {{ 84, 204, 170,  77}}, {{247,  65, 236, 218}}, 
+                {{252,  79, 229, 215}}, {{225,  93, 254, 192}}, {{234,  83, 247, 205}}, 
+                {{219, 121, 200, 238}}, {{208, 119, 193, 227}}, {{205, 101, 218, 244}}, 
+                {{198, 107, 211, 249}}, {{175,  49, 164, 178}}, {{164,  63, 173, 191}}, 
+                {{185,  45, 182, 168}}, {{178,  35, 191, 165}}, {{131,   9, 128, 134}}, 
+                {{136,   7, 137, 139}}, {{149,  21, 146, 156}}, {{158,  27, 155, 145}}, 
+                {{ 71, 161, 124,  10}}, {{ 76, 175, 117,   7}}, {{ 81, 189, 110,  16}}, 
+                {{ 90, 179, 103,  29}}, {{107, 153,  88,  62}}, {{ 96, 151,  81,  51}}, 
+                {{125, 133,  74,  36}}, {{118, 139,  67,  41}}, {{ 31, 209,  52,  98}}, 
+                {{ 20, 223,  61, 111}}, {{  9, 205,  38, 120}}, {{  2, 195,  47, 117}}, 
+                {{ 51, 233,  16,  86}}, {{ 56, 231,  25,  91}}, {{ 37, 245,   2,  76}}, 
+                {{ 46, 251,  11,  65}}, {{140, 154, 215,  97}}, {{135, 148, 222, 108}}, 
+                {{154, 134, 197, 123}}, {{145, 136, 204, 118}}, {{160, 162, 243,  85}}, 
+                {{171, 172, 250,  88}}, {{182, 190, 225,  79}}, {{189, 176, 232,  66}}, 
+                {{212, 234, 159,   9}}, {{223, 228, 150,   4}}, {{194, 246, 141,  19}}, 
+                {{201, 248, 132,  30}}, {{248, 210, 187,  61}}, {{243, 220, 178,  48}}, 
+                {{238, 206, 169,  39}}, {{229, 192, 160,  42}}, {{ 60, 122,  71, 177}}, 
+                {{ 55, 116,  78, 188}}, {{ 42, 102,  85, 171}}, {{ 33, 104,  92, 166}}, 
+                {{ 16,  66,  99, 133}}, {{ 27,  76, 106, 136}}, {{  6,  94, 113, 159}}, 
+                {{ 13,  80, 120, 146}}, {{100,  10,  15, 217}}, {{111,   4,   6, 212}}, 
+                {{114,  22,  29, 195}}, {{121,  24,  20, 206}}, {{ 72,  50,  43, 237}}, 
+                {{ 67,  60,  34, 224}}, {{ 94,  46,  57, 247}}, {{ 85,  32,  48, 250}}, 
+                {{  1, 236, 154, 183}}, {{ 10, 226, 147, 186}}, {{ 23, 240, 136, 173}}, 
+                {{ 28, 254, 129, 160}}, {{ 45, 212, 190, 131}}, {{ 38, 218, 183, 142}}, 
+                {{ 59, 200, 172, 153}}, {{ 48, 198, 165, 148}}, {{ 89, 156, 210, 223}}, 
+                {{ 82, 146, 219, 210}}, {{ 79, 128, 192, 197}}, {{ 68, 142, 201, 200}}, 
+                {{117, 164, 246, 235}}, {{126, 170, 255, 230}}, {{ 99, 184, 228, 241}}, 
+                {{104, 182, 237, 252}}, {{177,  12,  10, 103}}, {{186,   2,   3, 106}}, 
+                {{167,  16,  24, 125}}, {{172,  30,  17, 112}}, {{157,  52,  46,  83}}, 
+                {{150,  58,  39,  94}}, {{139,  40,  60,  73}}, {{128,  38,  53,  68}}, 
+                {{233, 124,  66,  15}}, {{226, 114,  75,   2}}, {{255,  96,  80,  21}}, 
+                {{244, 110,  89,  24}}, {{197,  68, 102,  59}}, {{206,  74, 111,  54}}, 
+                {{211,  88, 116,  33}}, {{216,  86, 125,  44}}, {{122,  55, 161,  12}}, 
+                {{113,  57, 168,   1}}, {{108,  43, 179,  22}}, {{103,  37, 186,  27}}, 
+                {{ 86,  15, 133,  56}}, {{ 93,   1, 140,  53}}, {{ 64,  19, 151,  34}}, 
+                {{ 75,  29, 158,  47}}, {{ 34,  71, 233, 100}}, {{ 41,  73, 224, 105}}, 
+                {{ 52,  91, 251, 126}}, {{ 63,  85, 242, 115}}, {{ 14, 127, 205,  80}}, 
+                {{  5, 113, 196,  93}}, {{ 24,  99, 223,  74}}, {{ 19, 109, 214,  71}}, 
+                {{202, 215,  49, 220}}, {{193, 217,  56, 209}}, {{220, 203,  35, 198}}, 
+                {{215, 197,  42, 203}}, {{230, 239,  21, 232}}, {{237, 225,  28, 229}}, 
+                {{240, 243,   7, 242}}, {{251, 253,  14, 255}}, {{146, 167, 121, 180}}, 
+                {{153, 169, 112, 185}}, {{132, 187, 107, 174}}, {{143, 181,  98, 163}}, 
+                {{190, 159,  93, 128}}, {{181, 145,  84, 141}}, {{168, 131,  79, 154}}, 
+                {{163, 141,  70, 151}}, 
+        },
+        {
+                {{  0,   0,   0,   0}}, {{ 13,  11,  14,   9}}, {{ 26,  22,  28,  18}}, 
+                {{ 23,  29,  18,  27}}, {{ 52,  44,  56,  36}}, {{ 57,  39,  54,  45}}, 
+                {{ 46,  58,  36,  54}}, {{ 35,  49,  42,  63}}, {{104,  88, 112,  72}}, 
+                {{101,  83, 126,  65}}, {{114,  78, 108,  90}}, {{127,  69,  98,  83}}, 
+                {{ 92, 116,  72, 108}}, {{ 81, 127,  70, 101}}, {{ 70,  98,  84, 126}}, 
+                {{ 75, 105,  90, 119}}, {{208, 176, 224, 144}}, {{221, 187, 238, 153}}, 
+                {{202, 166, 252, 130}}, {{199, 173, 242, 139}}, {{228, 156, 216, 180}}, 
+                {{233, 151, 214, 189}}, {{254, 138, 196, 166}}, {{243, 129, 202, 175}}, 
+                {{184, 232, 144, 216}}, {{181, 227, 158, 209}}, {{162, 254, 140, 202}}, 
+                {{175, 245, 130, 195}}, {{140, 196, 168, 252}}, {{129, 207, 166, 245}}, 
+                {{150, 210, 180, 238}}, {{155, 217, 186, 231}}, {{187, 123, 219,  59}}, 
+                {{182, 112, 213,  50}}, {{161, 109, 199,  41}}, {{172, 102, 201,  32}}, 
+                {{143,  87, 227,  31}}, {{130,  92, 237,  22}}, {{149,  65, 255,  13}}, 
+                {{152,  74, 241,   4}}, {{211,  35, 171, 115}}, {{222,  40, 165, 122}}, 
+                {{201,  53, 183,  97}}, {{196,  62, 185, 104}}, {{231,  15, 147,  87}}, 
+                {{234,   4, 157,  94}}, {{253,  25, 143,  69}}, {{240,  18, 129,  76}}, 
+                {{107, 203,  59, 171}}, {{102, 192,  53, 162}}, {{113, 221,  39, 185}}, 
+                {{124, 214,  41, 176}}, {{ 95, 231,   3, 143}}, {{ 82, 236,  13, 134}}, 
+                {{ 69, 241,  31, 157}}, {{ 72, 250,  17, 148}}, {{  3, 147,  75, 227}}, 
+                {{ 14, 152,  69, 234}}, {{ 25, 133,  87, 241}}, {{ 20, 142,  89, 248}}, 
+                {{ 55, 191, 115, 199}}, {{ 58, 180, 125, 206}}, {{ 45, 169, 111, 213}}, 
+                {{ 32, 162,  97, 220}}, {{109, 246, 173, 118}}, {{ 96, 253, 163, 127}}, 
+                {{119, 224, 177, 100}}, {{122, 235, 191, 109}}, {{ 89, 218, 149,  82}}, 
+                {{ 84, 209, 155,  91}}, {{ 67, 204, 137,  64}}, {{ 78, 199, 135,  73}}, 
+                {{  5, 174, 221,  62}}, {{  8, 165, 211,  55}}, {{ 31, 184, 193,  44}}, 
+                {{ 18, 179, 207,  37}}, {{ 49, 130, 229,  26}}, {{ 60, 137, 235,  19}}, 
+                {{ 43, 148, 249,   8}}, {{ 38, 159, 247,   1}}, {{189,  70,  77, 230}}, 
+                {{176,  77,  67, 239}}, {{167,  80,  81, 244}}, {{170,  91,  95, 253}}, 
+                {{137, 106, 117, 194}}, {{132,  97, 123, 203}}, {{147, 124, 105, 208}}, 
+                {{158, 119, 103, 217}}, {{213,  30,  61, 174}}, {{216,  21,  51, 167}}, 
+                {{207,   8,  33, 188}}, {{194,   3,  47, 181}}, {{225,  50,   5, 138}}, 
+                {{236,  57,  11, 131}}, {{251,  36,  25, 152}}, {{246,  47,  23, 145}}, 
+                {{214, 141, 118,  77}}, {{219, 134, 120,  68}}, {{204, 155, 106,  95}}, 
+                {{193, 144, 100,  86}}, {{226, 161,  78, 105}}, {{239, 170,  64,  96}}, 
+                {{248, 183,  82, 123}}, {{245, 188,  92, 114}}, {{190, 213,   6,   5}}, 
+                {{179, 222,   8,  12}}, {{164, 195,  26,  23}}, {{169, 200,  20,  30}}, 
+                {{138, 249,  62,  33}}, {{135, 242,  48,  40}}, {{144, 239,  34,  51}}, 
+                {{157, 228,  44,  58}}, {{  6,  61, 150, 221}}, {{ 11,  54, 152, 212}}, 
+                {{ 28,  43, 138, 207}}, {{ 17,  32, 132, 198}}, {{ 50,  17, 174, 249}}, 
+                {{ 63,  26, 160, 240}}, {{ 40,   7, 178, 235}}, {{ 37,  12, 188, 226}}, 
+                {{110, 101, 230, 149}}, {{ 99, 110, 232, 156}}, {{116, 115, 250, 135}}, 
+                {{121, 120, 244, 142}}, {{ 90,  73, 222, 177}}, {{ 87,  66, 208, 184}}, 
+                {{ 64,  95, 194, 163}}, {{ 77,  84, 204, 170}}, {{218, 247,  65, 236}}, 
+                {{215, 252,  79, 229}}, {{192, 225,  93, 254}}, {{205, 234,  83, 247}}, 
+                {{238, 219, 121, 200}}, {{227, 208, 119, 193}}, {{244, 205, 101, 218}}, 
+                {{249, 198, 107, 211}}, {{178, 175,  49, 164}}, {{191, 164,  63, 173}}, 
+                {{168, 185,  45, 182}}, {{165, 178,  35, 191}}, {{134, 131,   9, 128}}, 
+                {{139, 136,   7, 137}}, {{156, 149,  21, 146}}, {{145, 158,  27, 155}}, 
+                {{ 10,  71, 161, 124}}, {{  7,  76, 175, 117}}, {{ 16,  81, 189, 110}}, 
+                {{ 29,  90, 179, 103}}, {{ 62, 107, 153,  88}}, {{ 51,  96, 151,  81}}, 
+                {{ 36, 125, 133,  74}}, {{ 41, 118, 139,  67}}, {{ 98,  31, 209,  52}}, 
+                {{111,  20, 223,  61}}, {{120,   9, 205,  38}}, {{117,   2, 195,  47}}, 
+                {{ 86,  51, 233,  16}}, {{ 91,  56, 231,  25}}, {{ 76,  37, 245,   2}}, 
+                {{ 65,  46, 251,  11}}, {{ 97, 140, 154, 215}}, {{108, 135, 148, 222}}, 
+                {{123, 154, 134, 197}}, {{118, 145, 136, 204}}, {{ 85, 160, 162, 243}}, 
+                {{ 88, 171, 172, 250}}, {{ 79, 182, 190, 225}}, {{ 66, 189, 176, 232}}, 
+                {{  9, 212, 234, 159}}, {{  4, 223, 228, 150}}, {{ 19, 194, 246, 141}}, 
+                {{ 30, 201, 248, 132}}, {{ 61, 248, 210, 187}}, {{ 48, 243, 220, 178}}, 
+                {{ 39, 238, 206, 169}}, {{ 42, 229, 192, 160}}, {{177,  60, 122,  71}}, 
+                {{188,  55, 116,  78}}, {{171,  42, 102,  85}}, {{166,  33, 104,  92}}, 
+                {{133,  16,  66,  99}}, {{136,  27,  76, 106}}, {{159,   6,  94, 113}}, 
+                {{146,  13,  80, 120}}, {{217, 100,  10,  15}}, {{212, 111,   4,   6}}, 
+                {{195, 114,  22,  29}}, {{206, 121,  24,  20}}, {{237,  72,  50,  43}}, 
+                {{224,  67,  60,  34}}, {{247,  94,  46,  57}}, {{250,  85,  32,  48}}, 
+                {{183,   1, 236, 154}}, {{186,  10, 226, 147}}, {{173,  23, 240, 136}}, 
+                {{160,  28, 254, 129}}, {{131,  45, 212, 190}}, {{142,  38, 218, 183}}, 
+                {{153,  59, 200, 172}}, {{148,  48, 198, 165}}, {{223,  89, 156, 210}}, 
+                {{210,  82, 146, 219}}, {{197,  79, 128, 192}}, {{200,  68, 142, 201}}, 
+                {{235, 117, 164, 246}}, {{230, 126, 170, 255}}, {{241,  99, 184, 228}}, 
+                {{252, 104, 182, 237}}, {{103, 177,  12,  10}}, {{106, 186,   2,   3}}, 
+                {{125, 167,  16,  24}}, {{112, 172,  30,  17}}, {{ 83, 157,  52,  46}}, 
+                {{ 94, 150,  58,  39}}, {{ 73, 139,  40,  60}}, {{ 68, 128,  38,  53}}, 
+                {{ 15, 233, 124,  66}}, {{  2, 226, 114,  75}}, {{ 21, 255,  96,  80}}, 
+                {{ 24, 244, 110,  89}}, {{ 59, 197,  68, 102}}, {{ 54, 206,  74, 111}}, 
+                {{ 33, 211,  88, 116}}, {{ 44, 216,  86, 125}}, {{ 12, 122,  55, 161}}, 
+                {{  1, 113,  57, 168}}, {{ 22, 108,  43, 179}}, {{ 27, 103,  37, 186}}, 
+                {{ 56,  86,  15, 133}}, {{ 53,  93,   1, 140}}, {{ 34,  64,  19, 151}}, 
+                {{ 47,  75,  29, 158}}, {{100,  34,  71, 233}}, {{105,  41,  73, 224}}, 
+                {{126,  52,  91, 251}}, {{115,  63,  85, 242}}, {{ 80,  14, 127, 205}}, 
+                {{ 93,   5, 113, 196}}, {{ 74,  24,  99, 223}}, {{ 71,  19, 109, 214}}, 
+                {{220, 202, 215,  49}}, {{209, 193, 217,  56}}, {{198, 220, 203,  35}}, 
+                {{203, 215, 197,  42}}, {{232, 230, 239,  21}}, {{229, 237, 225,  28}}, 
+                {{242, 240, 243,   7}}, {{255, 251, 253,  14}}, {{180, 146, 167, 121}}, 
+                {{185, 153, 169, 112}}, {{174, 132, 187, 107}}, {{163, 143, 181,  98}}, 
+                {{128, 190, 159,  93}}, {{141, 181, 145,  84}}, {{154, 168, 131,  79}}, 
+                {{151, 163, 141,  70}}, 
+        },
+        {
+                {{  0,   0,   0,   0}}, {{  9,  13,  11,  14}}, {{ 18,  26,  22,  28}}, 
+                {{ 27,  23,  29,  18}}, {{ 36,  52,  44,  56}}, {{ 45,  57,  39,  54}}, 
+                {{ 54,  46,  58,  36}}, {{ 63,  35,  49,  42}}, {{ 72, 104,  88, 112}}, 
+                {{ 65, 101,  83, 126}}, {{ 90, 114,  78, 108}}, {{ 83, 127,  69,  98}}, 
+                {{108,  92, 116,  72}}, {{101,  81, 127,  70}}, {{126,  70,  98,  84}}, 
+                {{119,  75, 105,  90}}, {{144, 208, 176, 224}}, {{153, 221, 187, 238}}, 
+                {{130, 202, 166, 252}}, {{139, 199, 173, 242}}, {{180, 228, 156, 216}}, 
+                {{189, 233, 151, 214}}, {{166, 254, 138, 196}}, {{175, 243, 129, 202}}, 
+                {{216, 184, 232, 144}}, {{209, 181, 227, 158}}, {{202, 162, 254, 140}}, 
+                {{195, 175, 245, 130}}, {{252, 140, 196, 168}}, {{245, 129, 207, 166}}, 
+                {{238, 150, 210, 180}}, {{231, 155, 217, 186}}, {{ 59, 187, 123, 219}}, 
+                {{ 50, 182, 112, 213}}, {{ 41, 161, 109, 199}}, {{ 32, 172, 102, 201}}, 
+                {{ 31, 143,  87, 227}}, {{ 22, 130,  92, 237}}, {{ 13, 149,  65, 255}}, 
+                {{  4, 152,  74, 241}}, {{115, 211,  35, 171}}, {{122, 222,  40, 165}}, 
+                {{ 97, 201,  53, 183}}, {{104, 196,  62, 185}}, {{ 87, 231,  15, 147}}, 
+                {{ 94, 234,   4, 157}}, {{ 69, 253,  25, 143}}, {{ 76, 240,  18, 129}}, 
+                {{171, 107, 203,  59}}, {{162, 102, 192,  53}}, {{185, 113, 221,  39}}, 
+                {{176, 124, 214,  41}}, {{143,  95, 231,   3}}, {{134,  82, 236,  13}}, 
+                {{157,  69, 241,  31}}, {{148,  72, 250,  17}}, {{227,   3, 147,  75}}, 
+                {{234,  14, 152,  69}}, {{241,  25, 133,  87}}, {{248,  20, 142,  89}}, 
+                {{199,  55, 191, 115}}, {{206,  58, 180, 125}}, {{213,  45, 169, 111}}, 
+                {{220,  32, 162,  97}}, {{118, 109, 246, 173}}, {{127,  96, 253, 163}}, 
+                {{100, 119, 224, 177}}, {{109, 122, 235, 191}}, {{ 82,  89, 218, 149}}, 
+                {{ 91,  84, 209, 155}}, {{ 64,  67, 204, 137}}, {{ 73,  78, 199, 135}}, 
+                {{ 62,   5, 174, 221}}, {{ 55,   8, 165, 211}}, {{ 44,  31, 184, 193}}, 
+                {{ 37,  18, 179, 207}}, {{ 26,  49, 130, 229}}, {{ 19,  60, 137, 235}}, 
+                {{  8,  43, 148, 249}}, {{  1,  38, 159, 247}}, {{230, 189,  70,  77}}, 
+                {{239, 176,  77,  67}}, {{244, 167,  80,  81}}, {{253, 170,  91,  95}}, 
+                {{194, 137, 106, 117}}, {{203, 132,  97, 123}}, {{208, 147, 124, 105}}, 
+                {{217, 158, 119, 103}}, {{174, 213,  30,  61}}, {{167, 216,  21,  51}}, 
+                {{188, 207,   8,  33}}, {{181, 194,   3,  47}}, {{138, 225,  50,   5}}, 
+                {{131, 236,  57,  11}}, {{152, 251,  36,  25}}, {{145, 246,  47,  23}}, 
+                {{ 77, 214, 141, 118}}, {{ 68, 219, 134, 120}}, {{ 95, 204, 155, 106}}, 
+                {{ 86, 193, 144, 100}}, {{105, 226, 161,  78}}, {{ 96, 239, 170,  64}}, 
+                {{123, 248, 183,  82}}, {{114, 245, 188,  92}}, {{  5, 190, 213,   6}}, 
+                {{ 12, 179, 222,   8}}, {{ 23, 164, 195,  26}}, {{ 30, 169, 200,  20}}, 
+                {{ 33, 138, 249,  62}}, {{ 40, 135, 242,  48}}, {{ 51, 144, 239,  34}}, 
+                {{ 58, 157, 228,  44}}, {{221,   6,  61, 150}}, {{212,  11,  54, 152}}, 
+                {{207,  28,  43, 138}}, {{198,  17,  32, 132}}, {{249,  50,  17, 174}}, 
+                {{240,  63,  26, 160}}, {{235,  40,   7, 178}}, {{226,  37,  12, 188}}, 
+                {{149, 110, 101, 230}}, {{156,  99, 110, 232}}, {{135, 116, 115, 250}}, 
+                {{142, 121, 120, 244}}, {{177,  90,  73, 222}}, {{184,  87,  66, 208}}, 
+                {{163,  64,  95, 194}}, {{170,  77,  84, 204}}, {{236, 218, 247,  65}}, 
+                {{229, 215, 252,  79}}, {{254, 192, 225,  93}}, {{247, 205, 234,  83}}, 
+                {{200, 238, 219, 121}}, {{193, 227, 208, 119}}, {{218, 244, 205, 101}}, 
+                {{211, 249, 198, 107}}, {{164, 178, 175,  49}}, {{173, 191, 164,  63}}, 
+                {{182, 168, 185,  45}}, {{191, 165, 178,  35}}, {{128, 134, 131,   9}}, 
+                {{137, 139, 136,   7}}, {{146, 156, 149,  21}}, {{155, 145, 158,  27}}, 
+                {{124,  10,  71, 161}}, {{117,   7,  76, 175}}, {{110,  16,  81, 189}}, 
+                {{103,  29,  90, 179}}, {{ 88,  62, 107, 153}}, {{ 81,  51,  96, 151}}, 
+                {{ 74,  36, 125, 133}}, {{ 67,  41, 118, 139}}, {{ 52,  98,  31, 209}}, 
+                {{ 61, 111,  20, 223}}, {{ 38, 120,   9, 205}}, {{ 47, 117,   2, 195}}, 
+                {{ 16,  86,  51, 233}}, {{ 25,  91,  56, 231}}, {{  2,  76,  37, 245}}, 
+                {{ 11,  65,  46, 251}}, {{215,  97, 140, 154}}, {{222, 108, 135, 148}}, 
+                {{197, 123, 154, 134}}, {{204, 118, 145, 136}}, {{243,  85, 160, 162}}, 
+                {{250,  88, 171, 172}}, {{225,  79, 182, 190}}, {{232,  66, 189, 176}}, 
+                {{159,   9, 212, 234}}, {{150,   4, 223, 228}}, {{141,  19, 194, 246}}, 
+                {{132,  30, 201, 248}}, {{187,  61, 248, 210}}, {{178,  48, 243, 220}}, 
+                {{169,  39, 238, 206}}, {{160,  42, 229, 192}}, {{ 71, 177,  60, 122}}, 
+                {{ 78, 188,  55, 116}}, {{ 85, 171,  42, 102}}, {{ 92, 166,  33, 104}}, 
+                {{ 99, 133,  16,  66}}, {{106, 136,  27,  76}}, {{113, 159,   6,  94}}, 
+                {{120, 146,  13,  80}}, {{ 15, 217, 100,  10}}, {{  6, 212, 111,   4}}, 
+                {{ 29, 195, 114,  22}}, {{ 20, 206, 121,  24}}, {{ 43, 237,  72,  50}}, 
+                {{ 34, 224,  67,  60}}, {{ 57, 247,  94,  46}}, {{ 48, 250,  85,  32}}, 
+                {{154, 183,   1, 236}}, {{147, 186,  10, 226}}, {{136, 173,  23, 240}}, 
+                {{129, 160,  28, 254}}, {{190, 131,  45, 212}}, {{183, 142,  38, 218}}, 
+                {{172, 153,  59, 200}}, {{165, 148,  48, 198}}, {{210, 223,  89, 156}}, 
+                {{219, 210,  82, 146}}, {{192, 197,  79, 128}}, {{201, 200,  68, 142}}, 
+                {{246, 235, 117, 164}}, {{255, 230, 126, 170}}, {{228, 241,  99, 184}}, 
+                {{237, 252, 104, 182}}, {{ 10, 103, 177,  12}}, {{  3, 106, 186,   2}}, 
+                {{ 24, 125, 167,  16}}, {{ 17, 112, 172,  30}}, {{ 46,  83, 157,  52}}, 
+                {{ 39,  94, 150,  58}}, {{ 60,  73, 139,  40}}, {{ 53,  68, 128,  38}}, 
+                {{ 66,  15, 233, 124}}, {{ 75,   2, 226, 114}}, {{ 80,  21, 255,  96}}, 
+                {{ 89,  24, 244, 110}}, {{102,  59, 197,  68}}, {{111,  54, 206,  74}}, 
+                {{116,  33, 211,  88}}, {{125,  44, 216,  86}}, {{161,  12, 122,  55}}, 
+                {{168,   1, 113,  57}}, {{179,  22, 108,  43}}, {{186,  27, 103,  37}}, 
+                {{133,  56,  86,  15}}, {{140,  53,  93,   1}}, {{151,  34,  64,  19}}, 
+                {{158,  47,  75,  29}}, {{233, 100,  34,  71}}, {{224, 105,  41,  73}}, 
+                {{251, 126,  52,  91}}, {{242, 115,  63,  85}}, {{205,  80,  14, 127}}, 
+                {{196,  93,   5, 113}}, {{223,  74,  24,  99}}, {{214,  71,  19, 109}}, 
+                {{ 49, 220, 202, 215}}, {{ 56, 209, 193, 217}}, {{ 35, 198, 220, 203}}, 
+                {{ 42, 203, 215, 197}}, {{ 21, 232, 230, 239}}, {{ 28, 229, 237, 225}}, 
+                {{  7, 242, 240, 243}}, {{ 14, 255, 251, 253}}, {{121, 180, 146, 167}}, 
+                {{112, 185, 153, 169}}, {{107, 174, 132, 187}}, {{ 98, 163, 143, 181}}, 
+                {{ 93, 128, 190, 159}}, {{ 84, 141, 181, 145}}, {{ 79, 154, 168, 131}}, 
+                {{ 70, 151, 163, 141}}, 
+        },
+};
+
+int xrcon[30] = {
+        0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 
+        0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 
+        0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 
+};
+
+word8 xS[256] = {
+        99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 
+        171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 
+        156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 
+        229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154, 
+        7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110, 
+        90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237, 
+        32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239, 
+        170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168, 
+        81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 
+        243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 
+        100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 
+        184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 
+        194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213, 
+        78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46, 
+        28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
+        181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 
+        225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85, 
+        40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 
+        176,  84, 187,  22, 
+};
+
+word8 xSi[256] = {
+        82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 
+        215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 
+        196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 
+        149,  11,  66, 250, 195,  78,   8,  46, 161, 102,  40, 217,  36, 178, 
+        118,  91, 162,  73, 109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 
+        152,  22, 212, 164,  92, 204,  93, 101, 182, 146, 108, 112,  72,  80, 
+        253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132, 144, 216, 
+        171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6, 
+        208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 
+        138, 107,  58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 
+        240, 180, 230, 115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249, 
+        55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 
+        111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210, 
+        121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,  51, 
+        136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81, 
+        127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 
+        160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 
+        153,  97,  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99, 
+        85,  33,  12, 125, 
+};
+
+/* -------------------------------- */
+
+#define MAXBC		(256/32)
+#define MAXKC		(256/32)
+#define MAXROUNDS	14
+#define MAXRK           ((MAXROUNDS+1)*MAXBC)
+
+typedef struct {
+        int BC;
+        int KC;
+        int ROUNDS;
+        int shift[2][4];
+        word32 rk[MAXRK];
+} roundkey;
+
+/* keys and blocks are externally treated as word32 arrays, to
+   make sure they are aligned on 4-byte boundaries on architectures
+   that require it. */
+
+static int xshifts[3][2][4] = {
+        {{0, 1, 2, 3},
+         {0, 3, 2, 1}},
+
+        {{0, 1, 2, 3},
+         {0, 5, 4, 3}},
+
+        {{0, 1, 3, 4},
+         {0, 7, 5, 4}},
+};
+
+/* Exor corresponding text input and round key input bytes */
+/* the result is written to res, which can be the same as a */
+static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC],
+                                word32 rk[MAXBC], int BC)
+{
+        int j;
+
+        for (j = 0; j < BC; j++) {
+                res[j] = a[j] ^ rk[j];
+        }
+}
+
+/* profiling shows that the ccrypt program spends about 50% of its
+   time in the function xShiftSubst. Splitting the inner "for"
+   statement into two parts - versus using the expensive "%" modulo
+   operation, makes this function about 44% faster, thereby making the
+   entire program about 28% faster. With -O3 optimization, the time
+   savings are even more dramatic - ccrypt runs between 55% and 65%
+   faster on most platforms. */
+
+/* do ShiftRow and Substitution together. res must not be a. */
+static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC],
+                               int shift[4], int BC, word8 box[256])
+{
+        int i, j;
+        int s;
+        word8 (*a8)[4] = (word8 (*)[4]) a;
+        word8 (*res8)[4] = (word8 (*)[4]) res;
+
+        for (j = 0; j < BC; j++) {
+                res8[j][0] = box[a8[j][0]];
+        }
+        for (i = 1; i < 4; i++) {
+                s = shift[i];
+                for (j = 0; j < BC - s; j++) {
+                        res8[j][i] = box[a8[(j + s)][i]];
+                }
+                for (j = BC - s; j < BC; j++) {
+                        res8[j][i] = box[a8[(j + s) - BC][i]];
+                }
+        }
+}
+
+/* do MixColumn and KeyAddition together */
+static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC],
+                           word32 rk[MAXBC], int BC)
+{
+        int j;
+        word32 b;
+        word8 (*a8)[4] = (word8 (*)[4]) a;
+
+        for (j = 0; j < BC; j++) {
+                b = M0[0][a8[j][0]].w32;
+                b ^= M0[1][a8[j][1]].w32;
+                b ^= M0[2][a8[j][2]].w32;
+                b ^= M0[3][a8[j][3]].w32;
+                b ^= rk[j];
+                res[j] = b;
+        }
+}
+
+/* Mix the four bytes of every column in a linear way
+ * This is the opposite operation of xMixColumn */
+/* the result is written to res, which may equal a */
+static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC)
+{
+        int j;
+        word32 b;
+        word8 (*a8)[4] = (word8 (*)[4]) a;
+
+        for (j = 0; j < BC; j++) {
+                b = M1[0][a8[j][0]].w32;
+                b ^= M1[1][a8[j][1]].w32;
+                b ^= M1[2][a8[j][2]].w32;
+                b ^= M1[3][a8[j][3]].w32;
+                res[j] = b;
+        }
+}
+
+/* make a roundkey rkk from key. key must have appropriate size given
+   by keyBits. keyBits and blockBits may only be 128, 196, or
+   256. Returns non-zero if arguments are invalid. */
+
+int xrijndaelKeySched(word32 key[], int keyBits, int blockBits,
+		      roundkey *rkk)
+{
+        /* Calculate the necessary round keys
+         * The number of calculations depends on keyBits and blockBits */
+        int KC, BC, ROUNDS;
+        int i, j, t, rconpointer = 0;
+        word8 (*k8)[4] = (word8 (*)[4]) key;
+
+        switch (keyBits) {
+        case 128:
+                KC = 4;
+                break;
+        case 192:
+                KC = 6;
+                break;
+        case 256:
+                KC = 8;
+                break;
+        default:
+                return -1;
+        }
+
+        switch (blockBits) {
+        case 128:
+                BC = 4;
+                break;
+        case 192:
+                BC = 6;
+                break;
+        case 256:
+                BC = 8;
+                break;
+        default:
+                return -2;
+        }
+
+        ROUNDS = KC > BC ? KC + 6 : BC + 6;
+
+        t = 0;
+        /* copy values into round key array */
+        for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++)
+                rkk->rk[t] = key[j];
+
+        while (t < (ROUNDS + 1) * BC) {  /* while not enough round key material */
+                /* calculate new values */
+                for (i = 0; i < 4; i++) {
+                        k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]];
+                }
+                k8[0][0] ^= xrcon[rconpointer++];
+
+                if (KC != 8) {
+                        for (j = 1; j < KC; j++) {
+                                key[j] ^= key[j - 1];
+                        }
+                } else {
+                        for (j = 1; j < 4; j++) {
+                                key[j] ^= key[j - 1];
+                        }
+                        for (i = 0; i < 4; i++) {
+                                k8[4][i] ^= xS[k8[3][i]];
+                        }
+                        for (j = 5; j < 8; j++) {
+                                key[j] ^= key[j - 1];
+                        }
+                }
+                /* copy values into round key array */
+                for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) {
+                        rkk->rk[t] = key[j];
+                }
+        }
+
+        /* make roundkey structure */
+        rkk->BC = BC;
+        rkk->KC = KC;
+        rkk->ROUNDS = ROUNDS;
+        for (i = 0; i < 2; i++) {
+                for (j = 0; j < 4; j++) {
+                        rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j];
+                }
+        }
+
+        return 0;
+}
+
+/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must
+   have been created with xrijndaelKeySched. Size of block, in bits,
+   must be equal to blockBits parameter that was used to make rkk. In
+   all other cases, behavior is undefined - for reasons of speed, no
+   check for error conditions is done. */
+
+/* Encryption of one block. */
+
+void xrijndaelEncrypt(word32 block[], roundkey *rkk)
+{
+        word32 block2[MAXBC];		/* hold intermediate result */
+        int r;
+
+        int *shift = rkk->shift[0];
+        int BC = rkk->BC;
+        int ROUNDS = rkk->ROUNDS;
+        word32 *rp = rkk->rk;
+
+        /* begin with a key addition */
+        xKeyAddition(block, block, rp, BC);
+        rp += BC;
+
+        /* ROUNDS-1 ordinary rounds */
+        for (r = 1; r < ROUNDS; r++) {
+                xShiftSubst(block2, block, shift, BC, xS);
+                xMixAdd(block, block2, rp, BC);
+                rp += BC;
+        }
+
+        /* Last round is special: there is no xMixColumn */
+        xShiftSubst(block2, block, shift, BC, xS);
+        xKeyAddition(block, block2, rp, BC);
+}
+
+void xrijndaelDecrypt(word32 block[], roundkey *rkk)
+{
+        word32 block2[MAXBC];		/* hold intermediate result */
+        int r;
+
+        int *shift = rkk->shift[1];
+        int BC = rkk->BC;
+        int ROUNDS = rkk->ROUNDS;
+        word32 *rp = rkk->rk + ROUNDS * BC;
+
+        /* To decrypt: apply the inverse operations of the encrypt routine,
+         *             in opposite order
+         * 
+         * (xKeyAddition is an involution: it's equal to its inverse)
+         * (the inverse of xSubstitution with table S is xSubstitution with the 
+         * inverse table of S)
+         * (the inverse of xShiftRow is xShiftRow over a suitable distance)
+         */
+
+        /* First the special round:
+         *   without xInvMixColumn
+         *   with extra xKeyAddition
+         */
+        xKeyAddition(block2, block, rp, BC);
+        xShiftSubst(block, block2, shift, BC, xSi);
+        rp -= BC;
+
+        /* ROUNDS-1 ordinary rounds
+         */
+        for (r = ROUNDS - 1; r > 0; r--) {
+                xKeyAddition(block, block, rp, BC);
+                xInvMixColumn(block2, block, BC);
+                xShiftSubst(block, block2, shift, BC, xSi);
+                rp -= BC;
+        }
+
+        /* End with the extra key addition
+         */
+
+        xKeyAddition(block, block, rp, BC);
+}
+
+/* -------------------------------- */
+
+
+#define MAGIC "c051"   /* magic string for this version of ccrypt */
+
+/* private struct, not visible by applications */
+struct ccrypt_state_s {
+        int n;          /* number of keys. n=1 for encryption, n>=1 for decryption */
+        roundkey *rkks; /* array of n keys */
+        int ak;         /* rkks[ak] is the active key */
+        int iv;         /* are we reading/writing the IV? */
+        int bufindex;   /* in bytes */
+        word32 buf[8];  /* current buffer; partly ciphertext, partly mask */
+        int flags;      /* flags determining behavior */
+};
+typedef struct ccrypt_state_s ccrypt_state_t;
+
+
+int ccrypt_errno;
+
+#ifdef DEBUG
+static void print_state(ccrypt_state_t *st) {
+        if (st) {
+                printf("State:\n");
+                memory_display(st,0,sizeof(st),1,0);
+                if (st->rkks) {
+                        printf("Roundkey:\n");
+                        memory_display(st->rkks,0,sizeof(roundkey),1,0);
+                }
+        }
+}
+#endif
+
+static void ccrypt_state_free(ccrypt_state_t *st) {
+        if (st) {
+                free(st->rkks);
+        }
+        free(st);
+}
+
+/* ---------------------------------------------------------------------- */
+/* some private functions dealing with hashes, keys, and nonces */
+
+/* hash a keystring into a 256-bit cryptographic random value. */
+static void hashstring(const char *keystring, const int keylen, word32 hash[8]) {
+        int i,j;
+        roundkey rkk;
+        word32 key[8];      /* rijndael key */
+
+        for (i=0; i<8; i++) 
+                key[i] = hash[i] = 0;
+  
+        for ( j=0; j<keylen; ) {
+                for (i=0; i<32; i++) {
+                        if ( j<keylen ) {
+                                ((word8 *)key)[i] ^= keystring[j];
+                                j++;
+                        }
+                }
+                xrijndaelKeySched(key, 256, 256, &rkk);
+                xrijndaelEncrypt(hash, &rkk);
+        }
+
+#if 0
+        do {
+                for (i=0; i<32; i++) {
+                        if (*keystring != 0) {
+                                ((word8 *)key)[i] ^= *keystring;
+                                keystring++;
+                        }
+                }
+                xrijndaelKeySched(key, 256, 256, &rkk);
+                xrijndaelEncrypt(hash, &rkk);
+        } while (*keystring != 0);
+#endif
+        
+}
+
+/* return a 256-bit value that is practically unique */
+static void make_nonce(word32 nonce[8]) {
+        char acc[512];
+        static int count=0;
+  
+        sprintf(acc, "%s,%d,%d,%d,%d,%d", "barebox", rand(),rand(),rand(),rand(),count++);
+        hashstring(acc, strlen(acc), nonce); 
+}
+
+/* ---------------------------------------------------------------------- */
+/* core functions for encryption */
+
+int ccencrypt_init(ccrypt_stream_t *b, const char *key, const int keylen) {
+        word32 keyblock[8];
+        ccrypt_state_t *st;
+        roundkey *rkks;
+
+        b->state = NULL;
+  
+        st = malloc(sizeof(ccrypt_state_t));
+        if (st == NULL) {
+                return -1;
+        }
+        rkks = malloc(sizeof(roundkey));
+        if (!rkks) {
+                free(st);
+                return -1;
+        }
+
+        st->n = 1;
+        st->rkks = rkks;
+        st->ak = 0; /* not used */
+
+        /* generate the roundkey */
+        hashstring(key, keylen, keyblock);
+        xrijndaelKeySched(keyblock, 256, 256, &st->rkks[0]);
+  
+        /* make a nonce */
+        make_nonce(st->buf);
+
+        /* mark the nonce with a "magic number". */
+        strncpy((char *)st->buf, MAGIC, 4);
+
+        /* encrypt the nonce with the given key */
+        xrijndaelEncrypt(st->buf, &st->rkks[0]);
+
+        /* IV is now contained in st->buf. Initialize rest of the state. */
+        st->iv = 1;
+        st->bufindex = 0; /* initially use bufsize to count iv bytes output */
+
+#ifdef DEBUG
+        print_state(st);
+#endif
+        b->state = (void *)st;
+        return 0;
+}
+
+EXPORT_SYMBOL(ccencrypt_init);
+
+int ccencrypt(ccrypt_stream_t *b) {
+        ccrypt_state_t *st = (ccrypt_state_t *)b->state;
+        word32 lbuf[8];
+        char *cbuf = (char *)st->buf;
+        int i;
+        char c, cc;
+
+        while (1) {
+                /* handle the typical case efficiently, one block at a time */
+
+                if (st->iv == 0 && st->bufindex == 32) {
+                        while (b->avail_in >= 32 && b->avail_out >= 32) {
+
+                                /* block-encrypt buffer */
+                                xrijndaelEncrypt(st->buf, &st->rkks[0]);
+	
+                                /* read input to local buffer for word alignment */
+                                memcpy(lbuf, b->next_in, 32);
+                                b->next_in += 32;
+                                b->avail_in -= 32;
+	
+                                /* compute ciphertext */
+                                for (i=0; i<8; i++) {
+                                        st->buf[i] ^= lbuf[i];
+                                }
+
+                                /* write output */
+                                memcpy(b->next_out, st->buf, 32);
+                                b->next_out += 32;
+                                b->avail_out -= 32;
+                        }
+                }
+    
+                /* handle the general case systematically, one byte at a time */
+
+                if (b->avail_out == 0) {
+                        break;
+                } 
+
+                else if (st->iv) {  /* write IV byte */
+                        *b->next_out = cbuf[st->bufindex];
+                        b->next_out++;
+                        b->avail_out--;
+                        st->bufindex++;
+                        if (st->bufindex == 32) {
+                                st->iv = 0;
+                        }
+                } 
+
+                else if (b->avail_in == 0) {
+                        break;
+                }
+
+                else {              /* encrypt one byte */
+                        if (st->bufindex == 32) {
+                                xrijndaelEncrypt(st->buf, &st->rkks[0]);
+                                st->bufindex = 0;
+                        }
+                        c = *b->next_in;
+                        b->next_in++;
+                        b->avail_in--;
+                        cc = c ^ cbuf[st->bufindex];
+                        cbuf[st->bufindex] = cc;
+                        *b->next_out = cc;
+                        b->next_out++;
+                        b->avail_out--;
+                        st->bufindex++;
+                }
+        }
+#ifdef DEBUG
+        print_state(st);
+#endif
+        return 0;
+}
+
+EXPORT_SYMBOL(ccencrypt);
+
+int ccencrypt_end(ccrypt_stream_t *b) {
+        ccrypt_state_free(b->state);
+        b->state = NULL; /* guard against double free */
+        return 0;
+}
+
+EXPORT_SYMBOL(ccencrypt_end);
+
+/* ---------------------------------------------------------------------- */
+/* core functions for decryption */
+
+int ccdecrypt_init(ccrypt_stream_t *b, const char *key, const int keylen) {
+        word32 keyblock[8];
+        ccrypt_state_t *st;
+        roundkey *rkks;
+  
+        b->state = NULL;
+
+        st = malloc(sizeof(ccrypt_state_t));
+        if (st == NULL) {
+                return -1;
+        }
+        rkks = malloc(sizeof(roundkey));
+        if (!rkks) {
+                free(st);
+                return -1;
+        }
+
+        st->n = 1;
+        st->rkks = rkks;
+        st->ak = 0;
+
+        /* generate the roundkeys */
+        hashstring(key, keylen, keyblock);
+        xrijndaelKeySched(keyblock, 256, 256, &st->rkks[0]);
+
+        /* Initialize rest of the state. */
+        st->iv = 1;
+        st->bufindex = 0;
+        st->flags = 0;
+
+#ifdef DEBUG
+        print_state(st);
+#endif
+        b->state = (void *)st;
+        return 0;
+}
+
+EXPORT_SYMBOL(ccdecrypt_init);
+
+int ccdecrypt(ccrypt_stream_t *b) {
+        ccrypt_state_t *st = (ccrypt_state_t *)b->state;
+        word32 lbuf[8];
+        char *cbuf = (char *)st->buf;
+        int i;
+        char c, cc;
+  
+        while (1) {
+                /* handle the typical case efficiently, one block at a time */
+
+                if (st->iv == 0 && st->bufindex == 32) {
+                        while (b->avail_in >= 32 && b->avail_out >= 32) {
+	
+                                /* block-encrypt buffer */
+                                xrijndaelEncrypt(st->buf, &st->rkks[st->ak]);
+                                memcpy(lbuf, st->buf, 32);
+
+                                /* read input */
+                                memcpy(st->buf, b->next_in, 32);
+                                b->next_in += 32;
+                                b->avail_in -= 32;
+
+                                /* compute plaintext */
+                                for (i=0; i<8; i++) {
+                                        lbuf[i] ^= st->buf[i];
+                                }
+
+                                /* write output */
+                                memcpy(b->next_out, lbuf, 32);
+                                b->next_out += 32;
+                                b->avail_out -= 32;
+                        }
+                }
+
+                /* handle the general case systematically, one byte at a time */
+
+                if (b->avail_in == 0) {
+                        break;
+                }
+
+                else if (st->iv) {  /* read IV byte */
+                        cbuf[st->bufindex] = *b->next_in;
+                        b->next_in++;
+                        b->avail_in--;
+                        st->bufindex++;
+                        if (st->bufindex == 32) {
+                                st->iv = 0;
+                                /* find the first matching key */
+                                for (i=0; i<st->n; i++) {
+                                        /* check the "magic number" */
+                                        memcpy(lbuf, st->buf, 32);
+                                        xrijndaelDecrypt(lbuf, &st->rkks[i]);
+                                        if ((st->flags & CCRYPT_MISMATCH) != 0 || strncmp((char *)lbuf, MAGIC, 4) == 0) {
+                                                /* key matches */
+                                                break;
+                                        }
+                                }
+                                if (i<st->n) { /* matching key found */
+                                        st->ak = i;
+                                } else {       /* not found */
+                                        /* on error, invalidate the state so that the client cannot
+                                           call here again. */
+                                        ccrypt_state_free((ccrypt_state_t *)b->state);
+                                        b->state = NULL;
+                                        ccrypt_errno = CCRYPT_EMISMATCH;
+                                        return -2;
+                                }
+                        }
+                }
+
+                else if (b->avail_out == 0) {
+                        break;
+                }
+
+                else {              /* decrypt one byte */
+                        if (st->bufindex == 32) {
+                                xrijndaelEncrypt(st->buf, &st->rkks[st->ak]);
+                                st->bufindex = 0;
+                        }
+                        cc = *b->next_in;
+                        b->next_in++;
+                        b->avail_in--;
+                        c = cc ^ cbuf[st->bufindex];
+                        cbuf[st->bufindex] = cc;
+                        *b->next_out = c;
+                        b->next_out++;
+                        b->avail_out--;
+                        st->bufindex++;
+                }
+        }
+#ifdef DEBUG
+        print_state(st);
+#endif
+        return 0;
+}
+
+EXPORT_SYMBOL(ccdecrypt);
+
+int ccdecrypt_end(ccrypt_stream_t *b) {
+        ccrypt_state_t *st;
+  
+        if (b->state) {
+
+                /* verify that we have read and verified the IV */
+                st = (ccrypt_state_t *)b->state;
+                if (st->iv) {
+                        ccrypt_state_free(b->state);
+                        b->state = NULL;
+                        ccrypt_errno = CCRYPT_EFORMAT;
+                        return -2;
+                }
+        }
+
+        ccrypt_state_free(b->state);
+        b->state = NULL;
+        return 0;
+}
+
+EXPORT_SYMBOL(ccdecrypt_end);
diff --git a/include/ccryptlib.h b/include/ccryptlib.h
new file mode 100644
index 000000000..b2446a232
--- /dev/null
+++ b/include/ccryptlib.h
@@ -0,0 +1,102 @@
+/* -*- Mode:C; c-file-style:"linux"; -*- */
+
+/* Ported to barebox by Gerd Pauli <gp at high-consulting.de> 2018 */
+
+/* Copyright (C) 2000-2009 Peter Selinger.
+   This file is part of ccrypt. It is free software and it is covered
+   by the GNU general public license. See the file COPYING for details. */
+
+/* ccryptlib.h: library for encrypting/decrypting a character stream */
+/* $Id: ccryptlib.h 258 2009-08-26 17:46:10Z selinger $ */
+
+#ifndef _CCRYPTLIB_H
+#define _CCRYPTLIB_H
+
+struct ccrypt_stream_s {
+        char          *next_in;  /* next input byte */
+        unsigned int  avail_in;  /* number of bytes available at next_in */
+
+        char          *next_out; /* next output byte should be put there */
+        unsigned int  avail_out; /* remaining free space at next_out */
+
+        void *state;             /* internal state, not visible by applications */
+};
+typedef struct ccrypt_stream_s ccrypt_stream_t;
+
+/* 
+   The application may update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when
+   avail_out has dropped to zero. All other fields are set by the
+   compression library and must not be updated by the application.
+*/
+
+int ccencrypt_init(ccrypt_stream_t *b, const char *key, const int keylen);
+int ccencrypt     (ccrypt_stream_t *b);
+int ccencrypt_end (ccrypt_stream_t *b);
+
+int ccdecrypt_init(ccrypt_stream_t *b, const char *key, const int keylen);
+int ccdecrypt     (ccrypt_stream_t *b);
+int ccdecrypt_end (ccrypt_stream_t *b);
+
+/* The interface for encryption and decryption is the same. The
+   application must first call the respective init function to
+   initialize the internal state. Then it calls the encrypt/decrypt
+   function repeatedly, as follows: next_in and next_out must point to
+   valid, non-overlapping regions of memory of size at least avail_in
+   and avail_out, respectively. Avail_out must be non-zero. Avail_in
+   may be zero to retrieve some pending output when no input is
+   available, for instance, in an interactive application or at the
+   end of stream. Otherwise, avail_in should be non-zero. 
+
+   The encryption/decryption function will read and process as many
+   input bytes as possible as long as there is room in the output
+   buffer. It will update next_in, avail_in, next_out, and avail_out
+   accordingly. It will always flush as much output as possible.
+   However, it is possible that some input bytes produce no output,
+   because some part of the input may be used for internal purposes.
+   Conversely, it is possible that output is produced without reading
+   any input. When the encryption/decryption function returns, at
+   least one of avail_in or avail_out is 0. If avail_out is non-zero
+   after a call, the application may conclude that no more output is
+   pending.
+
+   Finally, the internal state must be freed by calling the respective
+   end function. This function will discard any unprocessed input
+   and/or output, so it should only be called after the application
+   has retrieved any pending output. Note: the call to the end
+   function should be checked for errors, because this is the only
+   place where certain format errors (like a file that is too short)
+   are detected.
+
+   All functions return 0 on success, or -1 on error with errno set,
+   or -2 on error with ccrypt_errno set. Callers must check for
+   errors. If an error occurs, the state is invalid and its resources
+   are freed. It may not be used again. It is then safe, but not
+   required, to call the corresponding *_end function.
+
+   The flags argument to ccdecrypt_init should be 0 by default, or
+   CCRYPT_MISMATCH if non-matching keys should be ignored. All other
+   values are undefined and reserved for future use.
+*/
+
+/* ccdecrypt_multi_init this is a variant of ccdecrypt_init that
+   allows a list of n>=1 keys to be defined. During decryption, the
+   first matching key is used. This is useful when batch decrypting a
+   set of files that have non-uniform keys. If flags includes
+   CCRYPT_MISMATCH, then the first key is always used regardless of
+   whether it matches or not. */
+int ccdecrypt_multi_init(ccrypt_stream_t *b, int n, const char **keylist, int flags);
+
+/* errors */
+
+#define CCRYPT_EFORMAT   1          /* bad file format */
+#define CCRYPT_EMISMATCH 2          /* key does not match */
+#define CCRYPT_EBUFFER   3          /* buffer overflow */
+
+/* flags */
+
+#define CCRYPT_MISMATCH  1          /* ignore non-matching key */
+
+extern int ccrypt_errno;
+
+#endif /* _CCRYPTLIB_H */
-- 
2.11.0



From l.stach at pengutronix.de  Fri Apr 20 03:35:41 2018
From: l.stach at pengutronix.de (Lucas Stach)
Date: Fri, 20 Apr 2018 12:35:41 +0200
Subject: [PATCH] video: tc358767: don't link AUX i2c adapter to parent OF node
Message-ID: <20180420103541.26772-1-l.stach@pengutronix.de>

Otherwise the i2c core will try to populate the TC358767 child nodes
as i2c devices, which is wrong.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 drivers/video/tc358767.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/video/tc358767.c b/drivers/video/tc358767.c
index d4749b15c7a1..125e8236c153 100644
--- a/drivers/video/tc358767.c
+++ b/drivers/video/tc358767.c
@@ -1413,7 +1413,6 @@ static int tc_probe(struct device_d *dev)
 	tc->adapter.master_xfer = tc_aux_i2c_xfer;
 	tc->adapter.nr = -1; /* any free */
 	tc->adapter.dev.parent = dev;
-	tc->adapter.dev.device_node = dev->device_node;
 	/* Add I2C adapter */
 	ret = i2c_add_numbered_adapter(&tc->adapter);
 	if (ret < 0) {
-- 
2.16.3



From s.riedmueller at phytec.de  Fri Apr 20 04:01:01 2018
From: s.riedmueller at phytec.de (Stefan Riedmueller)
Date: Fri, 20 Apr 2018 13:01:01 +0200
Subject: [PATCH] commands: of_display_timings: Add simple-panel support
Message-ID: <1524222061-8825-1-git-send-email-s.riedmueller@phytec.de>

Display timings can now be set with simple-panel method which selects
the required timings by the compatible of the simple panel devicetree
node.

This patch adds an option to set simple panel timings with the
of_display_timings command by setting the compatible of the display node.
The options -P and -c were implemented. The -P option requires the display
node path as argument and the -c option requires the compatible to set.

This has one downside. The available simple panel timings cannot be
listed since the timings are defined in the kernel. Account for this in the
help text.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
---
 commands/of_display_timings.c | 65 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 61 insertions(+), 4 deletions(-)

diff --git a/commands/of_display_timings.c b/commands/of_display_timings.c
index ccf2db0..ca8275f 100644
--- a/commands/of_display_timings.c
+++ b/commands/of_display_timings.c
@@ -28,6 +28,39 @@
 #include <linux/err.h>
 #include <string.h>
 
+struct panel_info {
+	char *displaypath;
+	char *compatible;
+};
+
+static int of_panel_timing(struct device_node *root, void *context)
+{
+	int ret = 0;
+	struct panel_info *panel = (struct panel_info*)context;
+	struct device_node *display;
+
+	display = of_find_node_by_path_from(root, panel->displaypath);
+	if (!display) {
+		pr_err("Path to display node is not vaild.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = of_set_property(display, "compatible",
+			      panel->compatible,
+			      strlen(panel->compatible) + 1, 1);
+
+	if (ret < 0) {
+		pr_err("Could not update compatible property\n");
+		goto out;
+	}
+
+	ret = of_device_enable(display);
+
+out:
+	return ret;
+}
+
 static int of_display_timing(struct device_node *root, void *timingpath)
 {
 	int ret = 0;
@@ -55,10 +88,12 @@ static int do_of_display_timings(int argc, char *argv[])
 	struct device_node *root = NULL;
 	struct device_node *display = NULL;
 	struct device_node *timings = NULL;
+	struct panel_info *panel = NULL;
 	char *timingpath = NULL;
 	char *dtbfile = NULL;
+	char *compatible = NULL;
 
-	while ((opt = getopt(argc, argv, "sS:lf:")) > 0) {
+	while ((opt = getopt(argc, argv, "sS:lf:c:P:")) > 0) {
 		switch (opt) {
 		case 'l':
 			list = 1;
@@ -69,10 +104,18 @@ static int do_of_display_timings(int argc, char *argv[])
 		case 's':
 			selected = 1;
 			break;
+		case 'c':
+			compatible = optarg;
+			break;
 		case 'S':
 			timingpath = xzalloc(strlen(optarg) + 1);
 			strcpy(timingpath, optarg);
 			break;
+		case 'P':
+			panel = xzalloc(sizeof(struct panel_info));
+			panel->displaypath = xzalloc(strlen(optarg) + 1);
+			strcpy(panel->displaypath, optarg);
+			break;
 		default:
 			return COMMAND_ERROR_USAGE;
 		}
@@ -140,6 +183,18 @@ static int do_of_display_timings(int argc, char *argv[])
 			printf("No selected display-timings found.\n");
 	}
 
+	if (panel) {
+		if (!compatible) {
+			pr_err("No compatible argument. -P option requires compatible with -c option\n");
+			return -EINVAL;
+		} else {
+			panel->compatible = xzalloc(strlen(compatible) + 1);
+			strcpy(panel->compatible, compatible);
+		}
+
+		of_register_fixup(of_panel_timing, panel);
+	}
+
 	if (timingpath)
 		of_register_fixup(of_display_timing, timingpath);
 
@@ -148,16 +203,18 @@ static int do_of_display_timings(int argc, char *argv[])
 
 BAREBOX_CMD_HELP_START(of_display_timings)
 BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT("-l",  "list path of all available display-timings\n")
-BAREBOX_CMD_HELP_OPT("-s",  "list path of all selected display-timings\n")
+BAREBOX_CMD_HELP_OPT("-l",  "list path of all available display-timings\n\t\tNOTE: simple-panel timings cannot be listed\n")
+BAREBOX_CMD_HELP_OPT("-s",  "list path of all selected display-timings\n\t\tNOTE: simple-panel timings cannot be listed\n")
+BAREBOX_CMD_HELP_OPT("-c",  "display compatible to enable with -P option. Has no effect on -S option\n")
 BAREBOX_CMD_HELP_OPT("-S path",  "select display-timings and register oftree fixup\n")
+BAREBOX_CMD_HELP_OPT("-P path",  "select simple-panel node and register oftree fixup with -c compatible\n")
 BAREBOX_CMD_HELP_OPT("-f dtb",  "work on dtb. Has no effect on -s option\n")
 BAREBOX_CMD_HELP_END
 
 BAREBOX_CMD_START(of_display_timings)
 	.cmd	= do_of_display_timings,
 	BAREBOX_CMD_DESC("print and select display-timings")
-	BAREBOX_CMD_OPTS("[-ls] [-S path] [-f dtb]")
+	BAREBOX_CMD_OPTS("[-ls] [-S path] [-P path -c compatible] [-f dtb]")
 	BAREBOX_CMD_GROUP(CMD_GRP_MISC)
 	BAREBOX_CMD_COMPLETE(devicetree_file_complete)
 	BAREBOX_CMD_HELP(cmd_of_display_timings_help)
-- 
2.7.4



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:29 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:29 -0700
Subject: [PATCH v2 01/10] common: reset_source: Add the notion of "reset
 source instance"
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-2-andrew.smirnov@gmail.com>

In order to accomodate SoCs that come with multiple watchdogs (or any
other reset sources of the same kind) add a notion of "reset source
instance", similar to what we already have for bootsource API.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/reset_source.c  | 17 +++++++++++++++++
 include/reset_source.h | 11 +++++++++++
 2 files changed, 28 insertions(+)

diff --git a/common/reset_source.c b/common/reset_source.c
index 06e2ca85f..6a6c4f5da 100644
--- a/common/reset_source.c
+++ b/common/reset_source.c
@@ -32,6 +32,7 @@ static const char * const reset_src_names[] = {
 
 static enum reset_src_type reset_source;
 static unsigned int reset_source_priority;
+static int reset_source_instance;
 
 enum reset_src_type reset_source_get(void)
 {
@@ -39,6 +40,12 @@ enum reset_src_type reset_source_get(void)
 }
 EXPORT_SYMBOL(reset_source_get);
 
+int reset_source_get_instance(void)
+{
+	return reset_source_instance;
+}
+EXPORT_SYMBOL(reset_source_get_instance);
+
 void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
 {
 	if (priority <= reset_source_priority)
@@ -46,17 +53,27 @@ void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
 
 	reset_source = st;
 	reset_source_priority = priority;
+	reset_source_instance = 0;
 
 	pr_debug("Setting reset source to %s with priority %d\n",
 			reset_src_names[reset_source], priority);
 }
 EXPORT_SYMBOL(reset_source_set_priority);
 
+void reset_source_set_instance(enum reset_src_type type, int instance)
+{
+	if (reset_source == type)
+		reset_source_instance = instance;
+}
+EXPORT_SYMBOL(reset_source_set_instance);
+
 static int reset_source_init(void)
 {
 	globalvar_add_simple_enum("system.reset", (unsigned int *)&reset_source,
 			reset_src_names, ARRAY_SIZE(reset_src_names));
 
+	globalvar_add_simple_int("system.reset_instance", &reset_source_instance,
+				 "%d");
 	return 0;
 }
 
diff --git a/include/reset_source.h b/include/reset_source.h
index 3ff06b70a..c9911c008 100644
--- a/include/reset_source.h
+++ b/include/reset_source.h
@@ -27,6 +27,8 @@ enum reset_src_type {
 #ifdef CONFIG_RESET_SOURCE
 void reset_source_set_priority(enum reset_src_type, unsigned int priority);
 enum reset_src_type reset_source_get(void);
+void reset_source_set_instance(enum reset_src_type type, int instance);
+int reset_source_get_instance(void);
 unsigned int of_get_reset_source_priority(struct device_node *node);
 #else
 static inline void reset_source_set_priority(enum reset_src_type type,
@@ -34,11 +36,20 @@ static inline void reset_source_set_priority(enum reset_src_type type,
 {
 }
 
+static inline void reset_source_set_instance(enum reset_src_type type, int instance)
+{
+}
+
 static inline enum reset_src_type reset_source_get(void)
 {
 	return RESET_UKWN;
 }
 
+static inline int reset_source_get_instance(void)
+{
+	return 0;
+}
+
 static inline unsigned int of_get_reset_source_priority(struct device_node *node)
 {
 	return 0;
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:28 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:28 -0700
Subject: [PATCH v2 00/10] i.MX reset reason detection support
Message-ID: <20180421010538.16488-1-andrew.smirnov@gmail.com>

Everyone:

This patchset is the result of my work on adding support for detecting
and reporting reset reason as can be obtained from System Reset
Controller (to be more precise via SRSR register) on i.MX family of
SoC.

Currently list of supported SoC is as follows:

	  - i.MX6 (tested on i.MX6Q)
	  - i.MX7 (tested on i.MX7D)
	  - VFxxx (tested on VF610)


Changes since [v1]:

	- i.MX reset reason detection code was converted to do detect
          the source with bitmasking as opposed to having a switch
          statement, due to potential problems with the latter as was
          pointed out by Philipp in [thread1]

	- Change above also allowed to unify VFxxx and i.MX codepaths
          without the need to introduce a dedicated VFxxx centric
          function

[v1] http://lists.infradead.org/pipermail/barebox/2018-April/032614.html
[thread1] http://lists.infradead.org/pipermail/barebox/2018-April/032708.html

Feedback is wellcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (10):
  common: reset_source: Add the notion of "reset source instance"
  ARM: i.MX: Add infrastructure to record SoC reset reason
  ARM: i.MX6: Record reset reason as a part of startup
  ARM: i.MX7: Record reset reason as a part of startup
  common: reset_source: Introduce reset_source_name()
  ARM: i.MX: Log detected reset reason
  ARM: i.MX: Print "revision unknown" if that is the case
  ARM: VFxxx: Add code to detect cpu variant
  ARM: VFxxx: Detect cpu variant on start
  ARM: VFxxx: Record reset reason as a part of startup

 arch/arm/mach-imx/Makefile                    |  1 +
 arch/arm/mach-imx/imx.c                       | 43 ++++++++++++++++++-
 arch/arm/mach-imx/imx6.c                      | 13 +++++-
 arch/arm/mach-imx/imx7.c                      | 14 +++++++
 arch/arm/mach-imx/include/mach/generic.h      |  1 +
 arch/arm/mach-imx/include/mach/reset-reason.h | 37 +++++++++++++++++
 arch/arm/mach-imx/include/mach/vf610-regs.h   |  3 ++
 arch/arm/mach-imx/include/mach/vf610.h        | 51 +++++++++++++++++++++++
 arch/arm/mach-imx/vf610.c                     | 59 +++++++++++++++++++++++++++
 common/reset_source.c                         | 23 +++++++++++
 include/reset_source.h                        | 17 ++++++++
 11 files changed, 259 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h
 create mode 100644 arch/arm/mach-imx/include/mach/vf610.h
 create mode 100644 arch/arm/mach-imx/vf610.c

-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:34 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:34 -0700
Subject: [PATCH v2 06/10] ARM: i.MX: Log detected reset reason
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-7-andrew.smirnov@gmail.com>

Log detected reset reason as well as raw value of SRSR for better
clarity.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 29dad9a41..7dee1433b 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -179,4 +179,7 @@ void imx_set_reset_reason(void __iomem *srsr,
 	reset_source_set_priority(type,
 				  RESET_SOURCE_DEFAULT_PRIORITY + 1);
 	reset_source_set_instance(type, instance);
+
+	pr_info("i.MX reset reason %s (SRSR: 0x%08x)\n",
+		reset_source_name(), reg);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:35 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:35 -0700
Subject: [PATCH v2 07/10] ARM: i.MX: Print "revision unknown" if that is the
 case
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-8-andrew.smirnov@gmail.com>

Printing "revision 16.16" if i.MX SoC's revision is unknown is a bit
confusing so modify the code to actually say "revision unknown" in
such a case.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 7dee1433b..32d8e11a7 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -30,7 +30,10 @@ void imx_set_silicon_revision(const char *soc, int revision)
 {
 	__imx_silicon_revision = revision;
 
-	pr_info("detected %s revision %d.%d\n", soc,
+	if (revision == IMX_CHIP_REV_UNKNOWN)
+		pr_info("detected %s revision unknown\n", soc);
+	else
+		pr_info("detected %s revision %d.%d\n", soc,
 			(revision >> 4) & 0xf,
 			revision & 0xf);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:30 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:30 -0700
Subject: [PATCH v2 02/10] ARM: i.MX: Add infrastructure to record SoC reset
 reason
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-3-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c                       | 33 +++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/reset-reason.h | 25 ++++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 9400105c6..29dad9a41 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -14,8 +14,10 @@
 #include <common.h>
 #include <of.h>
 #include <init.h>
+#include <io.h>
 #include <mach/revision.h>
 #include <mach/generic.h>
+#include <mach/reset-reason.h>
 
 static int __imx_silicon_revision = IMX_CHIP_REV_UNKNOWN;
 
@@ -147,3 +149,34 @@ static int imx_init(void)
 	return ret;
 }
 postcore_initcall(imx_init);
+
+void imx_set_reset_reason(void __iomem *srsr,
+			  const struct imx_reset_reason *reasons)
+{
+	enum reset_src_type type = RESET_UKWN;
+	const u32 reg = readl(srsr);
+	int i, instance = 0;
+
+	/*
+	 * SRSR register captures ALL reset event that occured since
+	 * POR, so we need to clear it to make sure we only caputre
+	 * the latest one.
+	 */
+	writel(reg, srsr);
+
+	for (i = 0; reasons[i].mask; i++) {
+		if (reg & reasons[i].mask) {
+			type     = reasons[i].type;
+			instance = reasons[i].instance;
+			break;
+		}
+	}
+
+	/*
+	 * Report this with above default priority in order to make
+	 * sure we'll always override info from watchdog driver.
+	 */
+	reset_source_set_priority(type,
+				  RESET_SOURCE_DEFAULT_PRIORITY + 1);
+	reset_source_set_instance(type, instance);
+}
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
new file mode 100644
index 000000000..39afc4b28
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -0,0 +1,25 @@
+#ifndef __MACH_RESET_REASON_H__
+#define __MACH_RESET_REASON_H__
+
+#include <reset_source.h>
+
+#define IMX_SRC_SRSR_IPP_RESET		BIT(0)
+#define IMX_SRC_SRSR_CSU_RESET		BIT(1)
+#define IMX_SRC_SRSR_IPP_USER_RESET	BIT(3)
+#define IMX_SRC_SRSR_WDOG1_RESET	BIT(4)
+#define IMX_SRC_SRSR_JTAG_RESET		BIT(5)
+#define IMX_SRC_SRSR_JTAG_SW_RESET	BIT(6)
+#define IMX_SRC_SRSR_WDOG3_RESET	BIT(7)
+#define IMX_SRC_SRSR_WDOG4_RESET	BIT(8)
+#define IMX_SRC_SRSR_TEMPSENSE_RESET	BIT(9)
+#define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
+
+struct imx_reset_reason {
+	uint32_t mask;
+	enum reset_src_type type;
+	int instance;
+};
+
+void imx_set_reset_reason(void __iomem *, const struct imx_reset_reason *);
+
+#endif /* __MACH_RESET_REASON_H__ */
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:32 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:32 -0700
Subject: [PATCH v2 04/10] ARM: i.MX7: Record reset reason as a part of startup
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-5-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx7.c                      | 14 ++++++++++++++
 arch/arm/mach-imx/include/mach/reset-reason.h |  1 +
 2 files changed, 15 insertions(+)

diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c
index 4eef99c87..5ad91c2d7 100644
--- a/arch/arm/mach-imx/imx7.c
+++ b/arch/arm/mach-imx/imx7.c
@@ -19,6 +19,7 @@
 #include <mach/imx7.h>
 #include <mach/generic.h>
 #include <mach/revision.h>
+#include <mach/reset-reason.h>
 #include <mach/imx7-regs.h>
 
 void imx7_init_lowlevel(void)
@@ -167,10 +168,22 @@ static struct psci_ops imx7_psci_ops = {
 	.cpu_off = imx7_cpu_off,
 };
 
+static const struct imx_reset_reason imx7_reset_reasons[] = {
+	{ IMX_SRC_SRSR_IPP_RESET,       RESET_POR,   0 },
+	{ IMX_SRC_SRSR_WDOG1_RESET,     RESET_WDG,   0 },
+	{ IMX_SRC_SRSR_JTAG_RESET,      RESET_JTAG,  0 },
+	{ IMX_SRC_SRSR_JTAG_SW_RESET,   RESET_JTAG,  0 },
+	{ IMX_SRC_SRSR_WDOG3_RESET,     RESET_WDG,   1 },
+	{ IMX_SRC_SRSR_WDOG4_RESET,     RESET_WDG,   2 },
+	{ IMX_SRC_SRSR_TEMPSENSE_RESET, RESET_THERM, 0 },
+	{ /* sentinel */ }
+};
+
 int imx7_init(void)
 {
 	const char *cputypestr;
 	u32 imx7_silicon_revision;
+	void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR);
 
 	imx7_init_lowlevel();
 
@@ -197,6 +210,7 @@ int imx7_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, imx7_silicon_revision);
+	imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons);
 
 	return 0;
 }
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index f2544a303..96e52486c 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -15,6 +15,7 @@
 #define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
 
 #define IMX6_SRC_SRSR	0x008
+#define IMX7_SRC_SRSR	0x05c
 
 struct imx_reset_reason {
 	uint32_t mask;
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:31 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:31 -0700
Subject: [PATCH v2 03/10] ARM: i.MX6: Record reset reason as a part of startup
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-4-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx6.c                      | 13 ++++++++++++-
 arch/arm/mach-imx/include/mach/reset-reason.h |  2 ++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 88165adee..49610bf08 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -19,6 +19,7 @@
 #include <mach/imx6.h>
 #include <mach/generic.h>
 #include <mach/revision.h>
+#include <mach/reset-reason.h>
 #include <mach/imx6-anadig.h>
 #include <mach/imx6-regs.h>
 #include <mach/generic.h>
@@ -173,10 +174,20 @@ int imx6_cpu_revision(void)
 	return soc_revision;
 }
 
+static const struct imx_reset_reason imx6_reset_reasons[] = {
+	{ IMX_SRC_SRSR_IPP_RESET,     RESET_POR,  0 },
+	{ IMX_SRC_SRSR_WDOG1_RESET,   RESET_WDG,  0 },
+	{ IMX_SRC_SRSR_JTAG_RESET,    RESET_JTAG, 0 },
+	{ IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 },
+	{ IMX_SRC_SRSR_WARM_BOOT,     RESET_RST,  0 },
+	{ /* sentinel */ }
+};
+
 int imx6_init(void)
 {
 	const char *cputypestr;
 	u32 mx6_silicon_revision;
+	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
 
 	imx6_init_lowlevel();
 
@@ -221,7 +232,7 @@ int imx6_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
-
+	imx_set_reset_reason(src + IMX6_SRC_SRSR, imx6_reset_reasons);
 	imx6_setup_ipu_qos();
 	imx6ul_enet_clk_init();
 
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index 39afc4b28..f2544a303 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -14,6 +14,8 @@
 #define IMX_SRC_SRSR_TEMPSENSE_RESET	BIT(9)
 #define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
 
+#define IMX6_SRC_SRSR	0x008
+
 struct imx_reset_reason {
 	uint32_t mask;
 	enum reset_src_type type;
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:33 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:33 -0700
Subject: [PATCH v2 05/10] common: reset_source: Introduce reset_source_name()
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-6-andrew.smirnov@gmail.com>

Introduce reset_source_name() to get string representation of current
reset source.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 common/reset_source.c  | 6 ++++++
 include/reset_source.h | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/common/reset_source.c b/common/reset_source.c
index 6a6c4f5da..b2985ee85 100644
--- a/common/reset_source.c
+++ b/common/reset_source.c
@@ -60,6 +60,12 @@ void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
 }
 EXPORT_SYMBOL(reset_source_set_priority);
 
+const char *reset_source_name(void)
+{
+	return reset_src_names[reset_source];
+}
+EXPORT_SYMBOL(reset_source_name)
+
 void reset_source_set_instance(enum reset_src_type type, int instance)
 {
 	if (reset_source == type)
diff --git a/include/reset_source.h b/include/reset_source.h
index c9911c008..f9aed6a7a 100644
--- a/include/reset_source.h
+++ b/include/reset_source.h
@@ -30,6 +30,7 @@ enum reset_src_type reset_source_get(void);
 void reset_source_set_instance(enum reset_src_type type, int instance);
 int reset_source_get_instance(void);
 unsigned int of_get_reset_source_priority(struct device_node *node);
+const char *reset_source_name(void);
 #else
 static inline void reset_source_set_priority(enum reset_src_type type,
 		unsigned int priority)
@@ -54,6 +55,11 @@ static inline unsigned int of_get_reset_source_priority(struct device_node *node
 {
 	return 0;
 }
+
+const char *reset_source_name(void)
+{
+	return "unknown";
+}
 #endif
 
 #define RESET_SOURCE_DEFAULT_PRIORITY 100
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:36 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:36 -0700
Subject: [PATCH v2 08/10] ARM: VFxxx: Add code to detect cpu variant
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-9-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/include/mach/vf610-regs.h |  3 ++
 arch/arm/mach-imx/include/mach/vf610.h      | 51 +++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 arch/arm/mach-imx/include/mach/vf610.h

diff --git a/arch/arm/mach-imx/include/mach/vf610-regs.h b/arch/arm/mach-imx/include/mach/vf610-regs.h
index 87772ee76..416b457af 100644
--- a/arch/arm/mach-imx/include/mach/vf610-regs.h
+++ b/arch/arm/mach-imx/include/mach/vf610-regs.h
@@ -109,4 +109,7 @@
 #define VF610_MSCM_IRSPRC_CP0_EN	1
 #define VF610_MSCM_IRSPRC_NUM		112
 
+#define VF610_MSCM_CPxCOUNT		0x00c
+#define VF610_MSCM_CPxCFG1		0x014
+
 #endif
diff --git a/arch/arm/mach-imx/include/mach/vf610.h b/arch/arm/mach-imx/include/mach/vf610.h
new file mode 100644
index 000000000..6d00d2e45
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/vf610.h
@@ -0,0 +1,51 @@
+#ifndef __MACH_VF610_H
+#define __MACH_VF610_H
+
+#include <io.h>
+#include <mach/generic.h>
+#include <mach/vf610-regs.h>
+#include <mach/revision.h>
+
+#define VF610_CPUTYPE_VFx10	0x010
+
+#define VF610_CPUTYPE_VF610	0x610
+#define VF610_CPUTYPE_VF600	0x600
+#define VF610_CPUTYPE_VF510	0x510
+#define VF610_CPUTYPE_VF500	0x500
+
+#define VF610_ROM_VERSION_OFFSET	0x80
+
+static inline int __vf610_cpu_type(void)
+{
+	void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
+	const u32 cpxcount = readl(mscm + VF610_MSCM_CPxCOUNT);
+	const u32 cpxcfg1  = readl(mscm + VF610_MSCM_CPxCFG1);
+	int cpu_type;
+
+	cpu_type = cpxcount ? VF610_CPUTYPE_VF600 : VF610_CPUTYPE_VF500;
+
+	return cpxcfg1 ? cpu_type | VF610_CPUTYPE_VFx10 : cpu_type;
+}
+
+static inline int vf610_cpu_type(void)
+{
+	if (!cpu_is_vf610())
+		return 0;
+
+	return __vf610_cpu_type();
+}
+
+static inline int vf610_cpu_revision(void)
+{
+	if (!cpu_is_vf610())
+		return IMX_CHIP_REV_UNKNOWN;
+
+	/*
+	 * There doesn't seem to be a documented way of retreiving
+	 * silicon revision on VFxxx cpus, so we just report Mask ROM
+	 * version instead
+	 */
+	return readl(VF610_ROM_VERSION_OFFSET) & 0xff;
+}
+
+#endif
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:37 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:37 -0700
Subject: [PATCH v2 09/10] ARM: VFxxx: Detect cpu variant on start
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-10-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/Makefile               |  1 +
 arch/arm/mach-imx/imx.c                  |  2 +-
 arch/arm/mach-imx/include/mach/generic.h |  1 +
 arch/arm/mach-imx/vf610.c                | 47 ++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/vf610.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 8ec846cce..160ed4b08 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o
 CFLAGS_imx6.o := -march=armv7-a
 lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
 obj-$(CONFIG_ARCH_IMX7) += imx7.o
+obj-$(CONFIG_ARCH_VF610) += vf610.o
 obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o
 obj-$(CONFIG_IMX_IIM)	+= iim.o
 obj-$(CONFIG_IMX_OCOTP)	+= ocotp.o
diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 32d8e11a7..bf15f0b06 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -119,7 +119,7 @@ static int imx_init(void)
 	else if (cpu_is_mx7())
 		ret = imx7_init();
 	else if (cpu_is_vf610())
-		ret = 0;
+		ret = vf610_init();
 	else
 		return -EINVAL;
 
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index dedb4bbf0..ad9d9cb02 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -36,6 +36,7 @@ int imx51_init(void);
 int imx53_init(void);
 int imx6_init(void);
 int imx7_init(void);
+int vf610_init(void);
 
 int imx1_devices_init(void);
 int imx21_devices_init(void);
diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
new file mode 100644
index 000000000..c2d02632f
--- /dev/null
+++ b/arch/arm/mach-imx/vf610.c
@@ -0,0 +1,47 @@
+/*
+ * 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 <init.h>
+#include <common.h>
+#include <io.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <mach/revision.h>
+#include <mach/vf610.h>
+
+int vf610_init(void)
+{
+	const char *cputypestr;
+	void __iomem *src = IOMEM(VF610_SRC_BASE_ADDR);
+
+	switch (vf610_cpu_type()) {
+	case VF610_CPUTYPE_VF610:
+		cputypestr = "VF610";
+		break;
+	case VF610_CPUTYPE_VF600:
+		cputypestr = "VF600";
+		break;
+	case VF610_CPUTYPE_VF510:
+		cputypestr = "VF510";
+		break;
+	case VF610_CPUTYPE_VF500:
+		cputypestr = "VF500";
+		break;
+	default:
+		cputypestr = "unknown VFxxx";
+		break;
+	}
+
+	imx_set_silicon_revision(cputypestr, vf610_cpu_revision());
+	return 0;
+}
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:05:38 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:05:38 -0700
Subject: [PATCH v2 10/10] ARM: VFxxx: Record reset reason as a part of startup
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180421010538.16488-11-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/include/mach/reset-reason.h |  9 +++++++++
 arch/arm/mach-imx/vf610.c                     | 12 ++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index 96e52486c..4919f68d5 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -16,6 +16,15 @@
 
 #define IMX6_SRC_SRSR	0x008
 #define IMX7_SRC_SRSR	0x05c
+#define VF610_SRC_SRSR	0x008
+
+
+#define VF610_SRC_SRSR_SW_RST		BIT(18)
+#define VF610_SRC_SRSR_RESETB		BIT(7)
+#define VF610_SRC_SRSR_JTAG_RST		BIT(5)
+#define VF610_SRC_SRSR_WDOG_M4		BIT(4)
+#define VF610_SRC_SRSR_WDOG_A5		BIT(3)
+#define VF610_SRC_SRSR_POR_RST		BIT(0)
 
 struct imx_reset_reason {
 	uint32_t mask;
diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
index c2d02632f..df8cfcd6b 100644
--- a/arch/arm/mach-imx/vf610.c
+++ b/arch/arm/mach-imx/vf610.c
@@ -18,6 +18,17 @@
 #include <mach/generic.h>
 #include <mach/revision.h>
 #include <mach/vf610.h>
+#include <mach/reset-reason.h>
+
+static const struct imx_reset_reason vf610_reset_reasons[] = {
+	{ VF610_SRC_SRSR_POR_RST,       RESET_POR,   0 },
+	{ VF610_SRC_SRSR_WDOG_A5,       RESET_WDG,   0 },
+	{ VF610_SRC_SRSR_WDOG_M4,       RESET_WDG,   1 },
+	{ VF610_SRC_SRSR_JTAG_RST,      RESET_JTAG,  0 },
+	{ VF610_SRC_SRSR_RESETB,        RESET_EXT,   0 },
+	{ VF610_SRC_SRSR_SW_RST,        RESET_RST,   0 },
+	{ /* sentinel */ }
+};
 
 int vf610_init(void)
 {
@@ -43,5 +54,6 @@ int vf610_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, vf610_cpu_revision());
+	imx_set_reset_reason(src + VF610_SRC_SRSR, vf610_reset_reasons);
 	return 0;
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:33:36 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:33:36 -0700
Subject: [PATCH 0/2] Initial RAVE SP Linux driver port
Message-ID: <20180421013338.10115-1-andrew.smirnov@gmail.com>

Everyone:

These two patches are first results of an effort to port RAVE SP
(Supervisory Processor) MFD and it's children drivers from Linux
kernel to Barebox. Patch 1/2 brings MFD driver with its core API and
patch 2/2 adds support for watchdog "cell" of the RAVE SP device.

With a very few exceptions, the code of the drivers is identical to
the code of their Linux counterparts.

These drivers are also first users of "serdev" API work that was
recently merged and should server as a reasonable example of its
usage.

Feedback is wellcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (2):
  mfd: Port RAVE SP driver from Linux kernel
  watchdog: Port RAVE SP watchdog driver from Linux kernel

 drivers/mfd/Kconfig            |   8 +
 drivers/mfd/Makefile           |   1 +
 drivers/mfd/rave-sp.c          | 758 +++++++++++++++++++++++++++++++++++++++++
 drivers/watchdog/Kconfig       |   5 +
 drivers/watchdog/Makefile      |   1 +
 drivers/watchdog/rave-sp-wdt.c | 426 +++++++++++++++++++++++
 include/linux/mfd/rave-sp.h    |  78 +++++
 7 files changed, 1277 insertions(+)
 create mode 100644 drivers/mfd/rave-sp.c
 create mode 100644 drivers/watchdog/rave-sp-wdt.c
 create mode 100644 include/linux/mfd/rave-sp.h

-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:33:38 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:33:38 -0700
Subject: [PATCH 2/2] watchdog: Port RAVE SP watchdog driver from Linux kernel
In-Reply-To: <20180421013338.10115-1-andrew.smirnov@gmail.com>
References: <20180421013338.10115-1-andrew.smirnov@gmail.com>
Message-ID: <20180421013338.10115-3-andrew.smirnov@gmail.com>

Port RAVE SP watchdog driver from Linux kernel

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 drivers/watchdog/Kconfig       |   5 +
 drivers/watchdog/Makefile      |   1 +
 drivers/watchdog/rave-sp-wdt.c | 426 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 432 insertions(+)
 create mode 100644 drivers/watchdog/rave-sp-wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 1d6b15617..27e9f6d8b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -70,4 +70,9 @@ config WATCHDOG_BCM2835
 	help
 	  Add support for watchdog on the Broadcom BCM283X SoCs.
 
+config RAVE_SP_WATCHDOG
+	bool "RAVE SP Watchdog timer"
+	depends on RAVE_SP_CORE
+	help
+	  Support for the watchdog on RAVE SP device.
 endif
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 237640121..faf06110a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o
 obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o
 obj-$(CONFIG_WATCHDOG_ORION) += orion_wdt.o
 obj-$(CONFIG_ARCH_BCM283X) += bcm2835_wdt.o
+obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
diff --git a/drivers/watchdog/rave-sp-wdt.c b/drivers/watchdog/rave-sp-wdt.c
new file mode 100644
index 000000000..77d0195db
--- /dev/null
+++ b/drivers/watchdog/rave-sp-wdt.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Driver for watchdog aspect of for Zodiac Inflight Innovations RAVE
+ * Supervisory Processor(SP) MCU
+ *
+ * Copyright (C) 2018 Zodiac Inflight Innovation
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <of_device.h>
+#include <restart.h>
+#include <watchdog.h>
+
+#include <debug_ll.h>
+
+#include <linux/mfd/rave-sp.h>
+#include <linux/nvmem-consumer.h>
+
+enum {
+	RAVE_SP_RESET_BYTE = 1,
+	RAVE_SP_RESET_REASON_NORMAL         = 0,
+	RAVE_SP_RESET_REASON_HW_WATCHDOG    = 1,
+	RAVE_SP_RESET_REASON_SW_WATCHDOG    = 2,
+	RAVE_SP_RESET_REASON_VOLTAGE        = 3,
+	RAVE_SP_RESET_REASON_HOST_REQUEST   = 4,
+	RAVE_SP_RESET_REASON_TEMPERATURE    = 5,
+	RAVE_SP_RESET_REASON_BUTTON_PRESS   = 6,
+	RAVE_SP_RESET_REASON_PIC_CM         = 7,
+	RAVE_SP_RESET_REASON_PIC_ILL_INST   = 8,
+	RAVE_SP_RESET_REASON_PIC_TRAP       = 9,
+	RAVE_SP_RESET_REASON_UKNOWN_REASON  = 10,
+	RAVE_SP_RESET_REASON_THERMAL_SENSOR = 11,
+	RAVE_SP_RESET_REASON_SW_VOLTAGE     = 12,
+	RAVE_SP_RESET_REASON_CP_REQUEST     = 13,
+
+	RAVE_SP_RESET_DELAY_MS = 500,
+
+	RAVE_SP_BOOT_SOURCE_GET = 0,
+	RAVE_SP_BOOT_SOURCE_SET = 1,
+};
+
+/**
+ * struct rave_sp_wdt_variant - RAVE SP watchdog variant
+ *
+ * @max_timeout:	Largest possible watchdog timeout setting
+ * @min_timeout:	Smallest possible watchdog timeout setting
+ *
+ * @configure:		Function to send configuration command
+ * @restart:		Function to send "restart" command
+ */
+struct rave_sp_wdt_variant {
+	unsigned int max_timeout;
+	unsigned int min_timeout;
+
+	int (*configure)(struct watchdog *, bool);
+	int (*restart)(struct watchdog *);
+	int (*reset_reason)(struct watchdog *);
+};
+
+/**
+ * struct rave_sp_wdt - RAVE SP watchdog
+ *
+ * @wdd:		Underlying watchdog device
+ * @sp:			Pointer to parent RAVE SP device
+ * @variant:		Device specific variant information
+ * @reboot_notifier:	Reboot notifier implementing machine reset
+ */
+struct rave_sp_wdt {
+	struct watchdog wdd;
+	struct rave_sp *sp;
+	const struct rave_sp_wdt_variant *variant;
+	struct restart_handler restart;
+	unsigned int timeout;
+	unsigned int boot_source;
+	struct device_d dev;
+};
+
+static struct rave_sp_wdt *to_rave_sp_wdt(struct watchdog *wdd)
+{
+	return container_of(wdd, struct rave_sp_wdt, wdd);
+}
+
+static int rave_sp_wdt_exec(struct watchdog *wdd, void *data,
+			    size_t data_size)
+{
+	return rave_sp_exec(to_rave_sp_wdt(wdd)->sp,
+			    data, data_size, NULL, 0);
+}
+
+
+static int rave_sp_wdt_access_boot_source(struct rave_sp_wdt *sp_wd, u8 set_get)
+{
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_BOOT_SOURCE,
+		[1] = 0,
+		[2] = set_get,
+		[3] = sp_wd->boot_source,
+	};
+	u8 response;
+	int ret;
+
+	ret = rave_sp_exec(sp_wd->sp, cmd, sizeof(cmd), &response,
+			   sizeof(response));
+	if (ret)
+		return ret;
+
+	return response;
+}
+
+static int __rave_sp_wdt_rdu_reset_reason(struct watchdog *wdd,
+					  uint8_t response[],
+					  size_t response_len)
+{
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_RESET_REASON,
+		[1] = 0,
+	};
+	int ret;
+
+	ret = rave_sp_exec(to_rave_sp_wdt(wdd)->sp, cmd, sizeof(cmd),
+			   response, response_len);
+	if (ret)
+		return ret;
+	/*
+	 * Non "legacy" watchdog variants return 2 bytes as response
+	 * whereas "legacy" ones return only one. Both however send
+	 * the data we need as a first byte of the response.
+	 */
+	return response[0];
+}
+
+static int rave_sp_wdt_rdu_reset_reason(struct watchdog *wdd)
+{
+	u8 response[2];
+	return __rave_sp_wdt_rdu_reset_reason(wdd, response, sizeof(response));
+}
+
+static int rave_sp_wdt_legacy_reset_reason(struct watchdog *wdd)
+{
+	u8 response[1];
+	return __rave_sp_wdt_rdu_reset_reason(wdd, response, sizeof(response));
+}
+
+static int rave_sp_wdt_legacy_configure(struct watchdog *wdd, bool on)
+{
+	struct rave_sp_wdt *sp_wd = to_rave_sp_wdt(wdd);
+
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_SW_WDT,
+		[1] = 0,
+		[2] = 0,
+		[3] = on,
+		[4] = on ? sp_wd->timeout : 0,
+	};
+
+	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
+}
+
+static int rave_sp_wdt_rdu_configure(struct watchdog *wdd, bool on)
+{
+	struct rave_sp_wdt *sp_wd = to_rave_sp_wdt(wdd);
+
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_SW_WDT,
+		[1] = 0,
+		[2] = on,
+		[3] = sp_wd->timeout,
+		[4] = (u8)(sp_wd->timeout >> 8),
+	};
+
+	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
+}
+
+static int rave_sp_wdt_configure(struct watchdog *wdd, bool on)
+{
+	return to_rave_sp_wdt(wdd)->variant->configure(wdd, on);
+}
+
+static int rave_sp_wdt_legacy_restart(struct watchdog *wdd)
+{
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_RESET,
+		[1] = 0,
+		[2] = RAVE_SP_RESET_BYTE
+	};
+
+	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
+}
+
+static int rave_sp_wdt_rdu_restart(struct watchdog *wdd)
+{
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_RESET,
+		[1] = 0,
+		[2] = RAVE_SP_RESET_BYTE,
+		[3] = RAVE_SP_RESET_REASON_NORMAL
+	};
+
+	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
+}
+
+static void __noreturn rave_sp_wdt_restart_handler(struct restart_handler *rst)
+{
+	struct rave_sp_wdt *sp_wd =
+			container_of(rst, struct rave_sp_wdt, restart);
+
+	const int ret = sp_wd->variant->restart(&sp_wd->wdd);
+
+	if (ret < 0)
+		dev_err(&sp_wd->wdd.dev,
+			"Failed to issue restart command (%d)", ret);
+	/*
+	 * The actual work was done by reboot notifier above. SP
+	 * firmware waits 500 ms before issuing reset, so let's hang
+	 * here for twice that delay and hopefuly we'd never reach
+	 * the return statement.
+	 */
+	mdelay(2 * RAVE_SP_RESET_DELAY_MS);
+	hang();
+}
+
+static int rave_sp_wdt_start(struct watchdog *wdd)
+{
+	return rave_sp_wdt_configure(wdd, true);
+}
+
+static int rave_sp_wdt_stop(struct watchdog *wdd)
+{
+	return rave_sp_wdt_configure(wdd, false);
+}
+
+static int rave_sp_wdt_set_timeout(struct watchdog *wdd,
+				   unsigned int timeout)
+{
+	struct rave_sp_wdt *sp_wd = to_rave_sp_wdt(wdd);
+
+	if (timeout < sp_wd->variant->min_timeout ||
+	    timeout > sp_wd->variant->max_timeout)
+		return -EINVAL;
+
+	if (!timeout)
+		return rave_sp_wdt_stop(wdd);
+
+	sp_wd->timeout = timeout;
+	return rave_sp_wdt_start(wdd);
+}
+
+static const struct rave_sp_wdt_variant rave_sp_wdt_legacy = {
+	.max_timeout  = 255,
+	.min_timeout  = 1,
+	.configure    = rave_sp_wdt_legacy_configure,
+	.restart      = rave_sp_wdt_legacy_restart,
+	.reset_reason = rave_sp_wdt_legacy_reset_reason,
+};
+
+static const struct rave_sp_wdt_variant rave_sp_wdt_rdu = {
+	.max_timeout  = 180,
+	.min_timeout  = 60,
+	.configure    = rave_sp_wdt_rdu_configure,
+	.restart      = rave_sp_wdt_rdu_restart,
+	.reset_reason = rave_sp_wdt_rdu_reset_reason,
+};
+
+static const struct of_device_id rave_sp_wdt_of_match[] = {
+	{
+		.compatible = "zii,rave-sp-watchdog-legacy",
+		.data = &rave_sp_wdt_legacy,
+	},
+	{
+		.compatible = "zii,rave-sp-watchdog",
+		.data = &rave_sp_wdt_rdu,
+	},
+	{ /* sentinel */ }
+};
+
+static int rave_sp_wdt_set_boot_source(struct param_d *param, void *priv)
+{
+	int ret;
+
+	ret = rave_sp_wdt_access_boot_source(priv, RAVE_SP_BOOT_SOURCE_SET);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rave_sp_wdt_get_boot_source(struct param_d *param, void *priv)
+{
+	struct rave_sp_wdt *sp_wd = priv;
+	int ret;
+
+	ret = rave_sp_wdt_access_boot_source(sp_wd, RAVE_SP_BOOT_SOURCE_GET);
+	if (ret < 0)
+		return ret;
+
+	sp_wd->boot_source = ret;
+	return 0;
+}
+
+static int rave_sp_wdt_probe(struct device_d *dev)
+{
+	struct rave_sp_wdt *sp_wd;
+	const char *reset_reason;
+	struct nvmem_cell *cell;
+	struct watchdog *wdd;
+	__le16 timeout = 60;
+	struct param_d *p;
+	int ret;
+
+	sp_wd = xzalloc(sizeof(*sp_wd));
+	sp_wd->variant = of_device_get_match_data(dev);
+	sp_wd->sp      = dev->parent->priv;
+
+	cell = nvmem_cell_get(dev, "wdt-timeout");
+	if (!IS_ERR(cell)) {
+		size_t len;
+		void *value = nvmem_cell_read(cell, &len);
+
+		if (!IS_ERR(value)) {
+			memcpy(&timeout, value, min(len, sizeof(timeout)));
+			kfree(value);
+		}
+		nvmem_cell_put(cell);
+	}
+	sp_wd->timeout = le16_to_cpu(timeout);
+
+	wdd              = &sp_wd->wdd;
+	wdd->hwdev       = dev;
+	wdd->set_timeout = rave_sp_wdt_set_timeout;
+
+	ret = rave_sp_wdt_stop(wdd);
+	if (ret) {
+		dev_err(dev, "Failed to stop watchdog device\n");
+		return ret;
+	}
+
+	ret = watchdog_register(wdd);
+	if (ret) {
+		dev_err(dev, "Failed to register watchdog device\n");
+
+		return ret;
+	}
+
+	sp_wd->restart.name = "rave-sp-wdt";
+	sp_wd->restart.restart = rave_sp_wdt_restart_handler;
+	sp_wd->restart.priority = 200;
+
+	ret = restart_handler_register(&sp_wd->restart);
+	if (ret)
+		dev_warn(dev, "Cannot register restart handler\n");
+
+
+	p = dev_add_param_int(&wdd->dev, "boot_source",
+			      rave_sp_wdt_set_boot_source,
+			      rave_sp_wdt_get_boot_source,
+			      &sp_wd->boot_source, "%u", sp_wd);
+	if (IS_ERR(p)) {
+		unregister_device(&sp_wd->dev);
+		return PTR_ERR(p);
+	}
+
+	ret = sp_wd->variant->reset_reason(wdd);
+	if (ret < 0) {
+		dev_warn(dev, "Failed to query reset reason\n");
+		return 0;
+	}
+
+	switch (ret) {
+	case RAVE_SP_RESET_REASON_NORMAL:
+		reset_reason = "Normal poweroff";
+		break;
+	case RAVE_SP_RESET_REASON_HW_WATCHDOG:
+		reset_reason = "PIC hardware watchdog";
+		break;
+	case RAVE_SP_RESET_REASON_SW_WATCHDOG:
+		reset_reason = "PIC software watchdog";
+		break;
+	case RAVE_SP_RESET_REASON_VOLTAGE:
+		reset_reason = "Input voltage out of range";
+		break;
+	case RAVE_SP_RESET_REASON_HOST_REQUEST:
+		reset_reason = "Host requested";
+		break;
+	case RAVE_SP_RESET_REASON_TEMPERATURE:
+		reset_reason = "Temperature out of range";
+		break;
+	case RAVE_SP_RESET_REASON_BUTTON_PRESS:
+		reset_reason = "User requested";
+		break;
+	case RAVE_SP_RESET_REASON_PIC_CM:
+		reset_reason = "Illegal configuration word";
+		break;
+	case RAVE_SP_RESET_REASON_PIC_ILL_INST:
+		reset_reason = "Illegal instruction";
+		break;
+	case RAVE_SP_RESET_REASON_PIC_TRAP:
+		reset_reason = "Illegal trap";
+		break;
+	default:
+	case RAVE_SP_RESET_REASON_UKNOWN_REASON:
+		reset_reason = "Unknown";
+		break;
+	case RAVE_SP_RESET_REASON_THERMAL_SENSOR:
+		reset_reason = "Thermal sensor";
+		break;
+	case RAVE_SP_RESET_REASON_SW_VOLTAGE:
+		reset_reason = "Software detected brownout";
+		break;
+	case RAVE_SP_RESET_REASON_CP_REQUEST:
+		reset_reason = "Command request";
+		break;
+	}
+
+	dev_info(dev, "Reset reason: %s\n", reset_reason);
+	return 0;
+}
+
+static struct driver_d rave_sp_wdt_driver = {
+	.name  = "rave-sp-wdt",
+	.probe = rave_sp_wdt_probe,
+	.of_compatible = DRV_OF_COMPAT(rave_sp_wdt_of_match),
+};
+console_platform_driver(rave_sp_wdt_driver);
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:33:37 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:33:37 -0700
Subject: [PATCH 1/2] mfd: Port RAVE SP driver from Linux kernel
In-Reply-To: <20180421013338.10115-1-andrew.smirnov@gmail.com>
References: <20180421013338.10115-1-andrew.smirnov@gmail.com>
Message-ID: <20180421013338.10115-2-andrew.smirnov@gmail.com>

Port MFD driver for RAVE SP from Linux kernel.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 drivers/mfd/Kconfig         |   8 +
 drivers/mfd/Makefile        |   1 +
 drivers/mfd/rave-sp.c       | 758 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/rave-sp.h |  78 +++++
 4 files changed, 845 insertions(+)
 create mode 100644 drivers/mfd/rave-sp.c
 create mode 100644 include/linux/mfd/rave-sp.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 521cf042a..d04431fbc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -53,4 +53,12 @@ config MFD_TWL6030
 	select MFD_TWLCORE
 	bool "TWL6030 driver"
 
+config RAVE_SP_CORE
+	tristate "RAVE SP MCU core driver"
+	depends on SERIAL_DEV_BUS
+	select CRC_CCITT
+	help
+	  Select this to get support for the Supervisory Processor
+	  device found on several devices in RAVE line of hardware.
+
 endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 041915a7c..8b23a1023 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_TWLCORE)	+= twl-core.o
 obj-$(CONFIG_MFD_TWL4030)	+= twl4030.o
 obj-$(CONFIG_MFD_TWL6030)	+= twl6030.o
+obj-$(CONFIG_RAVE_SP_CORE)	+= rave-sp.o
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
new file mode 100644
index 000000000..d55e913ff
--- /dev/null
+++ b/drivers/mfd/rave-sp.c
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Multifunction core driver for Zodiac Inflight Innovations RAVE
+ * Supervisory Processor(SP) MCU that is connected via dedicated UART
+ * port
+ *
+ * Copyright (C) 2017 Zodiac Inflight Innovations
+ */
+
+#include <common.h>
+#include <init.h>
+#include <of_device.h>
+
+#include <asm/unaligned.h>
+
+#include <linux/crc-ccitt.h>
+#include <linux/mfd/rave-sp.h>
+
+#define DUMP_PREFIX_NONE 0
+
+/*
+ * UART protocol using following entities:
+ *  - message to MCU => ACK response
+ *  - event from MCU => event ACK
+ *
+ * Frame structure:
+ * <STX> <DATA> <CHECKSUM> <ETX>
+ * Where:
+ * - STX - is start of transmission character
+ * - ETX - end of transmission
+ * - DATA - payload
+ * - CHECKSUM - checksum calculated on <DATA>
+ *
+ * If <DATA> or <CHECKSUM> contain one of control characters, then it is
+ * escaped using <DLE> control code. Added <DLE> does not participate in
+ * checksum calculation.
+ */
+#define RAVE_SP_STX			0x02
+#define RAVE_SP_ETX			0x03
+#define RAVE_SP_DLE			0x10
+
+#define RAVE_SP_MAX_DATA_SIZE		64
+#define RAVE_SP_CHECKSUM_SIZE		2  /* Worst case scenario on RDU2 */
+/*
+ * We don't store STX, ETX and unescaped bytes, so Rx is only
+ * DATA + CSUM
+ */
+#define RAVE_SP_RX_BUFFER_SIZE				\
+	(RAVE_SP_MAX_DATA_SIZE + RAVE_SP_CHECKSUM_SIZE)
+
+#define RAVE_SP_STX_ETX_SIZE		2
+/*
+ * For Tx we have to have space for everything, STX, EXT and
+ * potentially stuffed DATA + CSUM data + csum
+ */
+#define RAVE_SP_TX_BUFFER_SIZE				\
+	(RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
+
+#define RAVE_SP_BOOT_SOURCE_GET		0
+#define RAVE_SP_BOOT_SOURCE_SET		1
+
+#define RAVE_SP_RDU2_BOARD_TYPE_RMB	0
+#define RAVE_SP_RDU2_BOARD_TYPE_DEB	1
+
+#define RAVE_SP_BOOT_SOURCE_SD		0
+#define RAVE_SP_BOOT_SOURCE_EMMC	1
+#define RAVE_SP_BOOT_SOURCE_NOR		2
+
+/**
+ * enum rave_sp_deframer_state - Possible state for de-framer
+ *
+ * @RAVE_SP_EXPECT_SOF:		 Scanning input for start-of-frame marker
+ * @RAVE_SP_EXPECT_DATA:	 Got start of frame marker, collecting frame
+ * @RAVE_SP_EXPECT_ESCAPED_DATA: Got escape character, collecting escaped byte
+ */
+enum rave_sp_deframer_state {
+	RAVE_SP_EXPECT_SOF,
+	RAVE_SP_EXPECT_DATA,
+	RAVE_SP_EXPECT_ESCAPED_DATA,
+};
+
+/**
+ * struct rave_sp_deframer - Device protocol deframer
+ *
+ * @state:  Current state of the deframer
+ * @data:   Buffer used to collect deframed data
+ * @length: Number of bytes de-framed so far
+ */
+struct rave_sp_deframer {
+	enum rave_sp_deframer_state state;
+	unsigned char data[RAVE_SP_RX_BUFFER_SIZE];
+	size_t length;
+};
+
+/**
+ * struct rave_sp_reply - Reply as per RAVE device protocol
+ *
+ * @length:	Expected reply length
+ * @data:	Buffer to store reply payload in
+ * @code:	Expected reply code
+ * @ackid:	Expected reply ACK ID
+ * @completion: Successful reply reception completion
+ */
+struct rave_sp_reply {
+	size_t length;
+	void  *data;
+	u8     code;
+	u8     ackid;
+
+	bool   received;
+};
+
+/**
+ * struct rave_sp_checksum - Variant specific checksum implementation details
+ *
+ * @length:	Caculated checksum length
+ * @subroutine:	Utilized checksum algorithm implementation
+ */
+struct rave_sp_checksum {
+	size_t length;
+	void (*subroutine)(const u8 *, size_t, u8 *);
+};
+
+/**
+ * struct rave_sp_variant_cmds - Variant specific command routines
+ *
+ * @translate:	Generic to variant specific command mapping routine
+ */
+struct rave_sp_variant_cmds {
+	int (*translate)(enum rave_sp_command);
+};
+
+/**
+ * struct rave_sp_variant - RAVE supervisory processor core variant
+ *
+ * @checksum:	Variant specific checksum implementation
+ * @cmd:	Variant specific command pointer table
+ *
+ */
+struct rave_sp_variant {
+	const struct rave_sp_checksum *checksum;
+	struct rave_sp_variant_cmds cmd;
+};
+
+/**
+ * struct rave_sp - RAVE supervisory processor core
+ *
+ * @serdev:			Pointer to underlying serdev
+ * @deframer:			Stored state of the protocol deframer
+ * @ackid:			ACK ID used in last reply sent to the device
+ * @bus_lock:			Lock to serialize access to the device
+ * @reply_lock:			Lock protecting @reply
+ * @reply:			Pointer to memory to store reply payload
+ *
+ * @variant:			Device variant specific information
+ * @event_notifier_list:	Input event notification chain
+ *
+ * @part_number_firmware:	Firmware version
+ * @part_number_bootloader:	Bootloader version
+ */
+struct rave_sp {
+	struct serdev_device *serdev;
+	struct rave_sp_deframer deframer;
+	unsigned int ackid;
+	struct rave_sp_reply *reply;
+
+	const struct rave_sp_variant *variant;
+
+	const char *part_number_firmware;
+	const char *part_number_bootloader;
+};
+
+struct rave_sp_version {
+	u8     hardware;
+	__le16 major;
+	u8     minor;
+	u8     letter[2];
+} __packed;
+
+struct rave_sp_status {
+	struct rave_sp_version bootloader_version;
+	struct rave_sp_version firmware_version;
+	u16 rdu_eeprom_flag;
+	u16 dds_eeprom_flag;
+	u8  pic_flag;
+	u8  orientation;
+	u32 etc;
+	s16 temp[2];
+	u8  backlight_current[3];
+	u8  dip_switch;
+	u8  host_interrupt;
+	u16 voltage_28;
+	u8  i2c_device_status;
+	u8  power_status;
+	u8  general_status;
+#define RAVE_SP_STATUS_GS_FIRMWARE_MODE	BIT(1)
+
+	u8  deprecated1;
+	u8  power_led_status;
+	u8  deprecated2;
+	u8  periph_power_shutoff;
+} __packed;
+
+static bool rave_sp_id_is_event(u8 code)
+{
+	return (code & 0xF0) == RAVE_SP_EVNT_BASE;
+}
+
+static void csum_8b2c(const u8 *buf, size_t size, u8 *crc)
+{
+	*crc = *buf++;
+	size--;
+
+	while (size--)
+		*crc += *buf++;
+
+	*crc = 1 + ~(*crc);
+}
+
+static void csum_ccitt(const u8 *buf, size_t size, u8 *crc)
+{
+	const u16 calculated = crc_ccitt_false(0xffff, buf, size);
+
+	/*
+	 * While the rest of the wire protocol is little-endian,
+	 * CCITT-16 CRC in RDU2 device is sent out in big-endian order.
+	 */
+	put_unaligned_be16(calculated, crc);
+}
+
+static void *stuff(unsigned char *dest, const unsigned char *src, size_t n)
+{
+	while (n--) {
+		const unsigned char byte = *src++;
+
+		switch (byte) {
+		case RAVE_SP_STX:
+		case RAVE_SP_ETX:
+		case RAVE_SP_DLE:
+			*dest++ = RAVE_SP_DLE;
+			/* FALLTHROUGH */
+		default:
+			*dest++ = byte;
+		}
+	}
+
+	return dest;
+}
+
+static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
+{
+	const size_t checksum_length = sp->variant->checksum->length;
+	unsigned char frame[RAVE_SP_TX_BUFFER_SIZE];
+	unsigned char crc[RAVE_SP_CHECKSUM_SIZE];
+	unsigned char *dest = frame;
+	size_t length;
+
+	if (WARN_ON(checksum_length > sizeof(crc)))
+		return -ENOMEM;
+
+	if (WARN_ON(data_size > sizeof(frame)))
+		return -ENOMEM;
+
+	sp->variant->checksum->subroutine(data, data_size, crc);
+
+	*dest++ = RAVE_SP_STX;
+	dest = stuff(dest, data, data_size);
+	dest = stuff(dest, crc, checksum_length);
+	*dest++ = RAVE_SP_ETX;
+
+	length = dest - frame;
+
+	if (IS_ENABLED(DEBUG))
+		print_hex_dump(0, "rave-sp tx: ", DUMP_PREFIX_NONE,
+			       16, 1, frame, length, false);
+
+	return serdev_device_write(sp->serdev, frame, length, SECOND);
+}
+
+static u8 rave_sp_reply_code(u8 command)
+{
+	/*
+	 * There isn't a single rule that describes command code ->
+	 * ACK code transformation, but, going through various
+	 * versions of ICDs, there appear to be three distinct groups
+	 * that can be described by simple transformation.
+	 */
+	switch (command) {
+	case 0xA0 ... 0xBE:
+		/*
+		 * Commands implemented by firmware found in RDU1 and
+		 * older devices all seem to obey the following rule
+		 */
+		return command + 0x20;
+	case 0xE0 ... 0xEF:
+		/*
+		 * Events emitted by all versions of the firmare use
+		 * least significant bit to get an ACK code
+		 */
+		return command | 0x01;
+	default:
+		/*
+		 * Commands implemented by firmware found in RDU2 are
+		 * similar to "old" commands, but they use slightly
+		 * different offset
+		 */
+		return command + 0x40;
+	}
+}
+
+int rave_sp_exec(struct rave_sp *sp,
+		 void *__data,  size_t data_size,
+		 void *reply_data, size_t reply_data_size)
+{
+	struct device_d *dev = sp->serdev->dev;
+	struct rave_sp_reply reply = {
+		.data     = reply_data,
+		.length   = reply_data_size,
+		.received = false,
+	};
+	unsigned char *data = __data;
+	int command, ret = 0;
+	u8 ackid;
+	uint64_t start = get_time_ns();
+
+	command = sp->variant->cmd.translate(data[0]);
+	if (command < 0)
+		return command;
+
+	ackid       = sp->ackid++;
+	reply.ackid = ackid;
+	reply.code  = rave_sp_reply_code((u8)command),
+
+	sp->reply = &reply;
+
+	data[0] = command;
+	data[1] = ackid;
+
+	rave_sp_write(sp, data, data_size);
+	/*
+	 * is_timeout will implicitly poll serdev via poller
+	 * infrastructure
+	 */
+	while (!is_timeout(start, SECOND) && !reply.received)
+		;
+
+	if (!reply.received) {
+		dev_err(dev, "Command timeout\n");
+		ret = -ETIMEDOUT;
+		sp->reply = NULL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rave_sp_exec);
+
+static void rave_sp_receive_event(struct rave_sp *sp,
+				  const unsigned char *data, size_t length)
+{
+	u8 cmd[] = {
+		[0] = rave_sp_reply_code(data[0]),
+		[1] = data[1],
+	};
+
+	/*
+	 * The only thing we do for event, in case we get one, is to
+	 * acknowledge it to prevent RAVE SP from spamming us
+	 */
+	rave_sp_write(sp, cmd, sizeof(cmd));
+}
+
+static void rave_sp_receive_reply(struct rave_sp *sp,
+				  const unsigned char *data, size_t length)
+{
+	struct device_d *dev = sp->serdev->dev;
+	struct rave_sp_reply *reply;
+	const  size_t payload_length = length - 2;
+
+	reply = sp->reply;
+
+	if (reply) {
+		if (reply->code == data[0] && reply->ackid == data[1] &&
+		    payload_length >= reply->length) {
+			/*
+			 * We are relying on memcpy(dst, src, 0) to be a no-op
+			 * when handling commands that have a no-payload reply
+			 */
+			memcpy(reply->data, &data[2], reply->length);
+			reply->received = true;
+			sp->reply = NULL;
+		} else {
+			dev_err(dev, "Ignoring incorrect reply\n");
+			dev_dbg(dev, "Code:   expected = 0x%08x received = 0x%08x\n",
+				reply->code, data[0]);
+			dev_dbg(dev, "ACK ID: expected = 0x%08x received = 0x%08x\n",
+				reply->ackid, data[1]);
+			dev_dbg(dev, "Length: expected = %zu received = %zu\n",
+				reply->length, payload_length);
+		}
+	}
+
+}
+
+static void rave_sp_receive_frame(struct rave_sp *sp,
+				  const unsigned char *data,
+				  size_t length)
+{
+	const size_t checksum_length = sp->variant->checksum->length;
+	const size_t payload_length  = length - checksum_length;
+	const u8 *crc_reported       = &data[payload_length];
+	struct device_d *dev         = sp->serdev->dev;
+	u8 crc_calculated[checksum_length];
+
+	if (IS_ENABLED(DEBUG))
+		print_hex_dump(0, "rave-sp rx: ", DUMP_PREFIX_NONE,
+			       16, 1, data, length, false);
+
+	if (unlikely(length <= checksum_length)) {
+		dev_warn(dev, "Dropping short frame\n");
+		return;
+	}
+
+	sp->variant->checksum->subroutine(data, payload_length,
+					  crc_calculated);
+
+	if (memcmp(crc_calculated, crc_reported, checksum_length)) {
+		dev_warn(dev, "Dropping bad frame\n");
+		return;
+	}
+
+	if (rave_sp_id_is_event(data[0]))
+		rave_sp_receive_event(sp, data, length);
+	else
+		rave_sp_receive_reply(sp, data, length);
+}
+
+static int rave_sp_receive_buf(struct serdev_device *serdev,
+			       const unsigned char *buf, size_t size)
+{
+	struct device_d *dev = serdev->dev;
+	struct rave_sp *sp = dev->priv;
+	struct rave_sp_deframer *deframer = &sp->deframer;
+	const unsigned char *src = buf;
+	const unsigned char *end = buf + size;
+
+	while (src < end) {
+		const unsigned char byte = *src++;
+
+		switch (deframer->state) {
+		case RAVE_SP_EXPECT_SOF:
+			if (byte == RAVE_SP_STX)
+				deframer->state = RAVE_SP_EXPECT_DATA;
+			break;
+
+		case RAVE_SP_EXPECT_DATA:
+			/*
+			 * Treat special byte values first
+			 */
+			switch (byte) {
+			case RAVE_SP_ETX:
+				rave_sp_receive_frame(sp,
+						      deframer->data,
+						      deframer->length);
+				/*
+				 * Once we extracted a complete frame
+				 * out of a stream, we call it done
+				 * and proceed to bailing out while
+				 * resetting the framer to initial
+				 * state, regardless if we've consumed
+				 * all of the stream or not.
+				 */
+				goto reset_framer;
+			case RAVE_SP_STX:
+				dev_warn(dev, "Bad frame: STX before ETX\n");
+				/*
+				 * If we encounter second "start of
+				 * the frame" marker before seeing
+				 * corresponding "end of frame", we
+				 * reset the framer and ignore both:
+				 * frame started by first SOF and
+				 * frame started by current SOF.
+				 *
+				 * NOTE: The above means that only the
+				 * frame started by third SOF, sent
+				 * after this one will have a chance
+				 * to get throught.
+				 */
+				goto reset_framer;
+			case RAVE_SP_DLE:
+				deframer->state = RAVE_SP_EXPECT_ESCAPED_DATA;
+				/*
+				 * If we encounter escape sequence we
+				 * need to skip it and collect the
+				 * byte that follows. We do it by
+				 * forcing the next iteration of the
+				 * encompassing while loop.
+				 */
+				continue;
+			}
+			/*
+			 * For the rest of the bytes, that are not
+			 * speical snoflakes, we do the same thing
+			 * that we do to escaped data - collect it in
+			 * deframer buffer
+			 */
+
+			/* FALLTHROUGH */
+
+		case RAVE_SP_EXPECT_ESCAPED_DATA:
+			if (deframer->length == sizeof(deframer->data)) {
+				dev_warn(dev, "Bad frame: Too long\n");
+				/*
+				 * If the amount of data we've
+				 * accumulated for current frame so
+				 * far starts to exceed the capacity
+				 * of deframer's buffer, there's
+				 * nothing else we can do but to
+				 * discard that data and start
+				 * assemblying a new frame again
+				 */
+				goto reset_framer;
+			}
+
+			deframer->data[deframer->length++] = byte;
+
+			/*
+			 * We've extracted out special byte, now we
+			 * can go back to regular data collecting
+			 */
+			deframer->state = RAVE_SP_EXPECT_DATA;
+			break;
+		}
+	}
+
+	/*
+	 * The only way to get out of the above loop and end up here
+	 * is throught consuming all of the supplied data, so here we
+	 * report that we processed it all.
+	 */
+	return size;
+
+reset_framer:
+	/*
+	 * NOTE: A number of codepaths that will drop us here will do
+	 * so before consuming all 'size' bytes of the data passed by
+	 * serdev layer. We rely on the fact that serdev layer will
+	 * re-execute this handler with the remainder of the Rx bytes
+	 * once we report actual number of bytes that we processed.
+	 */
+	deframer->state  = RAVE_SP_EXPECT_SOF;
+	deframer->length = 0;
+
+	return src - buf;
+}
+
+static int rave_sp_rdu1_cmd_translate(enum rave_sp_command command)
+{
+	if (command >= RAVE_SP_CMD_STATUS &&
+	    command <= RAVE_SP_CMD_CONTROL_EVENTS)
+		return command;
+
+	return -EINVAL;
+}
+
+static int rave_sp_rdu2_cmd_translate(enum rave_sp_command command)
+{
+	if (command >= RAVE_SP_CMD_GET_FIRMWARE_VERSION &&
+	    command <= RAVE_SP_CMD_GET_GPIO_STATE)
+		return command;
+
+	if (command == RAVE_SP_CMD_REQ_COPPER_REV) {
+		/*
+		 * As per RDU2 ICD 3.4.47 CMD_GET_COPPER_REV code is
+		 * different from that for RDU1 and it is set to 0x28.
+		 */
+		return 0x28;
+	}
+
+	return rave_sp_rdu1_cmd_translate(command);
+}
+
+static int rave_sp_default_cmd_translate(enum rave_sp_command command)
+{
+	/*
+	 * All of the following command codes were taken from "Table :
+	 * Communications Protocol Message Types" in section 3.3
+	 * "MESSAGE TYPES" of Rave PIC24 ICD.
+	 */
+	switch (command) {
+	case RAVE_SP_CMD_GET_FIRMWARE_VERSION:
+		return 0x11;
+	case RAVE_SP_CMD_GET_BOOTLOADER_VERSION:
+		return 0x12;
+	case RAVE_SP_CMD_BOOT_SOURCE:
+		return 0x14;
+	case RAVE_SP_CMD_SW_WDT:
+		return 0x1C;
+	case RAVE_SP_CMD_RESET:
+		return 0x1E;
+	case RAVE_SP_CMD_RESET_REASON:
+		return 0x1F;
+	case RAVE_SP_CMD_BOOTLOADER:
+		return 0x2A;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const char *devm_rave_sp_version(struct device_d *dev,
+					struct rave_sp_version *version)
+{
+       /*
+        * NOTE: The format string below uses %02d to display u16
+        * intentionally for the sake of backwards compatibility with
+        * legacy software.
+        */
+       return basprintf("%02d%02d%02d.%c%c\n",
+			version->hardware,
+			le16_to_cpu(version->major),
+			version->minor,
+			version->letter[0],
+			version->letter[1]);
+}
+
+static int rave_sp_get_status(struct rave_sp *sp)
+{
+	struct device_d *dev = sp->serdev->dev;
+	u8 cmd[] = {
+		[0] = RAVE_SP_CMD_STATUS,
+		[1] = 0
+	};
+	struct rave_sp_status status;
+	const char *mode;
+	int ret;
+
+	ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
+	if (ret)
+		return ret;
+
+	if (status.general_status & RAVE_SP_STATUS_GS_FIRMWARE_MODE)
+		mode = "Application";
+	else
+		mode = "Bootloader";
+
+	dev_info(dev, "Device is in %s mode\n", mode);
+
+	sp->part_number_firmware   = devm_rave_sp_version(dev,
+						   &status.firmware_version);
+	sp->part_number_bootloader = devm_rave_sp_version(dev,
+						   &status.bootloader_version);
+	return 0;
+}
+
+static const struct rave_sp_checksum rave_sp_checksum_8b2c = {
+	.length     = 1,
+	.subroutine = csum_8b2c,
+};
+
+static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
+	.length     = 2,
+	.subroutine = csum_ccitt,
+};
+
+static const struct rave_sp_variant rave_sp_legacy = {
+	.checksum = &rave_sp_checksum_8b2c,
+	.cmd = {
+		.translate = rave_sp_default_cmd_translate,
+	},
+};
+
+static const struct rave_sp_variant rave_sp_rdu1 = {
+	.checksum = &rave_sp_checksum_8b2c,
+	.cmd = {
+		.translate = rave_sp_rdu1_cmd_translate,
+	},
+};
+
+static const struct rave_sp_variant rave_sp_rdu2 = {
+	.checksum = &rave_sp_checksum_ccitt,
+	.cmd = {
+		.translate = rave_sp_rdu2_cmd_translate,
+	},
+};
+
+static const struct of_device_id __maybe_unused rave_sp_dt_ids[] = {
+	{ .compatible = "zii,rave-sp-niu",  .data = &rave_sp_legacy },
+	{ .compatible = "zii,rave-sp-mezz", .data = &rave_sp_legacy },
+	{ .compatible = "zii,rave-sp-esb",  .data = &rave_sp_legacy },
+	{ .compatible = "zii,rave-sp-rdu1", .data = &rave_sp_rdu1   },
+	{ .compatible = "zii,rave-sp-rdu2", .data = &rave_sp_rdu2   },
+	{ /* sentinel */ }
+};
+
+static int rave_sp_probe(struct device_d *dev)
+{
+	struct serdev_device *serdev = to_serdev_device(dev->parent);
+	struct rave_sp *sp;
+	u32 baud;
+	int ret;
+
+	if (of_property_read_u32(dev->device_node, "current-speed", &baud)) {
+		dev_err(dev,
+			"'current-speed' is not specified in device node\n");
+		return -EINVAL;
+	}
+
+	sp = xzalloc(sizeof(*sp));
+	sp->serdev = serdev;
+	dev->priv = sp;
+	serdev->dev = dev;
+	serdev->receive_buf = rave_sp_receive_buf;
+	serdev->polling_interval = 500 * MSECOND;
+	/*
+	 * We have to set polling window to 200ms initially in order
+	 * to avoid timing out on get_status below when coming out of
+	 * power-cycle induced reset. It's adjusted right after
+	 */
+	serdev->polling_window = 200 * MSECOND;
+
+	sp->variant = of_device_get_match_data(dev);
+	if (!sp->variant)
+		return -ENODEV;
+
+	ret = serdev_device_open(serdev);
+	if (ret)
+		return ret;
+
+	serdev_device_set_baudrate(serdev, baud);
+
+	ret = rave_sp_get_status(sp);
+	if (ret) {
+		dev_warn(dev, "Failed to get firmware status: %d\n", ret);
+		return ret;
+	}
+	/*
+	 * 10ms is just a setting that was arrived at empirically when
+	 * trying to make sure that EEPROM or MAC address access
+	 * commnads to not time out.
+	 */
+	serdev->polling_window = 10 * MSECOND;
+
+	/*
+	 * Those strings already have a \n embedded, so there's no
+	 * need to have one in format string.
+	 */
+	dev_info(dev, "Firmware version: %s",   sp->part_number_firmware);
+	dev_info(dev, "Bootloader version: %s", sp->part_number_bootloader);
+
+	return of_platform_populate(dev->device_node, NULL, dev);
+}
+
+static struct driver_d rave_sp_drv = {
+	.name = "rave-sp",
+	.probe = rave_sp_probe,
+	.of_compatible = DRV_OF_COMPAT(rave_sp_dt_ids),
+};
+console_platform_driver(rave_sp_drv);
diff --git a/include/linux/mfd/rave-sp.h b/include/linux/mfd/rave-sp.h
new file mode 100644
index 000000000..e0d97a55d
--- /dev/null
+++ b/include/linux/mfd/rave-sp.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * Core definitions for RAVE SP MFD driver.
+ *
+ * Copyright (C) 2017 Zodiac Inflight Innovations
+ */
+
+#ifndef _LINUX_RAVE_SP_H_
+#define _LINUX_RAVE_SP_H_
+
+/* #include <linux/notifier.h> */
+
+enum rave_sp_command {
+	RAVE_SP_CMD_GET_FIRMWARE_VERSION	= 0x20,
+	RAVE_SP_CMD_GET_BOOTLOADER_VERSION	= 0x21,
+	RAVE_SP_CMD_BOOT_SOURCE			= 0x26,
+	RAVE_SP_CMD_GET_BOARD_COPPER_REV	= 0x2B,
+	RAVE_SP_CMD_GET_GPIO_STATE		= 0x2F,
+
+	RAVE_SP_CMD_STATUS			= 0xA0,
+	RAVE_SP_CMD_SW_WDT			= 0xA1,
+	RAVE_SP_CMD_PET_WDT			= 0xA2,
+	RAVE_SP_CMD_SET_BACKLIGHT		= 0xA6,
+	RAVE_SP_CMD_RESET			= 0xA7,
+	RAVE_SP_CMD_RESET_REASON		= 0xA8,
+
+	RAVE_SP_CMD_JUMP_TO_BOOTLOADER		= 0xB0,
+	RAVE_SP_CMD_BOOTLOADER			= 0xB1,
+	RAVE_SP_CMD_REQ_COPPER_REV		= 0xB6,
+	RAVE_SP_CMD_GET_I2C_DEVICE_STATUS	= 0xBA,
+	RAVE_SP_CMD_GET_SP_SILICON_REV		= 0xB9,
+	RAVE_SP_CMD_CONTROL_EVENTS		= 0xBB,
+
+	RAVE_SP_EVNT_BASE			= 0xE0,
+};
+
+enum rave_sp_bootloader_command {
+	RAVE_SP_BOOTLOADER_CMD_QUERY_DEVICE	= 0xA1,
+	RAVE_SP_BOOTLOADER_CMD_ERASE_APP	= 0xA3,
+	RAVE_SP_BOOTLOADER_CMD_PROGRAM_DEVICE	= 0xA4,
+	RAVE_SP_BOOTLOADER_CMD_PROGRAM_COMPLETE = 0xA5,
+	RAVE_SP_BOOTLOADER_CMD_READ_APP		= 0xA6,
+	RAVE_SP_BOOTLOADER_CMD_RESET_DEVICE	= 0xA7,
+	RAVE_SP_BOOTLOADER_CMD_LAUNCH_APP	= 0xA8,
+};
+
+struct rave_sp;
+
+static inline unsigned long rave_sp_action_pack(u8 event, u8 value)
+{
+	return ((unsigned long)value << 8) | event;
+}
+
+static inline u8 rave_sp_action_unpack_event(unsigned long action)
+{
+	return action;
+}
+
+static inline u8 rave_sp_action_unpack_value(unsigned long action)
+{
+	return action >> 8;
+}
+
+int rave_sp_exec(struct rave_sp *sp,
+		 void *__data,  size_t data_size,
+		 void *reply_data, size_t reply_data_size);
+
+struct device;
+/* int devm_rave_sp_register_event_notifier(struct device *dev, */
+/* 					 struct notifier_block *nb); */
+
+bool rave_sp_is_in_bootloader_mode(struct rave_sp *sp);
+const struct firmware *rave_sp_get_firmware(struct rave_sp *sp);
+void rave_sp_release_firmware(struct rave_sp *sp);
+void rave_sp_set_update_fw_status(struct rave_sp *sp, int status);
+
+#endif /* _LINUX_RAVE_SP_H_ */
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:49:43 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:49:43 -0700
Subject: [PATCH v3] ARM: i.MX: boot: Coalesce copy-pasted code
Message-ID: <20180421014943.11517-1-andrew.smirnov@gmail.com>

All of the instances of imx*_boot_save_loc() do exactly the same thing
with the only difference being SoC-specific imx*_get_boot_source
call. Convert the code into a generic function taking function pointer
to perform SoC specific bits.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---

Sascha:

This is my second take on the patch we discussed in [thread1]. It
saves a whole bunch of boilerpalte code while keeping all function
names greppable. Hopefully this is good enough to be merged.

Thanks,
Andrey Smirnov

[thread1] http://lists.infradead.org/pipermail/barebox/2018-April/032706.html

 arch/arm/mach-imx/boot.c | 70 +++++++++++++++---------------------------------
 1 file changed, 21 insertions(+), 49 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index c3e2ec501..22cf08e6a 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -29,6 +29,20 @@
 #include <mach/imx7-regs.h>
 #include <mach/vf610-regs.h>
 
+
+static void
+imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
+{
+	enum bootsource src = BOOTSOURCE_UNKNOWN;
+	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
+
+	get_boot_source(&src, &instance);
+
+	bootsource_set(src);
+	bootsource_set_instance(instance);
+}
+
+
 /* [CTRL][TYPE] */
 static const enum bootsource locations[4][4] = {
 	{ /* CTRL = WEIM */
@@ -93,13 +107,7 @@ void imx25_get_boot_source(enum bootsource *src, int *instance)
 
 void imx25_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx25_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(imx25_get_boot_source);
 }
 
 void imx35_get_boot_source(enum bootsource *src, int *instance)
@@ -114,13 +122,7 @@ void imx35_get_boot_source(enum bootsource *src, int *instance)
 
 void imx35_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx35_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(imx35_get_boot_source);
 }
 
 #define IMX27_SYSCTRL_GPCR	0x18
@@ -161,13 +163,7 @@ void imx27_get_boot_source(enum bootsource *src, int *instance)
 
 void imx27_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx27_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(imx27_get_boot_source);
 }
 
 #define IMX51_SRC_SBMR			0x4
@@ -205,13 +201,7 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
 
 void imx51_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx51_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(imx51_get_boot_source);
 }
 
 #define IMX53_SRC_SBMR	0x4
@@ -431,13 +421,7 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 
 void imx6_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx6_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(imx6_get_boot_source);
 }
 
 #define IMX7_SRC_SBMR1	0x58
@@ -543,13 +527,7 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
 
 void imx7_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	imx7_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(imx7_get_boot_source);
 }
 
 static int vf610_boot_instance_spi(uint32_t r)
@@ -643,11 +621,5 @@ void vf610_get_boot_source(enum bootsource *src, int *instance)
 
 void vf610_boot_save_loc(void)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-
-	vf610_get_boot_source(&src, &instance);
-
-	bootsource_set(src);
-	bootsource_set_instance(instance);
+	imx_boot_save_loc(vf610_get_boot_source);
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Fri Apr 20 18:50:13 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 20 Apr 2018 18:50:13 -0700
Subject: [PATCH] ARM: imx_v7_defconfig: Select various missing v7 boards by
 default
Message-ID: <20180421015013.11620-1-andrew.smirnov@gmail.com>

Add the following boards:

    - ZII RDU2 (all variants)
    - ZII Vybrid Dev Board (and its derivatives)
    - Freescale/NXP i.MX7D SabreSD
    - NXP i.MX6ULL EVK
    - element 14 WaRP7

to be selected by default by imx_v7_defconfig.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/configs/imx_v7_defconfig | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 13135f2b3..8aef9d6ef 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -33,10 +33,15 @@ CONFIG_MACH_VARISCITE_MX6=y
 CONFIG_MACH_GW_VENTANA=y
 CONFIG_MACH_CM_FX6=y
 CONFIG_MACH_ADVANTECH_ROM_742X=y
+CONFIG_MACH_WARP7=y
+CONFIG_MACH_VF610_TWR=y
+CONFIG_MACH_ZII_RDU2=y
+CONFIG_MACH_ZII_VF610_DEV=y
 CONFIG_MACH_PHYTEC_PHYCORE_IMX7=y
+CONFIG_MACH_FREESCALE_MX7_SABRESD=y
+CONFIG_MACH_NXP_IMX6ULL_EVK=y
 CONFIG_IMX_IIM=y
 CONFIG_IMX_IIM_FUSE_BLOW=y
-CONFIG_IMX_OCOTP=y
 CONFIG_THUMB2_BAREBOX=y
 CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
 CONFIG_ARM_UNWIND=y
-- 
2.14.3



From linux at rempel-privat.de  Sun Apr 22 01:27:11 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 22 Apr 2018 10:27:11 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
In-Reply-To: <20180420080114.9148-1-gp@high-consulting.de>
References: <20180420080114.9148-1-gp@high-consulting.de>
Message-ID: <51213c28-0443-3ba7-d161-d79dfaa3acdb@rempel-privat.de>

Hi Gerd,

please use scripts/checkpatch.pl

currently i get
total: 2020 errors, 0 warnings, 2020 lines checked

We use kernel coding style. Please read it:
https://www.kernel.org/doc/html/v4.16/process/coding-style.html

Am 20.04.2018 um 10:01 schrieb Gerd Pauli:
> Adds ccryptlib library in crypto which implements a
> stream cipher based on the block cipher Rijndael,
> the candidate for the AES standard.
> Compatible with the ccrypt tool in linux
> from Peter Selinger.
> 
> Usage: ccrypt [-e|-d] -k KEYNAME_IN_KEYSTORE SRC DST
> 
> Signed-off-by: Gerd Pauli <gp at high-consulting.de>
> ---
>  commands/Kconfig    |   17 +
>  commands/Makefile   |    1 +
>  commands/ccrypt.c   |  249 +++++++++
>  crypto/Kconfig      |    7 +
>  crypto/Makefile     |    1 +
>  crypto/ccryptlib.c  | 1467 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/ccryptlib.h |  102 ++++
>  7 files changed, 1844 insertions(+)
>  create mode 100644 commands/ccrypt.c
>  create mode 100644 crypto/ccryptlib.c
>  create mode 100644 include/ccryptlib.h
> 
> diff --git a/commands/Kconfig b/commands/Kconfig
> index 951a86963..b6911246a 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -2137,6 +2137,23 @@ config CMD_SEED
>  	help
>  	  Seed the pseudo random number generator (PRNG)
>  
> +config CMD_CCRYPT
> +        tristate
> +        prompt "ccrypt"
> +        select CRYPTO_CCRYPTLIB
> +        select CRYPTO_KEYSTORE
> +        help
> +          encrypting/decrypting a character stream
> +          ccrypt implements a stream cipher based on the block cipher
> +          Rijndael.

> +          Usage: ccrypt [-ed] [-K name] srcfile dstfile
> +
> +          Options:
> +                        -e            encrypt srcfile to dstfile
> +                        -d            decrypt srcfile to dstfile
> +                        -k name       use key with name from keystore
> +

usage help should be provided by the command, not within Kconfig

>  # end Miscellaneous commands
>  endmenu
>  
> diff --git a/commands/Makefile b/commands/Makefile
> index eb4796389..3693bf553 100644
> --- a/commands/Makefile
> +++ b/commands/Makefile
> @@ -123,3 +123,4 @@ obj-$(CONFIG_CMD_MMC_EXTCSD)	+= mmc_extcsd.o
>  obj-$(CONFIG_CMD_NAND_BITFLIP)	+= nand-bitflip.o
>  obj-$(CONFIG_CMD_SEED)		+= seed.o
>  obj-$(CONFIG_CMD_IP_ROUTE_GET)  += ip-route-get.o
> +obj-$(CONFIG_CMD_CCRYPT)        += ccrypt.o
> diff --git a/commands/ccrypt.c b/commands/ccrypt.c
> new file mode 100644
> index 000000000..1b0ee9f1a
> --- /dev/null
> +++ b/commands/ccrypt.c
> @@ -0,0 +1,249 @@
> +/* -*- Mode:C; c-file-style:"linux"; -*- */

please no style annotations here.

> +/* Copyright (C) 2018 Gerd Pauli <gp at high-consulting.de */
>
> +/* Copyright (C) 2000-2012 Peter Selinger. */

all this should be within one comment block

> +/* See file CREDITS for list of people who contributed to this
> + * project. 

no need for complete GPL text. Instead please use SPDX-License-Identifier
For example:
drivers/usb/gadget/f_fastboot.c
you will get some thing like:

/*
 * ccrypt implements a stream cipher based on the block cipher Rijndael
 *
 * Copyright (C) 2018 Gerd Pauli <gp at high-consulting.de>
 * Copyright (C) 2000-2012 Peter Selinger
 *
 * SPDX-License-Identifier: GPL-2.0+
 */


> + * 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.    
> + */
> +
> +/* ccrypt implements a stream cipher based on the block cipher
> +   Rijndael  */
> +
> +/* needs library ccryptlib and keystore from barebox */

no need for this comment, needed headers are already included

> +#include <common.h>
> +#include <command.h>
> +#include <libfile.h>
> +#include <getopt.h>
> +#include <fcntl.h>
> +#include <fs.h>
> +#include <ccryptlib.h>

i prefer headers sorted alphabetically. this helps to reduce
patch conflicts.

> +#define INBUFSIZE 1024  
> +#define OUTBUFSIZE INBUFSIZE+32
> +
> +void ccrypt_error( int e ) {
> +	if ( e == -1 ) {  
> +		printf("ccrypt: %s\n",strerror(-errno));
> +		return;
> +	} 
> +        if ( e == -2 ) {
> +                switch (ccrypt_errno) {
> +                case CCRYPT_EFORMAT:
> +                        printf("ccrypt: %s\n","bad file format");
> +                        break;
> +                case CCRYPT_EMISMATCH:
> +                        printf("ccrypt: %s\n","key does not match");
> +                        break;
> +                case CCRYPT_EBUFFER:
> +                        printf("ccrypt: %s\n","buffer overflow");
> +                        break;
> +                default:
> +                        /* do nothing */
> +                        printf("ccrypt: %s %d\n","unknown ccrypt error: ",ccrypt_errno);
> +                        break;
> +		}
> +		return;
> +	}
> +	if ( e == -3 ) {  
> +		printf("ccrypt: %s\n","no key");
> +		return;
> +	} 
> +	printf("ccrypt: %s: %d\n","unknown error",e);
> +}
> +
> +static int do_ccrypt(int argc, char *argv[])
> +{
> +	int opt;
> +	int ret=-EINVAL;
> +	int encrypt=0;
> +	int decrypt=0;
> +	char *extract = NULL;
> +	char *from = NULL;
> +	char *to = NULL;
> +	char *r_buf = NULL;
> +	char *w_buf = NULL;
> +	int from_fd = 0;
> +	int to_fd = 0;
> +	int r,w;
> +	void *buf;
> +	ccrypt_stream_t ccs;
> +	ccrypt_stream_t *b = &ccs;
> +	char *key;
> +	int keylen;
> +	int eof=0;
> +
> +	while ((opt = getopt(argc, argv, "dek:")) > 0) {
> +		switch(opt) {
> +		case 'e':
> +			encrypt=1;
> +			break;
> +		case 'd':
> +			decrypt=1;
> +			break;
> +		case 'k':
> +			extract = optarg;
> +			break;
> +		}
> +	}
> +	if ( encrypt == 1 && decrypt == 1 ) 
> +		return ret;
> +	if ( extract == NULL )
> +		return ret;
> +
> +	if ( optind != 4 ) 
> +		return ret;
> +
> +	if ( argc != 6 )
> +		return ret;
> +
> +	from = argv[optind];
> +	to = argv[optind + 1];
> +
> +	r_buf=malloc(INBUFSIZE);
> +        if ( r_buf == NULL ) {
> +                ret = -1;
> +                goto out;
> +        }
> +        
> +	w_buf=malloc(OUTBUFSIZE);
> +        if ( w_buf == NULL ) {
> +                free(r_buf);
> +                ret = -1;
> +                goto out;
> +        }
> +  
> +	ret=keystore_get_secret(extract, (const u8 **)&key, &keylen);
> +
> +#ifdef DEBUG
> +        if ( key && keystore ) 
> +                memory_display(key,0,keylen,1,0);
> +#endif
> +        
> +        if ( ret ) {
> +                ret=-3;
> +		goto out;
> +        }
> +        
> +	from_fd = open(from, O_RDONLY);
> +	if (from_fd < 0) {
> +		printf("could not open %s: %s\n", from, errno_str());
> +		ret=-1;
> +		goto out;
> +	}
> +
> +	to_fd = open(to, O_WRONLY | O_CREAT | O_TRUNC);
> +	if (to_fd < 0) {
> +		printf("could not open %s: %s\n", to, errno_str());
> +		ret=-1;
> +		goto out;
> +	}
> +
> +	ret=0;
> +
> +	if ( encrypt == 1 ) 
> +		ret = ccencrypt_init(b, key, keylen);
> +  
> +	if ( decrypt == 1 ) 
> +		ret = ccdecrypt_init(b, key, keylen);
> +  
> +	if ( ret != 0 ) {
> +                printf("cc init error\n");
> +		goto out;
> +	}
> +
> +	b->avail_in = 0;
> +  
> +	while (1) {
> +		/* fill input buffer */
> +		if (b->avail_in == 0 && !eof) {
> +			r = read(from_fd, r_buf, INBUFSIZE);
> +			if (r < 0) {
> +				perror("read");
> +                                ret=-1;
> +				goto out;
> +			}
> +			if (!r)
> +				eof=1;
> +			b->next_in = &r_buf[0];
> +			b->avail_in = r;
> +		}
> +    
> +		/* prepare output buffer */
> +		b->next_out = &w_buf[0];
> +		b->avail_out = OUTBUFSIZE;
> +    
> +		/* do some work */
> +		if ( encrypt == 1 ) {
> +			ret = ccencrypt(b);
> +		}
> +		if ( decrypt == 1 ) {
> +			ret = ccdecrypt(b);
> +			if (ret) {
> +                                printf("cc dec err\n");
> +				ret=-2;
> +				goto out;
> +			}
> +		}
> +    
> +		r = OUTBUFSIZE-b->avail_out;
> +		buf = &w_buf[0];
> +
> +		/* process output buffer */
> +		while (r) {
> +			w = write(to_fd, buf, r);
> +			if (w < 0) {
> +                                printf("write error\n");
> +                                ret=-1;
> +				goto out;
> +			}
> +			buf += w;
> +			r -= w;
> +		}
> +
> +		/* ready */ 
> +		if (eof && b->avail_out != 0) {
> +			break;
> +		}
> +	}
> +	ret = 0;
> +out:
> +        free(r_buf);
> +        free(w_buf);
> +	if (from_fd > 0)
> +		close(from_fd);
> +	if (to_fd > 0)
> +		close(to_fd);
> +
> +	return ret;
> +}
> +
> +BAREBOX_CMD_HELP_START(ccrypt)
> +BAREBOX_CMD_HELP_TEXT("Rijandel Crypt and Decrypt")
> +BAREBOX_CMD_HELP_TEXT("")
> +BAREBOX_CMD_HELP_TEXT("Options:")
> +BAREBOX_CMD_HELP_OPT("-e", "encrypt")
> +BAREBOX_CMD_HELP_OPT("-d", "decrypt")
> +BAREBOX_CMD_HELP_OPT("-k name", "Name of key in keystore")
> +BAREBOX_CMD_HELP_END
> +
> +BAREBOX_CMD_START(ccrypt)
> +.cmd	= do_ccrypt,
> +	BAREBOX_CMD_DESC("Crypt and Decrypt Files")
> +	BAREBOX_CMD_OPTS("[-e|-d] -k NAME SRC DST")
> +        BAREBOX_CMD_GROUP(CMD_GRP_MISC)
> +	BAREBOX_CMD_HELP(cmd_ccrypt_help)
> +	BAREBOX_CMD_END
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index 6d65c24d4..08669a2de 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -101,4 +101,11 @@ config CRYPTO_KEYSTORE
>  	  This is a simple keystore, which can be used to pass keys
>  	  between several components via simple interface.
>  
> +config CRYPTO_CCRYPTLIB
> +        bool "ccryptlib"
> +        help
> +          This option provides functions implementing a stream cipher based
> +          on the block cipher rijandel.
> +          The cipher is based on Peter Selingers ccrypt implementation.
> +
>  endmenu
> diff --git a/crypto/Makefile b/crypto/Makefile
> index a7240d1d6..1231bc76d 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_DIGEST_SHA512_GENERIC)	+= sha4.o
>  obj-$(CONFIG_CRYPTO_PBKDF2)	+= pbkdf2.o
>  obj-$(CONFIG_CRYPTO_RSA)	+= rsa.o
>  obj-$(CONFIG_CRYPTO_KEYSTORE)	+= keystore.o
> +obj-$(CONFIG_CRYPTO_CCRYPTLIB)  += ccryptlib.o
> diff --git a/crypto/ccryptlib.c b/crypto/ccryptlib.c
> new file mode 100644
> index 000000000..78f0ac843
> --- /dev/null
> +++ b/crypto/ccryptlib.c
> @@ -0,0 +1,1467 @@
> +/* -*- Mode:C; c-file-style:"linux"; -*- */
> +
> +/* Ported to barebox by Gerd Pauli <gp at high-consulting.de> 2018 */
> +
> +/* Copyright (C) 2000-2012 Peter Selinger.
> +   This file is part of ccrypt. It is free software and it is covered
> +   by the GNU general public license. See the file COPYING for details. */
> +
> +/* NOTE: this library is copyrighted under the GNU General Public
> +   License, *not* under the GNU Library General Public License.  This
> +   means, among other things, that you cannot use this library in
> +   closed-source software. */
> +
> +/* ccryptlib implements a stream cipher based on the block cipher
> +   Rijndael, the candidate for the AES standard. */

Same header stile as before.

> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <ccryptlib.h>
> +#include <common.h>
> +#include <malloc.h>

includes alphabetically

> +/* ---------- rijandel.c ---------- */
> +
> +/* rijndael.c - optimized version of the Rijndeal cipher */
> +/* derived from original source: rijndael-alg-ref.c   v2.0   August '99
> + * Reference ANSI C code for NIST competition
> + * authors: Paulo Barreto
> + *          Vincent Rijmen
> + */
> +
> +typedef unsigned char word8;
> +
> +#ifdef UINT32_TYPE
> +typedef UINT32_TYPE word32;
> +#else
> +typedef int word32;		/* should be a 32-bit integer type */
> +#endif
> +
> +/* a type to hold 32 bits accessible as 1 integer or 4 bytes */
> +union word8x4_u {
> +        word8 w8[4];
> +        word32 w32;
> +};
> +typedef union word8x4_u word8x4;
> +
> +/* ---------- tables.c ------------ */
> +
> +word8x4 M0[4][256] = {
> +        {
> +                {{  0,   0,   0,   0}}, {{  2,   1,   1,   3}}, {{  4,   2,   2,   6}}, 
> +                {{  6,   3,   3,   5}}, {{  8,   4,   4,  12}}, {{ 10,   5,   5,  15}}, 
> +                {{ 12,   6,   6,  10}}, {{ 14,   7,   7,   9}}, {{ 16,   8,   8,  24}}, 
> +                {{ 18,   9,   9,  27}}, {{ 20,  10,  10,  30}}, {{ 22,  11,  11,  29}}, 
> +                {{ 24,  12,  12,  20}}, {{ 26,  13,  13,  23}}, {{ 28,  14,  14,  18}}, 
> +                {{ 30,  15,  15,  17}}, {{ 32,  16,  16,  48}}, {{ 34,  17,  17,  51}}, 
> +                {{ 36,  18,  18,  54}}, {{ 38,  19,  19,  53}}, {{ 40,  20,  20,  60}}, 
> +                {{ 42,  21,  21,  63}}, {{ 44,  22,  22,  58}}, {{ 46,  23,  23,  57}}, 
> +                {{ 48,  24,  24,  40}}, {{ 50,  25,  25,  43}}, {{ 52,  26,  26,  46}}, 
> +                {{ 54,  27,  27,  45}}, {{ 56,  28,  28,  36}}, {{ 58,  29,  29,  39}}, 
> +                {{ 60,  30,  30,  34}}, {{ 62,  31,  31,  33}}, {{ 64,  32,  32,  96}}, 
> +                {{ 66,  33,  33,  99}}, {{ 68,  34,  34, 102}}, {{ 70,  35,  35, 101}}, 
> +                {{ 72,  36,  36, 108}}, {{ 74,  37,  37, 111}}, {{ 76,  38,  38, 106}}, 
> +                {{ 78,  39,  39, 105}}, {{ 80,  40,  40, 120}}, {{ 82,  41,  41, 123}}, 
> +                {{ 84,  42,  42, 126}}, {{ 86,  43,  43, 125}}, {{ 88,  44,  44, 116}}, 
> +                {{ 90,  45,  45, 119}}, {{ 92,  46,  46, 114}}, {{ 94,  47,  47, 113}}, 
> +                {{ 96,  48,  48,  80}}, {{ 98,  49,  49,  83}}, {{100,  50,  50,  86}}, 
> +                {{102,  51,  51,  85}}, {{104,  52,  52,  92}}, {{106,  53,  53,  95}}, 
> +                {{108,  54,  54,  90}}, {{110,  55,  55,  89}}, {{112,  56,  56,  72}}, 
> +                {{114,  57,  57,  75}}, {{116,  58,  58,  78}}, {{118,  59,  59,  77}}, 
> +                {{120,  60,  60,  68}}, {{122,  61,  61,  71}}, {{124,  62,  62,  66}}, 
> +                {{126,  63,  63,  65}}, {{128,  64,  64, 192}}, {{130,  65,  65, 195}}, 
> +                {{132,  66,  66, 198}}, {{134,  67,  67, 197}}, {{136,  68,  68, 204}}, 
> +                {{138,  69,  69, 207}}, {{140,  70,  70, 202}}, {{142,  71,  71, 201}}, 
> +                {{144,  72,  72, 216}}, {{146,  73,  73, 219}}, {{148,  74,  74, 222}}, 
> +                {{150,  75,  75, 221}}, {{152,  76,  76, 212}}, {{154,  77,  77, 215}}, 
> +                {{156,  78,  78, 210}}, {{158,  79,  79, 209}}, {{160,  80,  80, 240}}, 
> +                {{162,  81,  81, 243}}, {{164,  82,  82, 246}}, {{166,  83,  83, 245}}, 
> +                {{168,  84,  84, 252}}, {{170,  85,  85, 255}}, {{172,  86,  86, 250}}, 
> +                {{174,  87,  87, 249}}, {{176,  88,  88, 232}}, {{178,  89,  89, 235}}, 
> +                {{180,  90,  90, 238}}, {{182,  91,  91, 237}}, {{184,  92,  92, 228}}, 
> +                {{186,  93,  93, 231}}, {{188,  94,  94, 226}}, {{190,  95,  95, 225}}, 
> +                {{192,  96,  96, 160}}, {{194,  97,  97, 163}}, {{196,  98,  98, 166}}, 
> +                {{198,  99,  99, 165}}, {{200, 100, 100, 172}}, {{202, 101, 101, 175}}, 
> +                {{204, 102, 102, 170}}, {{206, 103, 103, 169}}, {{208, 104, 104, 184}}, 
> +                {{210, 105, 105, 187}}, {{212, 106, 106, 190}}, {{214, 107, 107, 189}}, 
> +                {{216, 108, 108, 180}}, {{218, 109, 109, 183}}, {{220, 110, 110, 178}}, 
> +                {{222, 111, 111, 177}}, {{224, 112, 112, 144}}, {{226, 113, 113, 147}}, 
> +                {{228, 114, 114, 150}}, {{230, 115, 115, 149}}, {{232, 116, 116, 156}}, 
> +                {{234, 117, 117, 159}}, {{236, 118, 118, 154}}, {{238, 119, 119, 153}}, 
> +                {{240, 120, 120, 136}}, {{242, 121, 121, 139}}, {{244, 122, 122, 142}}, 
> +                {{246, 123, 123, 141}}, {{248, 124, 124, 132}}, {{250, 125, 125, 135}}, 
> +                {{252, 126, 126, 130}}, {{254, 127, 127, 129}}, {{ 27, 128, 128, 155}}, 
> +                {{ 25, 129, 129, 152}}, {{ 31, 130, 130, 157}}, {{ 29, 131, 131, 158}}, 
> +                {{ 19, 132, 132, 151}}, {{ 17, 133, 133, 148}}, {{ 23, 134, 134, 145}}, 
> +                {{ 21, 135, 135, 146}}, {{ 11, 136, 136, 131}}, {{  9, 137, 137, 128}}, 
> +                {{ 15, 138, 138, 133}}, {{ 13, 139, 139, 134}}, {{  3, 140, 140, 143}}, 
> +                {{  1, 141, 141, 140}}, {{  7, 142, 142, 137}}, {{  5, 143, 143, 138}}, 
> +                {{ 59, 144, 144, 171}}, {{ 57, 145, 145, 168}}, {{ 63, 146, 146, 173}}, 
> +                {{ 61, 147, 147, 174}}, {{ 51, 148, 148, 167}}, {{ 49, 149, 149, 164}}, 
> +                {{ 55, 150, 150, 161}}, {{ 53, 151, 151, 162}}, {{ 43, 152, 152, 179}}, 
> +                {{ 41, 153, 153, 176}}, {{ 47, 154, 154, 181}}, {{ 45, 155, 155, 182}}, 
> +                {{ 35, 156, 156, 191}}, {{ 33, 157, 157, 188}}, {{ 39, 158, 158, 185}}, 
> +                {{ 37, 159, 159, 186}}, {{ 91, 160, 160, 251}}, {{ 89, 161, 161, 248}}, 
> +                {{ 95, 162, 162, 253}}, {{ 93, 163, 163, 254}}, {{ 83, 164, 164, 247}}, 
> +                {{ 81, 165, 165, 244}}, {{ 87, 166, 166, 241}}, {{ 85, 167, 167, 242}}, 
> +                {{ 75, 168, 168, 227}}, {{ 73, 169, 169, 224}}, {{ 79, 170, 170, 229}}, 
> +                {{ 77, 171, 171, 230}}, {{ 67, 172, 172, 239}}, {{ 65, 173, 173, 236}}, 
> +                {{ 71, 174, 174, 233}}, {{ 69, 175, 175, 234}}, {{123, 176, 176, 203}}, 
> +                {{121, 177, 177, 200}}, {{127, 178, 178, 205}}, {{125, 179, 179, 206}}, 
> +                {{115, 180, 180, 199}}, {{113, 181, 181, 196}}, {{119, 182, 182, 193}}, 
> +                {{117, 183, 183, 194}}, {{107, 184, 184, 211}}, {{105, 185, 185, 208}}, 
> +                {{111, 186, 186, 213}}, {{109, 187, 187, 214}}, {{ 99, 188, 188, 223}}, 
> +                {{ 97, 189, 189, 220}}, {{103, 190, 190, 217}}, {{101, 191, 191, 218}}, 
> +                {{155, 192, 192,  91}}, {{153, 193, 193,  88}}, {{159, 194, 194,  93}}, 
> +                {{157, 195, 195,  94}}, {{147, 196, 196,  87}}, {{145, 197, 197,  84}}, 
> +                {{151, 198, 198,  81}}, {{149, 199, 199,  82}}, {{139, 200, 200,  67}}, 
> +                {{137, 201, 201,  64}}, {{143, 202, 202,  69}}, {{141, 203, 203,  70}}, 
> +                {{131, 204, 204,  79}}, {{129, 205, 205,  76}}, {{135, 206, 206,  73}}, 
> +                {{133, 207, 207,  74}}, {{187, 208, 208, 107}}, {{185, 209, 209, 104}}, 
> +                {{191, 210, 210, 109}}, {{189, 211, 211, 110}}, {{179, 212, 212, 103}}, 
> +                {{177, 213, 213, 100}}, {{183, 214, 214,  97}}, {{181, 215, 215,  98}}, 
> +                {{171, 216, 216, 115}}, {{169, 217, 217, 112}}, {{175, 218, 218, 117}}, 
> +                {{173, 219, 219, 118}}, {{163, 220, 220, 127}}, {{161, 221, 221, 124}}, 
> +                {{167, 222, 222, 121}}, {{165, 223, 223, 122}}, {{219, 224, 224,  59}}, 
> +                {{217, 225, 225,  56}}, {{223, 226, 226,  61}}, {{221, 227, 227,  62}}, 
> +                {{211, 228, 228,  55}}, {{209, 229, 229,  52}}, {{215, 230, 230,  49}}, 
> +                {{213, 231, 231,  50}}, {{203, 232, 232,  35}}, {{201, 233, 233,  32}}, 
> +                {{207, 234, 234,  37}}, {{205, 235, 235,  38}}, {{195, 236, 236,  47}}, 
> +                {{193, 237, 237,  44}}, {{199, 238, 238,  41}}, {{197, 239, 239,  42}}, 
> +                {{251, 240, 240,  11}}, {{249, 241, 241,   8}}, {{255, 242, 242,  13}}, 
> +                {{253, 243, 243,  14}}, {{243, 244, 244,   7}}, {{241, 245, 245,   4}}, 
> +                {{247, 246, 246,   1}}, {{245, 247, 247,   2}}, {{235, 248, 248,  19}}, 
> +                {{233, 249, 249,  16}}, {{239, 250, 250,  21}}, {{237, 251, 251,  22}}, 
> +                {{227, 252, 252,  31}}, {{225, 253, 253,  28}}, {{231, 254, 254,  25}}, 
> +                {{229, 255, 255,  26}}, 
> +        },
> +        {
> +                {{  0,   0,   0,   0}}, {{  3,   2,   1,   1}}, {{  6,   4,   2,   2}}, 
> +                {{  5,   6,   3,   3}}, {{ 12,   8,   4,   4}}, {{ 15,  10,   5,   5}}, 
> +                {{ 10,  12,   6,   6}}, {{  9,  14,   7,   7}}, {{ 24,  16,   8,   8}}, 
> +                {{ 27,  18,   9,   9}}, {{ 30,  20,  10,  10}}, {{ 29,  22,  11,  11}}, 
> +                {{ 20,  24,  12,  12}}, {{ 23,  26,  13,  13}}, {{ 18,  28,  14,  14}}, 
> +                {{ 17,  30,  15,  15}}, {{ 48,  32,  16,  16}}, {{ 51,  34,  17,  17}}, 
> +                {{ 54,  36,  18,  18}}, {{ 53,  38,  19,  19}}, {{ 60,  40,  20,  20}}, 
> +                {{ 63,  42,  21,  21}}, {{ 58,  44,  22,  22}}, {{ 57,  46,  23,  23}}, 
> +                {{ 40,  48,  24,  24}}, {{ 43,  50,  25,  25}}, {{ 46,  52,  26,  26}}, 
> +                {{ 45,  54,  27,  27}}, {{ 36,  56,  28,  28}}, {{ 39,  58,  29,  29}}, 
> +                {{ 34,  60,  30,  30}}, {{ 33,  62,  31,  31}}, {{ 96,  64,  32,  32}}, 
> +                {{ 99,  66,  33,  33}}, {{102,  68,  34,  34}}, {{101,  70,  35,  35}}, 
> +                {{108,  72,  36,  36}}, {{111,  74,  37,  37}}, {{106,  76,  38,  38}}, 
> +                {{105,  78,  39,  39}}, {{120,  80,  40,  40}}, {{123,  82,  41,  41}}, 
> +                {{126,  84,  42,  42}}, {{125,  86,  43,  43}}, {{116,  88,  44,  44}}, 
> +                {{119,  90,  45,  45}}, {{114,  92,  46,  46}}, {{113,  94,  47,  47}}, 
> +                {{ 80,  96,  48,  48}}, {{ 83,  98,  49,  49}}, {{ 86, 100,  50,  50}}, 
> +                {{ 85, 102,  51,  51}}, {{ 92, 104,  52,  52}}, {{ 95, 106,  53,  53}}, 
> +                {{ 90, 108,  54,  54}}, {{ 89, 110,  55,  55}}, {{ 72, 112,  56,  56}}, 
> +                {{ 75, 114,  57,  57}}, {{ 78, 116,  58,  58}}, {{ 77, 118,  59,  59}}, 
> +                {{ 68, 120,  60,  60}}, {{ 71, 122,  61,  61}}, {{ 66, 124,  62,  62}}, 
> +                {{ 65, 126,  63,  63}}, {{192, 128,  64,  64}}, {{195, 130,  65,  65}}, 
> +                {{198, 132,  66,  66}}, {{197, 134,  67,  67}}, {{204, 136,  68,  68}}, 
> +                {{207, 138,  69,  69}}, {{202, 140,  70,  70}}, {{201, 142,  71,  71}}, 
> +                {{216, 144,  72,  72}}, {{219, 146,  73,  73}}, {{222, 148,  74,  74}}, 
> +                {{221, 150,  75,  75}}, {{212, 152,  76,  76}}, {{215, 154,  77,  77}}, 
> +                {{210, 156,  78,  78}}, {{209, 158,  79,  79}}, {{240, 160,  80,  80}}, 
> +                {{243, 162,  81,  81}}, {{246, 164,  82,  82}}, {{245, 166,  83,  83}}, 
> +                {{252, 168,  84,  84}}, {{255, 170,  85,  85}}, {{250, 172,  86,  86}}, 
> +                {{249, 174,  87,  87}}, {{232, 176,  88,  88}}, {{235, 178,  89,  89}}, 
> +                {{238, 180,  90,  90}}, {{237, 182,  91,  91}}, {{228, 184,  92,  92}}, 
> +                {{231, 186,  93,  93}}, {{226, 188,  94,  94}}, {{225, 190,  95,  95}}, 
> +                {{160, 192,  96,  96}}, {{163, 194,  97,  97}}, {{166, 196,  98,  98}}, 
> +                {{165, 198,  99,  99}}, {{172, 200, 100, 100}}, {{175, 202, 101, 101}}, 
> +                {{170, 204, 102, 102}}, {{169, 206, 103, 103}}, {{184, 208, 104, 104}}, 
> +                {{187, 210, 105, 105}}, {{190, 212, 106, 106}}, {{189, 214, 107, 107}}, 
> +                {{180, 216, 108, 108}}, {{183, 218, 109, 109}}, {{178, 220, 110, 110}}, 
> +                {{177, 222, 111, 111}}, {{144, 224, 112, 112}}, {{147, 226, 113, 113}}, 
> +                {{150, 228, 114, 114}}, {{149, 230, 115, 115}}, {{156, 232, 116, 116}}, 
> +                {{159, 234, 117, 117}}, {{154, 236, 118, 118}}, {{153, 238, 119, 119}}, 
> +                {{136, 240, 120, 120}}, {{139, 242, 121, 121}}, {{142, 244, 122, 122}}, 
> +                {{141, 246, 123, 123}}, {{132, 248, 124, 124}}, {{135, 250, 125, 125}}, 
> +                {{130, 252, 126, 126}}, {{129, 254, 127, 127}}, {{155,  27, 128, 128}}, 
> +                {{152,  25, 129, 129}}, {{157,  31, 130, 130}}, {{158,  29, 131, 131}}, 
> +                {{151,  19, 132, 132}}, {{148,  17, 133, 133}}, {{145,  23, 134, 134}}, 
> +                {{146,  21, 135, 135}}, {{131,  11, 136, 136}}, {{128,   9, 137, 137}}, 
> +                {{133,  15, 138, 138}}, {{134,  13, 139, 139}}, {{143,   3, 140, 140}}, 
> +                {{140,   1, 141, 141}}, {{137,   7, 142, 142}}, {{138,   5, 143, 143}}, 
> +                {{171,  59, 144, 144}}, {{168,  57, 145, 145}}, {{173,  63, 146, 146}}, 
> +                {{174,  61, 147, 147}}, {{167,  51, 148, 148}}, {{164,  49, 149, 149}}, 
> +                {{161,  55, 150, 150}}, {{162,  53, 151, 151}}, {{179,  43, 152, 152}}, 
> +                {{176,  41, 153, 153}}, {{181,  47, 154, 154}}, {{182,  45, 155, 155}}, 
> +                {{191,  35, 156, 156}}, {{188,  33, 157, 157}}, {{185,  39, 158, 158}}, 
> +                {{186,  37, 159, 159}}, {{251,  91, 160, 160}}, {{248,  89, 161, 161}}, 
> +                {{253,  95, 162, 162}}, {{254,  93, 163, 163}}, {{247,  83, 164, 164}}, 
> +                {{244,  81, 165, 165}}, {{241,  87, 166, 166}}, {{242,  85, 167, 167}}, 
> +                {{227,  75, 168, 168}}, {{224,  73, 169, 169}}, {{229,  79, 170, 170}}, 
> +                {{230,  77, 171, 171}}, {{239,  67, 172, 172}}, {{236,  65, 173, 173}}, 
> +                {{233,  71, 174, 174}}, {{234,  69, 175, 175}}, {{203, 123, 176, 176}}, 
> +                {{200, 121, 177, 177}}, {{205, 127, 178, 178}}, {{206, 125, 179, 179}}, 
> +                {{199, 115, 180, 180}}, {{196, 113, 181, 181}}, {{193, 119, 182, 182}}, 
> +                {{194, 117, 183, 183}}, {{211, 107, 184, 184}}, {{208, 105, 185, 185}}, 
> +                {{213, 111, 186, 186}}, {{214, 109, 187, 187}}, {{223,  99, 188, 188}}, 
> +                {{220,  97, 189, 189}}, {{217, 103, 190, 190}}, {{218, 101, 191, 191}}, 
> +                {{ 91, 155, 192, 192}}, {{ 88, 153, 193, 193}}, {{ 93, 159, 194, 194}}, 
> +                {{ 94, 157, 195, 195}}, {{ 87, 147, 196, 196}}, {{ 84, 145, 197, 197}}, 
> +                {{ 81, 151, 198, 198}}, {{ 82, 149, 199, 199}}, {{ 67, 139, 200, 200}}, 
> +                {{ 64, 137, 201, 201}}, {{ 69, 143, 202, 202}}, {{ 70, 141, 203, 203}}, 
> +                {{ 79, 131, 204, 204}}, {{ 76, 129, 205, 205}}, {{ 73, 135, 206, 206}}, 
> +                {{ 74, 133, 207, 207}}, {{107, 187, 208, 208}}, {{104, 185, 209, 209}}, 
> +                {{109, 191, 210, 210}}, {{110, 189, 211, 211}}, {{103, 179, 212, 212}}, 
> +                {{100, 177, 213, 213}}, {{ 97, 183, 214, 214}}, {{ 98, 181, 215, 215}}, 
> +                {{115, 171, 216, 216}}, {{112, 169, 217, 217}}, {{117, 175, 218, 218}}, 
> +                {{118, 173, 219, 219}}, {{127, 163, 220, 220}}, {{124, 161, 221, 221}}, 
> +                {{121, 167, 222, 222}}, {{122, 165, 223, 223}}, {{ 59, 219, 224, 224}}, 
> +                {{ 56, 217, 225, 225}}, {{ 61, 223, 226, 226}}, {{ 62, 221, 227, 227}}, 
> +                {{ 55, 211, 228, 228}}, {{ 52, 209, 229, 229}}, {{ 49, 215, 230, 230}}, 
> +                {{ 50, 213, 231, 231}}, {{ 35, 203, 232, 232}}, {{ 32, 201, 233, 233}}, 
> +                {{ 37, 207, 234, 234}}, {{ 38, 205, 235, 235}}, {{ 47, 195, 236, 236}}, 
> +                {{ 44, 193, 237, 237}}, {{ 41, 199, 238, 238}}, {{ 42, 197, 239, 239}}, 
> +                {{ 11, 251, 240, 240}}, {{  8, 249, 241, 241}}, {{ 13, 255, 242, 242}}, 
> +                {{ 14, 253, 243, 243}}, {{  7, 243, 244, 244}}, {{  4, 241, 245, 245}}, 
> +                {{  1, 247, 246, 246}}, {{  2, 245, 247, 247}}, {{ 19, 235, 248, 248}}, 
> +                {{ 16, 233, 249, 249}}, {{ 21, 239, 250, 250}}, {{ 22, 237, 251, 251}}, 
> +                {{ 31, 227, 252, 252}}, {{ 28, 225, 253, 253}}, {{ 25, 231, 254, 254}}, 
> +                {{ 26, 229, 255, 255}}, 
> +        },
> +        {
> +                {{  0,   0,   0,   0}}, {{  1,   3,   2,   1}}, {{  2,   6,   4,   2}}, 
> +                {{  3,   5,   6,   3}}, {{  4,  12,   8,   4}}, {{  5,  15,  10,   5}}, 
> +                {{  6,  10,  12,   6}}, {{  7,   9,  14,   7}}, {{  8,  24,  16,   8}}, 
> +                {{  9,  27,  18,   9}}, {{ 10,  30,  20,  10}}, {{ 11,  29,  22,  11}}, 
> +                {{ 12,  20,  24,  12}}, {{ 13,  23,  26,  13}}, {{ 14,  18,  28,  14}}, 
> +                {{ 15,  17,  30,  15}}, {{ 16,  48,  32,  16}}, {{ 17,  51,  34,  17}}, 
> +                {{ 18,  54,  36,  18}}, {{ 19,  53,  38,  19}}, {{ 20,  60,  40,  20}}, 
> +                {{ 21,  63,  42,  21}}, {{ 22,  58,  44,  22}}, {{ 23,  57,  46,  23}}, 
> +                {{ 24,  40,  48,  24}}, {{ 25,  43,  50,  25}}, {{ 26,  46,  52,  26}}, 
> +                {{ 27,  45,  54,  27}}, {{ 28,  36,  56,  28}}, {{ 29,  39,  58,  29}}, 
> +                {{ 30,  34,  60,  30}}, {{ 31,  33,  62,  31}}, {{ 32,  96,  64,  32}}, 
> +                {{ 33,  99,  66,  33}}, {{ 34, 102,  68,  34}}, {{ 35, 101,  70,  35}}, 
> +                {{ 36, 108,  72,  36}}, {{ 37, 111,  74,  37}}, {{ 38, 106,  76,  38}}, 
> +                {{ 39, 105,  78,  39}}, {{ 40, 120,  80,  40}}, {{ 41, 123,  82,  41}}, 
> +                {{ 42, 126,  84,  42}}, {{ 43, 125,  86,  43}}, {{ 44, 116,  88,  44}}, 
> +                {{ 45, 119,  90,  45}}, {{ 46, 114,  92,  46}}, {{ 47, 113,  94,  47}}, 
> +                {{ 48,  80,  96,  48}}, {{ 49,  83,  98,  49}}, {{ 50,  86, 100,  50}}, 
> +                {{ 51,  85, 102,  51}}, {{ 52,  92, 104,  52}}, {{ 53,  95, 106,  53}}, 
> +                {{ 54,  90, 108,  54}}, {{ 55,  89, 110,  55}}, {{ 56,  72, 112,  56}}, 
> +                {{ 57,  75, 114,  57}}, {{ 58,  78, 116,  58}}, {{ 59,  77, 118,  59}}, 
> +                {{ 60,  68, 120,  60}}, {{ 61,  71, 122,  61}}, {{ 62,  66, 124,  62}}, 
> +                {{ 63,  65, 126,  63}}, {{ 64, 192, 128,  64}}, {{ 65, 195, 130,  65}}, 
> +                {{ 66, 198, 132,  66}}, {{ 67, 197, 134,  67}}, {{ 68, 204, 136,  68}}, 
> +                {{ 69, 207, 138,  69}}, {{ 70, 202, 140,  70}}, {{ 71, 201, 142,  71}}, 
> +                {{ 72, 216, 144,  72}}, {{ 73, 219, 146,  73}}, {{ 74, 222, 148,  74}}, 
> +                {{ 75, 221, 150,  75}}, {{ 76, 212, 152,  76}}, {{ 77, 215, 154,  77}}, 
> +                {{ 78, 210, 156,  78}}, {{ 79, 209, 158,  79}}, {{ 80, 240, 160,  80}}, 
> +                {{ 81, 243, 162,  81}}, {{ 82, 246, 164,  82}}, {{ 83, 245, 166,  83}}, 
> +                {{ 84, 252, 168,  84}}, {{ 85, 255, 170,  85}}, {{ 86, 250, 172,  86}}, 
> +                {{ 87, 249, 174,  87}}, {{ 88, 232, 176,  88}}, {{ 89, 235, 178,  89}}, 
> +                {{ 90, 238, 180,  90}}, {{ 91, 237, 182,  91}}, {{ 92, 228, 184,  92}}, 
> +                {{ 93, 231, 186,  93}}, {{ 94, 226, 188,  94}}, {{ 95, 225, 190,  95}}, 
> +                {{ 96, 160, 192,  96}}, {{ 97, 163, 194,  97}}, {{ 98, 166, 196,  98}}, 
> +                {{ 99, 165, 198,  99}}, {{100, 172, 200, 100}}, {{101, 175, 202, 101}}, 
> +                {{102, 170, 204, 102}}, {{103, 169, 206, 103}}, {{104, 184, 208, 104}}, 
> +                {{105, 187, 210, 105}}, {{106, 190, 212, 106}}, {{107, 189, 214, 107}}, 
> +                {{108, 180, 216, 108}}, {{109, 183, 218, 109}}, {{110, 178, 220, 110}}, 
> +                {{111, 177, 222, 111}}, {{112, 144, 224, 112}}, {{113, 147, 226, 113}}, 
> +                {{114, 150, 228, 114}}, {{115, 149, 230, 115}}, {{116, 156, 232, 116}}, 
> +                {{117, 159, 234, 117}}, {{118, 154, 236, 118}}, {{119, 153, 238, 119}}, 
> +                {{120, 136, 240, 120}}, {{121, 139, 242, 121}}, {{122, 142, 244, 122}}, 
> +                {{123, 141, 246, 123}}, {{124, 132, 248, 124}}, {{125, 135, 250, 125}}, 
> +                {{126, 130, 252, 126}}, {{127, 129, 254, 127}}, {{128, 155,  27, 128}}, 
> +                {{129, 152,  25, 129}}, {{130, 157,  31, 130}}, {{131, 158,  29, 131}}, 
> +                {{132, 151,  19, 132}}, {{133, 148,  17, 133}}, {{134, 145,  23, 134}}, 
> +                {{135, 146,  21, 135}}, {{136, 131,  11, 136}}, {{137, 128,   9, 137}}, 
> +                {{138, 133,  15, 138}}, {{139, 134,  13, 139}}, {{140, 143,   3, 140}}, 
> +                {{141, 140,   1, 141}}, {{142, 137,   7, 142}}, {{143, 138,   5, 143}}, 
> +                {{144, 171,  59, 144}}, {{145, 168,  57, 145}}, {{146, 173,  63, 146}}, 
> +                {{147, 174,  61, 147}}, {{148, 167,  51, 148}}, {{149, 164,  49, 149}}, 
> +                {{150, 161,  55, 150}}, {{151, 162,  53, 151}}, {{152, 179,  43, 152}}, 
> +                {{153, 176,  41, 153}}, {{154, 181,  47, 154}}, {{155, 182,  45, 155}}, 
> +                {{156, 191,  35, 156}}, {{157, 188,  33, 157}}, {{158, 185,  39, 158}}, 
> +                {{159, 186,  37, 159}}, {{160, 251,  91, 160}}, {{161, 248,  89, 161}}, 
> +                {{162, 253,  95, 162}}, {{163, 254,  93, 163}}, {{164, 247,  83, 164}}, 
> +                {{165, 244,  81, 165}}, {{166, 241,  87, 166}}, {{167, 242,  85, 167}}, 
> +                {{168, 227,  75, 168}}, {{169, 224,  73, 169}}, {{170, 229,  79, 170}}, 
> +                {{171, 230,  77, 171}}, {{172, 239,  67, 172}}, {{173, 236,  65, 173}}, 
> +                {{174, 233,  71, 174}}, {{175, 234,  69, 175}}, {{176, 203, 123, 176}}, 
> +                {{177, 200, 121, 177}}, {{178, 205, 127, 178}}, {{179, 206, 125, 179}}, 
> +                {{180, 199, 115, 180}}, {{181, 196, 113, 181}}, {{182, 193, 119, 182}}, 
> +                {{183, 194, 117, 183}}, {{184, 211, 107, 184}}, {{185, 208, 105, 185}}, 
> +                {{186, 213, 111, 186}}, {{187, 214, 109, 187}}, {{188, 223,  99, 188}}, 
> +                {{189, 220,  97, 189}}, {{190, 217, 103, 190}}, {{191, 218, 101, 191}}, 
> +                {{192,  91, 155, 192}}, {{193,  88, 153, 193}}, {{194,  93, 159, 194}}, 
> +                {{195,  94, 157, 195}}, {{196,  87, 147, 196}}, {{197,  84, 145, 197}}, 
> +                {{198,  81, 151, 198}}, {{199,  82, 149, 199}}, {{200,  67, 139, 200}}, 
> +                {{201,  64, 137, 201}}, {{202,  69, 143, 202}}, {{203,  70, 141, 203}}, 
> +                {{204,  79, 131, 204}}, {{205,  76, 129, 205}}, {{206,  73, 135, 206}}, 
> +                {{207,  74, 133, 207}}, {{208, 107, 187, 208}}, {{209, 104, 185, 209}}, 
> +                {{210, 109, 191, 210}}, {{211, 110, 189, 211}}, {{212, 103, 179, 212}}, 
> +                {{213, 100, 177, 213}}, {{214,  97, 183, 214}}, {{215,  98, 181, 215}}, 
> +                {{216, 115, 171, 216}}, {{217, 112, 169, 217}}, {{218, 117, 175, 218}}, 
> +                {{219, 118, 173, 219}}, {{220, 127, 163, 220}}, {{221, 124, 161, 221}}, 
> +                {{222, 121, 167, 222}}, {{223, 122, 165, 223}}, {{224,  59, 219, 224}}, 
> +                {{225,  56, 217, 225}}, {{226,  61, 223, 226}}, {{227,  62, 221, 227}}, 
> +                {{228,  55, 211, 228}}, {{229,  52, 209, 229}}, {{230,  49, 215, 230}}, 
> +                {{231,  50, 213, 231}}, {{232,  35, 203, 232}}, {{233,  32, 201, 233}}, 
> +                {{234,  37, 207, 234}}, {{235,  38, 205, 235}}, {{236,  47, 195, 236}}, 
> +                {{237,  44, 193, 237}}, {{238,  41, 199, 238}}, {{239,  42, 197, 239}}, 
> +                {{240,  11, 251, 240}}, {{241,   8, 249, 241}}, {{242,  13, 255, 242}}, 
> +                {{243,  14, 253, 243}}, {{244,   7, 243, 244}}, {{245,   4, 241, 245}}, 
> +                {{246,   1, 247, 246}}, {{247,   2, 245, 247}}, {{248,  19, 235, 248}}, 
> +                {{249,  16, 233, 249}}, {{250,  21, 239, 250}}, {{251,  22, 237, 251}}, 
> +                {{252,  31, 227, 252}}, {{253,  28, 225, 253}}, {{254,  25, 231, 254}}, 
> +                {{255,  26, 229, 255}}, 
> +        },
> +        {
> +                {{  0,   0,   0,   0}}, {{  1,   1,   3,   2}}, {{  2,   2,   6,   4}}, 
> +                {{  3,   3,   5,   6}}, {{  4,   4,  12,   8}}, {{  5,   5,  15,  10}}, 
> +                {{  6,   6,  10,  12}}, {{  7,   7,   9,  14}}, {{  8,   8,  24,  16}}, 
> +                {{  9,   9,  27,  18}}, {{ 10,  10,  30,  20}}, {{ 11,  11,  29,  22}}, 
> +                {{ 12,  12,  20,  24}}, {{ 13,  13,  23,  26}}, {{ 14,  14,  18,  28}}, 
> +                {{ 15,  15,  17,  30}}, {{ 16,  16,  48,  32}}, {{ 17,  17,  51,  34}}, 
> +                {{ 18,  18,  54,  36}}, {{ 19,  19,  53,  38}}, {{ 20,  20,  60,  40}}, 
> +                {{ 21,  21,  63,  42}}, {{ 22,  22,  58,  44}}, {{ 23,  23,  57,  46}}, 
> +                {{ 24,  24,  40,  48}}, {{ 25,  25,  43,  50}}, {{ 26,  26,  46,  52}}, 
> +                {{ 27,  27,  45,  54}}, {{ 28,  28,  36,  56}}, {{ 29,  29,  39,  58}}, 
> +                {{ 30,  30,  34,  60}}, {{ 31,  31,  33,  62}}, {{ 32,  32,  96,  64}}, 
> +                {{ 33,  33,  99,  66}}, {{ 34,  34, 102,  68}}, {{ 35,  35, 101,  70}}, 
> +                {{ 36,  36, 108,  72}}, {{ 37,  37, 111,  74}}, {{ 38,  38, 106,  76}}, 
> +                {{ 39,  39, 105,  78}}, {{ 40,  40, 120,  80}}, {{ 41,  41, 123,  82}}, 
> +                {{ 42,  42, 126,  84}}, {{ 43,  43, 125,  86}}, {{ 44,  44, 116,  88}}, 
> +                {{ 45,  45, 119,  90}}, {{ 46,  46, 114,  92}}, {{ 47,  47, 113,  94}}, 
> +                {{ 48,  48,  80,  96}}, {{ 49,  49,  83,  98}}, {{ 50,  50,  86, 100}}, 
> +                {{ 51,  51,  85, 102}}, {{ 52,  52,  92, 104}}, {{ 53,  53,  95, 106}}, 
> +                {{ 54,  54,  90, 108}}, {{ 55,  55,  89, 110}}, {{ 56,  56,  72, 112}}, 
> +                {{ 57,  57,  75, 114}}, {{ 58,  58,  78, 116}}, {{ 59,  59,  77, 118}}, 
> +                {{ 60,  60,  68, 120}}, {{ 61,  61,  71, 122}}, {{ 62,  62,  66, 124}}, 
> +                {{ 63,  63,  65, 126}}, {{ 64,  64, 192, 128}}, {{ 65,  65, 195, 130}}, 
> +                {{ 66,  66, 198, 132}}, {{ 67,  67, 197, 134}}, {{ 68,  68, 204, 136}}, 
> +                {{ 69,  69, 207, 138}}, {{ 70,  70, 202, 140}}, {{ 71,  71, 201, 142}}, 
> +                {{ 72,  72, 216, 144}}, {{ 73,  73, 219, 146}}, {{ 74,  74, 222, 148}}, 
> +                {{ 75,  75, 221, 150}}, {{ 76,  76, 212, 152}}, {{ 77,  77, 215, 154}}, 
> +                {{ 78,  78, 210, 156}}, {{ 79,  79, 209, 158}}, {{ 80,  80, 240, 160}}, 
> +                {{ 81,  81, 243, 162}}, {{ 82,  82, 246, 164}}, {{ 83,  83, 245, 166}}, 
> +                {{ 84,  84, 252, 168}}, {{ 85,  85, 255, 170}}, {{ 86,  86, 250, 172}}, 
> +                {{ 87,  87, 249, 174}}, {{ 88,  88, 232, 176}}, {{ 89,  89, 235, 178}}, 
> +                {{ 90,  90, 238, 180}}, {{ 91,  91, 237, 182}}, {{ 92,  92, 228, 184}}, 
> +                {{ 93,  93, 231, 186}}, {{ 94,  94, 226, 188}}, {{ 95,  95, 225, 190}}, 
> +                {{ 96,  96, 160, 192}}, {{ 97,  97, 163, 194}}, {{ 98,  98, 166, 196}}, 
> +                {{ 99,  99, 165, 198}}, {{100, 100, 172, 200}}, {{101, 101, 175, 202}}, 
> +                {{102, 102, 170, 204}}, {{103, 103, 169, 206}}, {{104, 104, 184, 208}}, 
> +                {{105, 105, 187, 210}}, {{106, 106, 190, 212}}, {{107, 107, 189, 214}}, 
> +                {{108, 108, 180, 216}}, {{109, 109, 183, 218}}, {{110, 110, 178, 220}}, 
> +                {{111, 111, 177, 222}}, {{112, 112, 144, 224}}, {{113, 113, 147, 226}}, 
> +                {{114, 114, 150, 228}}, {{115, 115, 149, 230}}, {{116, 116, 156, 232}}, 
> +                {{117, 117, 159, 234}}, {{118, 118, 154, 236}}, {{119, 119, 153, 238}}, 
> +                {{120, 120, 136, 240}}, {{121, 121, 139, 242}}, {{122, 122, 142, 244}}, 
> +                {{123, 123, 141, 246}}, {{124, 124, 132, 248}}, {{125, 125, 135, 250}}, 
> +                {{126, 126, 130, 252}}, {{127, 127, 129, 254}}, {{128, 128, 155,  27}}, 
> +                {{129, 129, 152,  25}}, {{130, 130, 157,  31}}, {{131, 131, 158,  29}}, 
> +                {{132, 132, 151,  19}}, {{133, 133, 148,  17}}, {{134, 134, 145,  23}}, 
> +                {{135, 135, 146,  21}}, {{136, 136, 131,  11}}, {{137, 137, 128,   9}}, 
> +                {{138, 138, 133,  15}}, {{139, 139, 134,  13}}, {{140, 140, 143,   3}}, 
> +                {{141, 141, 140,   1}}, {{142, 142, 137,   7}}, {{143, 143, 138,   5}}, 
> +                {{144, 144, 171,  59}}, {{145, 145, 168,  57}}, {{146, 146, 173,  63}}, 
> +                {{147, 147, 174,  61}}, {{148, 148, 167,  51}}, {{149, 149, 164,  49}}, 
> +                {{150, 150, 161,  55}}, {{151, 151, 162,  53}}, {{152, 152, 179,  43}}, 
> +                {{153, 153, 176,  41}}, {{154, 154, 181,  47}}, {{155, 155, 182,  45}}, 
> +                {{156, 156, 191,  35}}, {{157, 157, 188,  33}}, {{158, 158, 185,  39}}, 
> +                {{159, 159, 186,  37}}, {{160, 160, 251,  91}}, {{161, 161, 248,  89}}, 
> +                {{162, 162, 253,  95}}, {{163, 163, 254,  93}}, {{164, 164, 247,  83}}, 
> +                {{165, 165, 244,  81}}, {{166, 166, 241,  87}}, {{167, 167, 242,  85}}, 
> +                {{168, 168, 227,  75}}, {{169, 169, 224,  73}}, {{170, 170, 229,  79}}, 
> +                {{171, 171, 230,  77}}, {{172, 172, 239,  67}}, {{173, 173, 236,  65}}, 
> +                {{174, 174, 233,  71}}, {{175, 175, 234,  69}}, {{176, 176, 203, 123}}, 
> +                {{177, 177, 200, 121}}, {{178, 178, 205, 127}}, {{179, 179, 206, 125}}, 
> +                {{180, 180, 199, 115}}, {{181, 181, 196, 113}}, {{182, 182, 193, 119}}, 
> +                {{183, 183, 194, 117}}, {{184, 184, 211, 107}}, {{185, 185, 208, 105}}, 
> +                {{186, 186, 213, 111}}, {{187, 187, 214, 109}}, {{188, 188, 223,  99}}, 
> +                {{189, 189, 220,  97}}, {{190, 190, 217, 103}}, {{191, 191, 218, 101}}, 
> +                {{192, 192,  91, 155}}, {{193, 193,  88, 153}}, {{194, 194,  93, 159}}, 
> +                {{195, 195,  94, 157}}, {{196, 196,  87, 147}}, {{197, 197,  84, 145}}, 
> +                {{198, 198,  81, 151}}, {{199, 199,  82, 149}}, {{200, 200,  67, 139}}, 
> +                {{201, 201,  64, 137}}, {{202, 202,  69, 143}}, {{203, 203,  70, 141}}, 
> +                {{204, 204,  79, 131}}, {{205, 205,  76, 129}}, {{206, 206,  73, 135}}, 
> +                {{207, 207,  74, 133}}, {{208, 208, 107, 187}}, {{209, 209, 104, 185}}, 
> +                {{210, 210, 109, 191}}, {{211, 211, 110, 189}}, {{212, 212, 103, 179}}, 
> +                {{213, 213, 100, 177}}, {{214, 214,  97, 183}}, {{215, 215,  98, 181}}, 
> +                {{216, 216, 115, 171}}, {{217, 217, 112, 169}}, {{218, 218, 117, 175}}, 
> +                {{219, 219, 118, 173}}, {{220, 220, 127, 163}}, {{221, 221, 124, 161}}, 
> +                {{222, 222, 121, 167}}, {{223, 223, 122, 165}}, {{224, 224,  59, 219}}, 
> +                {{225, 225,  56, 217}}, {{226, 226,  61, 223}}, {{227, 227,  62, 221}}, 
> +                {{228, 228,  55, 211}}, {{229, 229,  52, 209}}, {{230, 230,  49, 215}}, 
> +                {{231, 231,  50, 213}}, {{232, 232,  35, 203}}, {{233, 233,  32, 201}}, 
> +                {{234, 234,  37, 207}}, {{235, 235,  38, 205}}, {{236, 236,  47, 195}}, 
> +                {{237, 237,  44, 193}}, {{238, 238,  41, 199}}, {{239, 239,  42, 197}}, 
> +                {{240, 240,  11, 251}}, {{241, 241,   8, 249}}, {{242, 242,  13, 255}}, 
> +                {{243, 243,  14, 253}}, {{244, 244,   7, 243}}, {{245, 245,   4, 241}}, 
> +                {{246, 246,   1, 247}}, {{247, 247,   2, 245}}, {{248, 248,  19, 235}}, 
> +                {{249, 249,  16, 233}}, {{250, 250,  21, 239}}, {{251, 251,  22, 237}}, 
> +                {{252, 252,  31, 227}}, {{253, 253,  28, 225}}, {{254, 254,  25, 231}}, 
> +                {{255, 255,  26, 229}}, 
> +        },
> +};
> +
> +word8x4 M1[4][256] = {
> +        {
> +                {{  0,   0,   0,   0}}, {{ 14,   9,  13,  11}}, {{ 28,  18,  26,  22}}, 
> +                {{ 18,  27,  23,  29}}, {{ 56,  36,  52,  44}}, {{ 54,  45,  57,  39}}, 
> +                {{ 36,  54,  46,  58}}, {{ 42,  63,  35,  49}}, {{112,  72, 104,  88}}, 
> +                {{126,  65, 101,  83}}, {{108,  90, 114,  78}}, {{ 98,  83, 127,  69}}, 
> +                {{ 72, 108,  92, 116}}, {{ 70, 101,  81, 127}}, {{ 84, 126,  70,  98}}, 
> +                {{ 90, 119,  75, 105}}, {{224, 144, 208, 176}}, {{238, 153, 221, 187}}, 
> +                {{252, 130, 202, 166}}, {{242, 139, 199, 173}}, {{216, 180, 228, 156}}, 
> +                {{214, 189, 233, 151}}, {{196, 166, 254, 138}}, {{202, 175, 243, 129}}, 
> +                {{144, 216, 184, 232}}, {{158, 209, 181, 227}}, {{140, 202, 162, 254}}, 
> +                {{130, 195, 175, 245}}, {{168, 252, 140, 196}}, {{166, 245, 129, 207}}, 
> +                {{180, 238, 150, 210}}, {{186, 231, 155, 217}}, {{219,  59, 187, 123}}, 
> +                {{213,  50, 182, 112}}, {{199,  41, 161, 109}}, {{201,  32, 172, 102}}, 
> +                {{227,  31, 143,  87}}, {{237,  22, 130,  92}}, {{255,  13, 149,  65}}, 
> +                {{241,   4, 152,  74}}, {{171, 115, 211,  35}}, {{165, 122, 222,  40}}, 
> +                {{183,  97, 201,  53}}, {{185, 104, 196,  62}}, {{147,  87, 231,  15}}, 
> +                {{157,  94, 234,   4}}, {{143,  69, 253,  25}}, {{129,  76, 240,  18}}, 
> +                {{ 59, 171, 107, 203}}, {{ 53, 162, 102, 192}}, {{ 39, 185, 113, 221}}, 
> +                {{ 41, 176, 124, 214}}, {{  3, 143,  95, 231}}, {{ 13, 134,  82, 236}}, 
> +                {{ 31, 157,  69, 241}}, {{ 17, 148,  72, 250}}, {{ 75, 227,   3, 147}}, 
> +                {{ 69, 234,  14, 152}}, {{ 87, 241,  25, 133}}, {{ 89, 248,  20, 142}}, 
> +                {{115, 199,  55, 191}}, {{125, 206,  58, 180}}, {{111, 213,  45, 169}}, 
> +                {{ 97, 220,  32, 162}}, {{173, 118, 109, 246}}, {{163, 127,  96, 253}}, 
> +                {{177, 100, 119, 224}}, {{191, 109, 122, 235}}, {{149,  82,  89, 218}}, 
> +                {{155,  91,  84, 209}}, {{137,  64,  67, 204}}, {{135,  73,  78, 199}}, 
> +                {{221,  62,   5, 174}}, {{211,  55,   8, 165}}, {{193,  44,  31, 184}}, 
> +                {{207,  37,  18, 179}}, {{229,  26,  49, 130}}, {{235,  19,  60, 137}}, 
> +                {{249,   8,  43, 148}}, {{247,   1,  38, 159}}, {{ 77, 230, 189,  70}}, 
> +                {{ 67, 239, 176,  77}}, {{ 81, 244, 167,  80}}, {{ 95, 253, 170,  91}}, 
> +                {{117, 194, 137, 106}}, {{123, 203, 132,  97}}, {{105, 208, 147, 124}}, 
> +                {{103, 217, 158, 119}}, {{ 61, 174, 213,  30}}, {{ 51, 167, 216,  21}}, 
> +                {{ 33, 188, 207,   8}}, {{ 47, 181, 194,   3}}, {{  5, 138, 225,  50}}, 
> +                {{ 11, 131, 236,  57}}, {{ 25, 152, 251,  36}}, {{ 23, 145, 246,  47}}, 
> +                {{118,  77, 214, 141}}, {{120,  68, 219, 134}}, {{106,  95, 204, 155}}, 
> +                {{100,  86, 193, 144}}, {{ 78, 105, 226, 161}}, {{ 64,  96, 239, 170}}, 
> +                {{ 82, 123, 248, 183}}, {{ 92, 114, 245, 188}}, {{  6,   5, 190, 213}}, 
> +                {{  8,  12, 179, 222}}, {{ 26,  23, 164, 195}}, {{ 20,  30, 169, 200}}, 
> +                {{ 62,  33, 138, 249}}, {{ 48,  40, 135, 242}}, {{ 34,  51, 144, 239}}, 
> +                {{ 44,  58, 157, 228}}, {{150, 221,   6,  61}}, {{152, 212,  11,  54}}, 
> +                {{138, 207,  28,  43}}, {{132, 198,  17,  32}}, {{174, 249,  50,  17}}, 
> +                {{160, 240,  63,  26}}, {{178, 235,  40,   7}}, {{188, 226,  37,  12}}, 
> +                {{230, 149, 110, 101}}, {{232, 156,  99, 110}}, {{250, 135, 116, 115}}, 
> +                {{244, 142, 121, 120}}, {{222, 177,  90,  73}}, {{208, 184,  87,  66}}, 
> +                {{194, 163,  64,  95}}, {{204, 170,  77,  84}}, {{ 65, 236, 218, 247}}, 
> +                {{ 79, 229, 215, 252}}, {{ 93, 254, 192, 225}}, {{ 83, 247, 205, 234}}, 
> +                {{121, 200, 238, 219}}, {{119, 193, 227, 208}}, {{101, 218, 244, 205}}, 
> +                {{107, 211, 249, 198}}, {{ 49, 164, 178, 175}}, {{ 63, 173, 191, 164}}, 
> +                {{ 45, 182, 168, 185}}, {{ 35, 191, 165, 178}}, {{  9, 128, 134, 131}}, 
> +                {{  7, 137, 139, 136}}, {{ 21, 146, 156, 149}}, {{ 27, 155, 145, 158}}, 
> +                {{161, 124,  10,  71}}, {{175, 117,   7,  76}}, {{189, 110,  16,  81}}, 
> +                {{179, 103,  29,  90}}, {{153,  88,  62, 107}}, {{151,  81,  51,  96}}, 
> +                {{133,  74,  36, 125}}, {{139,  67,  41, 118}}, {{209,  52,  98,  31}}, 
> +                {{223,  61, 111,  20}}, {{205,  38, 120,   9}}, {{195,  47, 117,   2}}, 
> +                {{233,  16,  86,  51}}, {{231,  25,  91,  56}}, {{245,   2,  76,  37}}, 
> +                {{251,  11,  65,  46}}, {{154, 215,  97, 140}}, {{148, 222, 108, 135}}, 
> +                {{134, 197, 123, 154}}, {{136, 204, 118, 145}}, {{162, 243,  85, 160}}, 
> +                {{172, 250,  88, 171}}, {{190, 225,  79, 182}}, {{176, 232,  66, 189}}, 
> +                {{234, 159,   9, 212}}, {{228, 150,   4, 223}}, {{246, 141,  19, 194}}, 
> +                {{248, 132,  30, 201}}, {{210, 187,  61, 248}}, {{220, 178,  48, 243}}, 
> +                {{206, 169,  39, 238}}, {{192, 160,  42, 229}}, {{122,  71, 177,  60}}, 
> +                {{116,  78, 188,  55}}, {{102,  85, 171,  42}}, {{104,  92, 166,  33}}, 
> +                {{ 66,  99, 133,  16}}, {{ 76, 106, 136,  27}}, {{ 94, 113, 159,   6}}, 
> +                {{ 80, 120, 146,  13}}, {{ 10,  15, 217, 100}}, {{  4,   6, 212, 111}}, 
> +                {{ 22,  29, 195, 114}}, {{ 24,  20, 206, 121}}, {{ 50,  43, 237,  72}}, 
> +                {{ 60,  34, 224,  67}}, {{ 46,  57, 247,  94}}, {{ 32,  48, 250,  85}}, 
> +                {{236, 154, 183,   1}}, {{226, 147, 186,  10}}, {{240, 136, 173,  23}}, 
> +                {{254, 129, 160,  28}}, {{212, 190, 131,  45}}, {{218, 183, 142,  38}}, 
> +                {{200, 172, 153,  59}}, {{198, 165, 148,  48}}, {{156, 210, 223,  89}}, 
> +                {{146, 219, 210,  82}}, {{128, 192, 197,  79}}, {{142, 201, 200,  68}}, 
> +                {{164, 246, 235, 117}}, {{170, 255, 230, 126}}, {{184, 228, 241,  99}}, 
> +                {{182, 237, 252, 104}}, {{ 12,  10, 103, 177}}, {{  2,   3, 106, 186}}, 
> +                {{ 16,  24, 125, 167}}, {{ 30,  17, 112, 172}}, {{ 52,  46,  83, 157}}, 
> +                {{ 58,  39,  94, 150}}, {{ 40,  60,  73, 139}}, {{ 38,  53,  68, 128}}, 
> +                {{124,  66,  15, 233}}, {{114,  75,   2, 226}}, {{ 96,  80,  21, 255}}, 
> +                {{110,  89,  24, 244}}, {{ 68, 102,  59, 197}}, {{ 74, 111,  54, 206}}, 
> +                {{ 88, 116,  33, 211}}, {{ 86, 125,  44, 216}}, {{ 55, 161,  12, 122}}, 
> +                {{ 57, 168,   1, 113}}, {{ 43, 179,  22, 108}}, {{ 37, 186,  27, 103}}, 
> +                {{ 15, 133,  56,  86}}, {{  1, 140,  53,  93}}, {{ 19, 151,  34,  64}}, 
> +                {{ 29, 158,  47,  75}}, {{ 71, 233, 100,  34}}, {{ 73, 224, 105,  41}}, 
> +                {{ 91, 251, 126,  52}}, {{ 85, 242, 115,  63}}, {{127, 205,  80,  14}}, 
> +                {{113, 196,  93,   5}}, {{ 99, 223,  74,  24}}, {{109, 214,  71,  19}}, 
> +                {{215,  49, 220, 202}}, {{217,  56, 209, 193}}, {{203,  35, 198, 220}}, 
> +                {{197,  42, 203, 215}}, {{239,  21, 232, 230}}, {{225,  28, 229, 237}}, 
> +                {{243,   7, 242, 240}}, {{253,  14, 255, 251}}, {{167, 121, 180, 146}}, 
> +                {{169, 112, 185, 153}}, {{187, 107, 174, 132}}, {{181,  98, 163, 143}}, 
> +                {{159,  93, 128, 190}}, {{145,  84, 141, 181}}, {{131,  79, 154, 168}}, 
> +                {{141,  70, 151, 163}}, 
> +        },
> +        {
> +                {{  0,   0,   0,   0}}, {{ 11,  14,   9,  13}}, {{ 22,  28,  18,  26}}, 
> +                {{ 29,  18,  27,  23}}, {{ 44,  56,  36,  52}}, {{ 39,  54,  45,  57}}, 
> +                {{ 58,  36,  54,  46}}, {{ 49,  42,  63,  35}}, {{ 88, 112,  72, 104}}, 
> +                {{ 83, 126,  65, 101}}, {{ 78, 108,  90, 114}}, {{ 69,  98,  83, 127}}, 
> +                {{116,  72, 108,  92}}, {{127,  70, 101,  81}}, {{ 98,  84, 126,  70}}, 
> +                {{105,  90, 119,  75}}, {{176, 224, 144, 208}}, {{187, 238, 153, 221}}, 
> +                {{166, 252, 130, 202}}, {{173, 242, 139, 199}}, {{156, 216, 180, 228}}, 
> +                {{151, 214, 189, 233}}, {{138, 196, 166, 254}}, {{129, 202, 175, 243}}, 
> +                {{232, 144, 216, 184}}, {{227, 158, 209, 181}}, {{254, 140, 202, 162}}, 
> +                {{245, 130, 195, 175}}, {{196, 168, 252, 140}}, {{207, 166, 245, 129}}, 
> +                {{210, 180, 238, 150}}, {{217, 186, 231, 155}}, {{123, 219,  59, 187}}, 
> +                {{112, 213,  50, 182}}, {{109, 199,  41, 161}}, {{102, 201,  32, 172}}, 
> +                {{ 87, 227,  31, 143}}, {{ 92, 237,  22, 130}}, {{ 65, 255,  13, 149}}, 
> +                {{ 74, 241,   4, 152}}, {{ 35, 171, 115, 211}}, {{ 40, 165, 122, 222}}, 
> +                {{ 53, 183,  97, 201}}, {{ 62, 185, 104, 196}}, {{ 15, 147,  87, 231}}, 
> +                {{  4, 157,  94, 234}}, {{ 25, 143,  69, 253}}, {{ 18, 129,  76, 240}}, 
> +                {{203,  59, 171, 107}}, {{192,  53, 162, 102}}, {{221,  39, 185, 113}}, 
> +                {{214,  41, 176, 124}}, {{231,   3, 143,  95}}, {{236,  13, 134,  82}}, 
> +                {{241,  31, 157,  69}}, {{250,  17, 148,  72}}, {{147,  75, 227,   3}}, 
> +                {{152,  69, 234,  14}}, {{133,  87, 241,  25}}, {{142,  89, 248,  20}}, 
> +                {{191, 115, 199,  55}}, {{180, 125, 206,  58}}, {{169, 111, 213,  45}}, 
> +                {{162,  97, 220,  32}}, {{246, 173, 118, 109}}, {{253, 163, 127,  96}}, 
> +                {{224, 177, 100, 119}}, {{235, 191, 109, 122}}, {{218, 149,  82,  89}}, 
> +                {{209, 155,  91,  84}}, {{204, 137,  64,  67}}, {{199, 135,  73,  78}}, 
> +                {{174, 221,  62,   5}}, {{165, 211,  55,   8}}, {{184, 193,  44,  31}}, 
> +                {{179, 207,  37,  18}}, {{130, 229,  26,  49}}, {{137, 235,  19,  60}}, 
> +                {{148, 249,   8,  43}}, {{159, 247,   1,  38}}, {{ 70,  77, 230, 189}}, 
> +                {{ 77,  67, 239, 176}}, {{ 80,  81, 244, 167}}, {{ 91,  95, 253, 170}}, 
> +                {{106, 117, 194, 137}}, {{ 97, 123, 203, 132}}, {{124, 105, 208, 147}}, 
> +                {{119, 103, 217, 158}}, {{ 30,  61, 174, 213}}, {{ 21,  51, 167, 216}}, 
> +                {{  8,  33, 188, 207}}, {{  3,  47, 181, 194}}, {{ 50,   5, 138, 225}}, 
> +                {{ 57,  11, 131, 236}}, {{ 36,  25, 152, 251}}, {{ 47,  23, 145, 246}}, 
> +                {{141, 118,  77, 214}}, {{134, 120,  68, 219}}, {{155, 106,  95, 204}}, 
> +                {{144, 100,  86, 193}}, {{161,  78, 105, 226}}, {{170,  64,  96, 239}}, 
> +                {{183,  82, 123, 248}}, {{188,  92, 114, 245}}, {{213,   6,   5, 190}}, 
> +                {{222,   8,  12, 179}}, {{195,  26,  23, 164}}, {{200,  20,  30, 169}}, 
> +                {{249,  62,  33, 138}}, {{242,  48,  40, 135}}, {{239,  34,  51, 144}}, 
> +                {{228,  44,  58, 157}}, {{ 61, 150, 221,   6}}, {{ 54, 152, 212,  11}}, 
> +                {{ 43, 138, 207,  28}}, {{ 32, 132, 198,  17}}, {{ 17, 174, 249,  50}}, 
> +                {{ 26, 160, 240,  63}}, {{  7, 178, 235,  40}}, {{ 12, 188, 226,  37}}, 
> +                {{101, 230, 149, 110}}, {{110, 232, 156,  99}}, {{115, 250, 135, 116}}, 
> +                {{120, 244, 142, 121}}, {{ 73, 222, 177,  90}}, {{ 66, 208, 184,  87}}, 
> +                {{ 95, 194, 163,  64}}, {{ 84, 204, 170,  77}}, {{247,  65, 236, 218}}, 
> +                {{252,  79, 229, 215}}, {{225,  93, 254, 192}}, {{234,  83, 247, 205}}, 
> +                {{219, 121, 200, 238}}, {{208, 119, 193, 227}}, {{205, 101, 218, 244}}, 
> +                {{198, 107, 211, 249}}, {{175,  49, 164, 178}}, {{164,  63, 173, 191}}, 
> +                {{185,  45, 182, 168}}, {{178,  35, 191, 165}}, {{131,   9, 128, 134}}, 
> +                {{136,   7, 137, 139}}, {{149,  21, 146, 156}}, {{158,  27, 155, 145}}, 
> +                {{ 71, 161, 124,  10}}, {{ 76, 175, 117,   7}}, {{ 81, 189, 110,  16}}, 
> +                {{ 90, 179, 103,  29}}, {{107, 153,  88,  62}}, {{ 96, 151,  81,  51}}, 
> +                {{125, 133,  74,  36}}, {{118, 139,  67,  41}}, {{ 31, 209,  52,  98}}, 
> +                {{ 20, 223,  61, 111}}, {{  9, 205,  38, 120}}, {{  2, 195,  47, 117}}, 
> +                {{ 51, 233,  16,  86}}, {{ 56, 231,  25,  91}}, {{ 37, 245,   2,  76}}, 
> +                {{ 46, 251,  11,  65}}, {{140, 154, 215,  97}}, {{135, 148, 222, 108}}, 
> +                {{154, 134, 197, 123}}, {{145, 136, 204, 118}}, {{160, 162, 243,  85}}, 
> +                {{171, 172, 250,  88}}, {{182, 190, 225,  79}}, {{189, 176, 232,  66}}, 
> +                {{212, 234, 159,   9}}, {{223, 228, 150,   4}}, {{194, 246, 141,  19}}, 
> +                {{201, 248, 132,  30}}, {{248, 210, 187,  61}}, {{243, 220, 178,  48}}, 
> +                {{238, 206, 169,  39}}, {{229, 192, 160,  42}}, {{ 60, 122,  71, 177}}, 
> +                {{ 55, 116,  78, 188}}, {{ 42, 102,  85, 171}}, {{ 33, 104,  92, 166}}, 
> +                {{ 16,  66,  99, 133}}, {{ 27,  76, 106, 136}}, {{  6,  94, 113, 159}}, 
> +                {{ 13,  80, 120, 146}}, {{100,  10,  15, 217}}, {{111,   4,   6, 212}}, 
> +                {{114,  22,  29, 195}}, {{121,  24,  20, 206}}, {{ 72,  50,  43, 237}}, 
> +                {{ 67,  60,  34, 224}}, {{ 94,  46,  57, 247}}, {{ 85,  32,  48, 250}}, 
> +                {{  1, 236, 154, 183}}, {{ 10, 226, 147, 186}}, {{ 23, 240, 136, 173}}, 
> +                {{ 28, 254, 129, 160}}, {{ 45, 212, 190, 131}}, {{ 38, 218, 183, 142}}, 
> +                {{ 59, 200, 172, 153}}, {{ 48, 198, 165, 148}}, {{ 89, 156, 210, 223}}, 
> +                {{ 82, 146, 219, 210}}, {{ 79, 128, 192, 197}}, {{ 68, 142, 201, 200}}, 
> +                {{117, 164, 246, 235}}, {{126, 170, 255, 230}}, {{ 99, 184, 228, 241}}, 
> +                {{104, 182, 237, 252}}, {{177,  12,  10, 103}}, {{186,   2,   3, 106}}, 
> +                {{167,  16,  24, 125}}, {{172,  30,  17, 112}}, {{157,  52,  46,  83}}, 
> +                {{150,  58,  39,  94}}, {{139,  40,  60,  73}}, {{128,  38,  53,  68}}, 
> +                {{233, 124,  66,  15}}, {{226, 114,  75,   2}}, {{255,  96,  80,  21}}, 
> +                {{244, 110,  89,  24}}, {{197,  68, 102,  59}}, {{206,  74, 111,  54}}, 
> +                {{211,  88, 116,  33}}, {{216,  86, 125,  44}}, {{122,  55, 161,  12}}, 
> +                {{113,  57, 168,   1}}, {{108,  43, 179,  22}}, {{103,  37, 186,  27}}, 
> +                {{ 86,  15, 133,  56}}, {{ 93,   1, 140,  53}}, {{ 64,  19, 151,  34}}, 
> +                {{ 75,  29, 158,  47}}, {{ 34,  71, 233, 100}}, {{ 41,  73, 224, 105}}, 
> +                {{ 52,  91, 251, 126}}, {{ 63,  85, 242, 115}}, {{ 14, 127, 205,  80}}, 
> +                {{  5, 113, 196,  93}}, {{ 24,  99, 223,  74}}, {{ 19, 109, 214,  71}}, 
> +                {{202, 215,  49, 220}}, {{193, 217,  56, 209}}, {{220, 203,  35, 198}}, 
> +                {{215, 197,  42, 203}}, {{230, 239,  21, 232}}, {{237, 225,  28, 229}}, 
> +                {{240, 243,   7, 242}}, {{251, 253,  14, 255}}, {{146, 167, 121, 180}}, 
> +                {{153, 169, 112, 185}}, {{132, 187, 107, 174}}, {{143, 181,  98, 163}}, 
> +                {{190, 159,  93, 128}}, {{181, 145,  84, 141}}, {{168, 131,  79, 154}}, 
> +                {{163, 141,  70, 151}}, 
> +        },
> +        {
> +                {{  0,   0,   0,   0}}, {{ 13,  11,  14,   9}}, {{ 26,  22,  28,  18}}, 
> +                {{ 23,  29,  18,  27}}, {{ 52,  44,  56,  36}}, {{ 57,  39,  54,  45}}, 
> +                {{ 46,  58,  36,  54}}, {{ 35,  49,  42,  63}}, {{104,  88, 112,  72}}, 
> +                {{101,  83, 126,  65}}, {{114,  78, 108,  90}}, {{127,  69,  98,  83}}, 
> +                {{ 92, 116,  72, 108}}, {{ 81, 127,  70, 101}}, {{ 70,  98,  84, 126}}, 
> +                {{ 75, 105,  90, 119}}, {{208, 176, 224, 144}}, {{221, 187, 238, 153}}, 
> +                {{202, 166, 252, 130}}, {{199, 173, 242, 139}}, {{228, 156, 216, 180}}, 
> +                {{233, 151, 214, 189}}, {{254, 138, 196, 166}}, {{243, 129, 202, 175}}, 
> +                {{184, 232, 144, 216}}, {{181, 227, 158, 209}}, {{162, 254, 140, 202}}, 
> +                {{175, 245, 130, 195}}, {{140, 196, 168, 252}}, {{129, 207, 166, 245}}, 
> +                {{150, 210, 180, 238}}, {{155, 217, 186, 231}}, {{187, 123, 219,  59}}, 
> +                {{182, 112, 213,  50}}, {{161, 109, 199,  41}}, {{172, 102, 201,  32}}, 
> +                {{143,  87, 227,  31}}, {{130,  92, 237,  22}}, {{149,  65, 255,  13}}, 
> +                {{152,  74, 241,   4}}, {{211,  35, 171, 115}}, {{222,  40, 165, 122}}, 
> +                {{201,  53, 183,  97}}, {{196,  62, 185, 104}}, {{231,  15, 147,  87}}, 
> +                {{234,   4, 157,  94}}, {{253,  25, 143,  69}}, {{240,  18, 129,  76}}, 
> +                {{107, 203,  59, 171}}, {{102, 192,  53, 162}}, {{113, 221,  39, 185}}, 
> +                {{124, 214,  41, 176}}, {{ 95, 231,   3, 143}}, {{ 82, 236,  13, 134}}, 
> +                {{ 69, 241,  31, 157}}, {{ 72, 250,  17, 148}}, {{  3, 147,  75, 227}}, 
> +                {{ 14, 152,  69, 234}}, {{ 25, 133,  87, 241}}, {{ 20, 142,  89, 248}}, 
> +                {{ 55, 191, 115, 199}}, {{ 58, 180, 125, 206}}, {{ 45, 169, 111, 213}}, 
> +                {{ 32, 162,  97, 220}}, {{109, 246, 173, 118}}, {{ 96, 253, 163, 127}}, 
> +                {{119, 224, 177, 100}}, {{122, 235, 191, 109}}, {{ 89, 218, 149,  82}}, 
> +                {{ 84, 209, 155,  91}}, {{ 67, 204, 137,  64}}, {{ 78, 199, 135,  73}}, 
> +                {{  5, 174, 221,  62}}, {{  8, 165, 211,  55}}, {{ 31, 184, 193,  44}}, 
> +                {{ 18, 179, 207,  37}}, {{ 49, 130, 229,  26}}, {{ 60, 137, 235,  19}}, 
> +                {{ 43, 148, 249,   8}}, {{ 38, 159, 247,   1}}, {{189,  70,  77, 230}}, 
> +                {{176,  77,  67, 239}}, {{167,  80,  81, 244}}, {{170,  91,  95, 253}}, 
> +                {{137, 106, 117, 194}}, {{132,  97, 123, 203}}, {{147, 124, 105, 208}}, 
> +                {{158, 119, 103, 217}}, {{213,  30,  61, 174}}, {{216,  21,  51, 167}}, 
> +                {{207,   8,  33, 188}}, {{194,   3,  47, 181}}, {{225,  50,   5, 138}}, 
> +                {{236,  57,  11, 131}}, {{251,  36,  25, 152}}, {{246,  47,  23, 145}}, 
> +                {{214, 141, 118,  77}}, {{219, 134, 120,  68}}, {{204, 155, 106,  95}}, 
> +                {{193, 144, 100,  86}}, {{226, 161,  78, 105}}, {{239, 170,  64,  96}}, 
> +                {{248, 183,  82, 123}}, {{245, 188,  92, 114}}, {{190, 213,   6,   5}}, 
> +                {{179, 222,   8,  12}}, {{164, 195,  26,  23}}, {{169, 200,  20,  30}}, 
> +                {{138, 249,  62,  33}}, {{135, 242,  48,  40}}, {{144, 239,  34,  51}}, 
> +                {{157, 228,  44,  58}}, {{  6,  61, 150, 221}}, {{ 11,  54, 152, 212}}, 
> +                {{ 28,  43, 138, 207}}, {{ 17,  32, 132, 198}}, {{ 50,  17, 174, 249}}, 
> +                {{ 63,  26, 160, 240}}, {{ 40,   7, 178, 235}}, {{ 37,  12, 188, 226}}, 
> +                {{110, 101, 230, 149}}, {{ 99, 110, 232, 156}}, {{116, 115, 250, 135}}, 
> +                {{121, 120, 244, 142}}, {{ 90,  73, 222, 177}}, {{ 87,  66, 208, 184}}, 
> +                {{ 64,  95, 194, 163}}, {{ 77,  84, 204, 170}}, {{218, 247,  65, 236}}, 
> +                {{215, 252,  79, 229}}, {{192, 225,  93, 254}}, {{205, 234,  83, 247}}, 
> +                {{238, 219, 121, 200}}, {{227, 208, 119, 193}}, {{244, 205, 101, 218}}, 
> +                {{249, 198, 107, 211}}, {{178, 175,  49, 164}}, {{191, 164,  63, 173}}, 
> +                {{168, 185,  45, 182}}, {{165, 178,  35, 191}}, {{134, 131,   9, 128}}, 
> +                {{139, 136,   7, 137}}, {{156, 149,  21, 146}}, {{145, 158,  27, 155}}, 
> +                {{ 10,  71, 161, 124}}, {{  7,  76, 175, 117}}, {{ 16,  81, 189, 110}}, 
> +                {{ 29,  90, 179, 103}}, {{ 62, 107, 153,  88}}, {{ 51,  96, 151,  81}}, 
> +                {{ 36, 125, 133,  74}}, {{ 41, 118, 139,  67}}, {{ 98,  31, 209,  52}}, 
> +                {{111,  20, 223,  61}}, {{120,   9, 205,  38}}, {{117,   2, 195,  47}}, 
> +                {{ 86,  51, 233,  16}}, {{ 91,  56, 231,  25}}, {{ 76,  37, 245,   2}}, 
> +                {{ 65,  46, 251,  11}}, {{ 97, 140, 154, 215}}, {{108, 135, 148, 222}}, 
> +                {{123, 154, 134, 197}}, {{118, 145, 136, 204}}, {{ 85, 160, 162, 243}}, 
> +                {{ 88, 171, 172, 250}}, {{ 79, 182, 190, 225}}, {{ 66, 189, 176, 232}}, 
> +                {{  9, 212, 234, 159}}, {{  4, 223, 228, 150}}, {{ 19, 194, 246, 141}}, 
> +                {{ 30, 201, 248, 132}}, {{ 61, 248, 210, 187}}, {{ 48, 243, 220, 178}}, 
> +                {{ 39, 238, 206, 169}}, {{ 42, 229, 192, 160}}, {{177,  60, 122,  71}}, 
> +                {{188,  55, 116,  78}}, {{171,  42, 102,  85}}, {{166,  33, 104,  92}}, 
> +                {{133,  16,  66,  99}}, {{136,  27,  76, 106}}, {{159,   6,  94, 113}}, 
> +                {{146,  13,  80, 120}}, {{217, 100,  10,  15}}, {{212, 111,   4,   6}}, 
> +                {{195, 114,  22,  29}}, {{206, 121,  24,  20}}, {{237,  72,  50,  43}}, 
> +                {{224,  67,  60,  34}}, {{247,  94,  46,  57}}, {{250,  85,  32,  48}}, 
> +                {{183,   1, 236, 154}}, {{186,  10, 226, 147}}, {{173,  23, 240, 136}}, 
> +                {{160,  28, 254, 129}}, {{131,  45, 212, 190}}, {{142,  38, 218, 183}}, 
> +                {{153,  59, 200, 172}}, {{148,  48, 198, 165}}, {{223,  89, 156, 210}}, 
> +                {{210,  82, 146, 219}}, {{197,  79, 128, 192}}, {{200,  68, 142, 201}}, 
> +                {{235, 117, 164, 246}}, {{230, 126, 170, 255}}, {{241,  99, 184, 228}}, 
> +                {{252, 104, 182, 237}}, {{103, 177,  12,  10}}, {{106, 186,   2,   3}}, 
> +                {{125, 167,  16,  24}}, {{112, 172,  30,  17}}, {{ 83, 157,  52,  46}}, 
> +                {{ 94, 150,  58,  39}}, {{ 73, 139,  40,  60}}, {{ 68, 128,  38,  53}}, 
> +                {{ 15, 233, 124,  66}}, {{  2, 226, 114,  75}}, {{ 21, 255,  96,  80}}, 
> +                {{ 24, 244, 110,  89}}, {{ 59, 197,  68, 102}}, {{ 54, 206,  74, 111}}, 
> +                {{ 33, 211,  88, 116}}, {{ 44, 216,  86, 125}}, {{ 12, 122,  55, 161}}, 
> +                {{  1, 113,  57, 168}}, {{ 22, 108,  43, 179}}, {{ 27, 103,  37, 186}}, 
> +                {{ 56,  86,  15, 133}}, {{ 53,  93,   1, 140}}, {{ 34,  64,  19, 151}}, 
> +                {{ 47,  75,  29, 158}}, {{100,  34,  71, 233}}, {{105,  41,  73, 224}}, 
> +                {{126,  52,  91, 251}}, {{115,  63,  85, 242}}, {{ 80,  14, 127, 205}}, 
> +                {{ 93,   5, 113, 196}}, {{ 74,  24,  99, 223}}, {{ 71,  19, 109, 214}}, 
> +                {{220, 202, 215,  49}}, {{209, 193, 217,  56}}, {{198, 220, 203,  35}}, 
> +                {{203, 215, 197,  42}}, {{232, 230, 239,  21}}, {{229, 237, 225,  28}}, 
> +                {{242, 240, 243,   7}}, {{255, 251, 253,  14}}, {{180, 146, 167, 121}}, 
> +                {{185, 153, 169, 112}}, {{174, 132, 187, 107}}, {{163, 143, 181,  98}}, 
> +                {{128, 190, 159,  93}}, {{141, 181, 145,  84}}, {{154, 168, 131,  79}}, 
> +                {{151, 163, 141,  70}}, 
> +        },
> +        {
> +                {{  0,   0,   0,   0}}, {{  9,  13,  11,  14}}, {{ 18,  26,  22,  28}}, 
> +                {{ 27,  23,  29,  18}}, {{ 36,  52,  44,  56}}, {{ 45,  57,  39,  54}}, 
> +                {{ 54,  46,  58,  36}}, {{ 63,  35,  49,  42}}, {{ 72, 104,  88, 112}}, 
> +                {{ 65, 101,  83, 126}}, {{ 90, 114,  78, 108}}, {{ 83, 127,  69,  98}}, 
> +                {{108,  92, 116,  72}}, {{101,  81, 127,  70}}, {{126,  70,  98,  84}}, 
> +                {{119,  75, 105,  90}}, {{144, 208, 176, 224}}, {{153, 221, 187, 238}}, 
> +                {{130, 202, 166, 252}}, {{139, 199, 173, 242}}, {{180, 228, 156, 216}}, 
> +                {{189, 233, 151, 214}}, {{166, 254, 138, 196}}, {{175, 243, 129, 202}}, 
> +                {{216, 184, 232, 144}}, {{209, 181, 227, 158}}, {{202, 162, 254, 140}}, 
> +                {{195, 175, 245, 130}}, {{252, 140, 196, 168}}, {{245, 129, 207, 166}}, 
> +                {{238, 150, 210, 180}}, {{231, 155, 217, 186}}, {{ 59, 187, 123, 219}}, 
> +                {{ 50, 182, 112, 213}}, {{ 41, 161, 109, 199}}, {{ 32, 172, 102, 201}}, 
> +                {{ 31, 143,  87, 227}}, {{ 22, 130,  92, 237}}, {{ 13, 149,  65, 255}}, 
> +                {{  4, 152,  74, 241}}, {{115, 211,  35, 171}}, {{122, 222,  40, 165}}, 
> +                {{ 97, 201,  53, 183}}, {{104, 196,  62, 185}}, {{ 87, 231,  15, 147}}, 
> +                {{ 94, 234,   4, 157}}, {{ 69, 253,  25, 143}}, {{ 76, 240,  18, 129}}, 
> +                {{171, 107, 203,  59}}, {{162, 102, 192,  53}}, {{185, 113, 221,  39}}, 
> +                {{176, 124, 214,  41}}, {{143,  95, 231,   3}}, {{134,  82, 236,  13}}, 
> +                {{157,  69, 241,  31}}, {{148,  72, 250,  17}}, {{227,   3, 147,  75}}, 
> +                {{234,  14, 152,  69}}, {{241,  25, 133,  87}}, {{248,  20, 142,  89}}, 
> +                {{199,  55, 191, 115}}, {{206,  58, 180, 125}}, {{213,  45, 169, 111}}, 
> +                {{220,  32, 162,  97}}, {{118, 109, 246, 173}}, {{127,  96, 253, 163}}, 
> +                {{100, 119, 224, 177}}, {{109, 122, 235, 191}}, {{ 82,  89, 218, 149}}, 
> +                {{ 91,  84, 209, 155}}, {{ 64,  67, 204, 137}}, {{ 73,  78, 199, 135}}, 
> +                {{ 62,   5, 174, 221}}, {{ 55,   8, 165, 211}}, {{ 44,  31, 184, 193}}, 
> +                {{ 37,  18, 179, 207}}, {{ 26,  49, 130, 229}}, {{ 19,  60, 137, 235}}, 
> +                {{  8,  43, 148, 249}}, {{  1,  38, 159, 247}}, {{230, 189,  70,  77}}, 
> +                {{239, 176,  77,  67}}, {{244, 167,  80,  81}}, {{253, 170,  91,  95}}, 
> +                {{194, 137, 106, 117}}, {{203, 132,  97, 123}}, {{208, 147, 124, 105}}, 
> +                {{217, 158, 119, 103}}, {{174, 213,  30,  61}}, {{167, 216,  21,  51}}, 
> +                {{188, 207,   8,  33}}, {{181, 194,   3,  47}}, {{138, 225,  50,   5}}, 
> +                {{131, 236,  57,  11}}, {{152, 251,  36,  25}}, {{145, 246,  47,  23}}, 
> +                {{ 77, 214, 141, 118}}, {{ 68, 219, 134, 120}}, {{ 95, 204, 155, 106}}, 
> +                {{ 86, 193, 144, 100}}, {{105, 226, 161,  78}}, {{ 96, 239, 170,  64}}, 
> +                {{123, 248, 183,  82}}, {{114, 245, 188,  92}}, {{  5, 190, 213,   6}}, 
> +                {{ 12, 179, 222,   8}}, {{ 23, 164, 195,  26}}, {{ 30, 169, 200,  20}}, 
> +                {{ 33, 138, 249,  62}}, {{ 40, 135, 242,  48}}, {{ 51, 144, 239,  34}}, 
> +                {{ 58, 157, 228,  44}}, {{221,   6,  61, 150}}, {{212,  11,  54, 152}}, 
> +                {{207,  28,  43, 138}}, {{198,  17,  32, 132}}, {{249,  50,  17, 174}}, 
> +                {{240,  63,  26, 160}}, {{235,  40,   7, 178}}, {{226,  37,  12, 188}}, 
> +                {{149, 110, 101, 230}}, {{156,  99, 110, 232}}, {{135, 116, 115, 250}}, 
> +                {{142, 121, 120, 244}}, {{177,  90,  73, 222}}, {{184,  87,  66, 208}}, 
> +                {{163,  64,  95, 194}}, {{170,  77,  84, 204}}, {{236, 218, 247,  65}}, 
> +                {{229, 215, 252,  79}}, {{254, 192, 225,  93}}, {{247, 205, 234,  83}}, 
> +                {{200, 238, 219, 121}}, {{193, 227, 208, 119}}, {{218, 244, 205, 101}}, 
> +                {{211, 249, 198, 107}}, {{164, 178, 175,  49}}, {{173, 191, 164,  63}}, 
> +                {{182, 168, 185,  45}}, {{191, 165, 178,  35}}, {{128, 134, 131,   9}}, 
> +                {{137, 139, 136,   7}}, {{146, 156, 149,  21}}, {{155, 145, 158,  27}}, 
> +                {{124,  10,  71, 161}}, {{117,   7,  76, 175}}, {{110,  16,  81, 189}}, 
> +                {{103,  29,  90, 179}}, {{ 88,  62, 107, 153}}, {{ 81,  51,  96, 151}}, 
> +                {{ 74,  36, 125, 133}}, {{ 67,  41, 118, 139}}, {{ 52,  98,  31, 209}}, 
> +                {{ 61, 111,  20, 223}}, {{ 38, 120,   9, 205}}, {{ 47, 117,   2, 195}}, 
> +                {{ 16,  86,  51, 233}}, {{ 25,  91,  56, 231}}, {{  2,  76,  37, 245}}, 
> +                {{ 11,  65,  46, 251}}, {{215,  97, 140, 154}}, {{222, 108, 135, 148}}, 
> +                {{197, 123, 154, 134}}, {{204, 118, 145, 136}}, {{243,  85, 160, 162}}, 
> +                {{250,  88, 171, 172}}, {{225,  79, 182, 190}}, {{232,  66, 189, 176}}, 
> +                {{159,   9, 212, 234}}, {{150,   4, 223, 228}}, {{141,  19, 194, 246}}, 
> +                {{132,  30, 201, 248}}, {{187,  61, 248, 210}}, {{178,  48, 243, 220}}, 
> +                {{169,  39, 238, 206}}, {{160,  42, 229, 192}}, {{ 71, 177,  60, 122}}, 
> +                {{ 78, 188,  55, 116}}, {{ 85, 171,  42, 102}}, {{ 92, 166,  33, 104}}, 
> +                {{ 99, 133,  16,  66}}, {{106, 136,  27,  76}}, {{113, 159,   6,  94}}, 
> +                {{120, 146,  13,  80}}, {{ 15, 217, 100,  10}}, {{  6, 212, 111,   4}}, 
> +                {{ 29, 195, 114,  22}}, {{ 20, 206, 121,  24}}, {{ 43, 237,  72,  50}}, 
> +                {{ 34, 224,  67,  60}}, {{ 57, 247,  94,  46}}, {{ 48, 250,  85,  32}}, 
> +                {{154, 183,   1, 236}}, {{147, 186,  10, 226}}, {{136, 173,  23, 240}}, 
> +                {{129, 160,  28, 254}}, {{190, 131,  45, 212}}, {{183, 142,  38, 218}}, 
> +                {{172, 153,  59, 200}}, {{165, 148,  48, 198}}, {{210, 223,  89, 156}}, 
> +                {{219, 210,  82, 146}}, {{192, 197,  79, 128}}, {{201, 200,  68, 142}}, 
> +                {{246, 235, 117, 164}}, {{255, 230, 126, 170}}, {{228, 241,  99, 184}}, 
> +                {{237, 252, 104, 182}}, {{ 10, 103, 177,  12}}, {{  3, 106, 186,   2}}, 
> +                {{ 24, 125, 167,  16}}, {{ 17, 112, 172,  30}}, {{ 46,  83, 157,  52}}, 
> +                {{ 39,  94, 150,  58}}, {{ 60,  73, 139,  40}}, {{ 53,  68, 128,  38}}, 
> +                {{ 66,  15, 233, 124}}, {{ 75,   2, 226, 114}}, {{ 80,  21, 255,  96}}, 
> +                {{ 89,  24, 244, 110}}, {{102,  59, 197,  68}}, {{111,  54, 206,  74}}, 
> +                {{116,  33, 211,  88}}, {{125,  44, 216,  86}}, {{161,  12, 122,  55}}, 
> +                {{168,   1, 113,  57}}, {{179,  22, 108,  43}}, {{186,  27, 103,  37}}, 
> +                {{133,  56,  86,  15}}, {{140,  53,  93,   1}}, {{151,  34,  64,  19}}, 
> +                {{158,  47,  75,  29}}, {{233, 100,  34,  71}}, {{224, 105,  41,  73}}, 
> +                {{251, 126,  52,  91}}, {{242, 115,  63,  85}}, {{205,  80,  14, 127}}, 
> +                {{196,  93,   5, 113}}, {{223,  74,  24,  99}}, {{214,  71,  19, 109}}, 
> +                {{ 49, 220, 202, 215}}, {{ 56, 209, 193, 217}}, {{ 35, 198, 220, 203}}, 
> +                {{ 42, 203, 215, 197}}, {{ 21, 232, 230, 239}}, {{ 28, 229, 237, 225}}, 
> +                {{  7, 242, 240, 243}}, {{ 14, 255, 251, 253}}, {{121, 180, 146, 167}}, 
> +                {{112, 185, 153, 169}}, {{107, 174, 132, 187}}, {{ 98, 163, 143, 181}}, 
> +                {{ 93, 128, 190, 159}}, {{ 84, 141, 181, 145}}, {{ 79, 154, 168, 131}}, 
> +                {{ 70, 151, 163, 141}}, 
> +        },
> +};
> +
> +int xrcon[30] = {
> +        0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 
> +        0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 
> +        0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 
> +};
> +
> +word8 xS[256] = {
> +        99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 
> +        171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 
> +        156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 
> +        229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154, 
> +        7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110, 
> +        90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237, 
> +        32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239, 
> +        170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168, 
> +        81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 
> +        243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 
> +        100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 
> +        184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 
> +        194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213, 
> +        78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46, 
> +        28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
> +        181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 
> +        225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85, 
> +        40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 
> +        176,  84, 187,  22, 
> +};
> +
> +word8 xSi[256] = {
> +        82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 
> +        215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 
> +        196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 
> +        149,  11,  66, 250, 195,  78,   8,  46, 161, 102,  40, 217,  36, 178, 
> +        118,  91, 162,  73, 109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 
> +        152,  22, 212, 164,  92, 204,  93, 101, 182, 146, 108, 112,  72,  80, 
> +        253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132, 144, 216, 
> +        171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6, 
> +        208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 
> +        138, 107,  58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 
> +        240, 180, 230, 115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249, 
> +        55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 
> +        111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210, 
> +        121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,  51, 
> +        136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81, 
> +        127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 
> +        160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 
> +        153,  97,  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99, 
> +        85,  33,  12, 125, 
> +};
> +
> +/* -------------------------------- */
> +
> +#define MAXBC		(256/32)
> +#define MAXKC		(256/32)
> +#define MAXROUNDS	14
> +#define MAXRK           ((MAXROUNDS+1)*MAXBC)
> +
> +typedef struct {
> +        int BC;
> +        int KC;
> +        int ROUNDS;
> +        int shift[2][4];
> +        word32 rk[MAXRK];
> +} roundkey;
> +
> +/* keys and blocks are externally treated as word32 arrays, to
> +   make sure they are aligned on 4-byte boundaries on architectures
> +   that require it. */
> +
> +static int xshifts[3][2][4] = {
> +        {{0, 1, 2, 3},
> +         {0, 3, 2, 1}},
> +
> +        {{0, 1, 2, 3},
> +         {0, 5, 4, 3}},
> +
> +        {{0, 1, 3, 4},
> +         {0, 7, 5, 4}},
> +};
> +
> +/* Exor corresponding text input and round key input bytes */
> +/* the result is written to res, which can be the same as a */
> +static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC],
> +                                word32 rk[MAXBC], int BC)
> +{
> +        int j;
> +
> +        for (j = 0; j < BC; j++) {
> +                res[j] = a[j] ^ rk[j];
> +        }
> +}
> +
> +/* profiling shows that the ccrypt program spends about 50% of its
> +   time in the function xShiftSubst. Splitting the inner "for"
> +   statement into two parts - versus using the expensive "%" modulo
> +   operation, makes this function about 44% faster, thereby making the
> +   entire program about 28% faster. With -O3 optimization, the time
> +   savings are even more dramatic - ccrypt runs between 55% and 65%
> +   faster on most platforms. */
> +
> +/* do ShiftRow and Substitution together. res must not be a. */
> +static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC],
> +                               int shift[4], int BC, word8 box[256])
> +{
> +        int i, j;
> +        int s;
> +        word8 (*a8)[4] = (word8 (*)[4]) a;
> +        word8 (*res8)[4] = (word8 (*)[4]) res;
> +
> +        for (j = 0; j < BC; j++) {
> +                res8[j][0] = box[a8[j][0]];
> +        }
> +        for (i = 1; i < 4; i++) {
> +                s = shift[i];
> +                for (j = 0; j < BC - s; j++) {
> +                        res8[j][i] = box[a8[(j + s)][i]];
> +                }
> +                for (j = BC - s; j < BC; j++) {
> +                        res8[j][i] = box[a8[(j + s) - BC][i]];
> +                }
> +        }
> +}
> +
> +/* do MixColumn and KeyAddition together */
> +static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC],
> +                           word32 rk[MAXBC], int BC)
> +{
> +        int j;
> +        word32 b;
> +        word8 (*a8)[4] = (word8 (*)[4]) a;
> +
> +        for (j = 0; j < BC; j++) {
> +                b = M0[0][a8[j][0]].w32;
> +                b ^= M0[1][a8[j][1]].w32;
> +                b ^= M0[2][a8[j][2]].w32;
> +                b ^= M0[3][a8[j][3]].w32;
> +                b ^= rk[j];
> +                res[j] = b;
> +        }
> +}
> +
> +/* Mix the four bytes of every column in a linear way
> + * This is the opposite operation of xMixColumn */
> +/* the result is written to res, which may equal a */
> +static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC)
> +{
> +        int j;
> +        word32 b;
> +        word8 (*a8)[4] = (word8 (*)[4]) a;
> +
> +        for (j = 0; j < BC; j++) {
> +                b = M1[0][a8[j][0]].w32;
> +                b ^= M1[1][a8[j][1]].w32;
> +                b ^= M1[2][a8[j][2]].w32;
> +                b ^= M1[3][a8[j][3]].w32;
> +                res[j] = b;
> +        }
> +}
> +
> +/* make a roundkey rkk from key. key must have appropriate size given
> +   by keyBits. keyBits and blockBits may only be 128, 196, or
> +   256. Returns non-zero if arguments are invalid. */

> +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits,
> +		      roundkey *rkk)
> +{
> +        /* Calculate the necessary round keys
> +         * The number of calculations depends on keyBits and blockBits */
> +        int KC, BC, ROUNDS;
> +        int i, j, t, rconpointer = 0;
> +        word8 (*k8)[4] = (word8 (*)[4]) key;
> +
> +        switch (keyBits) {
> +        case 128:
> +                KC = 4;
> +                break;
> +        case 192:
> +                KC = 6;
> +                break;
> +        case 256:
> +                KC = 8;
> +                break;
> +        default:
> +                return -1;
> +        }
> +
> +        switch (blockBits) {
> +        case 128:
> +                BC = 4;
> +                break;
> +        case 192:
> +                BC = 6;
> +                break;
> +        case 256:
> +                BC = 8;
> +                break;
> +        default:
> +                return -2;
> +        }
> +
> +        ROUNDS = KC > BC ? KC + 6 : BC + 6;
> +
> +        t = 0;
> +        /* copy values into round key array */
> +        for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++)
> +                rkk->rk[t] = key[j];
> +
> +        while (t < (ROUNDS + 1) * BC) {  /* while not enough round key material */
> +                /* calculate new values */
> +                for (i = 0; i < 4; i++) {
> +                        k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]];
> +                }
> +                k8[0][0] ^= xrcon[rconpointer++];
> +
> +                if (KC != 8) {
> +                        for (j = 1; j < KC; j++) {
> +                                key[j] ^= key[j - 1];
> +                        }
> +                } else {
> +                        for (j = 1; j < 4; j++) {
> +                                key[j] ^= key[j - 1];
> +                        }
> +                        for (i = 0; i < 4; i++) {
> +                                k8[4][i] ^= xS[k8[3][i]];
> +                        }
> +                        for (j = 5; j < 8; j++) {
> +                                key[j] ^= key[j - 1];
> +                        }
> +                }
> +                /* copy values into round key array */
> +                for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) {
> +                        rkk->rk[t] = key[j];
> +                }
> +        }
> +
> +        /* make roundkey structure */
> +        rkk->BC = BC;
> +        rkk->KC = KC;
> +        rkk->ROUNDS = ROUNDS;
> +        for (i = 0; i < 2; i++) {
> +                for (j = 0; j < 4; j++) {
> +                        rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j];
> +                }
> +        }
> +
> +        return 0;
> +}
> +
> +/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must
> +   have been created with xrijndaelKeySched. Size of block, in bits,
> +   must be equal to blockBits parameter that was used to make rkk. In
> +   all other cases, behavior is undefined - for reasons of speed, no
> +   check for error conditions is done. */
> +
> +/* Encryption of one block. */
> +
> +void xrijndaelEncrypt(word32 block[], roundkey *rkk)
> +{
> +        word32 block2[MAXBC];		/* hold intermediate result */
> +        int r;
> +
> +        int *shift = rkk->shift[0];
> +        int BC = rkk->BC;
> +        int ROUNDS = rkk->ROUNDS;
> +        word32 *rp = rkk->rk;
> +
> +        /* begin with a key addition */
> +        xKeyAddition(block, block, rp, BC);
> +        rp += BC;
> +
> +        /* ROUNDS-1 ordinary rounds */
> +        for (r = 1; r < ROUNDS; r++) {
> +                xShiftSubst(block2, block, shift, BC, xS);
> +                xMixAdd(block, block2, rp, BC);
> +                rp += BC;
> +        }
> +
> +        /* Last round is special: there is no xMixColumn */
> +        xShiftSubst(block2, block, shift, BC, xS);
> +        xKeyAddition(block, block2, rp, BC);
> +}
> +
> +void xrijndaelDecrypt(word32 block[], roundkey *rkk)
> +{
> +        word32 block2[MAXBC];		/* hold intermediate result */
> +        int r;
> +
> +        int *shift = rkk->shift[1];
> +        int BC = rkk->BC;
> +        int ROUNDS = rkk->ROUNDS;
> +        word32 *rp = rkk->rk + ROUNDS * BC;
> +
> +        /* To decrypt: apply the inverse operations of the encrypt routine,
> +         *             in opposite order
> +         * 
> +         * (xKeyAddition is an involution: it's equal to its inverse)
> +         * (the inverse of xSubstitution with table S is xSubstitution with the 
> +         * inverse table of S)
> +         * (the inverse of xShiftRow is xShiftRow over a suitable distance)
> +         */
> +
> +        /* First the special round:
> +         *   without xInvMixColumn
> +         *   with extra xKeyAddition
> +         */
> +        xKeyAddition(block2, block, rp, BC);
> +        xShiftSubst(block, block2, shift, BC, xSi);
> +        rp -= BC;
> +
> +        /* ROUNDS-1 ordinary rounds
> +         */
> +        for (r = ROUNDS - 1; r > 0; r--) {
> +                xKeyAddition(block, block, rp, BC);
> +                xInvMixColumn(block2, block, BC);
> +                xShiftSubst(block, block2, shift, BC, xSi);
> +                rp -= BC;
> +        }
> +
> +        /* End with the extra key addition
> +         */
> +
> +        xKeyAddition(block, block, rp, BC);
> +}
> +
> +/* -------------------------------- */
> +
> +
> +#define MAGIC "c051"   /* magic string for this version of ccrypt */
> +
> +/* private struct, not visible by applications */
> +struct ccrypt_state_s {
> +        int n;          /* number of keys. n=1 for encryption, n>=1 for decryption */
> +        roundkey *rkks; /* array of n keys */
> +        int ak;         /* rkks[ak] is the active key */
> +        int iv;         /* are we reading/writing the IV? */
> +        int bufindex;   /* in bytes */
> +        word32 buf[8];  /* current buffer; partly ciphertext, partly mask */
> +        int flags;      /* flags determining behavior */
> +};
> +typedef struct ccrypt_state_s ccrypt_state_t;
> +
> +
> +int ccrypt_errno;
> +
> +#ifdef DEBUG
> +static void print_state(ccrypt_state_t *st) {
> +        if (st) {
> +                printf("State:\n");
> +                memory_display(st,0,sizeof(st),1,0);
> +                if (st->rkks) {
> +                        printf("Roundkey:\n");
> +                        memory_display(st->rkks,0,sizeof(roundkey),1,0);
> +                }
> +        }
> +}
> +#endif
> +
> +static void ccrypt_state_free(ccrypt_state_t *st) {
> +        if (st) {
> +                free(st->rkks);
> +        }
> +        free(st);
> +}
> +
> +/* ---------------------------------------------------------------------- */
> +/* some private functions dealing with hashes, keys, and nonces */
> +
> +/* hash a keystring into a 256-bit cryptographic random value. */
> +static void hashstring(const char *keystring, const int keylen, word32 hash[8]) {
> +        int i,j;
> +        roundkey rkk;
> +        word32 key[8];      /* rijndael key */
> +
> +        for (i=0; i<8; i++) 
> +                key[i] = hash[i] = 0;
> +  
> +        for ( j=0; j<keylen; ) {
> +                for (i=0; i<32; i++) {
> +                        if ( j<keylen ) {
> +                                ((word8 *)key)[i] ^= keystring[j];
> +                                j++;
> +                        }
> +                }
> +                xrijndaelKeySched(key, 256, 256, &rkk);
> +                xrijndaelEncrypt(hash, &rkk);
> +        }
> +
> +#if 0
> +        do {
> +                for (i=0; i<32; i++) {
> +                        if (*keystring != 0) {
> +                                ((word8 *)key)[i] ^= *keystring;
> +                                keystring++;
> +                        }
> +                }
> +                xrijndaelKeySched(key, 256, 256, &rkk);
> +                xrijndaelEncrypt(hash, &rkk);
> +        } while (*keystring != 0);
> +#endif
> +        
> +}
> +
> +/* return a 256-bit value that is practically unique */
> +static void make_nonce(word32 nonce[8]) {
> +        char acc[512];
> +        static int count=0;
> +  
> +        sprintf(acc, "%s,%d,%d,%d,%d,%d", "barebox", rand(),rand(),rand(),rand(),count++);
> +        hashstring(acc, strlen(acc), nonce); 
> +}
> +
> +/* ---------------------------------------------------------------------- */
> +/* core functions for encryption */
> +
> +int ccencrypt_init(ccrypt_stream_t *b, const char *key, const int keylen) {
> +        word32 keyblock[8];
> +        ccrypt_state_t *st;
> +        roundkey *rkks;
> +
> +        b->state = NULL;
> +  
> +        st = malloc(sizeof(ccrypt_state_t));
> +        if (st == NULL) {
> +                return -1;
> +        }
> +        rkks = malloc(sizeof(roundkey));
> +        if (!rkks) {
> +                free(st);
> +                return -1;
> +        }
> +
> +        st->n = 1;
> +        st->rkks = rkks;
> +        st->ak = 0; /* not used */
> +
> +        /* generate the roundkey */
> +        hashstring(key, keylen, keyblock);
> +        xrijndaelKeySched(keyblock, 256, 256, &st->rkks[0]);
> +  
> +        /* make a nonce */
> +        make_nonce(st->buf);
> +
> +        /* mark the nonce with a "magic number". */
> +        strncpy((char *)st->buf, MAGIC, 4);
> +
> +        /* encrypt the nonce with the given key */
> +        xrijndaelEncrypt(st->buf, &st->rkks[0]);
> +
> +        /* IV is now contained in st->buf. Initialize rest of the state. */
> +        st->iv = 1;
> +        st->bufindex = 0; /* initially use bufsize to count iv bytes output */
> +
> +#ifdef DEBUG
> +        print_state(st);
> +#endif
> +        b->state = (void *)st;
> +        return 0;
> +}
> +
> +EXPORT_SYMBOL(ccencrypt_init);
> +
> +int ccencrypt(ccrypt_stream_t *b) {
> +        ccrypt_state_t *st = (ccrypt_state_t *)b->state;
> +        word32 lbuf[8];
> +        char *cbuf = (char *)st->buf;
> +        int i;
> +        char c, cc;
> +
> +        while (1) {
> +                /* handle the typical case efficiently, one block at a time */
> +
> +                if (st->iv == 0 && st->bufindex == 32) {
> +                        while (b->avail_in >= 32 && b->avail_out >= 32) {
> +
> +                                /* block-encrypt buffer */
> +                                xrijndaelEncrypt(st->buf, &st->rkks[0]);
> +	
> +                                /* read input to local buffer for word alignment */
> +                                memcpy(lbuf, b->next_in, 32);
> +                                b->next_in += 32;
> +                                b->avail_in -= 32;
> +	
> +                                /* compute ciphertext */
> +                                for (i=0; i<8; i++) {
> +                                        st->buf[i] ^= lbuf[i];
> +                                }
> +
> +                                /* write output */
> +                                memcpy(b->next_out, st->buf, 32);
> +                                b->next_out += 32;
> +                                b->avail_out -= 32;
> +                        }
> +                }
> +    
> +                /* handle the general case systematically, one byte at a time */
> +
> +                if (b->avail_out == 0) {
> +                        break;
> +                } 
> +
> +                else if (st->iv) {  /* write IV byte */
> +                        *b->next_out = cbuf[st->bufindex];
> +                        b->next_out++;
> +                        b->avail_out--;
> +                        st->bufindex++;
> +                        if (st->bufindex == 32) {
> +                                st->iv = 0;
> +                        }
> +                } 
> +
> +                else if (b->avail_in == 0) {
> +                        break;
> +                }
> +
> +                else {              /* encrypt one byte */
> +                        if (st->bufindex == 32) {
> +                                xrijndaelEncrypt(st->buf, &st->rkks[0]);
> +                                st->bufindex = 0;
> +                        }
> +                        c = *b->next_in;
> +                        b->next_in++;
> +                        b->avail_in--;
> +                        cc = c ^ cbuf[st->bufindex];
> +                        cbuf[st->bufindex] = cc;
> +                        *b->next_out = cc;
> +                        b->next_out++;
> +                        b->avail_out--;
> +                        st->bufindex++;
> +                }
> +        }
> +#ifdef DEBUG
> +        print_state(st);
> +#endif
> +        return 0;
> +}
> +
> +EXPORT_SYMBOL(ccencrypt);
> +
> +int ccencrypt_end(ccrypt_stream_t *b) {
> +        ccrypt_state_free(b->state);
> +        b->state = NULL; /* guard against double free */
> +        return 0;
> +}
> +
> +EXPORT_SYMBOL(ccencrypt_end);
> +
> +/* ---------------------------------------------------------------------- */
> +/* core functions for decryption */
> +
> +int ccdecrypt_init(ccrypt_stream_t *b, const char *key, const int keylen) {
> +        word32 keyblock[8];
> +        ccrypt_state_t *st;
> +        roundkey *rkks;
> +  
> +        b->state = NULL;
> +
> +        st = malloc(sizeof(ccrypt_state_t));
> +        if (st == NULL) {
> +                return -1;
> +        }
> +        rkks = malloc(sizeof(roundkey));
> +        if (!rkks) {
> +                free(st);
> +                return -1;
> +        }
> +
> +        st->n = 1;
> +        st->rkks = rkks;
> +        st->ak = 0;
> +
> +        /* generate the roundkeys */
> +        hashstring(key, keylen, keyblock);
> +        xrijndaelKeySched(keyblock, 256, 256, &st->rkks[0]);
> +
> +        /* Initialize rest of the state. */
> +        st->iv = 1;
> +        st->bufindex = 0;
> +        st->flags = 0;
> +
> +#ifdef DEBUG
> +        print_state(st);
> +#endif
> +        b->state = (void *)st;
> +        return 0;
> +}
> +
> +EXPORT_SYMBOL(ccdecrypt_init);
> +
> +int ccdecrypt(ccrypt_stream_t *b) {
> +        ccrypt_state_t *st = (ccrypt_state_t *)b->state;
> +        word32 lbuf[8];
> +        char *cbuf = (char *)st->buf;
> +        int i;
> +        char c, cc;
> +  
> +        while (1) {
> +                /* handle the typical case efficiently, one block at a time */
> +
> +                if (st->iv == 0 && st->bufindex == 32) {
> +                        while (b->avail_in >= 32 && b->avail_out >= 32) {
> +	
> +                                /* block-encrypt buffer */
> +                                xrijndaelEncrypt(st->buf, &st->rkks[st->ak]);
> +                                memcpy(lbuf, st->buf, 32);
> +
> +                                /* read input */
> +                                memcpy(st->buf, b->next_in, 32);
> +                                b->next_in += 32;
> +                                b->avail_in -= 32;
> +
> +                                /* compute plaintext */
> +                                for (i=0; i<8; i++) {
> +                                        lbuf[i] ^= st->buf[i];
> +                                }
> +
> +                                /* write output */
> +                                memcpy(b->next_out, lbuf, 32);
> +                                b->next_out += 32;
> +                                b->avail_out -= 32;
> +                        }
> +                }
> +
> +                /* handle the general case systematically, one byte at a time */
> +
> +                if (b->avail_in == 0) {
> +                        break;
> +                }
> +
> +                else if (st->iv) {  /* read IV byte */
> +                        cbuf[st->bufindex] = *b->next_in;
> +                        b->next_in++;
> +                        b->avail_in--;
> +                        st->bufindex++;
> +                        if (st->bufindex == 32) {
> +                                st->iv = 0;
> +                                /* find the first matching key */
> +                                for (i=0; i<st->n; i++) {
> +                                        /* check the "magic number" */
> +                                        memcpy(lbuf, st->buf, 32);
> +                                        xrijndaelDecrypt(lbuf, &st->rkks[i]);
> +                                        if ((st->flags & CCRYPT_MISMATCH) != 0 || strncmp((char *)lbuf, MAGIC, 4) == 0) {
> +                                                /* key matches */
> +                                                break;
> +                                        }
> +                                }
> +                                if (i<st->n) { /* matching key found */
> +                                        st->ak = i;
> +                                } else {       /* not found */
> +                                        /* on error, invalidate the state so that the client cannot
> +                                           call here again. */
> +                                        ccrypt_state_free((ccrypt_state_t *)b->state);
> +                                        b->state = NULL;
> +                                        ccrypt_errno = CCRYPT_EMISMATCH;
> +                                        return -2;
> +                                }
> +                        }
> +                }
> +
> +                else if (b->avail_out == 0) {
> +                        break;
> +                }
> +
> +                else {              /* decrypt one byte */
> +                        if (st->bufindex == 32) {
> +                                xrijndaelEncrypt(st->buf, &st->rkks[st->ak]);
> +                                st->bufindex = 0;
> +                        }
> +                        cc = *b->next_in;
> +                        b->next_in++;
> +                        b->avail_in--;
> +                        c = cc ^ cbuf[st->bufindex];
> +                        cbuf[st->bufindex] = cc;
> +                        *b->next_out = c;
> +                        b->next_out++;
> +                        b->avail_out--;
> +                        st->bufindex++;
> +                }
> +        }
> +#ifdef DEBUG
> +        print_state(st);
> +#endif
> +        return 0;
> +}
> +
> +EXPORT_SYMBOL(ccdecrypt);
> +
> +int ccdecrypt_end(ccrypt_stream_t *b) {
> +        ccrypt_state_t *st;
> +  
> +        if (b->state) {
> +
> +                /* verify that we have read and verified the IV */
> +                st = (ccrypt_state_t *)b->state;
> +                if (st->iv) {
> +                        ccrypt_state_free(b->state);
> +                        b->state = NULL;
> +                        ccrypt_errno = CCRYPT_EFORMAT;
> +                        return -2;
> +                }
> +        }
> +
> +        ccrypt_state_free(b->state);
> +        b->state = NULL;
> +        return 0;
> +}
> +
> +EXPORT_SYMBOL(ccdecrypt_end);
> diff --git a/include/ccryptlib.h b/include/ccryptlib.h
> new file mode 100644
> index 000000000..b2446a232
> --- /dev/null
> +++ b/include/ccryptlib.h
> @@ -0,0 +1,102 @@
> +/* -*- Mode:C; c-file-style:"linux"; -*- */
> +
> +/* Ported to barebox by Gerd Pauli <gp at high-consulting.de> 2018 */
> +
> +/* Copyright (C) 2000-2009 Peter Selinger.
> +   This file is part of ccrypt. It is free software and it is covered
> +   by the GNU general public license. See the file COPYING for details. */
> +
> +/* ccryptlib.h: library for encrypting/decrypting a character stream */
> +/* $Id: ccryptlib.h 258 2009-08-26 17:46:10Z selinger $ */
> +
> +#ifndef _CCRYPTLIB_H
> +#define _CCRYPTLIB_H
> +
> +struct ccrypt_stream_s {
> +        char          *next_in;  /* next input byte */
> +        unsigned int  avail_in;  /* number of bytes available at next_in */
> +
> +        char          *next_out; /* next output byte should be put there */
> +        unsigned int  avail_out; /* remaining free space at next_out */
> +
> +        void *state;             /* internal state, not visible by applications */
> +};
> +typedef struct ccrypt_stream_s ccrypt_stream_t;
> +
> +/* 
> +   The application may update next_in and avail_in when avail_in has
> +   dropped to zero. It must update next_out and avail_out when
> +   avail_out has dropped to zero. All other fields are set by the
> +   compression library and must not be updated by the application.
> +*/
> +
> +int ccencrypt_init(ccrypt_stream_t *b, const char *key, const int keylen);
> +int ccencrypt     (ccrypt_stream_t *b);
> +int ccencrypt_end (ccrypt_stream_t *b);
> +
> +int ccdecrypt_init(ccrypt_stream_t *b, const char *key, const int keylen);
> +int ccdecrypt     (ccrypt_stream_t *b);
> +int ccdecrypt_end (ccrypt_stream_t *b);
> +
> +/* The interface for encryption and decryption is the same. The
> +   application must first call the respective init function to
> +   initialize the internal state. Then it calls the encrypt/decrypt
> +   function repeatedly, as follows: next_in and next_out must point to
> +   valid, non-overlapping regions of memory of size at least avail_in
> +   and avail_out, respectively. Avail_out must be non-zero. Avail_in
> +   may be zero to retrieve some pending output when no input is
> +   available, for instance, in an interactive application or at the
> +   end of stream. Otherwise, avail_in should be non-zero. 
> +
> +   The encryption/decryption function will read and process as many
> +   input bytes as possible as long as there is room in the output
> +   buffer. It will update next_in, avail_in, next_out, and avail_out
> +   accordingly. It will always flush as much output as possible.
> +   However, it is possible that some input bytes produce no output,
> +   because some part of the input may be used for internal purposes.
> +   Conversely, it is possible that output is produced without reading
> +   any input. When the encryption/decryption function returns, at
> +   least one of avail_in or avail_out is 0. If avail_out is non-zero
> +   after a call, the application may conclude that no more output is
> +   pending.
> +
> +   Finally, the internal state must be freed by calling the respective
> +   end function. This function will discard any unprocessed input
> +   and/or output, so it should only be called after the application
> +   has retrieved any pending output. Note: the call to the end
> +   function should be checked for errors, because this is the only
> +   place where certain format errors (like a file that is too short)
> +   are detected.
> +
> +   All functions return 0 on success, or -1 on error with errno set,
> +   or -2 on error with ccrypt_errno set. Callers must check for
> +   errors. If an error occurs, the state is invalid and its resources
> +   are freed. It may not be used again. It is then safe, but not
> +   required, to call the corresponding *_end function.
> +
> +   The flags argument to ccdecrypt_init should be 0 by default, or
> +   CCRYPT_MISMATCH if non-matching keys should be ignored. All other
> +   values are undefined and reserved for future use.
> +*/
> +
> +/* ccdecrypt_multi_init this is a variant of ccdecrypt_init that
> +   allows a list of n>=1 keys to be defined. During decryption, the
> +   first matching key is used. This is useful when batch decrypting a
> +   set of files that have non-uniform keys. If flags includes
> +   CCRYPT_MISMATCH, then the first key is always used regardless of
> +   whether it matches or not. */
> +int ccdecrypt_multi_init(ccrypt_stream_t *b, int n, const char **keylist, int flags);
> +
> +/* errors */
> +
> +#define CCRYPT_EFORMAT   1          /* bad file format */
> +#define CCRYPT_EMISMATCH 2          /* key does not match */
> +#define CCRYPT_EBUFFER   3          /* buffer overflow */
> +
> +/* flags */
> +
> +#define CCRYPT_MISMATCH  1          /* ignore non-matching key */
> +
> +extern int ccrypt_errno;
> +
> +#endif /* _CCRYPTLIB_H */
> 


-- 
Regards,
Oleksij

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20180422/882a1316/attachment-0001.sig>

From mail at schmidt-andreas.de  Sun Apr 22 09:41:57 2018
From: mail at schmidt-andreas.de (Andreas Schmidt)
Date: Sun, 22 Apr 2018 18:41:57 +0200
Subject: [PATCH] ARM: arm32: fix realocate_to_curr_addr
Message-ID: <20180422164157.30691-1-mail@schmidt-andreas.de>

After add aarch64 support (commit 868df08038a91d674a0c50b0c0a2f70dbc445510)
to realocation, MLO on beaglebone black do not boot any more.
The issue is, that addition of offset in one if-case was not done.
This patch fix this.

Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
---
Hi!

I've tested this patch only on beablebone black REV C.

Regards,
Andreas
---
 arch/arm/cpu/common.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c
index 00ce3efb2..51fe7ed98 100644
--- a/arch/arm/cpu/common.c
+++ b/arch/arm/cpu/common.c
@@ -85,6 +85,7 @@ void relocate_to_current_adr(void)
 			unsigned long *fixup = (unsigned long *)(rel->r_offset + offset);
 
 			*fixup = *fixup + r + offset;
+			rel->r_offset += offset;
 		} else {
 			putc_ll('>');
 			puthex_ll(rel->r_info);
-- 
2.14.1



From mail at schmidt-andreas.de  Sun Apr 22 11:21:11 2018
From: mail at schmidt-andreas.de (Andreas Schmidt)
Date: Sun, 22 Apr 2018 20:21:11 +0200
Subject: [PATCH] watchdog: core: check hwdev before use it
Message-ID: <20180422182111.22256-1-mail@schmidt-andreas.de>

Avoid null pointer access, if hwdev was not
set before call watchdog_register.

Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
---
 drivers/watchdog/wd_core.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
index d3305443d..56e8626cb 100644
--- a/drivers/watchdog/wd_core.c
+++ b/drivers/watchdog/wd_core.c
@@ -112,10 +112,12 @@ static int watchdog_register_dev(struct watchdog *wd, const char *name, int id)
 int watchdog_register(struct watchdog *wd)
 {
 	struct param_d *p;
-	const char *alias;
+	const char *alias = NULL;
 	int ret = 0;
 
-	alias = of_alias_get(wd->hwdev->device_node);
+	if (wd->hwdev)
+		alias = of_alias_get(wd->hwdev->device_node);
+
 	if (alias)
 		ret = watchdog_register_dev(wd, alias, DEVICE_ID_SINGLE);
 
-- 
2.14.1



From mail at schmidt-andreas.de  Sun Apr 22 11:30:07 2018
From: mail at schmidt-andreas.de (Andreas Schmidt)
Date: Sun, 22 Apr 2018 20:30:07 +0200
Subject: [PATCH] watchdog: omap: set hwdev before call watchdog_register
Message-ID: <20180422183007.23235-1-mail@schmidt-andreas.de>

Since watchdog_register access to hwdev (see
commit 65a644388e845bde01215bf378d4df2a6a260a6a)
hwdev has to be initiate/set before calling watchdog_register.

Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
---
 drivers/watchdog/omap_wdt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 27fdfd13a..c8a7ccf60 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -160,6 +160,7 @@ static int omap_wdt_probe(struct device_d *dev)
 
 	wdev = xzalloc(sizeof(*wdev));
 	wdev->wdog.set_timeout	= omap_wdt_set_timeout;
+	wdev->wdog.hwdev = dev;
 	wdev->wdt_trgr_pattern	= 0x1234;
 
 	/* reserve static register mappings */
-- 
2.14.1



From s.hauer at pengutronix.de  Mon Apr 23 01:13:48 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Apr 2018 10:13:48 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
In-Reply-To: <51213c28-0443-3ba7-d161-d79dfaa3acdb@rempel-privat.de>
References: <20180420080114.9148-1-gp@high-consulting.de>
 <51213c28-0443-3ba7-d161-d79dfaa3acdb@rempel-privat.de>
Message-ID: <20180423081348.hylbpdraydokxvt4@pengutronix.de>

On Sun, Apr 22, 2018 at 10:27:11AM +0200, Oleksij Rempel wrote:
> Hi Gerd,
> 
> please use scripts/checkpatch.pl
> 
> currently i get
> total: 2020 errors, 0 warnings, 2020 lines checked
> 
> We use kernel coding style. Please read it:
> https://www.kernel.org/doc/html/v4.16/process/coding-style.html
> 
> Am 20.04.2018 um 10:01 schrieb Gerd Pauli:
> > Adds ccryptlib library in crypto which implements a
> > stream cipher based on the block cipher Rijndael,
> > the candidate for the AES standard.
> > Compatible with the ccrypt tool in linux
> > from Peter Selinger.
> > 
> > Usage: ccrypt [-e|-d] -k KEYNAME_IN_KEYSTORE SRC DST
> > 
> > Signed-off-by: Gerd Pauli <gp at high-consulting.de>
> > ---
> >  commands/Kconfig    |   17 +
> >  commands/Makefile   |    1 +
> >  commands/ccrypt.c   |  249 +++++++++
> >  crypto/Kconfig      |    7 +
> >  crypto/Makefile     |    1 +
> >  crypto/ccryptlib.c  | 1467 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/ccryptlib.h |  102 ++++
> >  7 files changed, 1844 insertions(+)
> >  create mode 100644 commands/ccrypt.c
> >  create mode 100644 crypto/ccryptlib.c
> >  create mode 100644 include/ccryptlib.h
> > 
> > diff --git a/commands/Kconfig b/commands/Kconfig
> > index 951a86963..b6911246a 100644
> > --- a/commands/Kconfig
> > +++ b/commands/Kconfig
> > @@ -2137,6 +2137,23 @@ config CMD_SEED
> >  	help
> >  	  Seed the pseudo random number generator (PRNG)
> >  
> > +config CMD_CCRYPT
> > +        tristate
> > +        prompt "ccrypt"
> > +        select CRYPTO_CCRYPTLIB
> > +        select CRYPTO_KEYSTORE
> > +        help
> > +          encrypting/decrypting a character stream
> > +          ccrypt implements a stream cipher based on the block cipher
> > +          Rijndael.
> 
> > +          Usage: ccrypt [-ed] [-K name] srcfile dstfile
> > +
> > +          Options:
> > +                        -e            encrypt srcfile to dstfile
> > +                        -d            decrypt srcfile to dstfile
> > +                        -k name       use key with name from keystore
> > +
> 
> usage help should be provided by the command, not within Kconfig

Indeed we have the help provided in the Kconfig text for all commands
that were present at that change. I don't really think it's worth
continuing this though.

> > + * 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.    
> > + */
> > +
> > +/* ccrypt implements a stream cipher based on the block cipher
> > +   Rijndael  */
> > +
> > +/* needs library ccryptlib and keystore from barebox */
> 
> no need for this comment, needed headers are already included
> 
> > +#include <common.h>
> > +#include <command.h>
> > +#include <libfile.h>
> > +#include <getopt.h>
> > +#include <fcntl.h>
> > +#include <fs.h>
> > +#include <ccryptlib.h>
> 
> i prefer headers sorted alphabetically. this helps to reduce
> patch conflicts.

And I prefer the reverse christmas tree ordering ;)

To be honest, I don't care about the ordering at all, but at least as
long as we haven't agreed on some ordering and written it down somewhere
we shouldn't enforce any ordering for patch submitters.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From o.rempel at pengutronix.de  Mon Apr 23 01:33:22 2018
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 23 Apr 2018 10:33:22 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
In-Reply-To: <20180423081348.hylbpdraydokxvt4@pengutronix.de>
References: <20180420080114.9148-1-gp@high-consulting.de>
 <51213c28-0443-3ba7-d161-d79dfaa3acdb@rempel-privat.de>
 <20180423081348.hylbpdraydokxvt4@pengutronix.de>
Message-ID: <8fbdaa19-13bc-9b27-7b69-ca3ca50872cf@pengutronix.de>



On 23.04.2018 10:13, Sascha Hauer wrote:
> On Sun, Apr 22, 2018 at 10:27:11AM +0200, Oleksij Rempel wrote:
>> Hi Gerd,
>>
>> please use scripts/checkpatch.pl
>>
>> currently i get
>> total: 2020 errors, 0 warnings, 2020 lines checked
>>
>> We use kernel coding style. Please read it:
>> https://www.kernel.org/doc/html/v4.16/process/coding-style.html
>>
>> Am 20.04.2018 um 10:01 schrieb Gerd Pauli:
>>> Adds ccryptlib library in crypto which implements a
>>> stream cipher based on the block cipher Rijndael,
>>> the candidate for the AES standard.
>>> Compatible with the ccrypt tool in linux
>>> from Peter Selinger.
>>>
>>> Usage: ccrypt [-e|-d] -k KEYNAME_IN_KEYSTORE SRC DST
>>>
>>> Signed-off-by: Gerd Pauli <gp at high-consulting.de>
>>> ---
>>>  commands/Kconfig    |   17 +
>>>  commands/Makefile   |    1 +
>>>  commands/ccrypt.c   |  249 +++++++++
>>>  crypto/Kconfig      |    7 +
>>>  crypto/Makefile     |    1 +
>>>  crypto/ccryptlib.c  | 1467 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  include/ccryptlib.h |  102 ++++
>>>  7 files changed, 1844 insertions(+)
>>>  create mode 100644 commands/ccrypt.c
>>>  create mode 100644 crypto/ccryptlib.c
>>>  create mode 100644 include/ccryptlib.h
>>>
>>> diff --git a/commands/Kconfig b/commands/Kconfig
>>> index 951a86963..b6911246a 100644
>>> --- a/commands/Kconfig
>>> +++ b/commands/Kconfig
>>> @@ -2137,6 +2137,23 @@ config CMD_SEED
>>>  	help
>>>  	  Seed the pseudo random number generator (PRNG)
>>>  
>>> +config CMD_CCRYPT
>>> +        tristate
>>> +        prompt "ccrypt"
>>> +        select CRYPTO_CCRYPTLIB
>>> +        select CRYPTO_KEYSTORE
>>> +        help
>>> +          encrypting/decrypting a character stream
>>> +          ccrypt implements a stream cipher based on the block cipher
>>> +          Rijndael.
>>
>>> +          Usage: ccrypt [-ed] [-K name] srcfile dstfile
>>> +
>>> +          Options:
>>> +                        -e            encrypt srcfile to dstfile
>>> +                        -d            decrypt srcfile to dstfile
>>> +                        -k name       use key with name from keystore
>>> +
>>
>> usage help should be provided by the command, not within Kconfig
> 
> Indeed we have the help provided in the Kconfig text for all commands
> that were present at that change. I don't really think it's worth
> continuing this though.
> 
>>> + * 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.    
>>> + */
>>> +
>>> +/* ccrypt implements a stream cipher based on the block cipher
>>> +   Rijndael  */
>>> +
>>> +/* needs library ccryptlib and keystore from barebox */
>>
>> no need for this comment, needed headers are already included
>>
>>> +#include <common.h>
>>> +#include <command.h>
>>> +#include <libfile.h>
>>> +#include <getopt.h>
>>> +#include <fcntl.h>
>>> +#include <fs.h>
>>> +#include <ccryptlib.h>
>>
>> i prefer headers sorted alphabetically. this helps to reduce
>> patch conflicts.
> 
> And I prefer the reverse christmas tree ordering ;)
> 
> To be honest, I don't care about the ordering at all, but at least as
> long as we haven't agreed on some ordering and written it down somewhere
> we shouldn't enforce any ordering for patch submitters.

ok.

by applying old patches, i made experience that "append as last in the
list" will mostly end as patch conflict in comparison to "add in
alphabetically ordered list". May it is worth to start this practice.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20180423/9b7e50ee/attachment.sig>

From s.hauer at pengutronix.de  Mon Apr 23 01:39:26 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Apr 2018 10:39:26 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
In-Reply-To: <20180420080114.9148-1-gp@high-consulting.de>
References: <20180420080114.9148-1-gp@high-consulting.de>
Message-ID: <20180423083926.cemu3wzcosahvm4f@pengutronix.de>

Hi Gerd,

On Fri, Apr 20, 2018 at 10:01:14AM +0200, Gerd Pauli wrote:
> Adds ccryptlib library in crypto which implements a
> stream cipher based on the block cipher Rijndael,
> the candidate for the AES standard.
> Compatible with the ccrypt tool in linux
> from Peter Selinger.
> 
> +BAREBOX_CMD_START(ccrypt)
> +.cmd	= do_ccrypt,
> +	BAREBOX_CMD_DESC("Crypt and Decrypt Files")
> +	BAREBOX_CMD_OPTS("[-e|-d] -k NAME SRC DST")
> +        BAREBOX_CMD_GROUP(CMD_GRP_MISC)
> +	BAREBOX_CMD_HELP(cmd_ccrypt_help)
> +	BAREBOX_CMD_END
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index 6d65c24d4..08669a2de 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -101,4 +101,11 @@ config CRYPTO_KEYSTORE
>  	  This is a simple keystore, which can be used to pass keys
>  	  between several components via simple interface.
>  
> +config CRYPTO_CCRYPTLIB
> +        bool "ccryptlib"
> +        help
> +          This option provides functions implementing a stream cipher based
> +          on the block cipher rijandel.
> +          The cipher is based on Peter Selingers ccrypt implementation.
> +
>  endmenu
> diff --git a/crypto/Makefile b/crypto/Makefile
> index a7240d1d6..1231bc76d 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_DIGEST_SHA512_GENERIC)	+= sha4.o
>  obj-$(CONFIG_CRYPTO_PBKDF2)	+= pbkdf2.o
>  obj-$(CONFIG_CRYPTO_RSA)	+= rsa.o
>  obj-$(CONFIG_CRYPTO_KEYSTORE)	+= keystore.o
> +obj-$(CONFIG_CRYPTO_CCRYPTLIB)  += ccryptlib.o
> diff --git a/crypto/ccryptlib.c b/crypto/ccryptlib.c
> new file mode 100644
> index 000000000..78f0ac843
> --- /dev/null
> +++ b/crypto/ccryptlib.c

Is this the same as the Linux Kernel has in crypto/aes_generic.c? If
yes, then please use it. If no, then why not? ;)

Generally any crypto code should integrate into the barebox crypto API
(which is basically the same as the Linux crypto API). This is the main
road blocker that must be removed before we can merge this into barebox.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From gp at high-consulting.de  Mon Apr 23 05:52:50 2018
From: gp at high-consulting.de (Gerd Pauli)
Date: Mon, 23 Apr 2018 14:52:50 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
In-Reply-To: <20180423083926.cemu3wzcosahvm4f@pengutronix.de>
References: <20180420080114.9148-1-gp@high-consulting.de>
 <20180423083926.cemu3wzcosahvm4f@pengutronix.de>
Message-ID: <1524487970.8922.2.camel@high-consulting.de>

Hi Sascha,

This is not the same as in Linux Cryptop Api. The goal of this command
and library is to provide a compatible command with the ccrypt tool
from linux.
https://packages.debian.org/stretch/ccrypt
It is not intended to write a standard AES Crypting Tool.

Please tell me if this is useful for merging like this.?
Then i clean up some spaces in the code and send again ( checkscript ).

If not. Sorry for the dust :-)

Am Montag, den 23.04.2018, 10:39 +0200 schrieb Sascha Hauer:
> Hi Gerd,
> 
> On Fri, Apr 20, 2018 at 10:01:14AM +0200, Gerd Pauli wrote:
> > Adds ccryptlib library in crypto which implements a
> > stream cipher based on the block cipher Rijndael,
> > the candidate for the AES standard.
> > Compatible with the ccrypt tool in linux
> > from Peter Selinger.
> > 
> > +BAREBOX_CMD_START(ccrypt)
> > +.cmd	= do_ccrypt,
> > +	BAREBOX_CMD_DESC("Crypt and Decrypt Files")
> > +	BAREBOX_CMD_OPTS("[-e|-d] -k NAME SRC DST")
> > +????????BAREBOX_CMD_GROUP(CMD_GRP_MISC)
> > +	BAREBOX_CMD_HELP(cmd_ccrypt_help)
> > +	BAREBOX_CMD_END
> > diff --git a/crypto/Kconfig b/crypto/Kconfig
> > index 6d65c24d4..08669a2de 100644
> > --- a/crypto/Kconfig
> > +++ b/crypto/Kconfig
> > @@ -101,4 +101,11 @@ config CRYPTO_KEYSTORE
> > ?	??This is a simple keystore, which can be used to pass
> > keys
> > ?	??between several components via simple interface.
> > ?
> > +config CRYPTO_CCRYPTLIB
> > +????????bool "ccryptlib"
> > +????????help
> > +??????????This option provides functions implementing a stream
> > cipher based
> > +??????????on the block cipher rijandel.
> > +??????????The cipher is based on Peter Selingers ccrypt
> > implementation.
> > +
> > ?endmenu
> > diff --git a/crypto/Makefile b/crypto/Makefile
> > index a7240d1d6..1231bc76d 100644
> > --- a/crypto/Makefile
> > +++ b/crypto/Makefile
> > @@ -14,3 +14,4 @@ obj-$(CONFIG_DIGEST_SHA512_GENERIC)	+=
> > sha4.o
> > ?obj-$(CONFIG_CRYPTO_PBKDF2)	+= pbkdf2.o
> > ?obj-$(CONFIG_CRYPTO_RSA)	+= rsa.o
> > ?obj-$(CONFIG_CRYPTO_KEYSTORE)	+= keystore.o
> > +obj-$(CONFIG_CRYPTO_CCRYPTLIB)??+= ccryptlib.o
> > diff --git a/crypto/ccryptlib.c b/crypto/ccryptlib.c
> > new file mode 100644
> > index 000000000..78f0ac843
> > --- /dev/null
> > +++ b/crypto/ccryptlib.c
> 
> Is this the same as the Linux Kernel has in crypto/aes_generic.c? If
> yes, then please use it. If no, then why not? ;)
> 
> Generally any crypto code should integrate into the barebox crypto
> API
> (which is basically the same as the Linux crypto API). This is the
> main
> road blocker that must be removed before we can merge this into
> barebox.
> 
> Sascha
> 
> 

CU
--
Gerd



From s.hauer at pengutronix.de  Wed Apr 25 01:23:13 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 10:23:13 +0200
Subject: [PATCH v1] Crypt and decrypt files using password in keystore.
In-Reply-To: <1524487970.8922.2.camel@high-consulting.de>
References: <20180420080114.9148-1-gp@high-consulting.de>
 <20180423083926.cemu3wzcosahvm4f@pengutronix.de>
 <1524487970.8922.2.camel@high-consulting.de>
Message-ID: <20180425082313.ur6rzyepbxhtcvao@pengutronix.de>

On Mon, Apr 23, 2018 at 02:52:50PM +0200, Gerd Pauli wrote:
> Hi Sascha,
> 
> This is not the same as in Linux Cryptop Api. The goal of this command
> and library is to provide a compatible command with the ccrypt tool
> from linux.
> https://packages.debian.org/stretch/ccrypt
> It is not intended to write a standard AES Crypting Tool.
> 
> Please tell me if this is useful for merging like this.?
> Then i clean up some spaces in the code and send again ( checkscript ).

Sorry, I don't think adding a crypto implementation that is not using
the crypto API is acceptable for merging. Possible options for
upstreaming would be to either the Rijndael cipher with 128 bit block
size aka AES, based on the Kernel AES implementation or to convert
the Rijndael cipher with 256 bit block size as used by ccrypt to the
existing crypto API.

> If not. Sorry for the dust :-)

Don't worry, it's always nice to see what people do with barebox and
to get a view what might be missing.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 25 01:36:02 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 10:36:02 +0200
Subject: [PATCH] watchdog: core: check hwdev before use it
In-Reply-To: <20180422182111.22256-1-mail@schmidt-andreas.de>
References: <20180422182111.22256-1-mail@schmidt-andreas.de>
Message-ID: <20180425083602.hylx5g56iztydjih@pengutronix.de>

On Sun, Apr 22, 2018 at 08:21:11PM +0200, Andreas Schmidt wrote:
> Avoid null pointer access, if hwdev was not
> set before call watchdog_register.
> 
> Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
> ---
>  drivers/watchdog/wd_core.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
> index d3305443d..56e8626cb 100644
> --- a/drivers/watchdog/wd_core.c
> +++ b/drivers/watchdog/wd_core.c
> @@ -112,10 +112,12 @@ static int watchdog_register_dev(struct watchdog *wd, const char *name, int id)
>  int watchdog_register(struct watchdog *wd)
>  {
>  	struct param_d *p;
> -	const char *alias;
> +	const char *alias = NULL;
>  	int ret = 0;
>  
> -	alias = of_alias_get(wd->hwdev->device_node);
> +	if (wd->hwdev)
> +		alias = of_alias_get(wd->hwdev->device_node);
> +
>  	if (alias)
>  		ret = watchdog_register_dev(wd, alias, DEVICE_ID_SINGLE);
>  
> -- 
> 2.14.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 25 01:36:17 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 10:36:17 +0200
Subject: [PATCH] watchdog: omap: set hwdev before call watchdog_register
In-Reply-To: <20180422183007.23235-1-mail@schmidt-andreas.de>
References: <20180422183007.23235-1-mail@schmidt-andreas.de>
Message-ID: <20180425083617.ugyiosdtusotkjax@pengutronix.de>

On Sun, Apr 22, 2018 at 08:30:07PM +0200, Andreas Schmidt wrote:
> Since watchdog_register access to hwdev (see
> commit 65a644388e845bde01215bf378d4df2a6a260a6a)
> hwdev has to be initiate/set before calling watchdog_register.
> 
> Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
> ---
>  drivers/watchdog/omap_wdt.c | 1 +
>  1 file changed, 1 insertion(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
> index 27fdfd13a..c8a7ccf60 100644
> --- a/drivers/watchdog/omap_wdt.c
> +++ b/drivers/watchdog/omap_wdt.c
> @@ -160,6 +160,7 @@ static int omap_wdt_probe(struct device_d *dev)
>  
>  	wdev = xzalloc(sizeof(*wdev));
>  	wdev->wdog.set_timeout	= omap_wdt_set_timeout;
> +	wdev->wdog.hwdev = dev;
>  	wdev->wdt_trgr_pattern	= 0x1234;
>  
>  	/* reserve static register mappings */
> -- 
> 2.14.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 25 02:30:24 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 11:30:24 +0200
Subject: [PATCH] ARM: arm32: fix realocate_to_curr_addr
In-Reply-To: <20180422164157.30691-1-mail@schmidt-andreas.de>
References: <20180422164157.30691-1-mail@schmidt-andreas.de>
Message-ID: <20180425093024.joj7fo72khes57ba@pengutronix.de>

Hi Andreas,

On Sun, Apr 22, 2018 at 06:41:57PM +0200, Andreas Schmidt wrote:
> After add aarch64 support (commit 868df08038a91d674a0c50b0c0a2f70dbc445510)
> to realocation, MLO on beaglebone black do not boot any more.
> The issue is, that addition of offset in one if-case was not done.
> This patch fix this.
> 
> Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
> ---
> Hi!
> 
> I've tested this patch only on beablebone black REV C.

Applied, thanks.

It took me a while to reproduce this. I switched to gcc7 a while ago and
this gcc version no longer uses these types of relocation. Then after
using a gcc-4.9.2 I could really see the same issue. The problem arises
when relocate_to_current_adr() is called multiple times, as happens when
the board lowlevel code calls it and the startup code later again. Some
boards do this, one of them being the beagle bone.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 25 02:34:19 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 11:34:19 +0200
Subject: [PATCH] video: tc358767: don't link AUX i2c adapter to parent OF
 node
In-Reply-To: <20180420103541.26772-1-l.stach@pengutronix.de>
References: <20180420103541.26772-1-l.stach@pengutronix.de>
Message-ID: <20180425093419.yblvipqpui3awyrv@pengutronix.de>

On Fri, Apr 20, 2018 at 12:35:41PM +0200, Lucas Stach wrote:
> Otherwise the i2c core will try to populate the TC358767 child nodes
> as i2c devices, which is wrong.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> ---
>  drivers/video/tc358767.c | 1 -
>  1 file changed, 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/video/tc358767.c b/drivers/video/tc358767.c
> index d4749b15c7a1..125e8236c153 100644
> --- a/drivers/video/tc358767.c
> +++ b/drivers/video/tc358767.c
> @@ -1413,7 +1413,6 @@ static int tc_probe(struct device_d *dev)
>  	tc->adapter.master_xfer = tc_aux_i2c_xfer;
>  	tc->adapter.nr = -1; /* any free */
>  	tc->adapter.dev.parent = dev;
> -	tc->adapter.dev.device_node = dev->device_node;
>  	/* Add I2C adapter */
>  	ret = i2c_add_numbered_adapter(&tc->adapter);
>  	if (ret < 0) {
> -- 
> 2.16.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 25 02:35:44 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 11:35:44 +0200
Subject: [PATCH v3] ARM: i.MX: boot: Coalesce copy-pasted code
In-Reply-To: <20180421014943.11517-1-andrew.smirnov@gmail.com>
References: <20180421014943.11517-1-andrew.smirnov@gmail.com>
Message-ID: <20180425093544.puaouedi3634advj@pengutronix.de>

On Fri, Apr 20, 2018 at 06:49:43PM -0700, Andrey Smirnov wrote:
> All of the instances of imx*_boot_save_loc() do exactly the same thing
> with the only difference being SoC-specific imx*_get_boot_source
> call. Convert the code into a generic function taking function pointer
> to perform SoC specific bits.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
> 
> Sascha:
> 
> This is my second take on the patch we discussed in [thread1]. It
> saves a whole bunch of boilerpalte code while keeping all function
> names greppable. Hopefully this is good enough to be merged.

Yes, indeed. Applied, thanks

Sascha

> 
> Thanks,
> Andrey Smirnov
> 
> [thread1] http://lists.infradead.org/pipermail/barebox/2018-April/032706.html
> 
>  arch/arm/mach-imx/boot.c | 70 +++++++++++++++---------------------------------
>  1 file changed, 21 insertions(+), 49 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> index c3e2ec501..22cf08e6a 100644
> --- a/arch/arm/mach-imx/boot.c
> +++ b/arch/arm/mach-imx/boot.c
> @@ -29,6 +29,20 @@
>  #include <mach/imx7-regs.h>
>  #include <mach/vf610-regs.h>
>  
> +
> +static void
> +imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
> +{
> +	enum bootsource src = BOOTSOURCE_UNKNOWN;
> +	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> +
> +	get_boot_source(&src, &instance);
> +
> +	bootsource_set(src);
> +	bootsource_set_instance(instance);
> +}
> +
> +
>  /* [CTRL][TYPE] */
>  static const enum bootsource locations[4][4] = {
>  	{ /* CTRL = WEIM */
> @@ -93,13 +107,7 @@ void imx25_get_boot_source(enum bootsource *src, int *instance)
>  
>  void imx25_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	imx25_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(imx25_get_boot_source);
>  }
>  
>  void imx35_get_boot_source(enum bootsource *src, int *instance)
> @@ -114,13 +122,7 @@ void imx35_get_boot_source(enum bootsource *src, int *instance)
>  
>  void imx35_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	imx35_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(imx35_get_boot_source);
>  }
>  
>  #define IMX27_SYSCTRL_GPCR	0x18
> @@ -161,13 +163,7 @@ void imx27_get_boot_source(enum bootsource *src, int *instance)
>  
>  void imx27_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	imx27_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(imx27_get_boot_source);
>  }
>  
>  #define IMX51_SRC_SBMR			0x4
> @@ -205,13 +201,7 @@ void imx51_get_boot_source(enum bootsource *src, int *instance)
>  
>  void imx51_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	imx51_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(imx51_get_boot_source);
>  }
>  
>  #define IMX53_SRC_SBMR	0x4
> @@ -431,13 +421,7 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
>  
>  void imx6_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	imx6_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(imx6_get_boot_source);
>  }
>  
>  #define IMX7_SRC_SBMR1	0x58
> @@ -543,13 +527,7 @@ void imx7_get_boot_source(enum bootsource *src, int *instance)
>  
>  void imx7_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	imx7_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(imx7_get_boot_source);
>  }
>  
>  static int vf610_boot_instance_spi(uint32_t r)
> @@ -643,11 +621,5 @@ void vf610_get_boot_source(enum bootsource *src, int *instance)
>  
>  void vf610_boot_save_loc(void)
>  {
> -	enum bootsource src = BOOTSOURCE_UNKNOWN;
> -	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
> -
> -	vf610_get_boot_source(&src, &instance);
> -
> -	bootsource_set(src);
> -	bootsource_set_instance(instance);
> +	imx_boot_save_loc(vf610_get_boot_source);
>  }
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Wed Apr 25 02:39:23 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 25 Apr 2018 11:39:23 +0200
Subject: [PATCH] ARM: imx_v7_defconfig: Select various missing v7 boards
 by default
In-Reply-To: <20180421015013.11620-1-andrew.smirnov@gmail.com>
References: <20180421015013.11620-1-andrew.smirnov@gmail.com>
Message-ID: <20180425093923.r7mziguellrz7nue@pengutronix.de>

On Fri, Apr 20, 2018 at 06:50:13PM -0700, Andrey Smirnov wrote:
> Add the following boards:
> 
>     - ZII RDU2 (all variants)
>     - ZII Vybrid Dev Board (and its derivatives)
>     - Freescale/NXP i.MX7D SabreSD
>     - NXP i.MX6ULL EVK
>     - element 14 WaRP7
> 
> to be selected by default by imx_v7_defconfig.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---

Applied, thanks

Sascha

>  arch/arm/configs/imx_v7_defconfig | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
> index 13135f2b3..8aef9d6ef 100644
> --- a/arch/arm/configs/imx_v7_defconfig
> +++ b/arch/arm/configs/imx_v7_defconfig
> @@ -33,10 +33,15 @@ CONFIG_MACH_VARISCITE_MX6=y
>  CONFIG_MACH_GW_VENTANA=y
>  CONFIG_MACH_CM_FX6=y
>  CONFIG_MACH_ADVANTECH_ROM_742X=y
> +CONFIG_MACH_WARP7=y
> +CONFIG_MACH_VF610_TWR=y
> +CONFIG_MACH_ZII_RDU2=y
> +CONFIG_MACH_ZII_VF610_DEV=y
>  CONFIG_MACH_PHYTEC_PHYCORE_IMX7=y
> +CONFIG_MACH_FREESCALE_MX7_SABRESD=y
> +CONFIG_MACH_NXP_IMX6ULL_EVK=y
>  CONFIG_IMX_IIM=y
>  CONFIG_IMX_IIM_FUSE_BLOW=y
> -CONFIG_IMX_OCOTP=y
>  CONFIG_THUMB2_BAREBOX=y
>  CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
>  CONFIG_ARM_UNWIND=y
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From ohlf at mkt-sys.de  Wed Apr 25 02:45:06 2018
From: ohlf at mkt-sys.de (Marc Ohlf)
Date: Wed, 25 Apr 2018 11:45:06 +0200
Subject: [PATCH] arm: imx6: don't reset PFDs that are used by periph_clk
Message-ID: <20180425094502.GA27294@ohlf-Precision-7720>

Check if PLL2 PFD0 or PLL2 PFD2 is selected as clock source in
register CCM CBCMR->pre_periph_clk_sel or CCM CBCMR->pre_periph2_clk.
Don't reset the used PFDs to avoid system hang.

ported from https://github.com/Freescale/u-boot-fslc/
commit/9293d7fd502ce29302fadb8b4ccb9231ec0bcc66

Signed-off-by: Marc Ohlf <ohlf at mkt-sys.de>
---
 arch/arm/mach-imx/imx6.c | 58 +++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 14a1cba..2b55a3c 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -16,6 +16,7 @@
 #include <io.h>
 #include <linux/sizes.h>
 #include <mfd/imx6q-iomuxc-gpr.h>
+#include <mach/clock-imx6.h>
 #include <mach/imx6.h>
 #include <mach/generic.h>
 #include <mach/revision.h>
@@ -44,6 +45,11 @@ static void imx6_init_lowlevel(void)
 	void __iomem *aips2 = (void *)MX6_AIPS2_ON_BASE_ADDR;
 	bool is_imx6q = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
 	bool is_imx6d = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6D;
+	uint32_t val_480;
+	uint32_t val_528;
+	uint32_t periph_sel_1;
+	uint32_t periph_sel_2;
+	uint32_t reg;
 
 	/*
 	 * Set all MPROTx to be non-bufferable, trusted for R/W,
@@ -68,32 +74,38 @@ static void imx6_init_lowlevel(void)
 	/* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
 	 * to make sure PFD is working right, otherwise, PFDs may
 	 * not output clock after reset, MX6DL and MX6SL have added 396M pfd
-	 * workaround in ROM code, as bus clock need it
+	 * workaround in ROM code, as bus clock need it.
+	 * Don't reset PLL2 PFD0 / PLL2 PFD2 if is's used by periph_clk.
 	 */
 	if (is_imx6q || is_imx6d) {
-		writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
-		       BM_ANADIG_PFD_480_PFD2_CLKGATE |
-		       BM_ANADIG_PFD_480_PFD1_CLKGATE |
-		       BM_ANADIG_PFD_480_PFD0_CLKGATE,
-		       MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_SET);
-		writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
-		       BM_ANADIG_PFD_528_PFD2_CLKGATE |
-		       BM_ANADIG_PFD_528_PFD1_CLKGATE |
-		       BM_ANADIG_PFD_528_PFD0_CLKGATE,
-		       MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_SET);
-
-		writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
-		       BM_ANADIG_PFD_480_PFD2_CLKGATE |
-		       BM_ANADIG_PFD_480_PFD1_CLKGATE |
-		       BM_ANADIG_PFD_480_PFD0_CLKGATE,
-		       MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_CLR);
-		writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
-		       BM_ANADIG_PFD_528_PFD2_CLKGATE |
-		       BM_ANADIG_PFD_528_PFD1_CLKGATE |
-		       BM_ANADIG_PFD_528_PFD0_CLKGATE,
-		       MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
-	}
+		val_480 = BM_ANADIG_PFD_480_PFD3_CLKGATE |
+			   BM_ANADIG_PFD_480_PFD2_CLKGATE |
+			   BM_ANADIG_PFD_480_PFD1_CLKGATE |
+			   BM_ANADIG_PFD_480_PFD0_CLKGATE;
+
+		val_528 = BM_ANADIG_PFD_528_PFD3_CLKGATE |
+			   BM_ANADIG_PFD_528_PFD1_CLKGATE;
+
+		reg = readl(MXC_CCM_CBCMR);
+		periph_sel_1 = (reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
+			>> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
+
+		periph_sel_2 = (reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
+			>> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET;
 
+		if ((periph_sel_1 != 0x2) && (periph_sel_2 != 0x2))
+			val_528 |= BM_ANADIG_PFD_528_PFD0_CLKGATE;
+
+		if ((periph_sel_1 != 0x1) && (periph_sel_2 != 0x1)
+		    && (periph_sel_1 != 0x3) && (periph_sel_2 != 0x3))
+			val_528 |= BM_ANADIG_PFD_528_PFD2_CLKGATE;
+
+		writel(val_480, MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_SET);
+		writel(val_528, MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_SET);
+
+		writel(val_480, MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_CLR);
+		writel(val_528, MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
+	}
 }
 
 static void imx6_setup_ipu_qos(void)
-- 
2.7.4



From s.hauer at pengutronix.de  Thu Apr 26 05:54:56 2018
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 26 Apr 2018 14:54:56 +0200
Subject: [PATCH v2 00/10] i.MX reset reason detection support
In-Reply-To: <20180421010538.16488-1-andrew.smirnov@gmail.com>
References: <20180421010538.16488-1-andrew.smirnov@gmail.com>
Message-ID: <20180426125456.afjcgysoq5ehb7tv@pengutronix.de>

On Fri, Apr 20, 2018 at 06:05:28PM -0700, Andrey Smirnov wrote:
> Everyone:
> 
> This patchset is the result of my work on adding support for detecting
> and reporting reset reason as can be obtained from System Reset
> Controller (to be more precise via SRSR register) on i.MX family of
> SoC.
> 
> Currently list of supported SoC is as follows:
> 
> 	  - i.MX6 (tested on i.MX6Q)
> 	  - i.MX7 (tested on i.MX7D)
> 	  - VFxxx (tested on VF610)
> 
> 
> Changes since [v1]:
> 
> 	- i.MX reset reason detection code was converted to do detect
>           the source with bitmasking as opposed to having a switch
>           statement, due to potential problems with the latter as was
>           pointed out by Philipp in [thread1]
> 
> 	- Change above also allowed to unify VFxxx and i.MX codepaths
>           without the need to introduce a dedicated VFxxx centric
>           function
> 
> [v1] http://lists.infradead.org/pipermail/barebox/2018-April/032614.html
> [thread1] http://lists.infradead.org/pipermail/barebox/2018-April/032708.html
> 
> Feedback is wellcome!
> 
> Thanks,
> Andrey Smirnov

Applied, thanks

Sascha

> 
> Andrey Smirnov (10):
>   common: reset_source: Add the notion of "reset source instance"
>   ARM: i.MX: Add infrastructure to record SoC reset reason
>   ARM: i.MX6: Record reset reason as a part of startup
>   ARM: i.MX7: Record reset reason as a part of startup
>   common: reset_source: Introduce reset_source_name()
>   ARM: i.MX: Log detected reset reason
>   ARM: i.MX: Print "revision unknown" if that is the case
>   ARM: VFxxx: Add code to detect cpu variant
>   ARM: VFxxx: Detect cpu variant on start
>   ARM: VFxxx: Record reset reason as a part of startup
> 
>  arch/arm/mach-imx/Makefile                    |  1 +
>  arch/arm/mach-imx/imx.c                       | 43 ++++++++++++++++++-
>  arch/arm/mach-imx/imx6.c                      | 13 +++++-
>  arch/arm/mach-imx/imx7.c                      | 14 +++++++
>  arch/arm/mach-imx/include/mach/generic.h      |  1 +
>  arch/arm/mach-imx/include/mach/reset-reason.h | 37 +++++++++++++++++
>  arch/arm/mach-imx/include/mach/vf610-regs.h   |  3 ++
>  arch/arm/mach-imx/include/mach/vf610.h        | 51 +++++++++++++++++++++++
>  arch/arm/mach-imx/vf610.c                     | 59 +++++++++++++++++++++++++++
>  common/reset_source.c                         | 23 +++++++++++
>  include/reset_source.h                        | 17 ++++++++
>  11 files changed, 259 insertions(+), 3 deletions(-)
>  create mode 100644 arch/arm/mach-imx/include/mach/reset-reason.h
>  create mode 100644 arch/arm/mach-imx/include/mach/vf610.h
>  create mode 100644 arch/arm/mach-imx/vf610.c
> 
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From nikita.yoush at cogentembedded.com  Thu Apr 26 06:02:48 2018
From: nikita.yoush at cogentembedded.com (Nikita Yushchenko)
Date: Thu, 26 Apr 2018 16:02:48 +0300
Subject: [PATCH] usbnet: increase bulk message timeout
Message-ID: <216a62f9-5450-5ed6-945f-b3d26d65ae3e@cogentembedded.com>

Timeout of 1ms is too low for case when device operates in Full Speed
mode. This causes most incoming frames to be lost.

Since timeout is only used to get out of polling loop in case of no
response from hardware, increasing it should be safe for all platforms.

Signed-off-by: Nikita Yushchenko <nikita.yoush at cogentembedded.com>
Tested-By: Andrew Lunn <andrew at lunn.ch>
---
 drivers/net/usb/usbnet.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 33d900b70..60e67ff1a 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -125,7 +125,7 @@ static int usbnet_recv(struct eth_device *edev)
  	len = dev->rx_urb_size;
 -	ret = usb_bulk_msg(dev->udev, dev->in, rx_buf, len, &alen, 1);
+	ret = usb_bulk_msg(dev->udev, dev->in, rx_buf, len, &alen, 100);
 	if (ret)
 		return ret;
 -- 2.11.0



From akurz at blala.de  Thu Apr 26 10:56:44 2018
From: akurz at blala.de (Alexander Kurz)
Date: Thu, 26 Apr 2018 17:56:44 +0000
Subject: [PATCH 1/2] ARM omap beagle xload_defconfig: do not load drivers from
 DT
Message-ID: <20180426175645.15105-1-akurz@blala.de>

The first stage loader must run in SRAM and is limited in size.
Remove unused support to load drivers from DT at this stage and
save precious 9kB of code size.
Regenerating the defconfig removes CONFIG_TEXT_BASE.

Signed-off-by: Alexander Kurz <akurz at blala.de>
---
 arch/arm/configs/omap3530_beagle_xload_defconfig | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/arm/configs/omap3530_beagle_xload_defconfig b/arch/arm/configs/omap3530_beagle_xload_defconfig
index d36aaf319..2105c0b9d 100644
--- a/arch/arm/configs/omap3530_beagle_xload_defconfig
+++ b/arch/arm/configs/omap3530_beagle_xload_defconfig
@@ -8,7 +8,6 @@ CONFIG_THUMB2_BAREBOX=y
 CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
 CONFIG_ARM_UNWIND=y
 CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x0
 CONFIG_STACK_SIZE=0xc00
 CONFIG_MALLOC_SIZE=0x0
 CONFIG_MALLOC_DUMMY=y
@@ -18,7 +17,6 @@ CONFIG_SHELL_NONE=y
 # CONFIG_ERRNO_MESSAGES is not set
 # CONFIG_TIMESTAMP is not set
 CONFIG_CONSOLE_SIMPLE=y
-CONFIG_OFDEVICE=y
 CONFIG_DRIVER_SERIAL_NS16550=y
 CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
 # CONFIG_SPI is not set
@@ -36,7 +34,6 @@ CONFIG_MCI=y
 CONFIG_MCI_STARTUP=y
 # CONFIG_MCI_WRITE is not set
 CONFIG_MCI_OMAP_HSMMC=y
-# CONFIG_PINCTRL is not set
 # CONFIG_FS_RAMFS is not set
 # CONFIG_FS_DEVFS is not set
 CONFIG_FS_FAT=y
-- 
2.11.0



From akurz at blala.de  Thu Apr 26 10:56:45 2018
From: akurz at blala.de (Alexander Kurz)
Date: Thu, 26 Apr 2018 17:56:45 +0000
Subject: [PATCH 2/2] ARM omap beagle defconfig: remove trace initcalls
In-Reply-To: <20180426175645.15105-1-akurz@blala.de>
References: <20180426175645.15105-1-akurz@blala.de>
Message-ID: <20180426175645.15105-2-akurz@blala.de>

Debug output may be switched on when needed, but should not be on by default.
Regenerating the defconfig removes CONFIG_TEXT_BASE.

Signed-off-by: Alexander Kurz <akurz at blala.de>
---
 arch/arm/configs/omap3530_beagle_defconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/configs/omap3530_beagle_defconfig b/arch/arm/configs/omap3530_beagle_defconfig
index b454cf2b4..cf7914855 100644
--- a/arch/arm/configs/omap3530_beagle_defconfig
+++ b/arch/arm/configs/omap3530_beagle_defconfig
@@ -5,7 +5,6 @@ CONFIG_THUMB2_BAREBOX=y
 CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
 CONFIG_ARM_UNWIND=y
 CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x0
 CONFIG_MALLOC_SIZE=0x0
 CONFIG_MALLOC_TLSF=y
 CONFIG_KALLSYMS=y
@@ -26,7 +25,6 @@ CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
 CONFIG_RESET_SOURCE=y
 CONFIG_DEBUG_LL=y
 CONFIG_DEBUG_OMAP_UART_PORT=3
-CONFIG_DEBUG_INITCALLS=y
 CONFIG_CMD_DMESG=y
 CONFIG_LONGHELP=y
 CONFIG_CMD_IOMEM=y
-- 
2.11.0



From andrew.smirnov at gmail.com  Thu Apr 26 22:31:05 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:31:05 -0700
Subject: [PATCH] ARM: VFxxx: Recort cpu boot source as a part of startup
Message-ID: <20180427053105.9874-1-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/vf610.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
index df8cfcd6b..3ac7c356f 100644
--- a/arch/arm/mach-imx/vf610.c
+++ b/arch/arm/mach-imx/vf610.c
@@ -35,6 +35,8 @@ int vf610_init(void)
 	const char *cputypestr;
 	void __iomem *src = IOMEM(VF610_SRC_BASE_ADDR);
 
+	vf610_boot_save_loc();
+
 	switch (vf610_cpu_type()) {
 	case VF610_CPUTYPE_VF610:
 		cputypestr = "VF610";
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:32:16 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:32:16 -0700
Subject: [PATCH] ARM: i.MX7: Remove unnecessary local variable
Message-ID: <20180427053216.10040-1-andrew.smirnov@gmail.com>

It looks this code was based on analogous code for i.MX6, but there
that variable was being used as a part of following switch
statement. Since this is not the case for i.MX7, just replace the
variable with direct function call.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx7.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c
index 5ad91c2d7..e49baf6f7 100644
--- a/arch/arm/mach-imx/imx7.c
+++ b/arch/arm/mach-imx/imx7.c
@@ -182,7 +182,6 @@ static const struct imx_reset_reason imx7_reset_reasons[] = {
 int imx7_init(void)
 {
 	const char *cputypestr;
-	u32 imx7_silicon_revision;
 	void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR);
 
 	imx7_init_lowlevel();
@@ -193,8 +192,6 @@ int imx7_init(void)
 
 	imx7_boot_save_loc();
 
-	imx7_silicon_revision = imx7_cpu_revision();
-
 	psci_set_ops(&imx7_psci_ops);
 
 	switch (imx7_cpu_type()) {
@@ -209,7 +206,7 @@ int imx7_init(void)
 		break;
 	}
 
-	imx_set_silicon_revision(cputypestr, imx7_silicon_revision);
+	imx_set_silicon_revision(cputypestr, imx7_cpu_revision());
 	imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons);
 
 	return 0;
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:40 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:40 -0700
Subject: [PATCH 0/6] i.MX51, 53 reset reason detection support
Message-ID: <20180427054946.11687-1-andrew.smirnov@gmail.com>

Everyone:

This patchset is a followup to "i.MX reset reason detection support"
series I submited a couple of days ago. Mostly bits and pieces needed
for i.MX51 and i.MX53 integration with the rest of reset reason code.

Feedback is wellcome!

Sascha:

Let me know if you want me to squash these patches back into original
"i.MX reset reason detection support" series and re-submit it.

Thanks,
Andrey Smirnov

Andrey Smirnov (6):
  ARM: i.MX51: Replace expicit casts with IOMEM
  ARM: i.MX: Fix incorrect IMX_SRC_SRSR_CSU_RESET
  ARM: i.MX: Make imx6_reset_reasons global
  ARM: i.MX: Introduce IMX_SRC_SRSR
  ARM: i.MX53: Record reset reason as a part of startup
  ARM: i.MX51: Record reset reason as a part of startup

 arch/arm/mach-imx/imx.c                       |  9 +++++++++
 arch/arm/mach-imx/imx51.c                     | 20 ++++++++++++--------
 arch/arm/mach-imx/imx53.c                     |  4 ++++
 arch/arm/mach-imx/imx6.c                      | 11 +----------
 arch/arm/mach-imx/include/mach/reset-reason.h |  8 ++++----
 arch/arm/mach-imx/vf610.c                     |  2 +-
 6 files changed, 31 insertions(+), 23 deletions(-)

-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:41 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:41 -0700
Subject: [PATCH 1/6] ARM: i.MX51: Replace expicit casts with IOMEM
In-Reply-To: <20180427054946.11687-1-andrew.smirnov@gmail.com>
References: <20180427054946.11687-1-andrew.smirnov@gmail.com>
Message-ID: <20180427054946.11687-2-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx51.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c
index ffe6a7c65..13444ccdb 100644
--- a/arch/arm/mach-imx/imx51.c
+++ b/arch/arm/mach-imx/imx51.c
@@ -43,7 +43,7 @@ static int imx51_silicon_revision(void)
 
 static void imx51_ipu_mipi_setup(void)
 {
-	void __iomem *hsc_addr = (void __iomem *)MX51_MIPI_HSC_BASE_ADDR;
+	void __iomem *hsc_addr = IOMEM(MX51_MIPI_HSC_BASE_ADDR);
 	u32 val;
 
 	/* setup MIPI module to legacy mode */
@@ -97,7 +97,7 @@ int imx51_devices_init(void)
  */
 static void imx51_setup_pll800_bug(void)
 {
-	void __iomem *base = (void *)MX51_PLL1_BASE_ADDR;
+	void __iomem *base = IOMEM(MX51_PLL1_BASE_ADDR);
 	u32 dp_config;
 	volatile int i;
 
@@ -132,7 +132,7 @@ static void imx51_setup_pll800_bug(void)
 
 void imx51_init_lowlevel(unsigned int cpufreq_mhz)
 {
-	void __iomem *ccm = (void __iomem *)MX51_CCM_BASE_ADDR;
+	void __iomem *ccm = IOMEM(MX51_CCM_BASE_ADDR);
 	u32 r;
 	int rev = imx51_silicon_revision();
 
@@ -167,30 +167,30 @@ void imx51_init_lowlevel(unsigned int cpufreq_mhz)
 
 	switch (cpufreq_mhz) {
 	case 600:
-		imx5_setup_pll_600((void __iomem *)MX51_PLL1_BASE_ADDR);
+		imx5_setup_pll_600(IOMEM(MX51_PLL1_BASE_ADDR));
 		break;
 	default:
 		/* Default maximum 800MHz */
 		if (rev <= IMX_CHIP_REV_3_0)
 			imx51_setup_pll800_bug();
 		else
-			imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR);
+			imx5_setup_pll_800(IOMEM(MX51_PLL1_BASE_ADDR));
 		break;
 	}
 
-	imx5_setup_pll_665((void __iomem *)MX51_PLL3_BASE_ADDR);
+	imx5_setup_pll_665(IOMEM(MX51_PLL3_BASE_ADDR));
 
 	/* Switch peripheral to PLL 3 */
 	writel(0x000010C0, ccm + MX5_CCM_CBCMR);
 	writel(0x13239145, ccm + MX5_CCM_CBCDR);
 
-	imx5_setup_pll_665((void __iomem *)MX51_PLL2_BASE_ADDR);
+	imx5_setup_pll_665(IOMEM(MX51_PLL2_BASE_ADDR));
 
 	/* Switch peripheral to PLL2 */
 	writel(0x19239145, ccm + MX5_CCM_CBCDR);
 	writel(0x000020C0, ccm + MX5_CCM_CBCMR);
 
-	imx5_setup_pll_216((void __iomem *)MX51_PLL3_BASE_ADDR);
+	imx5_setup_pll_216(IOMEM(MX51_PLL3_BASE_ADDR));
 
 	/* Set the platform clock dividers */
 	writel(0x00000125, MX51_ARM_BASE_ADDR + 0x14);
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:42 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:42 -0700
Subject: [PATCH 2/6] ARM: i.MX: Fix incorrect IMX_SRC_SRSR_CSU_RESET
In-Reply-To: <20180427054946.11687-1-andrew.smirnov@gmail.com>
References: <20180427054946.11687-1-andrew.smirnov@gmail.com>
Message-ID: <20180427054946.11687-3-andrew.smirnov@gmail.com>

IMX_SRC_SRSR_CSU_RESET is bit 2, not 1.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/include/mach/reset-reason.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index 4919f68d5..23e73d3b5 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -4,7 +4,7 @@
 #include <reset_source.h>
 
 #define IMX_SRC_SRSR_IPP_RESET		BIT(0)
-#define IMX_SRC_SRSR_CSU_RESET		BIT(1)
+#define IMX_SRC_SRSR_CSU_RESET		BIT(2)
 #define IMX_SRC_SRSR_IPP_USER_RESET	BIT(3)
 #define IMX_SRC_SRSR_WDOG1_RESET	BIT(4)
 #define IMX_SRC_SRSR_JTAG_RESET		BIT(5)
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:43 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:43 -0700
Subject: [PATCH 3/6] ARM: i.MX: Make imx6_reset_reasons global
In-Reply-To: <20180427054946.11687-1-andrew.smirnov@gmail.com>
References: <20180427054946.11687-1-andrew.smirnov@gmail.com>
Message-ID: <20180427054946.11687-4-andrew.smirnov@gmail.com>

Both i.MX51 and i.MX53 have exactly the same reset source mapping, so
rename imx6_reset_reasons to imx_reset_reasons and make it a globally
visible constant so it could be shared.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx.c                       |  9 +++++++++
 arch/arm/mach-imx/imx6.c                      | 11 +----------
 arch/arm/mach-imx/include/mach/reset-reason.h |  2 ++
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index bf15f0b06..1b4c1b3df 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -153,6 +153,15 @@ static int imx_init(void)
 }
 postcore_initcall(imx_init);
 
+const struct imx_reset_reason imx_reset_reasons[] = {
+	{ IMX_SRC_SRSR_IPP_RESET,     RESET_POR,  0 },
+	{ IMX_SRC_SRSR_WDOG1_RESET,   RESET_WDG,  0 },
+	{ IMX_SRC_SRSR_JTAG_RESET,    RESET_JTAG, 0 },
+	{ IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 },
+	{ IMX_SRC_SRSR_WARM_BOOT,     RESET_RST,  0 },
+	{ /* sentinel */ }
+};
+
 void imx_set_reset_reason(void __iomem *srsr,
 			  const struct imx_reset_reason *reasons)
 {
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 49610bf08..dc09088ab 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -174,15 +174,6 @@ int imx6_cpu_revision(void)
 	return soc_revision;
 }
 
-static const struct imx_reset_reason imx6_reset_reasons[] = {
-	{ IMX_SRC_SRSR_IPP_RESET,     RESET_POR,  0 },
-	{ IMX_SRC_SRSR_WDOG1_RESET,   RESET_WDG,  0 },
-	{ IMX_SRC_SRSR_JTAG_RESET,    RESET_JTAG, 0 },
-	{ IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 },
-	{ IMX_SRC_SRSR_WARM_BOOT,     RESET_RST,  0 },
-	{ /* sentinel */ }
-};
-
 int imx6_init(void)
 {
 	const char *cputypestr;
@@ -232,7 +223,7 @@ int imx6_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
-	imx_set_reset_reason(src + IMX6_SRC_SRSR, imx6_reset_reasons);
+	imx_set_reset_reason(src + IMX6_SRC_SRSR, imx_reset_reasons);
 	imx6_setup_ipu_qos();
 	imx6ul_enet_clk_init();
 
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index 23e73d3b5..0894b95ab 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -34,4 +34,6 @@ struct imx_reset_reason {
 
 void imx_set_reset_reason(void __iomem *, const struct imx_reset_reason *);
 
+extern const struct imx_reset_reason imx_reset_reasons[];
+
 #endif /* __MACH_RESET_REASON_H__ */
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:44 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:44 -0700
Subject: [PATCH 4/6] ARM: i.MX: Introduce IMX_SRC_SRSR
In-Reply-To: <20180427054946.11687-1-andrew.smirnov@gmail.com>
References: <20180427054946.11687-1-andrew.smirnov@gmail.com>
Message-ID: <20180427054946.11687-5-andrew.smirnov@gmail.com>

Offset for SRSR register in SRC IP block for i.MX51, i.MX53, i.MX6 and
VFxxx is exactly the same so define a single constant for that and
replace all of the SoC specific definitions.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx6.c                      | 2 +-
 arch/arm/mach-imx/include/mach/reset-reason.h | 4 +---
 arch/arm/mach-imx/vf610.c                     | 2 +-
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index dc09088ab..dfa861d38 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -223,7 +223,7 @@ int imx6_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, mx6_silicon_revision);
-	imx_set_reset_reason(src + IMX6_SRC_SRSR, imx_reset_reasons);
+	imx_set_reset_reason(src + IMX_SRC_SRSR, imx_reset_reasons);
 	imx6_setup_ipu_qos();
 	imx6ul_enet_clk_init();
 
diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h
index 0894b95ab..0f644a8c1 100644
--- a/arch/arm/mach-imx/include/mach/reset-reason.h
+++ b/arch/arm/mach-imx/include/mach/reset-reason.h
@@ -14,10 +14,8 @@
 #define IMX_SRC_SRSR_TEMPSENSE_RESET	BIT(9)
 #define IMX_SRC_SRSR_WARM_BOOT		BIT(16)
 
-#define IMX6_SRC_SRSR	0x008
+#define IMX_SRC_SRSR	0x008
 #define IMX7_SRC_SRSR	0x05c
-#define VF610_SRC_SRSR	0x008
-
 
 #define VF610_SRC_SRSR_SW_RST		BIT(18)
 #define VF610_SRC_SRSR_RESETB		BIT(7)
diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
index 3ac7c356f..b548cbcb5 100644
--- a/arch/arm/mach-imx/vf610.c
+++ b/arch/arm/mach-imx/vf610.c
@@ -56,6 +56,6 @@ int vf610_init(void)
 	}
 
 	imx_set_silicon_revision(cputypestr, vf610_cpu_revision());
-	imx_set_reset_reason(src + VF610_SRC_SRSR, vf610_reset_reasons);
+	imx_set_reset_reason(src + IMX_SRC_SRSR, vf610_reset_reasons);
 	return 0;
 }
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:45 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:45 -0700
Subject: [PATCH 5/6] ARM: i.MX53: Record reset reason as a part of startup
In-Reply-To: <20180427054946.11687-1-andrew.smirnov@gmail.com>
References: <20180427054946.11687-1-andrew.smirnov@gmail.com>
Message-ID: <20180427054946.11687-6-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx53.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c
index 2758f1bbc..56f1bda75 100644
--- a/arch/arm/mach-imx/imx53.c
+++ b/arch/arm/mach-imx/imx53.c
@@ -21,6 +21,7 @@
 #include <mach/revision.h>
 #include <mach/clock-imx51_53.h>
 #include <mach/generic.h>
+#include <mach/reset-reason.h>
 
 #define SI_REV 0x48
 
@@ -52,7 +53,10 @@ static int imx53_silicon_revision(void)
 
 int imx53_init(void)
 {
+	void __iomem *src = IOMEM(MX53_SRC_BASE_ADDR);
+
 	imx53_silicon_revision();
+	imx_set_reset_reason(src + IMX_SRC_SRSR, imx_reset_reasons);
 	imx53_boot_save_loc();
 	add_generic_device("imx53-esdctl", 0, NULL, MX53_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL);
 
-- 
2.14.3



From andrew.smirnov at gmail.com  Thu Apr 26 22:49:46 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Thu, 26 Apr 2018 22:49:46 -0700
Subject: [PATCH 6/6] ARM: i.MX51: Record reset reason as a part of startup
In-Reply-To: <20180427054946.11687-1-andrew.smirnov@gmail.com>
References: <20180427054946.11687-1-andrew.smirnov@gmail.com>
Message-ID: <20180427054946.11687-7-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 arch/arm/mach-imx/imx51.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c
index 13444ccdb..ec8cdd868 100644
--- a/arch/arm/mach-imx/imx51.c
+++ b/arch/arm/mach-imx/imx51.c
@@ -21,6 +21,7 @@
 #include <mach/revision.h>
 #include <mach/clock-imx51_53.h>
 #include <mach/generic.h>
+#include <mach/reset-reason.h>
 
 #define IIM_SREV 0x24
 
@@ -57,7 +58,10 @@ static void imx51_ipu_mipi_setup(void)
 
 int imx51_init(void)
 {
+	void __iomem *src = IOMEM(MX51_SRC_BASE_ADDR);
+
 	imx_set_silicon_revision("i.MX51", imx51_silicon_revision());
+	imx_set_reset_reason(src + IMX_SRC_SRSR, imx_reset_reasons);
 	imx51_boot_save_loc();
 	add_generic_device("imx51-esdctl", 0, NULL, MX51_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL);
 	imx51_ipu_mipi_setup();
-- 
2.14.3



From r.hieber at pengutronix.de  Fri Apr 27 02:45:59 2018
From: r.hieber at pengutronix.de (Roland Hieber)
Date: Fri, 27 Apr 2018 11:45:59 +0200
Subject: [PATCH] ARM: VFxxx: Recort cpu boot source as a part of startup
In-Reply-To: <20180427053105.9874-1-andrew.smirnov@gmail.com>
References: <20180427053105.9874-1-andrew.smirnov@gmail.com>
Message-ID: <20180427094559.paxm7wqtaxsizonp@pengutronix.de>

In the subject: s/Record/Report/ ?

 - Roland

On Thu, Apr 26, 2018 at 10:31:05PM -0700, Andrey Smirnov wrote:
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
>  arch/arm/mach-imx/vf610.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
> index df8cfcd6b..3ac7c356f 100644
> --- a/arch/arm/mach-imx/vf610.c
> +++ b/arch/arm/mach-imx/vf610.c
> @@ -35,6 +35,8 @@ int vf610_init(void)
>  	const char *cputypestr;
>  	void __iomem *src = IOMEM(VF610_SRC_BASE_ADDR);
>  
> +	vf610_boot_save_loc();
> +
>  	switch (vf610_cpu_type()) {
>  	case VF610_CPUTYPE_VF610:
>  		cputypestr = "VF610";
> -- 
> 2.14.3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Roland Hieber                     | r.hieber at pengutronix.de     |
Pengutronix e.K.                  | https://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |


From andrew.smirnov at gmail.com  Fri Apr 27 12:01:22 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Fri, 27 Apr 2018 12:01:22 -0700
Subject: [PATCH] ARM: VFxxx: Recort cpu boot source as a part of startup
In-Reply-To: <20180427094559.paxm7wqtaxsizonp@pengutronix.de>
References: <20180427053105.9874-1-andrew.smirnov@gmail.com>
 <20180427094559.paxm7wqtaxsizonp@pengutronix.de>
Message-ID: <CAHQ1cqEBb3Dti=mHcgNiedMcUCp30yT1zdLkvCq5K1-04wbz_Q@mail.gmail.com>

On Fri, Apr 27, 2018 at 2:45 AM, Roland Hieber <r.hieber at pengutronix.de> wrote:
> In the subject: s/Record/Report/ ?

Yeah, my bad. Will fix in v2.

Thanks,
Andrey Smirnov


From linux at rempel-privat.de  Sun Apr 29 06:09:00 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:00 +0200
Subject: [RFC PATCH 0/7] provide ELF/KEXEC support for MIPS ath79 and malta
Message-ID: <20180429130907.20506-1-linux@rempel-privat.de>

This patch set is a squashed and rebased patch set of work done by:
Antony Pavlov and Yegor Yefremov.

This code suppose provide kernel start support for some MIPS machines.
For example ath79 (Atheros) and malta should be able to work with it.

So far only kernel and cmdline passing is supported. ARM and other arches would
probably work with some more or less work.

Antony Pavlov (5):
  resource: add create_resource() helper function
  filetype: add ELF type
  bootm: add kexec ELF support
  MIPS: add kexec ELF loading support
  MIPS: malta: enable kexec

Oleksij Rempel (2):
  MIPS: ath79: add kexec support
  MIPS: configs: add KEXEC=y to atheros devices

 arch/mips/Kconfig                                 |   2 +
 arch/mips/configs/8devices-lima_defconfig         |   1 +
 arch/mips/configs/black-swift_defconfig           |   1 +
 arch/mips/configs/dptechnics-dpt-module_defconfig |   1 +
 arch/mips/configs/tplink-mr3020_defconfig         |   1 +
 arch/mips/configs/tplink-wdr4300_defconfig        |   1 +
 arch/mips/include/asm/elf.h                       |   8 +-
 arch/mips/lib/Makefile                            |   3 +
 arch/mips/lib/kexec-mips.c                        | 272 +++++++++
 arch/mips/lib/machine_kexec.h                     |  21 +
 arch/mips/lib/relocate_kernel.S                   | 108 ++++
 arch/mips/mach-ath79/Makefile                     |   1 +
 arch/mips/mach-ath79/reboot.c                     |  42 ++
 arch/mips/mach-malta/Makefile                     |   1 +
 arch/mips/mach-malta/reboot.c                     | 106 ++++
 commands/Kconfig                                  |   7 +
 common/Kconfig                                    |   3 +
 common/filetype.c                                 |   5 +
 common/resource.c                                 |  15 +
 include/bootm.h                                   |   3 +
 include/filetype.h                                |   1 +
 include/linux/ioport.h                            |   2 +
 include/linux/reboot.h                            |  14 +
 lib/Makefile                                      |   1 +
 lib/kexec/Makefile                                |   4 +
 lib/kexec/kexec-bootm-elf.c                       |  37 ++
 lib/kexec/kexec-elf-exec.c                        |  79 +++
 lib/kexec/kexec-elf.c                             | 678 ++++++++++++++++++++++
 lib/kexec/kexec-elf.h                             |  66 +++
 lib/kexec/kexec.c                                 | 281 +++++++++
 lib/kexec/kexec.h                                 |  92 +++
 31 files changed, 1856 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/lib/kexec-mips.c
 create mode 100644 arch/mips/lib/machine_kexec.h
 create mode 100644 arch/mips/lib/relocate_kernel.S
 create mode 100644 arch/mips/mach-ath79/reboot.c
 create mode 100644 arch/mips/mach-malta/reboot.c
 create mode 100644 include/linux/reboot.h
 create mode 100644 lib/kexec/Makefile
 create mode 100644 lib/kexec/kexec-bootm-elf.c
 create mode 100644 lib/kexec/kexec-elf-exec.c
 create mode 100644 lib/kexec/kexec-elf.c
 create mode 100644 lib/kexec/kexec-elf.h
 create mode 100644 lib/kexec/kexec.c
 create mode 100644 lib/kexec/kexec.h

-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:06 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:06 +0200
Subject: [RFC PATCH 6/7] MIPS: malta: enable kexec
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-7-linux@rempel-privat.de>

From: Antony Pavlov <antonynpavlov at gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/mips/Kconfig             |   1 +
 arch/mips/mach-malta/Makefile |   1 +
 arch/mips/mach-malta/reboot.c | 106 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 arch/mips/mach-malta/reboot.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 2b549373a..ab5a05e0d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -51,6 +51,7 @@ config MACH_MIPS_MALTA
 	select HAS_DEBUG_LL
 	select GPIOLIB
 	select HW_HAS_PCI
+	select HAS_KEXEC
 
 config MACH_MIPS_AR231X
 	bool "Atheros ar231x-based boards"
diff --git a/arch/mips/mach-malta/Makefile b/arch/mips/mach-malta/Makefile
index 0c5a7018d..20d9204f3 100644
--- a/arch/mips/mach-malta/Makefile
+++ b/arch/mips/mach-malta/Makefile
@@ -1,2 +1,3 @@
 obj-y += reset.o
 obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_KEXEC) += reboot.o
diff --git a/arch/mips/mach-malta/reboot.c b/arch/mips/mach-malta/reboot.c
new file mode 100644
index 000000000..b4572fc1d
--- /dev/null
+++ b/arch/mips/mach-malta/reboot.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014, 2016 Antony Pavlov <antonynpavlov at 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 <memory.h>
+#include <boot.h>
+#include <linux/reboot.h>
+#include <bootm.h>
+#include "../../../lib/kexec/kexec.h"
+#include <asm/io.h>
+
+#define ENVP_ADDR	0x80002000l
+#define ENVP_NB_ENTRIES	16
+#define ENVP_ENTRY_SIZE	256
+
+static int reserve_yamon_prom_env(void)
+{
+	request_sdram_region("yamon env",
+		(unsigned long)ENVP_ADDR,
+		ENVP_NB_ENTRIES * ENVP_ENTRY_SIZE);
+
+	return 0;
+}
+late_initcall(reserve_yamon_prom_env);
+
+static void prom_set(uint32_t *prom_buf, int index,
+			const char *string, ...)
+{
+	va_list ap;
+	int32_t table_addr;
+
+	if (index >= ENVP_NB_ENTRIES)
+		return;
+
+	if (string == NULL) {
+		prom_buf[index] = 0;
+		return;
+	}
+
+	table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+	prom_buf[index] = (ENVP_ADDR + table_addr);
+
+	va_start(ap, string);
+	vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
+	va_end(ap);
+}
+
+static inline void yamon_prom_set(char *fname)
+{
+	void *prom_buf;
+	long prom_size;
+	int prom_index = 0;
+
+	/* Setup prom parameters. */
+	prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
+	prom_buf = (void *)ENVP_ADDR;
+
+	prom_set(prom_buf, prom_index++, "%s", fname);
+	prom_set(prom_buf, prom_index++, "%s", linux_bootargs_get());
+
+	prom_set(prom_buf, prom_index++, "memsize");
+	prom_set(prom_buf, prom_index++, "%i", 256 << 20);
+	prom_set(prom_buf, prom_index++, "modetty0");
+	prom_set(prom_buf, prom_index++, "38400n8r");
+	prom_set(prom_buf, prom_index++, NULL);
+}
+
+int reboot(int cmd, void *opaque)
+{
+	if (cmd == LINUX_REBOOT_CMD_KEXEC) {
+		extern unsigned long reboot_code_buffer;
+		extern unsigned long kexec_args[4];
+		void (*kexec_code_buffer)(void);
+		struct image_data *data = opaque;
+
+		yamon_prom_set(data->os_file);
+
+		shutdown_barebox();
+
+		kexec_code_buffer = phys_to_virt(reboot_code_buffer);
+
+		kexec_args[0] = 2; /* number of arguments? */
+		kexec_args[1] = ENVP_ADDR;
+		kexec_args[2] = ENVP_ADDR + 8;
+		kexec_args[3] = 0x10000000; /* no matter */
+		kexec_code_buffer();
+	}
+
+	return -1;
+}
+EXPORT_SYMBOL(reboot);
-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:01 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:01 +0200
Subject: [RFC PATCH 1/7] resource: add create_resource() helper function
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-2-linux@rempel-privat.de>

From: Antony Pavlov <antonynpavlov at gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 common/resource.c      | 15 +++++++++++++++
 include/linux/ioport.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/common/resource.c b/common/resource.c
index e4bbe15fd..fa9ffd084 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -150,3 +150,18 @@ struct resource *request_ioport_region(const char *name,
 
 	return res;
 }
+
+struct resource *create_resource(const char *name,
+	resource_size_t start, resource_size_t end)
+{
+	struct resource *t;
+
+	t = xzalloc(sizeof *t);
+	INIT_LIST_HEAD(&t->children);
+	t->parent = NULL;
+	t->name = xstrdup(name);
+	t->start = start;
+	t->end = end;
+
+	return t;
+}
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 3d375a874..2a944cc73 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -140,6 +140,8 @@ struct resource *__request_region(struct resource *parent,
 		resource_size_t size);
 
 int release_region(struct resource *res);
+struct resource *create_resource(const char *name,
+	resource_size_t start, resource_size_t end);
 
 extern struct resource iomem_resource;
 extern struct resource ioport_resource;
-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:02 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:02 +0200
Subject: [RFC PATCH 2/7] filetype: add ELF type
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-3-linux@rempel-privat.de>

From: Antony Pavlov <antonynpavlov at gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 common/filetype.c  | 5 +++++
 include/filetype.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/common/filetype.c b/common/filetype.c
index 444ec14cc..77cf9a105 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -27,6 +27,7 @@
 #include <envfs.h>
 #include <disks.h>
 #include <image-sparse.h>
+#include <elf.h>
 
 struct filetype_str {
 	const char *name;	/* human readable filetype */
@@ -68,6 +69,7 @@ static const struct filetype_str filetype_str[] = {
 	[filetype_kwbimage_v1] = { "MVEBU kwbimage (v1)", "kwb" },
 	[filetype_android_sparse] = { "Android sparse image", "sparse" },
 	[filetype_arm64_linux_image] = { "ARM aarch64 Linux image", "aarch64-linux" },
+	[filetype_elf] = { "ELF", "elf" },
 };
 
 const char *file_type_to_string(enum filetype f)
@@ -344,6 +346,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
 		buf[7] == 0x47530000)
 		return filetype_ch_image_be;
 
+	if (strncmp(buf8, ELFMAG, 4) == 0)
+		return filetype_elf;
+
 	return filetype_unknown;
 }
 
diff --git a/include/filetype.h b/include/filetype.h
index 9986938dd..3b930bf94 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -41,6 +41,7 @@ enum filetype {
 	filetype_kwbimage_v1,
 	filetype_android_sparse,
 	filetype_arm64_linux_image,
+	filetype_elf,
 	filetype_max,
 };
 
-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:05 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:05 +0200
Subject: [RFC PATCH 5/7] MIPS: ath79: add kexec support
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-6-linux@rempel-privat.de>

Signed-off-by: Oleksij Rempel <linux at rempel-privat.de>
---
 arch/mips/Kconfig             |  1 +
 arch/mips/mach-ath79/Makefile |  1 +
 arch/mips/mach-ath79/reboot.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 44 insertions(+)
 create mode 100644 arch/mips/mach-ath79/reboot.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c2c555dc3..2b549373a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -73,6 +73,7 @@ config MACH_MIPS_ATH79
 	select CLKDEV_LOOKUP
 	select OFTREE
 	select GPIOLIB
+	select HAS_KEXEC
 
 config MACH_MIPS_BCM47XX
 	bool "Broadcom BCM47xx-based boards"
diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile
index 3772daeba..9b8218dd6 100644
--- a/arch/mips/mach-ath79/Makefile
+++ b/arch/mips/mach-ath79/Makefile
@@ -1,2 +1,3 @@
 obj-y += reset.o
 obj-y += bbu.o
+obj-$(CONFIG_KEXEC) += reboot.o
diff --git a/arch/mips/mach-ath79/reboot.c b/arch/mips/mach-ath79/reboot.c
new file mode 100644
index 000000000..c207c58d3
--- /dev/null
+++ b/arch/mips/mach-ath79/reboot.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 Antony Pavlov <antonynpavlov at 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 <memory.h>
+#include <boot.h>
+#include <linux/reboot.h>
+#include <bootm.h>
+#include "../../../lib/kexec/kexec.h"
+#include <asm/io.h>
+
+int reboot(int cmd, void *opaque)
+{
+	if (cmd == LINUX_REBOOT_CMD_KEXEC) {
+		extern unsigned long reboot_code_buffer;
+		void (*kexec_code_buffer)(void);
+
+		shutdown_barebox();
+
+		kexec_code_buffer = phys_to_virt(reboot_code_buffer);
+
+		kexec_code_buffer();
+	}
+
+	return -1;
+}
+EXPORT_SYMBOL(reboot);
-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:04 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:04 +0200
Subject: [RFC PATCH 4/7] MIPS: add kexec ELF loading support
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-5-linux@rempel-privat.de>

From: Antony Pavlov <antonynpavlov at gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
Signed-off-by: Peter Mamonov <pmamonov at gmail.com>
---
 arch/mips/include/asm/elf.h     |   8 +-
 arch/mips/lib/Makefile          |   3 +
 arch/mips/lib/kexec-mips.c      | 272 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/lib/machine_kexec.h   |  21 ++++
 arch/mips/lib/relocate_kernel.S | 108 ++++++++++++++++
 5 files changed, 411 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/lib/kexec-mips.c
 create mode 100644 arch/mips/lib/machine_kexec.h
 create mode 100644 arch/mips/lib/relocate_kernel.S

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index b8b82191c..bf974f521 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -17,12 +17,18 @@
 
 #ifndef ELF_ARCH
 
+/* Legal values for e_machine (architecture).  */
+
+#define EM_MIPS		 8		/* MIPS R3000 big-endian */
+#define EM_MIPS_RS4_BE	10		/* MIPS R4000 big-endian */
+
 #ifdef CONFIG_32BIT
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(hdr)						\
+#define elf_check_arch(x) ((x)->e_machine == EM_MIPS)
+
 /*
  * These are used to set parameters in the core dumps.
  */
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index d25d0969f..8dc498986 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -18,4 +18,7 @@ obj-$(CONFIG_CPU_MIPS64) += c-r4k.o
 obj-$(CONFIG_CMD_MIPS_CPUINFO) += cpuinfo.o
 obj-$(CONFIG_CMD_BOOTM)	+= bootm.o
 
+obj-$(CONFIG_KEXEC) += kexec-mips.o
+obj-$(CONFIG_KEXEC) += relocate_kernel.o
+
 pbl-y	+= ashldi3.o
diff --git a/arch/mips/lib/kexec-mips.c b/arch/mips/lib/kexec-mips.c
new file mode 100644
index 000000000..656249db4
--- /dev/null
+++ b/arch/mips/lib/kexec-mips.c
@@ -0,0 +1,272 @@
+/*
+ * kexec-mips.c - kexec for mips
+ * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini
+ * Copyright (C) 2007 Tvblob s.r.l.
+ *
+ * derived from ../ppc/kexec-mips.c
+ * Copyright (C) 2004, 2005 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <memory.h>
+#include <elf.h>
+#include "../../../lib/kexec/kexec.h"
+#include "machine_kexec.h"
+
+
+static int elf_mips_probe(const char *buf, off_t len)
+{
+	struct mem_ehdr ehdr;
+	int result;
+
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
+	if (result < 0) {
+		goto out;
+	}
+
+	/* Verify the architecuture specific bits */
+	if (ehdr.e_machine != EM_MIPS) {
+		/* for a different architecture */
+		printf("Not for this architecture.\n");
+		result = -1;
+		goto out;
+	}
+	result = 0;
+
+ out:
+	free_elf_info(&ehdr);
+
+	return result;
+}
+
+static int elf_mips_load(const char *buf, off_t len, struct kexec_info *info)
+{
+	struct mem_ehdr ehdr;
+	int result;
+	size_t i;
+
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
+	if (result < 0) {
+		printf("ELF exec parse failed\n");
+		goto out;
+	}
+
+	/* Read in the PT_LOAD segments and remove CKSEG0 mask from address */
+	for (i = 0; i < ehdr.e_phnum; i++) {
+		struct mem_phdr *phdr;
+		phdr = &ehdr.e_phdr[i];
+		if (phdr->p_type == PT_LOAD) {
+			phdr->p_paddr = virt_to_phys((void *)phdr->p_paddr);
+		}
+	}
+
+	/* Load the ELF data */
+	result = elf_exec_load(&ehdr, info);
+	if (result < 0) {
+		printf("ELF exec load failed\n");
+		goto out;
+	}
+
+	info->entry = (void *)virt_to_phys((void *)ehdr.e_entry);
+
+out:
+	return result;
+}
+
+struct kexec_file_type kexec_file_type[] = {
+	{"elf-mips", elf_mips_probe, elf_mips_load },
+};
+int kexec_file_types = sizeof(kexec_file_type) / sizeof(kexec_file_type[0]);
+
+/*
+ * add_segment() should convert base to a physical address on mips,
+ * while the default is just to work with base as is */
+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
+		 unsigned long base, size_t memsz)
+{
+	add_segment_phys_virt(info, buf, bufsz,
+		virt_to_phys((void *)base), memsz, 1);
+}
+
+/* relocator parameters */
+extern unsigned long relocate_new_kernel;
+extern unsigned long relocate_new_kernel_size;
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_segments;
+extern unsigned long kexec_nr_segments;
+
+unsigned long reboot_code_buffer;
+
+static void machine_kexec_print_args(void)
+{
+	unsigned long argc = (int)kexec_args[0];
+	int i;
+
+	printf("kexec_args[0] (argc): %lu\n", argc);
+	printf("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]);
+	printf("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]);
+	printf("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
+
+	for (i = 0; i < argc; i++) {
+		printf("kexec_argv[%d] = %p, %s\n",
+				i, kexec_argv[i], kexec_argv[i]);
+	}
+}
+
+static void machine_kexec_init_argv(struct kexec_segment *segments, unsigned long nr_segments)
+{
+	const void __user *buf = NULL;
+	size_t bufsz;
+	size_t size;
+	int i;
+
+	bufsz = 0;
+	for (i = 0; i < nr_segments; i++) {
+		struct kexec_segment *seg;
+
+		seg = &segments[i];
+		if (seg->bufsz < 6)
+			continue;
+
+		if (strncmp((char *) seg->buf, "kexec ", 6)) {
+			continue;
+		}
+
+		buf = seg->buf + 6;
+		bufsz = seg->bufsz - 6;
+		break;
+	}
+
+	if (!buf)
+		return;
+
+	size = KEXEC_COMMAND_LINE_SIZE;
+	size = min(size, bufsz);
+	if (size < bufsz)
+		printf("kexec command line truncated to %zu bytes\n", size);
+
+	/* Copy to kernel space */
+	memcpy(kexec_argv_buf, buf, size);
+	kexec_argv_buf[size - 1] = 0;
+}
+
+static void machine_kexec_parse_argv(void)
+{
+	char *ptr;
+	int argc;
+
+	ptr = kexec_argv_buf;
+	argc = 1;
+
+	/*
+	 * convert command line string to array of parameters
+	 * (as bootloader does).
+	 */
+	while (ptr && *ptr && (KEXEC_MAX_ARGC > argc)) {
+		if (*ptr == ' ') {
+			*ptr++ = '\0';
+			continue;
+		}
+
+		kexec_argv[argc++] = ptr;
+		ptr = strchr(ptr, ' ');
+	}
+
+	if (!argc)
+		return;
+
+	kexec_args[0] = argc;
+	kexec_args[1] = (unsigned long)kexec_argv;
+	kexec_args[2] = 0;
+	kexec_args[3] = 0;
+}
+
+static int machine_kexec_prepare(struct kexec_segment *segments, unsigned long nr_segments)
+{
+	/*
+	 * Whenever arguments passed from kexec-tools, Init the arguments as
+	 * the original ones to try avoiding booting failure.
+	 */
+
+	machine_kexec_init_argv(segments, nr_segments);
+	machine_kexec_parse_argv();
+	machine_kexec_print_args();
+
+	return 0;
+}
+long kexec_load(void *entry, unsigned long nr_segments,
+		struct kexec_segment *segments, unsigned long flags)
+{
+	int i;
+	struct resource *elf;
+	resource_size_t start;
+	LIST_HEAD(elf_segments);
+
+	for (i = 0; i < nr_segments; i++) {
+		resource_size_t mem = (resource_size_t)segments[i].mem;
+
+		elf = create_resource("elf segment",
+			mem, mem + segments[i].memsz - 1);
+
+		list_add_used_region(&elf->sibling, &elf_segments);
+	}
+
+	if (check_room_for_elf(&elf_segments)) {
+		printf("ELF can't be loaded!\n");
+		return 0;
+	}
+
+	start = dcheck_res(&elf_segments);
+
+	/* relocate_new_kernel() copy by register (4 or 8 bytes)
+	   so start address must be aligned to 4/8 */
+	start = (start + 15) & 0xfffffff0;
+
+	for (i = 0; i < nr_segments; i++) {
+		segments[i].mem = (void *)(phys_to_virt((unsigned long)segments[i].mem));
+		memcpy(phys_to_virt(start), segments[i].buf, segments[i].bufsz);
+		request_sdram_region("kexec relocatable segment",
+			(unsigned long)phys_to_virt(start),
+			(unsigned long)segments[i].bufsz);
+
+		/* relocate_new_kernel() copy by register (4 or 8 bytes)
+		   so bufsz must be aligned to 4/8 */
+		segments[i].bufsz = (segments[i].bufsz + 15) & 0xfffffff0;
+		segments[i].buf = phys_to_virt(start);
+		start = start + segments[i].bufsz;
+	}
+
+	start = (start + 15) & 0xfffffff0;
+
+	reboot_code_buffer = start;
+
+	memcpy(phys_to_virt(start), &relocate_new_kernel,
+		relocate_new_kernel_size);
+	request_sdram_region("kexec relocator",
+		(unsigned long)phys_to_virt(start),
+		(unsigned long)relocate_new_kernel_size);
+
+	start = start + relocate_new_kernel_size;
+	start = (start + 15) & 0xfffffff0;
+
+	kexec_start_address = (unsigned long)phys_to_virt((unsigned long)entry);
+	kexec_segments = (unsigned long)phys_to_virt((unsigned long)start);
+	kexec_nr_segments = nr_segments;
+
+	memcpy(phys_to_virt(start), segments, nr_segments * sizeof(*segments));
+	request_sdram_region("kexec control segments",
+		(unsigned long)phys_to_virt(start),
+		(unsigned long)nr_segments * sizeof(*segments));
+
+	machine_kexec_prepare(segments, nr_segments);
+
+	return 1;
+}
diff --git a/arch/mips/lib/machine_kexec.h b/arch/mips/lib/machine_kexec.h
new file mode 100644
index 000000000..b495d15c2
--- /dev/null
+++ b/arch/mips/lib/machine_kexec.h
@@ -0,0 +1,21 @@
+#ifndef _MACHINE_KEXEC_H
+#define _MACHINE_KEXEC_H
+
+#ifndef __ASSEMBLY__
+extern const unsigned char kexec_relocate_new_kernel[];
+extern unsigned long kexec_relocate_new_kernel_end;
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+
+extern unsigned long kexec_args[4];
+extern char kexec_argv_buf[];
+extern char *kexec_argv[];
+
+#define KEXEC_RELOCATE_NEW_KERNEL_SIZE	((unsigned long)&kexec_relocate_new_kernel_end - (unsigned long)kexec_relocate_new_kernel)
+#endif /* !__ASSEMBLY__ */
+
+#define KEXEC_COMMAND_LINE_SIZE		256
+#define KEXEC_ARGV_SIZE			(KEXEC_COMMAND_LINE_SIZE / 16)
+#define KEXEC_MAX_ARGC			(KEXEC_ARGV_SIZE / sizeof(long))
+
+#endif
diff --git a/arch/mips/lib/relocate_kernel.S b/arch/mips/lib/relocate_kernel.S
new file mode 100644
index 000000000..8c79277a2
--- /dev/null
+++ b/arch/mips/lib/relocate_kernel.S
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012, 2016 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ * based on relocate_kernel.S for kexec
+ * Created by <nschichan at corp.free.fr> on Thu Oct 12 17:49:57 2006
+ *
+ * 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 <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include "machine_kexec.h"
+
+LEAF(relocate_new_kernel)
+	.set	push
+	.set	reorder
+	PTR_L		a0, arg0
+	PTR_L		a1, arg1
+	PTR_L		a2, arg2
+	PTR_L		a3, arg3
+
+	PTR_L		s0, kexec_segments
+	PTR_L		s1, kexec_nr_segments
+	PTR_L		s2, kexec_start_address
+
+process_segment:
+	PTR_L		s4, (s0) /* buf */
+	PTR_L		s5, SZREG (s0) /* bufsz */
+	PTR_L		s6, 2*SZREG (s0) /* mem */
+
+copy_segment:
+	/* copy segment word by word */
+	REG_L		s7, (s4)
+	REG_S		s7, (s6)
+	PTR_ADD		s4, s4, SZREG
+	PTR_ADD		s6, s6, SZREG
+	LONG_SUB	s5, s5, 1
+	bne		s5, zero, copy_segment
+
+	LONG_SUB	s1, s1, 1
+	beq		s1, zero, done
+
+	PTR_ADD		s0, s0, 4*SZREG
+
+	b		process_segment
+
+done:
+	/* jump to kexec_start_address */
+	j		s2
+	END(relocate_new_kernel)
+
+/* All parameters to new kernel are passed in registers a0-a3.
+ * kexec_args[0..3] are uses to prepare register values.
+ */
+
+kexec_args:
+	EXPORT(kexec_args)
+arg0:	PTR		0x0
+arg1:	PTR		0x0
+arg2:	PTR		0x0
+arg3:	PTR		0x0
+	.size	kexec_args,PTRSIZE*4
+
+kexec_start_address:
+	EXPORT(kexec_start_address)
+	PTR		0x0
+	.size		kexec_start_address, PTRSIZE
+
+kexec_argv_buf:
+	EXPORT(kexec_argv_buf)
+	.skip		KEXEC_COMMAND_LINE_SIZE
+	.size		kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE
+
+kexec_argv:
+	EXPORT(kexec_argv)
+	.skip		KEXEC_ARGV_SIZE
+	.size		kexec_argv, KEXEC_ARGV_SIZE
+
+kexec_segments:
+	EXPORT(kexec_segments)
+	PTR		0x0
+	.size		kexec_segments, PTRSIZE
+
+kexec_nr_segments:
+	EXPORT(kexec_nr_segments)
+	PTR		0x0
+	.size		kexec_nr_segments, PTRSIZE
+
+relocate_new_kernel_end:
+
+relocate_new_kernel_size:
+	EXPORT(relocate_new_kernel_size)
+	PTR		relocate_new_kernel_end - relocate_new_kernel
+	.size		relocate_new_kernel_size, PTRSIZE
+	.set	pop
-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:07 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:07 +0200
Subject: [RFC PATCH 7/7] MIPS: configs: add KEXEC=y to atheros devices
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-8-linux@rempel-privat.de>

currently kexec is the only way we can boot linux kernel on this
devices. So enable it in configs per default.

Signed-off-by: Oleksij Rempel <linux at rempel-privat.de>
---
 arch/mips/configs/8devices-lima_defconfig         | 1 +
 arch/mips/configs/black-swift_defconfig           | 1 +
 arch/mips/configs/dptechnics-dpt-module_defconfig | 1 +
 arch/mips/configs/tplink-mr3020_defconfig         | 1 +
 arch/mips/configs/tplink-wdr4300_defconfig        | 1 +
 5 files changed, 5 insertions(+)

diff --git a/arch/mips/configs/8devices-lima_defconfig b/arch/mips/configs/8devices-lima_defconfig
index 446369a54..107d6c5cf 100644
--- a/arch/mips/configs/8devices-lima_defconfig
+++ b/arch/mips/configs/8devices-lima_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_LOADB=y
 CONFIG_CMD_LOADY=y
 CONFIG_CMD_RESET=y
+CONFIG_KEXEC=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_DEFAULTENV=y
 CONFIG_CMD_LOADENV=y
diff --git a/arch/mips/configs/black-swift_defconfig b/arch/mips/configs/black-swift_defconfig
index 1a72cfbd7..71a4f5963 100644
--- a/arch/mips/configs/black-swift_defconfig
+++ b/arch/mips/configs/black-swift_defconfig
@@ -25,6 +25,7 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_LOADB=y
 CONFIG_CMD_LOADY=y
 CONFIG_CMD_RESET=y
+CONFIG_KEXEC=y
 CONFIG_CMD_PARTITION=y
 CONFIG_CMD_GLOBAL=y
 CONFIG_CMD_SHA1SUM=y
diff --git a/arch/mips/configs/dptechnics-dpt-module_defconfig b/arch/mips/configs/dptechnics-dpt-module_defconfig
index c01b22b98..33049164c 100644
--- a/arch/mips/configs/dptechnics-dpt-module_defconfig
+++ b/arch/mips/configs/dptechnics-dpt-module_defconfig
@@ -22,6 +22,7 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_LOADB=y
 CONFIG_CMD_LOADY=y
 CONFIG_CMD_RESET=y
+CONFIG_KEXEC=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_DEFAULTENV=y
 CONFIG_CMD_LOADENV=y
diff --git a/arch/mips/configs/tplink-mr3020_defconfig b/arch/mips/configs/tplink-mr3020_defconfig
index 4193bd628..84753650b 100644
--- a/arch/mips/configs/tplink-mr3020_defconfig
+++ b/arch/mips/configs/tplink-mr3020_defconfig
@@ -19,6 +19,7 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_LOADB=y
 CONFIG_CMD_LOADY=y
 CONFIG_CMD_RESET=y
+CONFIG_KEXEC=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_DEFAULTENV=y
 CONFIG_CMD_LOADENV=y
diff --git a/arch/mips/configs/tplink-wdr4300_defconfig b/arch/mips/configs/tplink-wdr4300_defconfig
index 46093d243..1ba799d27 100644
--- a/arch/mips/configs/tplink-wdr4300_defconfig
+++ b/arch/mips/configs/tplink-wdr4300_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_LOADB=y
 CONFIG_CMD_LOADY=y
 CONFIG_CMD_RESET=y
+CONFIG_KEXEC=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_DEFAULTENV=y
 CONFIG_CMD_LOADENV=y
-- 
2.14.1



From linux at rempel-privat.de  Sun Apr 29 06:09:03 2018
From: linux at rempel-privat.de (Oleksij Rempel)
Date: Sun, 29 Apr 2018 15:09:03 +0200
Subject: [RFC PATCH 3/7] bootm: add kexec ELF support
In-Reply-To: <20180429130907.20506-1-linux@rempel-privat.de>
References: <20180429130907.20506-1-linux@rempel-privat.de>
Message-ID: <20180429130907.20506-4-linux@rempel-privat.de>

From: Antony Pavlov <antonynpavlov at gmail.com>

Also introduce reboot() for starting already loaded
via kexec ELF segments.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 commands/Kconfig            |   7 +
 common/Kconfig              |   3 +
 include/bootm.h             |   3 +
 include/linux/reboot.h      |  14 +
 lib/Makefile                |   1 +
 lib/kexec/Makefile          |   4 +
 lib/kexec/kexec-bootm-elf.c |  37 +++
 lib/kexec/kexec-elf-exec.c  |  79 ++++++
 lib/kexec/kexec-elf.c       | 678 ++++++++++++++++++++++++++++++++++++++++++++
 lib/kexec/kexec-elf.h       |  66 +++++
 lib/kexec/kexec.c           | 281 ++++++++++++++++++
 lib/kexec/kexec.h           |  92 ++++++
 12 files changed, 1265 insertions(+)
 create mode 100644 include/linux/reboot.h
 create mode 100644 lib/kexec/Makefile
 create mode 100644 lib/kexec/kexec-bootm-elf.c
 create mode 100644 lib/kexec/kexec-elf-exec.c
 create mode 100644 lib/kexec/kexec-elf.c
 create mode 100644 lib/kexec/kexec-elf.h
 create mode 100644 lib/kexec/kexec.c
 create mode 100644 lib/kexec/kexec.h

diff --git a/commands/Kconfig b/commands/Kconfig
index 951a86963..a49928ad1 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -476,6 +476,13 @@ config CMD_SAVES
 
 	  Save S-Record file to serial line with offset OFFS and length LEN.
 
+config KEXEC
+	bool
+	prompt "bootm ELF image support"
+	depends on CMD_BOOTM && HAS_KEXEC
+	help
+	  Support using ELF Images.
+
 config CMD_UIMAGE
 	select UIMAGE
 	tristate
diff --git a/common/Kconfig b/common/Kconfig
index b7000c4d7..d40c79dbc 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1218,3 +1218,6 @@ config HAS_DEBUG_LL
 config DDR_SPD
 	bool
 	select CRC16
+
+config HAS_KEXEC
+	bool
diff --git a/include/bootm.h b/include/bootm.h
index 62951d605..3a642fe70 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -72,6 +72,9 @@ struct image_data {
 
 	char *oftree_file;
 	char *oftree_part;
+	unsigned long oftree_address;
+
+	unsigned long cmdline_address;
 
 	const void *fit_kernel;
 	unsigned long fit_kernel_size;
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
new file mode 100644
index 000000000..1679070b4
--- /dev/null
+++ b/include/linux/reboot.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_REBOOT_H
+#define _LINUX_REBOOT_H
+
+/*
+ * Commands accepted by the _reboot() system call.
+ *
+ * KEXEC       Restart system using a previously loaded Linux kernel
+ */
+
+#define	LINUX_REBOOT_CMD_KEXEC		0x45584543
+
+extern int reboot(int cmd, void *opaque);
+
+#endif /* _LINUX_REBOOT_H */
diff --git a/lib/Makefile b/lib/Makefile
index a7498288a..eebaf3488 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -65,3 +65,4 @@ obj-y			+= int_sqrt.o
 obj-y			+= parseopt.o
 obj-y			+= clz_ctz.o
 obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
+obj-$(CONFIG_KEXEC)	+= kexec/
diff --git a/lib/kexec/Makefile b/lib/kexec/Makefile
new file mode 100644
index 000000000..2f3dc1dd3
--- /dev/null
+++ b/lib/kexec/Makefile
@@ -0,0 +1,4 @@
+obj-y	+= kexec.o
+obj-y	+= kexec-elf.o
+obj-y	+= kexec-elf-exec.o
+obj-y	+= kexec-bootm-elf.o
diff --git a/lib/kexec/kexec-bootm-elf.c b/lib/kexec/kexec-bootm-elf.c
new file mode 100644
index 000000000..78c9f85cf
--- /dev/null
+++ b/lib/kexec/kexec-bootm-elf.c
@@ -0,0 +1,37 @@
+#include <bootm.h>
+#include <init.h>
+#include <binfmt.h>
+#include <errno.h>
+#include <linux/reboot.h>
+#include <environment.h>
+
+#include "kexec.h"
+
+static int do_bootm_elf(struct image_data *data)
+{
+	kexec_load_bootm_data(data);
+
+	reboot(LINUX_REBOOT_CMD_KEXEC, data);
+
+	return -ERESTARTSYS;
+}
+
+static struct image_handler elf_handler = {
+	.name = "ELF",
+	.bootm = do_bootm_elf,
+	.filetype = filetype_elf,
+};
+
+static struct binfmt_hook binfmt_elf_hook = {
+	.type = filetype_elf,
+	.exec = "bootm",
+};
+
+static int elf_register_image_handler(void)
+{
+	register_image_handler(&elf_handler);
+	binfmt_register(&binfmt_elf_hook);
+
+	return 0;
+}
+late_initcall(elf_register_image_handler);
diff --git a/lib/kexec/kexec-elf-exec.c b/lib/kexec/kexec-elf-exec.c
new file mode 100644
index 000000000..094970e3b
--- /dev/null
+++ b/lib/kexec/kexec-elf-exec.c
@@ -0,0 +1,79 @@
+#include <common.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <elf.h>
+#include "kexec.h"
+#include "kexec-elf.h"
+
+int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
+{
+	struct mem_phdr *phdr, *end_phdr;
+	int result;
+
+	result = build_elf_info(buf, len, ehdr, flags);
+	if (result < 0)
+		return result;
+
+	if (ehdr->e_type != ET_EXEC) {
+		printf("Not ELF type ET_EXEC\n");
+		return -1;
+	}
+
+	if (!ehdr->e_phdr) {
+		printf("No ELF program header\n");
+		return -1;
+	}
+
+	end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
+	for (phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
+		/* Kexec does not support loading interpreters.
+		 * In addition this check keeps us from attempting
+		 * to kexec ordinay executables.
+		 */
+		if (phdr->p_type == PT_INTERP) {
+			printf("Requires an ELF interpreter\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info)
+{
+	int result;
+	size_t i;
+
+	if (!ehdr->e_phdr) {
+		printf("No program header?\n");
+		result = -1;
+		goto out;
+	}
+
+	/* Read in the PT_LOAD segments */
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		struct mem_phdr *phdr;
+		size_t size;
+
+		phdr = &ehdr->e_phdr[i];
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		size = phdr->p_filesz;
+
+		if (size > phdr->p_memsz)
+			size = phdr->p_memsz;
+
+		add_segment(info,
+			phdr->p_data, size,
+			phdr->p_paddr, phdr->p_memsz);
+	}
+
+	result = 0;
+ out:
+	return result;
+}
diff --git a/lib/kexec/kexec-elf.c b/lib/kexec/kexec-elf.c
new file mode 100644
index 000000000..44eb23288
--- /dev/null
+++ b/lib/kexec/kexec-elf.c
@@ -0,0 +1,678 @@
+#include <common.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <asm/io.h>
+#include "elf.h"
+#include "kexec.h"
+#include "kexec-elf.h"
+
+uint16_t elf16_to_cpu(const struct mem_ehdr *ehdr, uint16_t value)
+{
+	if (ehdr->ei_data == ELFDATA2LSB)
+		value = le16_to_cpu(value);
+	else if (ehdr->ei_data == ELFDATA2MSB)
+		value = be16_to_cpu(value);
+
+	return value;
+}
+
+uint32_t elf32_to_cpu(const struct mem_ehdr *ehdr, uint32_t value)
+{
+	if (ehdr->ei_data == ELFDATA2LSB)
+		value = le32_to_cpu(value);
+	else if (ehdr->ei_data == ELFDATA2MSB)
+		value = be32_to_cpu(value);
+
+	return value;
+}
+
+uint64_t elf64_to_cpu(const struct mem_ehdr *ehdr, uint64_t value)
+{
+	if (ehdr->ei_data == ELFDATA2LSB)
+		value = le64_to_cpu(value);
+	else if (ehdr->ei_data == ELFDATA2MSB)
+		value = be64_to_cpu(value);
+
+	return value;
+}
+
+static int build_mem_elf32_ehdr(const char *buf, off_t len,
+				struct mem_ehdr *ehdr)
+{
+	Elf32_Ehdr lehdr;
+
+	if ((size_t)len < sizeof(lehdr)) {
+		printf("Buffer is too small to hold ELF header\n");
+		return -1;
+	}
+
+	memcpy(&lehdr, buf, sizeof(lehdr));
+	if (elf16_to_cpu(ehdr, lehdr.e_ehsize) != sizeof(Elf32_Ehdr)) {
+		printf("Bad ELF header size\n");
+		return -1;
+	}
+
+	if (elf32_to_cpu(ehdr, lehdr.e_entry) > UINT32_MAX) {
+		printf("ELF e_entry is too large\n");
+		return -1;
+	}
+
+	if (elf32_to_cpu(ehdr, lehdr.e_phoff) > UINT32_MAX) {
+		printf("ELF e_phoff is too large\n");
+		return -1;
+	}
+
+	if (elf32_to_cpu(ehdr, lehdr.e_shoff) > UINT32_MAX) {
+		printf("ELF e_shoff is too large\n");
+		return -1;
+	}
+
+	ehdr->e_type      = elf16_to_cpu(ehdr, lehdr.e_type);
+	ehdr->e_machine   = elf16_to_cpu(ehdr, lehdr.e_machine);
+	ehdr->e_version   = elf32_to_cpu(ehdr, lehdr.e_version);
+	ehdr->e_entry     = elf32_to_cpu(ehdr, lehdr.e_entry);
+	ehdr->e_phoff     = elf32_to_cpu(ehdr, lehdr.e_phoff);
+	ehdr->e_shoff     = elf32_to_cpu(ehdr, lehdr.e_shoff);
+	ehdr->e_flags     = elf32_to_cpu(ehdr, lehdr.e_flags);
+	ehdr->e_phnum     = elf16_to_cpu(ehdr, lehdr.e_phnum);
+	ehdr->e_shnum     = elf16_to_cpu(ehdr, lehdr.e_shnum);
+	ehdr->e_shstrndx  = elf16_to_cpu(ehdr, lehdr.e_shstrndx);
+
+	if ((ehdr->e_phnum > 0) &&
+		(elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf32_Phdr))) {
+		printf("ELF bad program header size\n");
+		return -1;
+	}
+
+	if ((ehdr->e_shnum > 0) &&
+		(elf16_to_cpu(ehdr, lehdr.e_shentsize) != sizeof(Elf32_Shdr))) {
+		printf("ELF bad section header size\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int build_mem_elf64_ehdr(const char *buf, off_t len,
+				struct mem_ehdr *ehdr)
+{
+	Elf64_Ehdr lehdr;
+
+	if ((size_t)len < sizeof(lehdr)) {
+		printf("Buffer is too small to hold ELF header\n");
+		return -1;
+	}
+
+	memcpy(&lehdr, buf, sizeof(lehdr));
+	if (elf16_to_cpu(ehdr, lehdr.e_ehsize) != sizeof(Elf64_Ehdr)) {
+		printf("Bad ELF header size\n");
+		return -1;
+	}
+
+	ehdr->e_type      = elf16_to_cpu(ehdr, lehdr.e_type);
+	ehdr->e_machine   = elf16_to_cpu(ehdr, lehdr.e_machine);
+	ehdr->e_version   = elf32_to_cpu(ehdr, lehdr.e_version);
+	ehdr->e_entry     = elf64_to_cpu(ehdr, lehdr.e_entry);
+	ehdr->e_phoff     = elf64_to_cpu(ehdr, lehdr.e_phoff);
+	ehdr->e_shoff     = elf64_to_cpu(ehdr, lehdr.e_shoff);
+	ehdr->e_flags     = elf32_to_cpu(ehdr, lehdr.e_flags);
+	ehdr->e_phnum     = elf16_to_cpu(ehdr, lehdr.e_phnum);
+	ehdr->e_shnum     = elf16_to_cpu(ehdr, lehdr.e_shnum);
+	ehdr->e_shstrndx  = elf16_to_cpu(ehdr, lehdr.e_shstrndx);
+
+	if ((ehdr->e_phnum > 0) &&
+		(elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf64_Phdr))) {
+		printf("ELF bad program header size\n");
+		return -1;
+	}
+
+	if ((ehdr->e_shnum > 0) &&
+		(elf16_to_cpu(ehdr, lehdr.e_shentsize) != sizeof(Elf64_Shdr))) {
+		printf("ELF bad section header size\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int build_mem_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+	unsigned char e_ident[EI_NIDENT];
+	int result;
+
+	memset(ehdr, 0, sizeof(*ehdr));
+
+	if ((size_t)len < sizeof(e_ident)) {
+		printf("Buffer is too small to hold ELF e_ident\n");
+
+		return -1;
+	}
+
+	memcpy(e_ident, buf, sizeof(e_ident));
+
+	ehdr->ei_class   = e_ident[EI_CLASS];
+	ehdr->ei_data    = e_ident[EI_DATA];
+	if ((ehdr->ei_class != ELFCLASS32) &&
+		(ehdr->ei_class != ELFCLASS64)) {
+		printf("Not a supported ELF class\n");
+		return -1;
+	}
+
+	if ((ehdr->ei_data != ELFDATA2LSB) &&
+		(ehdr->ei_data != ELFDATA2MSB)) {
+		printf("Not a supported ELF data format\n");
+		return -1;
+	}
+
+	result = -1;
+	if (ehdr->ei_class == ELFCLASS32)
+		result = build_mem_elf32_ehdr(buf, len, ehdr);
+
+	if (ehdr->ei_class == ELFCLASS64)
+		result = build_mem_elf64_ehdr(buf, len, ehdr);
+
+	if (result < 0)
+		return result;
+
+	if ((e_ident[EI_VERSION] != EV_CURRENT) ||
+		(ehdr->e_version != EV_CURRENT)) {
+		printf("Unknown ELF version\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int build_mem_elf32_phdr(const char *buf, struct mem_ehdr *ehdr, int idx)
+{
+	struct mem_phdr *phdr;
+	const char *pbuf;
+	Elf32_Phdr lphdr;
+
+	pbuf = buf + ehdr->e_phoff + (idx * sizeof(lphdr));
+	phdr = &ehdr->e_phdr[idx];
+	memcpy(&lphdr, pbuf, sizeof(lphdr));
+
+	if ((elf32_to_cpu(ehdr, lphdr.p_filesz) > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lphdr.p_memsz)  > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lphdr.p_offset) > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lphdr.p_paddr)  > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lphdr.p_vaddr)  > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lphdr.p_align)  > UINT32_MAX)) {
+		printf("Program segment size out of range\n");
+		return -1;
+	}
+
+	phdr->p_type   = elf32_to_cpu(ehdr, lphdr.p_type);
+	phdr->p_paddr  = elf32_to_cpu(ehdr, lphdr.p_paddr);
+	phdr->p_vaddr  = elf32_to_cpu(ehdr, lphdr.p_vaddr);
+	phdr->p_filesz = elf32_to_cpu(ehdr, lphdr.p_filesz);
+	phdr->p_memsz  = elf32_to_cpu(ehdr, lphdr.p_memsz);
+	phdr->p_offset = elf32_to_cpu(ehdr, lphdr.p_offset);
+	phdr->p_flags  = elf32_to_cpu(ehdr, lphdr.p_flags);
+	phdr->p_align  = elf32_to_cpu(ehdr, lphdr.p_align);
+
+	return 0;
+}
+
+static int build_mem_elf64_phdr(const char *buf, struct mem_ehdr *ehdr, int idx)
+{
+	struct mem_phdr *phdr;
+	const char *pbuf;
+	Elf64_Phdr lphdr;
+
+	pbuf = buf + ehdr->e_phoff + (idx * sizeof(lphdr));
+	phdr = &ehdr->e_phdr[idx];
+	memcpy(&lphdr, pbuf, sizeof(lphdr));
+	phdr->p_type   = elf32_to_cpu(ehdr, lphdr.p_type);
+	phdr->p_paddr  = elf64_to_cpu(ehdr, lphdr.p_paddr);
+	phdr->p_vaddr  = elf64_to_cpu(ehdr, lphdr.p_vaddr);
+	phdr->p_filesz = elf64_to_cpu(ehdr, lphdr.p_filesz);
+	phdr->p_memsz  = elf64_to_cpu(ehdr, lphdr.p_memsz);
+	phdr->p_offset = elf64_to_cpu(ehdr, lphdr.p_offset);
+	phdr->p_flags  = elf32_to_cpu(ehdr, lphdr.p_flags);
+	phdr->p_align  = elf64_to_cpu(ehdr, lphdr.p_align);
+
+	return 0;
+}
+
+static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
+{
+	size_t phdr_size, mem_phdr_size, i;
+
+	/* e_phnum is at most 65535 so calculating
+	 * the size of the program header cannot overflow.
+	 */
+	/* Is the program header in the file buffer? */
+	phdr_size = 0;
+	if (ehdr->ei_class == ELFCLASS32) {
+		phdr_size = sizeof(Elf32_Phdr);
+	} else if (ehdr->ei_class == ELFCLASS64) {
+		phdr_size = sizeof(Elf64_Phdr);
+	} else {
+		printf("Invalid ei_class?\n");
+		return -1;
+	}
+	phdr_size *= ehdr->e_phnum;
+
+	/* Allocate the e_phdr array */
+	mem_phdr_size = sizeof(ehdr->e_phdr[0]) * ehdr->e_phnum;
+	ehdr->e_phdr = xmalloc(mem_phdr_size);
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		struct mem_phdr *phdr;
+		int result;
+
+		result = -1;
+		if (ehdr->ei_class == ELFCLASS32)
+			result = build_mem_elf32_phdr(buf, ehdr, i);
+
+		if (ehdr->ei_class == ELFCLASS64)
+			result = build_mem_elf64_phdr(buf, ehdr, i);
+
+		if (result < 0)
+			return result;
+
+		/* Check the program headers to be certain
+		 * they are safe to use.
+		 */
+		phdr = &ehdr->e_phdr[i];
+		if ((phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) {
+			/* The memory address wraps */
+			printf("ELF address wrap around\n");
+			return -1;
+		}
+
+		/* Remember where the segment lives in the buffer */
+		phdr->p_data = buf + phdr->p_offset;
+	}
+
+	return 0;
+}
+
+static int build_mem_elf32_shdr(const char *buf, struct mem_ehdr *ehdr, int idx)
+{
+	struct mem_shdr *shdr;
+	const char *sbuf;
+	int size_ok;
+	Elf32_Shdr lshdr;
+
+	sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr));
+	shdr = &ehdr->e_shdr[idx];
+	memcpy(&lshdr, sbuf, sizeof(lshdr));
+
+	if ((elf32_to_cpu(ehdr, lshdr.sh_flags)     > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lshdr.sh_addr)      > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lshdr.sh_offset)    > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lshdr.sh_size)      > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lshdr.sh_addralign) > UINT32_MAX) ||
+		(elf32_to_cpu(ehdr, lshdr.sh_entsize)   > UINT32_MAX)) {
+		printf("Program section size out of range\n");
+		return -1;
+	}
+
+	shdr->sh_name      = elf32_to_cpu(ehdr, lshdr.sh_name);
+	shdr->sh_type      = elf32_to_cpu(ehdr, lshdr.sh_type);
+	shdr->sh_flags     = elf32_to_cpu(ehdr, lshdr.sh_flags);
+	shdr->sh_addr      = elf32_to_cpu(ehdr, lshdr.sh_addr);
+	shdr->sh_offset    = elf32_to_cpu(ehdr, lshdr.sh_offset);
+	shdr->sh_size      = elf32_to_cpu(ehdr, lshdr.sh_size);
+	shdr->sh_link      = elf32_to_cpu(ehdr, lshdr.sh_link);
+	shdr->sh_info      = elf32_to_cpu(ehdr, lshdr.sh_info);
+	shdr->sh_addralign = elf32_to_cpu(ehdr, lshdr.sh_addralign);
+	shdr->sh_entsize   = elf32_to_cpu(ehdr, lshdr.sh_entsize);
+
+	/* Now verify sh_entsize */
+	size_ok = 0;
+	switch (shdr->sh_type) {
+	case SHT_SYMTAB:
+		size_ok = shdr->sh_entsize == sizeof(Elf32_Sym);
+		break;
+	case SHT_RELA:
+		size_ok = shdr->sh_entsize == sizeof(Elf32_Rela);
+		break;
+	case SHT_DYNAMIC:
+		size_ok = shdr->sh_entsize == sizeof(Elf32_Dyn);
+		break;
+	case SHT_REL:
+		size_ok = shdr->sh_entsize == sizeof(Elf32_Rel);
+		break;
+	case SHT_NOTE:
+	case SHT_NULL:
+	case SHT_PROGBITS:
+	case SHT_HASH:
+	case SHT_NOBITS:
+	default:
+		/* This is a section whose entsize requirements
+		 * I don't care about.  If I don't know about
+		 * the section I can't care about it's entsize
+		 * requirements.
+		 */
+		size_ok = 1;
+		break;
+	}
+
+	if (!size_ok) {
+		printf("Bad section header(%x) entsize: %lld\n",
+			shdr->sh_type, shdr->sh_entsize);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int build_mem_elf64_shdr(const char *buf, struct mem_ehdr *ehdr, int idx)
+{
+	struct mem_shdr *shdr;
+	const char *sbuf;
+	int size_ok;
+	Elf64_Shdr lshdr;
+
+	sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr));
+	shdr = &ehdr->e_shdr[idx];
+	memcpy(&lshdr, sbuf, sizeof(lshdr));
+	shdr->sh_name      = elf32_to_cpu(ehdr, lshdr.sh_name);
+	shdr->sh_type      = elf32_to_cpu(ehdr, lshdr.sh_type);
+	shdr->sh_flags     = elf64_to_cpu(ehdr, lshdr.sh_flags);
+	shdr->sh_addr      = elf64_to_cpu(ehdr, lshdr.sh_addr);
+	shdr->sh_offset    = elf64_to_cpu(ehdr, lshdr.sh_offset);
+	shdr->sh_size      = elf64_to_cpu(ehdr, lshdr.sh_size);
+	shdr->sh_link      = elf32_to_cpu(ehdr, lshdr.sh_link);
+	shdr->sh_info      = elf32_to_cpu(ehdr, lshdr.sh_info);
+	shdr->sh_addralign = elf64_to_cpu(ehdr, lshdr.sh_addralign);
+	shdr->sh_entsize   = elf64_to_cpu(ehdr, lshdr.sh_entsize);
+
+	/* Now verify sh_entsize */
+	size_ok = 0;
+	switch (shdr->sh_type) {
+	case SHT_SYMTAB:
+		size_ok = shdr->sh_entsize == sizeof(Elf64_Sym);
+		break;
+	case SHT_RELA:
+		size_ok = shdr->sh_entsize == sizeof(Elf64_Rela);
+		break;
+	case SHT_DYNAMIC:
+		size_ok = shdr->sh_entsize == sizeof(Elf64_Dyn);
+		break;
+	case SHT_REL:
+		size_ok = shdr->sh_entsize == sizeof(Elf64_Rel);
+		break;
+	case SHT_NOTE:
+	case SHT_NULL:
+	case SHT_PROGBITS:
+	case SHT_HASH:
+	case SHT_NOBITS:
+	default:
+		/* This is a section whose entsize requirements
+		 * I don't care about.  If I don't know about
+		 * the section I can't care about it's entsize
+		 * requirements.
+		 */
+		size_ok = 1;
+		break;
+	}
+
+	if (!size_ok) {
+		printf("Bad section header(%x) entsize: %lld\n",
+			shdr->sh_type, shdr->sh_entsize);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
+{
+	size_t shdr_size, mem_shdr_size, i;
+
+	/* e_shnum is at most 65536 so calculating
+	 * the size of the section header cannot overflow.
+	 */
+	/* Is the program header in the file buffer? */
+	shdr_size = 0;
+	if (ehdr->ei_class == ELFCLASS32) {
+		shdr_size = sizeof(Elf32_Shdr);
+	} else if (ehdr->ei_class == ELFCLASS64) {
+		shdr_size = sizeof(Elf64_Shdr);
+	} else {
+		printf("Invalid ei_class?\n");
+		return -1;
+	}
+	shdr_size *= ehdr->e_shnum;
+
+	/* Allocate the e_shdr array */
+	mem_shdr_size = sizeof(ehdr->e_shdr[0]) * ehdr->e_shnum;
+	ehdr->e_shdr = xmalloc(mem_shdr_size);
+
+	for (i = 0; i < ehdr->e_shnum; i++) {
+		struct mem_shdr *shdr;
+		int result;
+
+		result = -1;
+		if (ehdr->ei_class == ELFCLASS32)
+			result = build_mem_elf32_shdr(buf, ehdr, i);
+
+		if (ehdr->ei_class == ELFCLASS64)
+			result = build_mem_elf64_shdr(buf, ehdr, i);
+
+		if (result < 0)
+			return result;
+
+		/* Check the section headers to be certain
+		 * they are safe to use.
+		 */
+		shdr = &ehdr->e_shdr[i];
+		if ((shdr->sh_addr + shdr->sh_size) < shdr->sh_addr) {
+			printf("ELF address wrap around\n");
+			return -1;
+		}
+
+		/* Remember where the section lives in the buffer */
+		shdr->sh_data = (unsigned char *)(buf + shdr->sh_offset);
+	}
+
+	return 0;
+}
+
+void free_elf_info(struct mem_ehdr *ehdr)
+{
+	free(ehdr->e_phdr);
+	free(ehdr->e_shdr);
+	memset(ehdr, 0, sizeof(*ehdr));
+}
+
+int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+			uint32_t flags)
+{
+	int result;
+
+	result = build_mem_ehdr(buf, len, ehdr);
+	if (result < 0)
+		return result;
+
+	if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) {
+		result = build_mem_phdrs(buf, len, ehdr, flags);
+		if (result < 0) {
+			free_elf_info(ehdr);
+			return result;
+		}
+	}
+
+	if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) {
+		result = build_mem_shdrs(buf, len, ehdr, flags);
+		if (result < 0) {
+			free_elf_info(ehdr);
+			return result;
+		}
+	}
+
+	return 0;
+}
+
+int check_room_for_elf(struct list_head *elf_segments)
+{
+	struct memory_bank *bank;
+	struct resource *res, *r;
+
+	list_for_each_entry(r, elf_segments, sibling) {
+		int got_bank;
+
+		got_bank = 0;
+		for_each_memory_bank(bank) {
+			resource_size_t start, end;
+
+			res = bank->res;
+
+			start = virt_to_phys((void *)res->start);
+			end = virt_to_phys((void *)res->end);
+
+			if ((start <= r->start) && (end >= r->end)) {
+				got_bank = 1;
+				break;
+			}
+		}
+
+		if (!got_bank)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* sort by size */
+static int compare(struct list_head *a, struct list_head *b)
+{
+	struct resource *ra = (struct resource *)list_entry(a,
+					struct resource, sibling);
+	struct resource *rb = (struct resource *)list_entry(b,
+					struct resource, sibling);
+	resource_size_t sa, sb;
+
+	sa = ra->end - ra->start;
+	sb = rb->end - rb->start;
+
+	if (sa > sb)
+		return -1;
+	if (sa < sb)
+		return 1;
+	return 0;
+}
+
+void list_add_used_region(struct list_head *new, struct list_head *head)
+{
+	struct list_head *pos, *insert = head;
+	struct resource *rb =
+		(struct resource *)list_entry(new, struct resource, sibling);
+	struct list_head *n;
+
+	/* rb --- new region */
+	list_for_each_safe(pos, n, head) {
+		struct resource *ra = (struct resource *)list_entry(pos,
+						struct resource, sibling);
+
+		if (((rb->end >= ra->start) && (rb->end <= ra->end))
+			|| ((rb->start >= ra->start) && (rb->start <= ra->end))
+			|| ((rb->start >= ra->start) && (rb->end <= ra->end))
+			|| ((ra->start >= rb->start) && (ra->end <= rb->end))
+			|| (ra->start == rb->end + 1)
+			|| (rb->start == ra->end + 1)) {
+			rb->start = min(ra->start, rb->start);
+			rb->end = max(ra->end, rb->end);
+			rb->name = "join";
+			list_del(pos);
+		}
+	}
+
+	list_for_each(pos, head) {
+		struct resource *ra = (struct resource *)list_entry(pos,
+						struct resource, sibling);
+
+		if (ra->start < rb->start)
+			continue;
+
+		insert = pos;
+		break;
+	}
+
+	list_add_tail(new, insert);
+}
+
+resource_size_t dcheck_res(struct list_head *elf_segments)
+{
+	struct memory_bank *bank;
+	struct resource *res, *r, *t;
+
+	LIST_HEAD(elf_relocate_banks);
+	LIST_HEAD(elf_relocate_banks_size_sorted);
+	LIST_HEAD(used_regions);
+
+	for_each_memory_bank(bank) {
+		res = bank->res;
+
+		list_for_each_entry(r, &res->children, sibling) {
+			t = create_resource("tmp",
+				virt_to_phys((void *)r->start),
+				virt_to_phys((void *)r->end));
+			list_add_used_region(&t->sibling, &used_regions);
+		}
+	}
+
+	list_for_each_entry(r, elf_segments, sibling) {
+		t = create_resource(r->name, r->start, r->end);
+		list_add_used_region(&t->sibling, &used_regions);
+	}
+
+	for_each_memory_bank(bank) {
+		resource_size_t start;
+
+		res = bank->res;
+		res = create_resource("tmp",
+				virt_to_phys((void *)res->start),
+				virt_to_phys((void *)res->end));
+		start = res->start;
+
+		list_for_each_entry(r, &used_regions, sibling) {
+			if (res->start > r->end)
+				continue;
+
+			if (res->end < r->start)
+				continue;
+
+			if (r->start - start) {
+				struct resource *t;
+
+				t = create_resource("ELF buffer", start,
+						    r->start - 1);
+				list_add_used_region(&t->sibling,
+						     &elf_relocate_banks);
+			}
+			start = r->end + 1;
+		}
+
+		if (res->end - start) {
+			struct resource *t;
+
+			t = create_resource("ELF buffer", start, res->end);
+			list_add_used_region(&t->sibling, &elf_relocate_banks);
+		}
+	}
+
+	list_for_each_entry(r, &elf_relocate_banks, sibling) {
+		struct resource *t;
+
+		t = create_resource("ELF buffer", r->start, r->end);
+		list_add_sort(&t->sibling,
+			&elf_relocate_banks_size_sorted, compare);
+	}
+
+	r = list_first_entry(&elf_relocate_banks_size_sorted, struct resource,
+			     sibling);
+
+	/* FIXME */
+	return r->start;
+}
diff --git a/lib/kexec/kexec-elf.h b/lib/kexec/kexec-elf.h
new file mode 100644
index 000000000..06826c44c
--- /dev/null
+++ b/lib/kexec/kexec-elf.h
@@ -0,0 +1,66 @@
+#ifndef KEXEC_ELF_H
+#define KEXEC_ELF_H
+
+struct kexec_info;
+
+struct mem_ehdr {
+	unsigned ei_class;
+	unsigned ei_data;
+	unsigned e_type;
+	unsigned e_machine;
+	unsigned e_version;
+	unsigned e_flags;
+	unsigned e_phnum;
+	unsigned e_shnum;
+	unsigned e_shstrndx;
+	unsigned long long e_entry;
+	unsigned long long e_phoff;
+	unsigned long long e_shoff;
+	struct mem_phdr *e_phdr;
+	struct mem_shdr *e_shdr;
+};
+
+struct mem_phdr {
+	unsigned long long p_paddr;
+	unsigned long long p_vaddr;
+	unsigned long long p_filesz;
+	unsigned long long p_memsz;
+	unsigned long long p_offset;
+	const char *p_data;
+	unsigned p_type;
+	unsigned p_flags;
+	unsigned long long p_align;
+};
+
+struct mem_shdr {
+	unsigned sh_name;
+	unsigned sh_type;
+	unsigned long long sh_flags;
+	unsigned long long sh_addr;
+	unsigned long long sh_offset;
+	unsigned long long sh_size;
+	unsigned sh_link;
+	unsigned sh_info;
+	unsigned long long sh_addralign;
+	unsigned long long sh_entsize;
+	const unsigned char *sh_data;
+};
+
+extern void free_elf_info(struct mem_ehdr *ehdr);
+extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags);
+extern int build_elf_exec_info(const char *buf, off_t len,
+				struct mem_ehdr *ehdr, uint32_t flags);
+
+extern int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info);
+
+uint16_t elf16_to_cpu(const struct mem_ehdr *ehdr, uint16_t value);
+uint32_t elf32_to_cpu(const struct mem_ehdr *ehdr, uint32_t value);
+uint64_t elf64_to_cpu(const struct mem_ehdr *ehdr, uint64_t value);
+
+unsigned long elf_max_addr(const struct mem_ehdr *ehdr);
+int check_room_for_elf(struct list_head *elf_segments);
+resource_size_t dcheck_res(struct list_head *elf_segments);
+void list_add_used_region(struct list_head *new, struct list_head *head);
+
+#endif /* KEXEC_ELF_H */
diff --git a/lib/kexec/kexec.c b/lib/kexec/kexec.c
new file mode 100644
index 000000000..3a021173e
--- /dev/null
+++ b/lib/kexec/kexec.c
@@ -0,0 +1,281 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005  Eric Biederman (ebiederm at xmission.com)
+ *
+ * Modified (2007-05-15) by Francesco Chiechi to rudely handle mips platform
+ *
+ * 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).
+ *
+ * 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 _GNU_SOURCE
+#include <common.h>
+#include <fs.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+#include <boot.h>
+#include <libfile.h>
+
+#include "kexec.h"
+#include "kexec-elf.h"
+
+static int sort_segments(struct kexec_info *info)
+{
+	int i, j;
+	void *end;
+
+	/* Do a stupid insertion sort... */
+	for (i = 0; i < info->nr_segments; i++) {
+		int tidx;
+		struct kexec_segment temp;
+		tidx = i;
+		for (j = i + 1; j < info->nr_segments; j++) {
+			if (info->segment[j].mem < info->segment[tidx].mem)
+				tidx = j;
+		}
+		if (tidx != i) {
+			temp = info->segment[tidx];
+			info->segment[tidx] = info->segment[i];
+			info->segment[i] = temp;
+		}
+	}
+
+	/* Now see if any of the segments overlap */
+	end = 0;
+	for (i = 0; i < info->nr_segments; i++) {
+		if (end > info->segment[i].mem) {
+			printf("Overlapping memory segments at %p\n",
+				end);
+			return -1;
+		}
+		end = ((char *)info->segment[i].mem) + info->segment[i].memsz;
+	}
+
+	return 0;
+}
+
+void add_segment_phys_virt(struct kexec_info *info,
+	const void *buf, size_t bufsz,
+	unsigned long base, size_t memsz, int phys)
+{
+	size_t size;
+	int pagesize;
+
+	if (bufsz > memsz)
+		bufsz = memsz;
+
+	/* Forget empty segments */
+	if (!memsz)
+		return;
+
+	/* Round memsz up to a multiple of pagesize */
+	pagesize = 4096;
+	memsz = (memsz + (pagesize - 1)) & ~(pagesize - 1);
+
+	if (phys)
+		base = virt_to_phys((void *)base);
+
+	size = (info->nr_segments + 1) * sizeof(info->segment[0]);
+	info->segment = xrealloc(info->segment, size);
+	info->segment[info->nr_segments].buf   = buf;
+	info->segment[info->nr_segments].bufsz = bufsz;
+	info->segment[info->nr_segments].mem   = (void *)base;
+	info->segment[info->nr_segments].memsz = memsz;
+	info->nr_segments++;
+	if (info->nr_segments > KEXEC_MAX_SEGMENTS) {
+		printf("Warning: kernel segment limit reached. "
+			"This will likely fail\n");
+	}
+}
+
+static int kexec_load_one_file(struct kexec_info *info, char *fname,
+			       unsigned long kexec_flags)
+{
+	char *buf;
+	size_t fsize;
+	int i = 0;
+
+	buf = read_file(fname, &fsize);
+
+	/* FIXME: check buf */
+
+	for (i = 0; i < kexec_file_types; i++) {
+		if (kexec_file_type[i].probe(buf, fsize) >= 0)
+			break;
+	}
+
+	if (i == kexec_file_types) {
+		printf("Cannot determine the file type "
+				"of %s\n", fname);
+		return -1;
+	}
+
+	return kexec_file_type[i].load(buf, fsize, info);
+}
+
+static int kexec_load_binary_file(struct kexec_info *info, char *fname,
+					size_t *fsize, unsigned long base)
+{
+	char *buf;
+
+	buf = read_file(fname, fsize);
+	if (!buf)
+		return -1;
+
+	add_segment(info, buf, *fsize, base, *fsize);
+
+	return 0;
+}
+
+static int print_segments(struct kexec_info *info)
+{
+	int i;
+
+	printf("print_segments\n");
+	for (i = 0; i < info->nr_segments; i++) {
+		struct kexec_segment *seg = &info->segment[i];
+
+		printf("  %d. buf=%#08p bufsz=%#lx mem=%#08p memsz=%#lx\n", i,
+			seg->buf, seg->bufsz, seg->mem, seg->memsz);
+	}
+
+	return 0;
+}
+
+static unsigned long find_unused_base(struct kexec_info *info, int *padded)
+{
+	unsigned long base = 0;
+
+	if (info->nr_segments) {
+		int i = info->nr_segments - 1;
+		struct kexec_segment *seg = &info->segment[i];
+
+		base = (unsigned long)seg->mem + seg->memsz;
+	}
+
+	if (!*padded) {
+		/*
+		 * Pad it; the kernel scribbles over memory
+		 * beyond its load address.
+		 * see grub-core/loader/mips/linux.c
+		 */
+		base += 0x100000;
+		*padded = 1;
+	}
+
+	return base;
+}
+
+#include <environment.h>
+
+int kexec_load_bootm_data(struct image_data *data)
+{
+	int result;
+	struct kexec_info info;
+	char *cmdline;
+	const char *t;
+	size_t tlen, klen;
+	size_t fsize;
+	char initrd_cmdline[40];
+	int padded = 0;
+
+	memset(&info, 0, sizeof(info));
+
+	initrd_cmdline[0] = 0;
+
+	result = kexec_load_one_file(&info, data->os_file, 0);
+	if (result < 0) {
+		printf("Cannot load %s\n", data->os_file);
+		return result;
+	}
+
+	if (data->oftree_file) {
+		unsigned long base = find_unused_base(&info, &padded);
+
+		base = ALIGN(base, 8);
+
+		result = kexec_load_binary_file(&info,
+				data->oftree_file, &fsize, base);
+		if (result < 0) {
+			printf("Cannot load %s\n", data->oftree_file);
+			return result;
+		}
+		data->oftree_address = base;
+	}
+
+	if (data->initrd_file) {
+		unsigned long base = find_unused_base(&info, &padded);
+
+		/*
+		 * initrd start must be page aligned,
+		 * max page size for mips is 64k.
+		 */
+		base = ALIGN(base, 0x10000);
+
+		result = kexec_load_binary_file(&info,
+				data->initrd_file, &fsize, base);
+		if (result < 0) {
+			printf("Cannot load %s\n", data->initrd_file);
+			return result;
+		}
+		data->initrd_address = base;
+
+		if (bootm_verbose(data)) {
+			printf("initrd: rd_start=0x%08x rd_size=0x%08x\n",
+					data->initrd_address, fsize);
+		}
+		snprintf(initrd_cmdline, sizeof(initrd_cmdline),
+				" rd_start=0x%08x rd_size=0x%08x",
+					phys_to_virt(data->initrd_address),
+					fsize);
+	}
+
+	/* FIXME: we can snprintf to cmdline directly */
+	t = linux_bootargs_get();
+	if (t)
+		tlen = strlen(t);
+	else
+		tlen = 0;
+
+	klen = strlen("kexec ");
+	cmdline = xzalloc(tlen + sizeof(initrd_cmdline) + klen);
+	memcpy(cmdline, "kexec ", klen);
+	if (tlen)
+		memcpy(cmdline + klen, t, tlen);
+
+	memcpy(cmdline + klen + tlen, initrd_cmdline, sizeof(initrd_cmdline));
+
+	if (cmdline) {
+		int cmdlinelen = strlen(cmdline) + 1;
+		unsigned long base = find_unused_base(&info, &padded);
+
+		base = ALIGN(base, 8);
+
+		/* FIXME */
+		add_segment(&info, cmdline, cmdlinelen, base, cmdlinelen);
+		data->cmdline_address = base;
+	}
+
+	if (bootm_verbose(data))
+		print_segments(&info);
+
+	/* Verify all of the segments load to a valid location in memory */
+
+	/* Sort the segments and verify we don't have overlaps */
+	if (sort_segments(&info) < 0)
+		return -1;
+
+	return kexec_load(info.entry,
+		info.nr_segments, info.segment, info.kexec_flags);
+}
diff --git a/lib/kexec/kexec.h b/lib/kexec/kexec.h
new file mode 100644
index 000000000..527a36861
--- /dev/null
+++ b/lib/kexec/kexec.h
@@ -0,0 +1,92 @@
+#ifndef KEXEC_H
+#define KEXEC_H
+
+#include "kexec-elf.h"
+
+struct kexec_segment {
+	const void *buf;
+	size_t bufsz;
+	const void *mem;
+	size_t memsz;
+};
+
+struct kexec_info {
+	struct kexec_segment *segment;
+	int nr_segments;
+	void *entry;
+	unsigned long kexec_flags;
+};
+
+typedef int (probe_t)(const char *kernel_buf, off_t kernel_size);
+typedef int (load_t)(const char *kernel_buf, off_t kernel_size,
+	struct kexec_info *info);
+struct kexec_file_type {
+	const char *name;
+	probe_t *probe;
+	load_t  *load;
+};
+
+extern struct kexec_file_type kexec_file_type[];
+extern int kexec_file_types;
+
+extern void add_segment(struct kexec_info *info,
+	const void *buf, size_t bufsz, unsigned long base, size_t memsz);
+extern void add_segment_phys_virt(struct kexec_info *info,
+	const void *buf, size_t bufsz, unsigned long base, size_t memsz,
+	int phys);
+
+extern long kexec_load(void *entry, unsigned long nr_segments,
+		       struct kexec_segment *segments, unsigned long flags);
+
+#include <bootm.h>
+
+extern int kexec_load_bootm_data(struct image_data *data);
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+/* These values match the ELF architecture values.
+ * Unless there is a good reason that should continue to be the case.
+ */
+#define KEXEC_ARCH_DEFAULT	(0 << 16)
+#define KEXEC_ARCH_386		(3 << 16)
+#define KEXEC_ARCH_X86_64	(62 << 16)
+#define KEXEC_ARCH_PPC		(20 << 16)
+#define KEXEC_ARCH_PPC64	(21 << 16)
+#define KEXEC_ARCH_IA_64	(50 << 16)
+#define KEXEC_ARCH_ARM		(40 << 16)
+#define KEXEC_ARCH_S390		(22 << 16)
+#define KEXEC_ARCH_SH		(42 << 16)
+#define KEXEC_ARCH_MIPS_LE	(10 << 16)
+#define KEXEC_ARCH_MIPS		(8 << 16)
+#define KEXEC_ARCH_CRIS		(76 << 16)
+
+#define KEXEC_MAX_SEGMENTS 16
+
+#endif /* KEXEC_H */
-- 
2.14.1



From mail at schmidt-andreas.de  Sun Apr 29 09:01:25 2018
From: mail at schmidt-andreas.de (Andreas Schmidt)
Date: Sun, 29 Apr 2018 18:01:25 +0200
Subject: [PATCH] blspec: add checking of optional key machine-id
Message-ID: <20180429160125.3193-1-mail@schmidt-andreas.de>

For filtering of Bootloader Spec entries, Bootloader Spec
specify an optional key machine-id. By set the
global.boot.machine-id variable the checking of machine-id
key in Bootloader Spec entries will be activate. If the
variable and key match, appropriate boot entry will be
booting. If it not match boot entry will be ignore and
barebox check the next boot entry.

Signed-off-by: Andreas Schmidt <mail at schmidt-andreas.de>
---
Hi,
we use the same barebox for all our devices. The devices have
same CPU-module but different interface boards. So the bootloader
has to choose the right boot entry. To determine the right boot entry we
decide to use Bootloader Spec. But we have a issue: Currently, only oftree 
compatibility is checking by barebox for Bootloader Spec entries. But all 
our ofstrees are compatible with our barebox, because we use only one. So
we need a additional possibility to check witch Bootloader Spec entry
is the right one for appropriate device. I guess, for such an use case
Bootloader Spec specify "machine-id" key. This patch implement the support
for machine-id key.
The machine-id key is optional. I decide to activate the checking of this
key only if "global.boot.machine_id" variable is set to non-empty value.
If "global.boot.machine_id" not set machine-id key will be ignored, 
independent if it exists in Bootloader Spec entry or not.

Regards,
Andreas

---
 Documentation/user/booting-linux.rst |  6 ++++++
 common/blspec.c                      | 31 ++++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index b5e4320ef..408f87d8e 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -212,6 +212,12 @@ The entry can be listed with the -l option:
 When on barebox the SD card shows up as ``mmc1`` then this entry can be booted with
 ``boot mmc1`` or with setting ``global.boot.default`` to ``mmc1``.
 
+``machine-id`` is an optional key. If ``global.boot.machine_id`` variable is set to
+non-empty value, then barebox accepts only Bootloader Spec entries with ``machine-id``
+key. In case if value of global variable and Bootloader Spec key match each other,
+barebox will choose the boot entry for booting. All other Bootloader Spec entries will
+be ignored.
+
 A bootloader spec entry can also reside on an NFS server in which case a RFC2224
 compatible NFS URI string must be passed to the boot command:
 
diff --git a/common/blspec.c b/common/blspec.c
index 6171461a7..4ffb25dd6 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -419,6 +419,30 @@ out:
 	return ret;
 }
 
+/*
+ * entry_is_match_machine_id - check if a bootspec entry is match with
+ *                            the machine id given by global variable.
+ *
+ * returns true if the entry is match, false otherwise
+ */
+
+static bool entry_is_match_machine_id(struct blspec_entry *entry)
+{
+	int ret = true;
+	const char *env_machineid = getenv_nonempty("global.boot.machine_id");
+
+	if (env_machineid) {
+		const char *machineid = blspec_entry_var_get(entry, "machine-id");
+		if (!machineid || strcmp(machineid, env_machineid)) {
+			pr_info("ignoring entry with missmatched machine-id \"%s\"\n",
+				env_machineid);
+			ret = false;
+		}
+	}
+
+	return ret;
+}
+
 /*
  * blspec_scan_directory - scan over a directory
  *
@@ -504,6 +528,11 @@ int blspec_scan_directory(struct bootentries *bootentries, const char *root)
 			continue;
 		}
 
+		if (!entry_is_match_machine_id(entry)) {
+			blspec_entry_free(&entry->entry);
+			continue;
+		}
+
 		found++;
 
 		if (entry->cdev && entry->cdev->dev) {
@@ -756,4 +785,4 @@ static int blspec_init(void)
 {
 	return bootentry_register_provider(blspec_bootentry_provider);
 }
-device_initcall(blspec_init);
\ No newline at end of file
+device_initcall(blspec_init);
-- 
2.14.1



From andrew.smirnov at gmail.com  Mon Apr 30 23:47:14 2018
From: andrew.smirnov at gmail.com (Andrey Smirnov)
Date: Mon, 30 Apr 2018 23:47:14 -0700
Subject: [PATCH v2] ARM: VFxxx: Record cpu boot source as a part of startup
Message-ID: <20180501064714.11780-1-andrew.smirnov@gmail.com>

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---

Same as original patch, but with fixed subject line.

 arch/arm/mach-imx/vf610.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c
index df8cfcd6b..3ac7c356f 100644
--- a/arch/arm/mach-imx/vf610.c
+++ b/arch/arm/mach-imx/vf610.c
@@ -35,6 +35,8 @@ int vf610_init(void)
 	const char *cputypestr;
 	void __iomem *src = IOMEM(VF610_SRC_BASE_ADDR);
 
+	vf610_boot_save_loc();
+
 	switch (vf610_cpu_type()) {
 	case VF610_CPUTYPE_VF610:
 		cputypestr = "VF610";
-- 
2.14.3



