From rhi at pengutronix.de  Sun Aug  1 11:41:58 2021
From: rhi at pengutronix.de (Roland Hieber)
Date: Sun, 1 Aug 2021 20:41:58 +0200
Subject: [PATCH] arm: mxs: Replace license and copyright boilerplate by
 SPDX identifiers
In-Reply-To: <20210730192802.1457345-1-u.kleine-koenig@pengutronix.de>
References: <20210730192802.1457345-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210801184158.5cqsrl4scflcu5vw@pengutronix.de>

On Fri, Jul 30, 2021 at 09:28:02PM +0200, Uwe Kleine-K?nig wrote:
> Converts the files that licensecheck can determine to be licensed under
> GPL-2.0-only or GPL-2.0-or-later and also convert their copyright
> statements to SPDX.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---
>  arch/arm/mach-mxs/bcb.c                      | 10 +++-------
>  arch/arm/mach-mxs/clocksource-imx23.c        | 16 ++-------------
>  arch/arm/mach-mxs/clocksource-imx28.c        | 15 ++------------
>  arch/arm/mach-mxs/imx.c                      | 16 ++-------------
>  arch/arm/mach-mxs/include/mach/clock.h       | 16 ++-------------
>  arch/arm/mach-mxs/include/mach/fb.h          | 12 +----------
>  arch/arm/mach-mxs/include/mach/generic.h     | 16 ++-------------
>  arch/arm/mach-mxs/include/mach/imx-regs.h    | 16 ++-------------
>  arch/arm/mach-mxs/include/mach/imx23-regs.h  | 15 ++------------
>  arch/arm/mach-mxs/include/mach/imx28-regs.h  | 12 +----------
>  arch/arm/mach-mxs/include/mach/iomux-imx23.h | 14 ++-----------
>  arch/arm/mach-mxs/include/mach/iomux-imx28.h | 12 +----------
>  arch/arm/mach-mxs/include/mach/iomux.h       | 16 ++-------------
>  arch/arm/mach-mxs/include/mach/mci.h         | 13 +-----------
>  arch/arm/mach-mxs/include/mach/ssp.h         | 15 ++++----------
>  arch/arm/mach-mxs/iomux-imx.c                | 16 ++-------------
>  arch/arm/mach-mxs/ocotp.c                    | 17 +++++-----------
>  arch/arm/mach-mxs/power.c                    | 17 ++++++----------
>  arch/arm/mach-mxs/soc-imx23.c                | 19 ++++--------------
>  arch/arm/mach-mxs/soc-imx28.c                | 19 ++++--------------
>  arch/arm/mach-mxs/usb-imx23.c                | 20 +++++--------------
>  arch/arm/mach-mxs/usb-imx28.c                | 21 +++++---------------
>  22 files changed, 60 insertions(+), 283 deletions(-)

Reviewed-by: Roland Hieber <rhi at pengutronix.de>

> diff --git a/arch/arm/mach-mxs/bcb.c b/arch/arm/mach-mxs/bcb.c
> index 860508bde7c5..749cf29af610 100644
> --- a/arch/arm/mach-mxs/bcb.c
> +++ b/arch/arm/mach-mxs/bcb.c
> @@ -1,11 +1,7 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2011 Wolfram Sang, Pengutronix e.K.
> +
>  /*
> - * (C) Copyright 2011 Wolfram Sang, Pengutronix e.K.
> - *
> - * 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.
> - *
>   * Based on a similar function in Karo Electronics TX28-U-Boot (flash.c).
>   * Probably written by Lothar Wa?mann (like tx28.c).
>   */
> diff --git a/arch/arm/mach-mxs/clocksource-imx23.c b/arch/arm/mach-mxs/clocksource-imx23.c
> index 8279ee2f2df8..0a6716f87958 100644
> --- a/arch/arm/mach-mxs/clocksource-imx23.c
> +++ b/arch/arm/mach-mxs/clocksource-imx23.c
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix
>  
>  #include <common.h>
>  #include <init.h>
> diff --git a/arch/arm/mach-mxs/clocksource-imx28.c b/arch/arm/mach-mxs/clocksource-imx28.c
> index 4f38af68b4a5..ea6d4b514630 100644
> --- a/arch/arm/mach-mxs/clocksource-imx28.c
> +++ b/arch/arm/mach-mxs/clocksource-imx28.c
> @@ -1,16 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix <kernel at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix <kernel at pengutronix.de>
>  
>  #include <common.h>
>  #include <init.h>
> diff --git a/arch/arm/mach-mxs/imx.c b/arch/arm/mach-mxs/imx.c
> index b7247b9b720a..5af9cca4e9fb 100644
> --- a/arch/arm/mach-mxs/imx.c
> +++ b/arch/arm/mach-mxs/imx.c
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix
>  
>  #include <common.h>
>  #include <bootsource.h>
> diff --git a/arch/arm/mach-mxs/include/mach/clock.h b/arch/arm/mach-mxs/include/mach/clock.h
> index adbc3304f88e..2050b959133e 100644
> --- a/arch/arm/mach-mxs/include/mach/clock.h
> +++ b/arch/arm/mach-mxs/include/mach/clock.h
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
>  
>  #ifndef __MACH_CLOCK_H
>  # define __MACH_CLOCK_H
> diff --git a/arch/arm/mach-mxs/include/mach/fb.h b/arch/arm/mach-mxs/include/mach/fb.h
> index ad28f79d57db..8fcfe8652067 100644
> --- a/arch/arm/mach-mxs/include/mach/fb.h
> +++ b/arch/arm/mach-mxs/include/mach/fb.h
> @@ -1,14 +1,4 @@
> -/*
> - * 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.
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>  
>  #ifndef __MACH_FB_H
>  # define __MACH_FB_H
> diff --git a/arch/arm/mach-mxs/include/mach/generic.h b/arch/arm/mach-mxs/include/mach/generic.h
> index d63fa4825743..dc1b6ed4a008 100644
> --- a/arch/arm/mach-mxs/include/mach/generic.h
> +++ b/arch/arm/mach-mxs/include/mach/generic.h
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
>  
>  #ifdef CONFIG_ARCH_IMX23
>  # define cpu_is_mx23()	(1)
> diff --git a/arch/arm/mach-mxs/include/mach/imx-regs.h b/arch/arm/mach-mxs/include/mach/imx-regs.h
> index f5abd8bf796b..4aede1bc9318 100644
> --- a/arch/arm/mach-mxs/include/mach/imx-regs.h
> +++ b/arch/arm/mach-mxs/include/mach/imx-regs.h
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
>  
>  #ifndef _IMX_REGS_H
>  # define _IMX_REGS_H
> diff --git a/arch/arm/mach-mxs/include/mach/imx23-regs.h b/arch/arm/mach-mxs/include/mach/imx23-regs.h
> index 3fd2f3d15b94..a9a295fcbcd6 100644
> --- a/arch/arm/mach-mxs/include/mach/imx23-regs.h
> +++ b/arch/arm/mach-mxs/include/mach/imx23-regs.h
> @@ -1,16 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License
> - * as published by the Free Software Foundation; either version 2
> - * of the License, or (at your option) any later version.
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
>  
>  #ifndef __ASM_ARCH_MX23_REGS_H
>  #define __ASM_ARCH_MX23_REGS_H
> diff --git a/arch/arm/mach-mxs/include/mach/imx28-regs.h b/arch/arm/mach-mxs/include/mach/imx28-regs.h
> index 1a90ec2aa561..67e1009a9917 100644
> --- a/arch/arm/mach-mxs/include/mach/imx28-regs.h
> +++ b/arch/arm/mach-mxs/include/mach/imx28-regs.h
> @@ -1,14 +1,4 @@
> -/*
> - * 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.
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>  
>  #ifndef __ASM_ARCH_MX28_REGS_H
>  #define __ASM_ARCH_MX28_REGS_H
> diff --git a/arch/arm/mach-mxs/include/mach/iomux-imx23.h b/arch/arm/mach-mxs/include/mach/iomux-imx23.h
> index 1e225f8fc51b..78a55a47b10d 100644
> --- a/arch/arm/mach-mxs/include/mach/iomux-imx23.h
> +++ b/arch/arm/mach-mxs/include/mach/iomux-imx23.h
> @@ -1,15 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License
> - * as published by the Free Software Foundation; either version 2
> - * of the License, or (at your option) any later version.
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
>  
>  #ifndef __ASM_MACH_IOMUX_MX23_H
>  #define __ASM_MACH_IOMUX_MX23_H
> diff --git a/arch/arm/mach-mxs/include/mach/iomux-imx28.h b/arch/arm/mach-mxs/include/mach/iomux-imx28.h
> index 6119f3caf98d..9fefe3a2af36 100644
> --- a/arch/arm/mach-mxs/include/mach/iomux-imx28.h
> +++ b/arch/arm/mach-mxs/include/mach/iomux-imx28.h
> @@ -1,14 +1,4 @@
> -/*
> - * 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.
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>  
>  #ifndef __MACH_IOMUX_IMX28_H
>  #define __MACH_IOMUX_IMX28_H
> diff --git a/arch/arm/mach-mxs/include/mach/iomux.h b/arch/arm/mach-mxs/include/mach/iomux.h
> index 0091dbae1194..47e843e43f50 100644
> --- a/arch/arm/mach-mxs/include/mach/iomux.h
> +++ b/arch/arm/mach-mxs/include/mach/iomux.h
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
>  
>  #ifndef __ASM_MACH_IOMUX_H
>  #define __ASM_MACH_IOMUX_H
> diff --git a/arch/arm/mach-mxs/include/mach/mci.h b/arch/arm/mach-mxs/include/mach/mci.h
> index c47c24cba831..3383635dfc13 100644
> --- a/arch/arm/mach-mxs/include/mach/mci.h
> +++ b/arch/arm/mach-mxs/include/mach/mci.h
> @@ -1,15 +1,4 @@
> -/*
> - * 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.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>  
>  #ifndef __MACH_MMC_H
>  #define __MACH_MMC_H
> diff --git a/arch/arm/mach-mxs/include/mach/ssp.h b/arch/arm/mach-mxs/include/mach/ssp.h
> index 5eee5c010a02..b90a44820519 100644
> --- a/arch/arm/mach-mxs/include/mach/ssp.h
> +++ b/arch/arm/mach-mxs/include/mach/ssp.h
> @@ -1,14 +1,7 @@
> -/*
> - * Freescale MXS SSP
> - *
> - * Copyright (C) 2013 Michael Grzeschik <mgr at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - */
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* SPDX-FileCopyrightText: 2013 Michael Grzeschik <mgr at pengutronix.de> */
> +
> +/* Freescale MXS SSP */
>  
>  #ifndef __SSP_H__
>  #define __SSP_H__
> diff --git a/arch/arm/mach-mxs/iomux-imx.c b/arch/arm/mach-mxs/iomux-imx.c
> index 68a4e3cbd6cb..6b96fc4ed9c9 100644
> --- a/arch/arm/mach-mxs/iomux-imx.c
> +++ b/arch/arm/mach-mxs/iomux-imx.c
> @@ -1,17 +1,5 @@
> -/*
> - * (C) Copyright 2010 Juergen Beisert - Pengutronix
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix
>  
>  #include <common.h>
>  #include <init.h>
> diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
> index a4df39c2e902..5f78d9d773ec 100644
> --- a/arch/arm/mach-mxs/ocotp.c
> +++ b/arch/arm/mach-mxs/ocotp.c
> @@ -1,15 +1,8 @@
> -/*
> - * ocotp.c - barebox driver for the On-Chip One Time Programmable for MXS
> - *
> - * Copyright (C) 2012 by Wolfram Sang, Pengutronix e.K.
> - * based on the kernel driver which is
> - * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
> - *
> - * 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.
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2012 Wolfram Sang, Pengutronix e.K.
> +// SPDX-FileCopyrightText: 2010 Freescale Semiconductor, Inc.
> +
> +/* ocotp.c - barebox driver for the On-Chip One Time Programmable for MXS */
>  
>  #include <common.h>
>  #include <init.h>
> diff --git a/arch/arm/mach-mxs/power.c b/arch/arm/mach-mxs/power.c
> index 6febf5dbaa52..342f7b0271c1 100644
> --- a/arch/arm/mach-mxs/power.c
> +++ b/arch/arm/mach-mxs/power.c
> @@ -1,14 +1,9 @@
> -/*
> - * i.MX28 power related functions
> - *
> - * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
> - * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
> +// SPDX-FileCopyrightText: 2012 Wolfram Sang <w.sang at pengutronix.de>, Pengutronix
> +
> +/* i.MX28 power related functions */
> +
>  #include <common.h>
>  #include <io.h>
>  #include <stmp-device.h>
> diff --git a/arch/arm/mach-mxs/soc-imx23.c b/arch/arm/mach-mxs/soc-imx23.c
> index 8c47c766cc2b..16b1fda5ed95 100644
> --- a/arch/arm/mach-mxs/soc-imx23.c
> +++ b/arch/arm/mach-mxs/soc-imx23.c
> @@ -1,18 +1,7 @@
> -/*
> - * (c) 2012 Juergen Beisert <kernel at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * Collection of some SoC specific functions
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2012 Juergen Beisert <kernel at pengutronix.de>
> +
> +/* Collection of some SoC specific functions */
>  
>  #include <common.h>
>  #include <init.h>
> diff --git a/arch/arm/mach-mxs/soc-imx28.c b/arch/arm/mach-mxs/soc-imx28.c
> index a214e2b7a6d9..e3d3cb1c0a30 100644
> --- a/arch/arm/mach-mxs/soc-imx28.c
> +++ b/arch/arm/mach-mxs/soc-imx28.c
> @@ -1,18 +1,7 @@
> -/*
> - * (c) 2012 Juergen Beisert <kernel at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * Collection of some SoC specific functions
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2012 Juergen Beisert <kernel at pengutronix.de>
> +
> +/* Collection of some SoC specific functions */
>  
>  #include <common.h>
>  #include <init.h>
> diff --git a/arch/arm/mach-mxs/usb-imx23.c b/arch/arm/mach-mxs/usb-imx23.c
> index d9a54b66f89d..6acf1bb7866b 100644
> --- a/arch/arm/mach-mxs/usb-imx23.c
> +++ b/arch/arm/mach-mxs/usb-imx23.c
> @@ -1,18 +1,8 @@
> -/*
> - * i.MX23 USBPHY setup
> - *
> - * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
> +
> +/* i.MX23 USBPHY setup */
> +
>  #include <common.h>
>  #include <io.h>
>  #include <mach/imx23-regs.h>
> diff --git a/arch/arm/mach-mxs/usb-imx28.c b/arch/arm/mach-mxs/usb-imx28.c
> index a4e1bdb2802e..3793169b5985 100644
> --- a/arch/arm/mach-mxs/usb-imx28.c
> +++ b/arch/arm/mach-mxs/usb-imx28.c
> @@ -1,19 +1,8 @@
> -/*
> - * i.MX28 USBPHY setup
> - *
> - * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// SPDX-FileCopyrightText: 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
> +
> +/* i.MX28 USBPHY setup */
> +
>  #include <common.h>
>  #include <io.h>
>  #include <errno.h>
> -- 
> 2.30.2
> 
> 

-- 
Roland Hieber, Pengutronix e.K.          | r.hieber at pengutronix.de     |
Steuerwalder Str. 21                     | https://www.pengutronix.de/ |
31137 Hildesheim, Germany                | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686         | Fax:   +49-5121-206917-5555 |


From renaud.barbier at abaco.com  Mon Aug  2 03:40:01 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Mon,  2 Aug 2021 11:40:01 +0100
Subject: [PATCH v2 0/3] NXP IFC nand driver
Message-ID: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>

This is the version 2 of the NXP IFC driver patch for the ls1046a.
It addresses the comments as follows::
	* Rebase the patch to the next branch to use existing header.
	* The use of the DT to retrieve the IFC controller address.
	* Remove the platform data support for PPC.
	* Remove unused functions.

Renaud Barbier (3):
  ARM: atomic.h: add 64-bit counter support
  nand: add NXP IFC nand driver
  ls1046ardb: enable IFC NAND.

 arch/arm/boards/ls1046ardb/board.c    |   42 +
 arch/arm/configs/layerscape_defconfig |   11 +
 drivers/mtd/nand/Kconfig              |    7 +
 drivers/mtd/nand/Makefile             |    1 +
 drivers/mtd/nand/fsl_ifc.h            |  116 +++
 drivers/mtd/nand/nand_fsl_ifc.c       | 1036 +++++++++++++++++++++++++
 include/asm-generic/atomic-long.h     |   63 --
 include/asm-generic/atomic.h          |   49 ++
 include/linux/fsl_ifc.h               |  305 ++++++++
 9 files changed, 1567 insertions(+), 63 deletions(-)
 create mode 100644 drivers/mtd/nand/fsl_ifc.h
 create mode 100644 drivers/mtd/nand/nand_fsl_ifc.c
 create mode 100644 include/linux/fsl_ifc.h

-- 
2.27.0



From renaud.barbier at abaco.com  Mon Aug  2 03:40:02 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Mon,  2 Aug 2021 11:40:02 +0100
Subject: [PATCH 1/3] ARM: atomic.h: add 64-bit counter support
In-Reply-To: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
Message-ID: <1627900804-15814-2-git-send-email-renaud.barbier@abaco.com>

In preparation for the introduction of the FSL IFC nand driver
for the layerscape CPU, add 64-bit counter support.

Remove functions calling undefined functions.

Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
---
 include/asm-generic/atomic-long.h | 63 -------------------------------
 include/asm-generic/atomic.h      | 49 ++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 63 deletions(-)

diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index 322d510f38..fd1fdad20f 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -66,69 +66,6 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
 	atomic64_sub(i, v);
 }
 
-static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_sub_and_test(i, v);
-}
-
-static inline int atomic_long_dec_and_test(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_dec_and_test(v);
-}
-
-static inline int atomic_long_inc_and_test(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_inc_and_test(v);
-}
-
-static inline int atomic_long_add_negative(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_add_negative(i, v);
-}
-
-static inline long atomic_long_add_return(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_add_return(i, v);
-}
-
-static inline long atomic_long_sub_return(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_sub_return(i, v);
-}
-
-static inline long atomic_long_inc_return(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_inc_return(v);
-}
-
-static inline long atomic_long_dec_return(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_dec_return(v);
-}
-
-static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_add_unless(v, a, u);
-}
-
 #define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
 
 #define atomic_long_cmpxchg(l, old, new) \
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 449cecaabc..6e63b8e8e7 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -11,7 +11,55 @@
 #ifdef CONFIG_SMP
 #error SMP not supported
 #endif
+#define ATOMIC_INIT(i)	{ (i) }
+
+#ifdef CONFIG_64BIT
+typedef struct { s64 counter; } atomic64_t;
+
+#define atomic64_read(v)	((v)->counter)
+#define atomic64_set(v, i)	(((v)->counter) = (i))
+
+static inline void atomic64_add(s64 i, volatile atomic64_t *v)
+{
+	v->counter += i;
+}
+
+static inline void atomic64_sub(s64 i, volatile atomic64_t *v)
+{
+	v->counter -= i;
+}
+
+static inline void atomic64_inc(volatile atomic64_t *v)
+{
+	v->counter += 1;
+}
+
+static inline void atomic64_dec(volatile atomic64_t *v)
+{
+	v->counter -= 1;
+}
+
+static inline int atomic64_dec_and_test(volatile atomic64_t *v)
+{
+	s64 val;
+
+	val = v->counter;
+	v->counter = val -= 1;
+
+	return val == 0;
+}
 
+static inline int atomic64_add_negative(s64 i, volatile atomic64_t *v)
+{
+	s64 val;
+
+	val = v->counter;
+	v->counter = val += i;
+
+	return val < 0;
+}
+
+#else
 typedef struct { volatile int counter; } atomic_t;
 
 #define ATOMIC_INIT(i)	{ (i) }
@@ -63,6 +111,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 {
 	*addr &= ~mask;
 }
+#endif
 
 /* Atomic operations are already serializing on ARM */
 #define smp_mb__before_atomic_dec()	barrier()
-- 
2.27.0



From renaud.barbier at abaco.com  Mon Aug  2 03:40:04 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Mon,  2 Aug 2021 11:40:04 +0100
Subject: [PATCH 3/3] ls1046ardb: enable IFC NAND.
In-Reply-To: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
Message-ID: <1627900804-15814-4-git-send-email-renaud.barbier@abaco.com>

Set the NAND timings and enable the IFC NAND driver.

Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
---
 arch/arm/boards/ls1046ardb/board.c    | 42 +++++++++++++++++++++++++++
 arch/arm/configs/layerscape_defconfig | 11 +++++++
 2 files changed, 53 insertions(+)

diff --git a/arch/arm/boards/ls1046ardb/board.c b/arch/arm/boards/ls1046ardb/board.c
index ef68e9c7f9..b2cfba58a8 100644
--- a/arch/arm/boards/ls1046ardb/board.c
+++ b/arch/arm/boards/ls1046ardb/board.c
@@ -8,10 +8,12 @@
 #include <fs.h>
 #include <envfs.h>
 #include <libfile.h>
+#include <of_address.h>
 #include <asm/memory.h>
 #include <linux/sizes.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/fsl_ifc.h>
 #include <asm/system.h>
 #include <mach/layerscape.h>
 #include <mach/bbu.h>
@@ -35,6 +37,11 @@ struct nxid {
 	u32 crc;          /* 0xfc - 0xff CRC32 checksum */
 } __packed;
 
+static const struct of_device_id fsl_ifc_of_ids[] = {
+	{ .compatible = "fsl,ifc", },
+	{ },
+};
+
 static int nxid_is_valid(struct nxid *nxid)
 {
 	unsigned char id[] = { 'N', 'X', 'I', 'D' };
@@ -161,3 +168,38 @@ static int rdb_postcore_init(void)
 }
 
 postcore_initcall(rdb_postcore_init);
+
+static int rdb_nand_init(void)
+{
+	struct device_node *np;
+	void __iomem *ifc;
+
+	np = of_find_matching_node(NULL, fsl_ifc_of_ids);
+	if (!np)
+		return -EINVAL;
+
+	ifc = of_iomap(np, 0);
+	if (!ifc)
+		return -EINVAL;
+
+	set_ifc_cspr(ifc, IFC_CS0, CSPR_PHYS_ADDR(0x7e800000) |
+			CSPR_PORT_SIZE_8 | CSPR_MSEL_NAND | CSPR_V);
+	set_ifc_csor(ifc, IFC_CS0, CSOR_NAND_ECC_ENC_EN | CSOR_NAND_ECC_DEC_EN |
+			CSOR_NAND_ECC_MODE_8 |
+			CSOR_NAND_RAL_3 | CSOR_NAND_PGS_4K |
+			CSOR_NAND_SPRZ_224 |  CSOR_NAND_PB(64) |
+			CSOR_NAND_TRHZ_20);
+	set_ifc_amask(ifc, IFC_CS0, IFC_AMASK(64*1024));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM0, FTIM0_NAND_TCCST(0x07) |
+			FTIM0_NAND_TWP(0x18) | FTIM0_NAND_TWCHT(0x07) |
+			FTIM0_NAND_TWH(0x0a));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM1, FTIM1_NAND_TADLE(0x32) |
+			FTIM1_NAND_TWBE(0x39) | FTIM1_NAND_TRR(0x0e)|
+			FTIM1_NAND_TRP(0x18));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM2, FTIM2_NAND_TRAD(0xf) |
+			FTIM2_NAND_TREH(0xa) | FTIM2_NAND_TWHRE(0x1e));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM3, 0);
+
+	return 0;
+}
+postcore_initcall(rdb_nand_init);
diff --git a/arch/arm/configs/layerscape_defconfig b/arch/arm/configs/layerscape_defconfig
index 394cd95c98..fb8e885353 100644
--- a/arch/arm/configs/layerscape_defconfig
+++ b/arch/arm/configs/layerscape_defconfig
@@ -34,6 +34,10 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_RESET=y
 CONFIG_CMD_UIMAGE=y
 CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UBI=y
+CONFIG_CMD_UBIFORMAT=y
+CONFIG_CMD_UMOUNT=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_LOADENV=y
 CONFIG_CMD_PRINTENV=y
@@ -69,6 +73,7 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_LED=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_NAND=y
 CONFIG_CMD_LED_TRIGGER=y
 CONFIG_CMD_WD=y
 CONFIG_CMD_BAREBOX_UPDATE=y
@@ -85,6 +90,10 @@ CONFIG_DP83867_PHY=y
 CONFIG_REALTEK_PHY=y
 CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_DRIVER_SPI_FSL_QUADSPI=y
+CONFIG_NAND=y
+CONFIG_NAND_FSL_IFC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=20
 CONFIG_I2C=y
 CONFIG_I2C_IMX=y
 CONFIG_I2C_MUX=y
@@ -112,5 +121,7 @@ CONFIG_FS_NFS=y
 CONFIG_FS_FAT=y
 CONFIG_FS_FAT_WRITE=y
 CONFIG_FS_FAT_LFN=y
+CONFIG_FS_UBIFS=y
+CONFIG_FS_UBIFS_COMPRESSION_LZO=y
 CONFIG_ZLIB=y
 CONFIG_LZO_DECOMPRESS=y
-- 
2.27.0



From renaud.barbier at abaco.com  Mon Aug  2 03:40:03 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Mon,  2 Aug 2021 11:40:03 +0100
Subject: [PATCH 2/3] nand: add NXP IFC nand driver
In-Reply-To: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
Message-ID: <1627900804-15814-3-git-send-email-renaud.barbier@abaco.com>

Add the NXP IFC nand driver support. This driver
can be used with the NXP QorIQ cores.

Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
---
 drivers/mtd/nand/Kconfig        |    7 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/fsl_ifc.h      |  116 ++++
 drivers/mtd/nand/nand_fsl_ifc.c | 1036 +++++++++++++++++++++++++++++++
 include/linux/fsl_ifc.h         |  305 +++++++++
 5 files changed, 1465 insertions(+)
 create mode 100644 drivers/mtd/nand/fsl_ifc.h
 create mode 100644 drivers/mtd/nand/nand_fsl_ifc.c
 create mode 100644 include/linux/fsl_ifc.h

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c69e5ce4e1..cf9f1fdc0c 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -42,6 +42,13 @@ config NAND_IMX
 	  and later, which use the GPMI NAND controller from the MXS series. 
 	  See the i.MX 'mxs' driver for those chips.
 
+config NAND_FSL_IFC
+	bool
+	prompt "FSL IFC NAND driver"
+	depends on ARCH_LAYERSCAPE
+	help
+	  Freescale IFC NAND driver for various chips.
+
 config NAND_MXS
 	bool
 	select STMP_DEVICE
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index f6e5b41e94..4fd14ddd63 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -22,3 +22,4 @@ pbl-$(CONFIG_NAND_S3C24XX)		+= nand_s3c24xx.o
 obj-$(CONFIG_NAND_MXS)			+= nand_mxs.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= nand_denali.o
 obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= nand_denali_dt.o
+obj-$(CONFIG_NAND_FSL_IFC)		+= nand_fsl_ifc.o
diff --git a/drivers/mtd/nand/fsl_ifc.h b/drivers/mtd/nand/fsl_ifc.h
new file mode 100644
index 0000000000..4c89f569f5
--- /dev/null
+++ b/drivers/mtd/nand/fsl_ifc.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ */
+
+/*
+ * The actual number of banks implemented depends on the IFC version
+ *    - IFC version 1.0 implements 4 banks.
+ *    - IFC version 1.1 onward implements 8 banks.
+ */
+#define FSL_IFC_BANK_COUNT 8
+
+#define FSL_IFC_REV		0x0000
+#define		FSL_IFC_V1_1_0	0x01010000
+#define		FSL_IFC_V2_0_0	0x02000000
+
+/*
+ * Version 1.1.0 adds offset 0x1000
+ * Version 2.0.0 adds offset 0x10000
+ */
+#define FSL_IFC_NCFGR		0x000
+
+#define		IFC_NAND_SRAM_INIT_EN           0x20000000
+
+/*
+ * NAND Flash Command Registers (NAND_FCR0/NAND_FCR1)
+ */
+#define FSL_IFC_FCR0		0x014
+/* General purpose FCM flash command bytes CMD0-CMD7 */
+#define		IFC_NAND_FCR0_CMD0_SHIFT	24
+#define		IFC_NAND_FCR0_CMD1_SHIFT	16
+#define		IFC_NAND_FCR0_CMD2_SHIFT	8
+#define		IFC_NAND_FCR0_CMD3_SHIFT	0
+#define FSL_IFC_ROW0		0x03c
+#define		IFC_NAND_COL_MS			0x80000000
+#define FSL_IFC_COL0		0x044
+#define FSL_IFC_ROW3		0x06c
+#define FSL_IFC_NAND_BC		0x108
+/*
+ * NAND Flash Instruction Registers (NAND_FIR0/NAND_FIR1/NAND_FIR2)
+ */
+#define FSL_IFC_FIR0		0x110
+/* NAND Machine specific opcodes OP0-OP14*/
+#define		IFC_NAND_FIR0_OP0_SHIFT		26
+#define		IFC_NAND_FIR0_OP1_SHIFT		20
+#define		IFC_NAND_FIR0_OP2_SHIFT		14
+#define		IFC_NAND_FIR0_OP3_SHIFT		8
+#define		IFC_NAND_FIR0_OP4_SHIFT		2
+#define FSL_IFC_FIR1		0x114
+#define		IFC_NAND_FIR1_OP5_SHIFT		26
+#define		IFC_NAND_FIR1_OP6_SHIFT		20
+#define		IFC_NAND_FIR1_OP7_SHIFT		14
+#define		IFC_NAND_FIR1_OP8_SHIFT		8
+#define FSL_IFC_NAND_CSEL	0x15c
+#define		IFC_NAND_CSEL_SHIFT		26
+#define FSL_IFC_NANDSEQ_STRT	0x164
+#define		IFC_NAND_SEQ_STRT_FIR_STRT	0x80000000
+/* NAND Event and Error Status Register */
+#define FSL_IFC_NAND_EVTER_STAT	0x16c
+#define		IFC_NAND_EVTER_STAT_OPC		0x80000000
+#define		IFC_NAND_EVTER_STAT_FTOER	0x08000000
+#define		IFC_NAND_EVTER_STAT_WPER	0x04000000
+/* NAND Flash Page Read Completion Event Status Register */
+#define FSL_IFC_PGRDCMPL_EVT_STAT 0x174
+/* NAND Event and Error Enable Register (NAND_EVTER_EN) */
+#define FSL_IFC_EVTER_EN	0x180
+#define		IFC_NAND_EVTER_EN_OPC_EN	0x80000000
+#define		IFC_NAND_EVTER_EN_PGRDCMPL_EN	0x20000000
+#define		IFC_NAND_EVTER_EN_FTOER_EN	0x08000000
+#define		IFC_NAND_EVTER_EN_WPER_EN	0x04000000
+
+#define FSL_IFC_NAND_FSR	0x1e0
+#define FSL_IFC_ECCSTAT(v)	(0x1e8 + (4 * v))
+#define		IFC_NAND_EVTER_STAT_ECCER	0x02000000
+
+/*
+ * Instruction opcodes to be programmed
+ * in FIR registers- 6bits
+ */
+enum ifc_nand_fir_opcodes {
+	IFC_FIR_OP_NOP,
+	IFC_FIR_OP_CA0,
+	IFC_FIR_OP_CA1,
+	IFC_FIR_OP_CA2,
+	IFC_FIR_OP_CA3,
+	IFC_FIR_OP_RA0,
+	IFC_FIR_OP_RA1,
+	IFC_FIR_OP_RA2,
+	IFC_FIR_OP_RA3,
+	IFC_FIR_OP_CMD0,
+	IFC_FIR_OP_CMD1,
+	IFC_FIR_OP_CMD2,
+	IFC_FIR_OP_CMD3,
+	IFC_FIR_OP_CMD4,
+	IFC_FIR_OP_CMD5,
+	IFC_FIR_OP_CMD6,
+	IFC_FIR_OP_CMD7,
+	IFC_FIR_OP_CW0,
+	IFC_FIR_OP_CW1,
+	IFC_FIR_OP_CW2,
+	IFC_FIR_OP_CW3,
+	IFC_FIR_OP_CW4,
+	IFC_FIR_OP_CW5,
+	IFC_FIR_OP_CW6,
+	IFC_FIR_OP_CW7,
+	IFC_FIR_OP_WBCD,
+	IFC_FIR_OP_RBCD,
+	IFC_FIR_OP_BTRD,
+	IFC_FIR_OP_RDSTAT,
+	IFC_FIR_OP_NWAIT,
+	IFC_FIR_OP_WFR,
+	IFC_FIR_OP_SBRD,
+	IFC_FIR_OP_UA,
+	IFC_FIR_OP_RB,
+};
diff --git a/drivers/mtd/nand/nand_fsl_ifc.c b/drivers/mtd/nand/nand_fsl_ifc.c
new file mode 100644
index 0000000000..833b96d0c7
--- /dev/null
+++ b/drivers/mtd/nand/nand_fsl_ifc.c
@@ -0,0 +1,1036 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Integrated Flash Controller NAND Machine Driver
+ *
+ * Copyright (c) 2012 Freescale Semiconductor, Inc
+ *
+ * Authors: Dipen Dudhat <Dipen.Dudhat at freescale.com>
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <nand.h>
+#include <errno.h>
+#include <clock.h>
+#include <io.h>
+#include <of_address.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/fsl_ifc.h>
+#include <asm-generic/io.h>
+#include "fsl_ifc.h"
+
+#define ERR_BYTE	0xFF
+#define IFC_TIMEOUT_MS	500
+/* overview of the fsl ifc controller */
+struct fsl_ifc_ctrl {
+	struct nand_controller controller;
+	/* device info */
+	void __iomem *rregs;  /* Run-time register		      */
+	void __iomem *gregs;  /* Global registers		      */
+	uint32_t version;
+	uint32_t page;       /* Last page written to / read from      */
+	uint32_t read_bytes; /* Number of bytes read during command   */
+	uint32_t column;     /* Saved column from SEQIN               */
+	uint32_t index;      /* Pointer to next byte to 'read'        */
+	uint32_t nand_stat;  /* status read from NEESR after last op  */
+	uint32_t oob;        /* Non zero if operating on OOB data     */
+	uint32_t eccread;    /* Non zero for a full-page ECC read     */
+	uint32_t max_bitflips; /* Saved during READ0 cmd              */
+	void __iomem *addr;  /* Address of assigned IFC buffer        */
+};
+
+/* mtd information per set */
+struct fsl_ifc_mtd {
+	struct device_d *dev;
+	struct nand_chip chip;
+	struct fsl_ifc_ctrl *ctrl;
+	uint32_t cs;		/* On which chipsel NAND is connected    */
+	uint32_t bufnum_mask;	/* bufnum = page & bufnum_mask */
+	void __iomem *vbase;    /* Chip select base virtual address     */
+	phys_addr_t pbase;	/* Chip select physical address		*/
+};
+
+static struct fsl_ifc_ctrl *ifc_ctrl;
+
+/* Generic flash bbt descriptors */
+static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
+};
+
+static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section,
+		struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->offset = 8;
+	oobregion->length = chip->ecc.total;
+
+	return 0;
+}
+
+static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section,
+		struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section > 1)
+		return -ERANGE;
+
+	if (mtd->writesize == 512 && !(chip->options & NAND_BUSWIDTH_16)) {
+		if (!section) {
+			oobregion->offset = 0;
+			oobregion->length = 5;
+		} else {
+			oobregion->offset = 6;
+			oobregion->length = 2;
+		}
+
+		return 0;
+	}
+
+	if (!section) {
+		oobregion->offset = 2;
+		oobregion->length = 6;
+	} else {
+		oobregion->offset = chip->ecc.total + 8;
+		oobregion->length = mtd->oobsize - oobregion->offset;
+	}
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops fsl_ifc_ooblayout_ops = {
+	.ecc = fsl_ifc_ooblayout_ecc,
+	.free = fsl_ifc_ooblayout_free,
+};
+
+/*
+ * Set up the IFC hardware block and page address fields, and the ifc nand
+ * structure addr field to point to the correct IFC buffer in memory
+ */
+static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	int buf_num;
+
+	if (page_addr != -1) {
+		ctrl->page = page_addr;
+		/* Program ROW0/COL0 */
+		ifc_out32(ctrl->rregs + FSL_IFC_ROW0, page_addr);
+		buf_num = page_addr & priv->bufnum_mask;
+		ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
+	}
+
+	ifc_out32(ctrl->rregs + FSL_IFC_COL0, (oob ? IFC_NAND_COL_MS : 0) |
+						column);
+	ctrl->index = column;
+
+	/* for OOB data point to the second half of the buffer */
+	if (oob)
+		ctrl->index += mtd->writesize;
+}
+
+/* returns nonzero if entire page is blank */
+static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
+			  uint32_t eccstat, uint32_t bufnum)
+{
+	return (eccstat >> ((3 - bufnum % 4) * 8)) & 15;
+}
+
+/* execute IFC NAND command and wait for it to complete */
+static void fsl_ifc_run_command(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint64_t time_start;
+	uint32_t eccstat;
+	int i;
+
+	/* set the chip select for NAND Transaction */
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_CSEL,
+			priv->cs << IFC_NAND_CSEL_SHIFT);
+
+	/* start read/write seq */
+	ifc_out32(ctrl->rregs + FSL_IFC_NANDSEQ_STRT,
+			IFC_NAND_SEQ_STRT_FIR_STRT);
+
+	ctrl->nand_stat = 0;
+
+	/* wait for NAND Machine complete flag or timeout */
+	time_start = get_time_ns();
+	while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
+		ctrl->nand_stat = ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
+
+		if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_OPC)
+			break;
+	}
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT, ctrl->nand_stat);
+
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_FTOER)
+		pr_err("%s: Flash Time Out Error\n", __func__);
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER)
+		pr_err("%s: Write Protect Error\n", __func__);
+
+	ctrl->max_bitflips = 0;
+
+	if (ctrl->eccread) {
+		int errors;
+		int bufnum = ctrl->page & priv->bufnum_mask;
+		int sector_start = bufnum * chip->ecc.steps;
+		int sector_end = sector_start + chip->ecc.steps - 1;
+
+		eccstat = ifc_in32(ctrl->rregs +
+				FSL_IFC_ECCSTAT(sector_start / 4));
+
+		for (i = sector_start; i <= sector_end; i++) {
+			if ((i != sector_start) && !(i % 4)) {
+				eccstat = ifc_in32(ctrl->rregs +
+						FSL_IFC_ECCSTAT(i / 4));
+			}
+			errors = check_read_ecc(mtd, ctrl, eccstat, i);
+
+			if (errors == 15) {
+				/*
+				 * Uncorrectable error.
+				 * We'll check for blank pages later.
+				 *
+				 * We disable ECCER reporting due to erratum
+				 * IFC-A002770 -- so report it now if we
+				 * see an uncorrectable error in ECCSTAT.
+				 */
+				ctrl->nand_stat |= IFC_NAND_EVTER_STAT_ECCER;
+				continue;
+			}
+
+			mtd->ecc_stats.corrected += errors;
+			ctrl->max_bitflips = max_t(unsigned int,
+					ctrl->max_bitflips, errors);
+		}
+
+		ctrl->eccread = 0;
+	}
+}
+
+static void
+fsl_ifc_do_read(struct nand_chip *chip, int oob, struct mtd_info *mtd)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	/* Program FIR/IFC_NAND_FCR0 for Small/Large page */
+	if (mtd->writesize > 512) {
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+			  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
+			  (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR1, 0x0);
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			  (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+	} else {
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
+			  (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR1, 0);
+
+		if (oob)
+			ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+				  NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
+		else
+			ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+				  NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+	}
+}
+
+/* cmdfunc send commands to the IFC NAND Machine */
+static void fsl_ifc_cmdfunc(struct nand_chip *chip, uint32_t command,
+			     int column, int page_addr)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	/* clear the read buffer */
+	ctrl->read_bytes = 0;
+	if (command != NAND_CMD_PAGEPROG)
+		ctrl->index = 0;
+
+	switch (command) {
+	/* READ0 read the entire buffer to use hardware ECC. */
+	case NAND_CMD_READ0: {
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+		set_addr(mtd, 0, page_addr, 0);
+
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		ctrl->index += column;
+
+		if (chip->ecc.mode == NAND_ECC_HW)
+			ctrl->eccread = 1;
+
+		fsl_ifc_do_read(chip, 0, mtd);
+		fsl_ifc_run_command(mtd);
+		return;
+	}
+
+	/* READOOB reads only the OOB because no ECC is performed. */
+	case NAND_CMD_READOOB:
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, mtd->oobsize - column);
+
+		set_addr(mtd, column, page_addr, 1);
+
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		fsl_ifc_do_read(chip, 1, mtd);
+		fsl_ifc_run_command(mtd);
+
+		return;
+
+	case NAND_CMD_RNDOUT:
+		if (chip->ecc.mode == NAND_ECC_HW)
+			break;
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+		set_addr(mtd, column, -1, 0);
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		/* For write size greater than 512 */
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			(IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			(IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR1, 0x0);
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			(NAND_CMD_RNDOUT << IFC_NAND_FCR0_CMD0_SHIFT) |
+			(NAND_CMD_RNDOUTSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+
+		fsl_ifc_run_command(mtd);
+		return;
+
+	case NAND_CMD_READID:
+	case NAND_CMD_PARAM: {
+		int timing = IFC_FIR_OP_RB;
+		int len = 8;
+
+		if (command == NAND_CMD_PARAM) {
+			timing = IFC_FIR_OP_RBCD;
+			len = 256 * 3;
+		}
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (timing << IFC_NAND_FIR0_OP2_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  command << IFC_NAND_FCR0_CMD0_SHIFT);
+		ifc_out32(ctrl->rregs + FSL_IFC_ROW3, column);
+
+		/*
+		 * although currently it's 8 bytes for READID, we always read
+		 * the maximum 256 bytes(for PARAM)
+		 */
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, len);
+		ctrl->read_bytes = len;
+
+		set_addr(mtd, 0, 0, 0);
+		fsl_ifc_run_command(mtd);
+		return;
+	}
+
+	/* ERASE1 stores the block and page address */
+	case NAND_CMD_ERASE1:
+		set_addr(mtd, 0, page_addr, 0);
+		return;
+
+	/* ERASE2 uses the block and page address from ERASE1 */
+	case NAND_CMD_ERASE2:
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			  (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
+
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+		ctrl->read_bytes = 0;
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* SEQIN sets up the addr buffer and all registers except the length */
+	case NAND_CMD_SEQIN: {
+		uint32_t nand_fcr0;
+
+		ctrl->column = column;
+		ctrl->oob = 0;
+
+		if (mtd->writesize > 512) {
+			nand_fcr0 =
+				(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
+				(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
+				(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
+
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+				  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+				  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				  (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
+				  (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR1,
+				  (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
+				  (IFC_FIR_OP_RDSTAT <<
+					IFC_NAND_FIR1_OP6_SHIFT) |
+				  (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
+		} else {
+			nand_fcr0 = ((NAND_CMD_PAGEPROG <<
+					IFC_NAND_FCR0_CMD1_SHIFT) |
+				    (NAND_CMD_SEQIN <<
+					IFC_NAND_FCR0_CMD2_SHIFT) |
+				    (NAND_CMD_STATUS <<
+					IFC_NAND_FCR0_CMD3_SHIFT));
+
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+				  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				  (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
+				  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
+				  (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR1,
+				  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
+				  (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
+				  (IFC_FIR_OP_RDSTAT <<
+					IFC_NAND_FIR1_OP7_SHIFT) |
+				  (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
+
+			if (column >= mtd->writesize)
+				nand_fcr0 |=
+				NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
+			else
+				nand_fcr0 |=
+				NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
+		}
+
+		if (column >= mtd->writesize) {
+			/* OOB area --> READOOB */
+			column -= mtd->writesize;
+			ctrl->oob = 1;
+		}
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0, nand_fcr0);
+		set_addr(mtd, column, page_addr, ctrl->oob);
+		return;
+	}
+
+	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+	case NAND_CMD_PAGEPROG:
+		if (ctrl->oob)
+			ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC,
+				  ctrl->index - ctrl->column);
+		else
+			ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+
+		fsl_ifc_run_command(mtd);
+		return;
+
+	case NAND_CMD_STATUS:
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 1);
+		set_addr(mtd, 0, 0, 0);
+		ctrl->read_bytes = 1;
+
+		fsl_ifc_run_command(mtd);
+
+		/*
+		 * The chip always seems to report that it is
+		 * write-protected, even when it is not.
+		 */
+		if (chip->options & NAND_BUSWIDTH_16)
+			out_be16(ctrl->addr, in_be16(ctrl->addr) |
+					NAND_STATUS_WP);
+		else
+			out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
+		return;
+
+	case NAND_CMD_RESET:
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	default:
+		pr_err("%s: error, unsupported command 0x%x.\n",
+			__func__, command);
+	}
+}
+
+/* Write buf to the IFC NAND Controller Data Buffer */
+static void fsl_ifc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t bufsize = mtd->writesize + mtd->oobsize;
+
+	if (len <= 0) {
+		pr_info("%s of %d bytes", __func__, len);
+		ctrl->nand_stat = 0;
+		return;
+	}
+
+	if ((uint32_t)len > bufsize - ctrl->index) {
+		pr_err("%s beyond end of buffer (%d requested, %u available)\n",
+			__func__, len, bufsize - ctrl->index);
+		len = bufsize - ctrl->index;
+	}
+
+	memcpy_toio(ctrl->addr + ctrl->index, buf, len);
+	ctrl->index += len;
+}
+
+/*
+ * read a byte from either the IFC hardware buffer if it has any data left
+ * otherwise issue a command to read a single byte.
+ */
+static uint8_t fsl_ifc_read_byte(struct nand_chip *chip)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t offset;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ctrl->index < ctrl->read_bytes) {
+		offset = ctrl->index++;
+		return in_8(ctrl->addr + offset);
+	}
+
+	return ERR_BYTE;
+}
+
+/*
+ * Read two bytes from the IFC hardware buffer
+ * read function for 16-bit buswith
+ */
+static uint8_t fsl_ifc_read_byte16(struct nand_chip *chip)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint16_t data;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ctrl->index < ctrl->read_bytes) {
+		data = ifc_in16(ctrl->addr + ctrl->index);
+		ctrl->index += 2;
+		return (uint8_t)data;
+	}
+
+	return ERR_BYTE;
+}
+
+/* Read from the IFC Controller Data Buffer */
+static void fsl_ifc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	int avail;
+
+	if (len < 0)
+		return;
+
+	avail = min((uint32_t)len, ctrl->read_bytes - ctrl->index);
+	memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
+
+	ctrl->index += avail;
+
+	if (len > avail)
+		pr_err("%s beyond end of buffer (%d requested, %d available)\n",
+		       __func__, len, avail);
+}
+
+/* This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+static int fsl_ifc_wait(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t nand_fsr;
+	int status;
+
+	/* Use READ_STATUS command, but wait for the device to be ready */
+	ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+		  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+		  (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
+	ifc_out32(ctrl->rregs + FSL_IFC_FCR0, NAND_CMD_STATUS <<
+		  IFC_NAND_FCR0_CMD0_SHIFT);
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 1);
+	set_addr(mtd, 0, 0, 0);
+	ctrl->read_bytes = 1;
+
+	fsl_ifc_run_command(mtd);
+
+	nand_fsr = ifc_in32(ctrl->rregs + FSL_IFC_NAND_FSR);
+	status = nand_fsr >> 24;
+
+	/* Chip sometimes reporting write protect even when it's not */
+	return status | NAND_STATUS_WP;
+}
+
+/*
+ * The controller does not check for bitflips in erased pages,
+ * therefore software must check instead.
+ */
+static int
+check_erased_page(struct nand_chip *chip, u8 *buf, struct mtd_info *mtd)
+{
+	u8 *ecc = chip->oob_poi;
+	const int ecc_size = chip->ecc.bytes;
+	const int pkt_size = chip->ecc.size;
+	int i, res, bitflips = 0;
+	struct mtd_oob_region oobregion = { };
+
+
+	mtd_ooblayout_ecc(mtd, 0, &oobregion);
+	ecc += oobregion.offset;
+	for (i = 0; i < chip->ecc.steps; i++) {
+		res = nand_check_erased_ecc_chunk(buf, pkt_size, ecc, ecc_size,
+		NULL, 0, chip->ecc.strength);
+
+		if (res < 0) {
+			pr_err("fsl-ifc: NAND Flash ECC Uncorrectable Error\n");
+			mtd->ecc_stats.failed++;
+		} else if (res > 0) {
+			mtd->ecc_stats.corrected += res;
+		}
+		bitflips = max(res, bitflips);
+		buf += pkt_size;
+		ecc += ecc_size;
+	}
+
+	return bitflips;
+}
+
+static int fsl_ifc_read_page(struct nand_chip *chip, uint8_t *buf,
+		int oob_required, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
+	/*fsl_ifc_read_buf(chip, buf, mtd->writesize); */
+	if (oob_required)
+		fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize);
+
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) {
+		if (!oob_required)
+			fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize);
+
+		return check_erased_page(chip, buf, mtd);
+	}
+
+	if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+		mtd->ecc_stats.failed++;
+
+	return ctrl->max_bitflips;
+}
+
+/*
+ * ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static int fsl_ifc_write_page(struct nand_chip *chip, const uint8_t *buf,
+		int oob_required, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
+	fsl_ifc_write_buf(chip, chip->oob_poi, mtd->oobsize);
+
+	return nand_prog_page_end_op(chip);
+}
+
+static int match_bank(struct fsl_ifc_ctrl *ctrl, int bank, phys_addr_t addr)
+{
+	u32 cspr = get_ifc_cspr(ctrl->gregs, bank);
+
+	if (!(cspr & CSPR_V))
+		return 0;
+	if ((cspr & CSPR_MSEL) != CSPR_MSEL_NAND)
+		return 0;
+
+	return (cspr & CSPR_BA) == (addr & CSPR_BA);
+}
+
+static void fsl_ifc_ctrl_init(void)
+{
+	struct fsl_ifc_ctrl *ctrl;
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,ifc");
+	if (!np)
+		return;
+
+	ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
+	if (!ifc_ctrl)
+		return;
+
+	ctrl = ifc_ctrl;
+	ctrl->read_bytes = 0;
+	ctrl->index = 0;
+	ctrl->addr = NULL;
+
+	ctrl->gregs = of_iomap(np, 0);
+
+	ctrl->version = ifc_in32(ctrl->gregs + FSL_IFC_REV);
+	if (ctrl->version >= FSL_IFC_V2_0_0)
+		ctrl->rregs = ctrl->gregs + 0x10000;
+	else
+		ctrl->rregs = ctrl->gregs + 0x1000;
+
+	/* clear event registers */
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT, ~0U);
+	ifc_out32(ctrl->rregs + FSL_IFC_PGRDCMPL_EVT_STAT, ~0U);
+
+	/* Enable error and event for any detected errors */
+	ifc_out32(ctrl->rregs + FSL_IFC_EVTER_EN,
+		  IFC_NAND_EVTER_EN_OPC_EN |
+		  IFC_NAND_EVTER_EN_PGRDCMPL_EN |
+		  IFC_NAND_EVTER_EN_FTOER_EN |
+		  IFC_NAND_EVTER_EN_WPER_EN);
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NCFGR, 0x0);
+}
+
+static void fsl_ifc_select_chip(struct nand_chip *chip, int cs)
+{
+}
+
+static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv, uint32_t ver)
+{
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
+	uint32_t ncfgr = 0;
+	uint32_t time_start;
+
+	if (ctrl->version > FSL_IFC_V1_1_0) {
+		ncfgr = ifc_in32(ctrl->rregs + FSL_IFC_NCFGR);
+		ifc_out32(ctrl->rregs + FSL_IFC_NCFGR,
+				ncfgr | IFC_NAND_SRAM_INIT_EN);
+
+		/* wait for  SRAM_INIT bit to be clear or timeout */
+		time_start = get_time_ns();
+		while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
+			ifc_ctrl->nand_stat =
+				ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
+
+			if (!(ifc_ctrl->nand_stat & IFC_NAND_SRAM_INIT_EN))
+				return 0;
+		}
+		pr_err("fsl-ifc: Failed to Initialise SRAM\n");
+		return 1;
+	}
+
+	cs = priv->cs;
+	/* Save CSOR and CSOR_ext */
+	csor = get_ifc_csor(ctrl->gregs, cs);
+	csor_ext = get_ifc_csor_ext(ctrl->gregs, cs);
+
+	/* change PageSize 8K and SpareSize 1K*/
+	csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
+	set_ifc_csor(ctrl->gregs, cs, csor_8k);
+	set_ifc_csor_ext(ctrl->gregs, cs, 0x0000400);
+
+	/* READID */
+	ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+		  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+		  (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+		  (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+	ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+		  NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+	ifc_out32(ctrl->rregs + FSL_IFC_ROW3, 0x0);
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0x0);
+
+	/* Program ROW0/COL0 */
+	ifc_out32(ctrl->rregs + FSL_IFC_ROW0, 0x0);
+	ifc_out32(ctrl->rregs + FSL_IFC_COL0, 0x0);
+
+	/* set the chip select for NAND Transaction */
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_CSEL,
+			priv->cs << IFC_NAND_CSEL_SHIFT);
+
+	/* start read seq */
+	ifc_out32(ctrl->rregs + FSL_IFC_NANDSEQ_STRT,
+			IFC_NAND_SEQ_STRT_FIR_STRT);
+
+	time_start = get_time_ns();
+	while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
+		ifc_ctrl->nand_stat =
+			ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
+
+		if (ifc_ctrl->nand_stat & IFC_NAND_EVTER_STAT_OPC)
+			break;
+	}
+
+	if (ifc_ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) {
+		pr_err("fsl-ifc: Failed to Initialise SRAM\n");
+		return 1;
+	}
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT, ifc_ctrl->nand_stat);
+
+	/* Restore CSOR and CSOR_ext */
+	set_ifc_csor(ctrl->gregs, priv->cs, csor);
+	set_ifc_csor_ext(ctrl->gregs, priv->cs, csor_ext);
+
+	return 0;
+}
+
+static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
+{
+	struct fsl_ifc_ctrl *ctrl;
+	struct nand_chip *nand = &priv->chip;
+	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
+	uint32_t cspr = 0, csor = 0;
+	int ret = 0;
+
+	if (!ifc_ctrl) {
+		fsl_ifc_ctrl_init();
+		if (!ifc_ctrl)
+			return -ENOMEM;
+	}
+	ctrl = priv->ctrl = ifc_ctrl;
+
+	if (priv->dev->device_node) {
+		int bank, banks;
+
+		 /* find which chip select it is connected to */
+		banks = (ctrl->version == FSL_IFC_V1_1_0) ? 4 : 8;
+		for (bank = 0; bank < banks; bank++) {
+			if (match_bank(ifc_ctrl, bank, priv->pbase))
+				break;
+		}
+		priv->cs = bank;
+		if (bank >= banks) {
+			pr_err("%s: address did not match any chip selects\n",
+				__func__);
+			return -ENODEV;
+		}
+	}
+
+	/*mtd->priv = nand; */
+	mtd->dev.parent = priv->dev;
+
+	/*
+	 * Fill in nand_chip structure
+	 * set up function call table
+	 */
+	nand->legacy.write_buf = fsl_ifc_write_buf;
+	nand->legacy.read_buf = fsl_ifc_read_buf;
+	nand->legacy.select_chip = fsl_ifc_select_chip;
+	nand->legacy.cmdfunc = fsl_ifc_cmdfunc;
+	nand->legacy.waitfunc = fsl_ifc_wait;
+
+	/* set up nand options */
+	nand->bbt_td = &bbt_main_descr;
+	nand->bbt_md = &bbt_mirror_descr;
+
+	/* set up nand options */
+	nand->options = NAND_NO_SUBPAGE_WRITE;
+	nand->bbt_options = NAND_BBT_USE_FLASH;
+
+	cspr = get_ifc_cspr(ctrl->gregs, priv->cs);
+	csor = get_ifc_csor(ctrl->gregs, priv->cs);
+
+	if (cspr & CSPR_PORT_SIZE_16) {
+		nand->legacy.read_byte = fsl_ifc_read_byte16;
+		nand->options |= NAND_BUSWIDTH_16;
+	} else {
+		nand->legacy.read_byte = fsl_ifc_read_byte;
+	}
+
+	nand->controller = &ifc_ctrl->controller;
+	nand->priv = priv;
+
+	nand->ecc.read_page = fsl_ifc_read_page;
+	nand->ecc.write_page = fsl_ifc_write_page;
+
+	/* Hardware generates ECC per 512 Bytes */
+	nand->ecc.size = 512;
+	nand->ecc.bytes = 8;
+
+	nand->legacy.chip_delay = 30;
+
+	switch (csor & CSOR_NAND_PGS_MASK) {
+	case CSOR_NAND_PGS_512:
+		if (!(nand->options & NAND_BUSWIDTH_16)) {
+			/* Avoid conflict with bad block marker */
+			bbt_main_descr.offs = 0;
+			bbt_mirror_descr.offs = 0;
+		}
+
+		nand->ecc.strength = 4;
+		priv->bufnum_mask = 15;
+		break;
+
+	case CSOR_NAND_PGS_2K:
+		nand->ecc.strength = 4;
+		priv->bufnum_mask = 3;
+		break;
+
+	case CSOR_NAND_PGS_4K:
+		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+		    CSOR_NAND_ECC_MODE_4) {
+			nand->ecc.strength = 4;
+		} else {
+			nand->ecc.strength = 8;
+			nand->ecc.bytes = 16;
+		}
+
+		priv->bufnum_mask = 1;
+		break;
+
+	case CSOR_NAND_PGS_8K:
+		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+		    CSOR_NAND_ECC_MODE_4) {
+			nand->ecc.strength = 4;
+		} else {
+			nand->ecc.strength = 8;
+			nand->ecc.bytes = 16;
+		}
+
+		priv->bufnum_mask = 0;
+		break;
+
+
+	default:
+		pr_err("ifc nand: bad csor %#x: bad page size\n", csor);
+		return -ENODEV;
+	}
+
+	/* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
+	if (csor & CSOR_NAND_ECC_DEC_EN) {
+		nand->ecc.mode = NAND_ECC_HW;
+		mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops);
+	} else {
+		nand->ecc.mode = NAND_ECC_SOFT;
+		nand->ecc.algo = NAND_ECC_HAMMING;
+	}
+
+	if (ctrl->version >= FSL_IFC_V1_1_0) {
+		ret = fsl_ifc_sram_init(priv, ctrl->version);
+		if (ret)
+			return ret;
+	}
+
+	if (ctrl->version >= FSL_IFC_V2_0_0)
+		priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
+
+	return 0;
+}
+
+static int fsl_ifc_nand_probe(struct device_d *dev)
+{
+	struct fsl_ifc_mtd *priv;
+	struct resource *iores;
+	struct mtd_info *mtd;
+	int ret = 0;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores)) {
+		ret = -ENOMEM;
+		goto bailout;
+	}
+	priv->pbase = iores->start;
+	priv->vbase = IOMEM(iores->start);
+
+	if (fsl_ifc_chip_init(priv)) {
+		ret = -ENOMEM;
+		goto bailout;
+	}
+
+	ret = nand_scan_ident(&priv->chip, 1, NULL);
+	if (ret)
+		goto bailout;
+
+	ret = nand_scan_tail(&priv->chip);
+	if (ret)
+		goto bailout;
+
+	mtd = nand_to_mtd(&priv->chip);
+	return add_mtd_nand_device(mtd, "nand");
+bailout:
+	kfree(priv);
+	return ret;
+}
+
+static __maybe_unused struct of_device_id fsl_nand_compatible[] = {
+	{
+		.compatible = "fsl,ifc-nand",
+	}, {
+	}
+};
+
+static struct driver_d fsl_ifc_driver = {
+	.name = "fsl_nand",
+	.probe = fsl_ifc_nand_probe,
+	.of_compatible = DRV_OF_COMPAT(fsl_nand_compatible),
+};
+device_platform_driver(fsl_ifc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FSL IFC NAND driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h
new file mode 100644
index 0000000000..2ff0626357
--- /dev/null
+++ b/include/linux/fsl_ifc.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later  */
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat at freescale.com>
+ *
+ */
+
+#ifndef __FSL_IFC_H
+#define __FSL_IFC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/log2.h>
+
+/* Big-Endian */
+#define ifc_in32(a)			ioread32be(a)
+#define ifc_out32(a, v)			iowrite32be(v, a)
+#define ifc_in16(a)			ioread16be(a)
+#define ifc_out16(a, v)			iowrite16be(v, a)
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+#define CSPR_BA				0xFFFF0000
+#define CSPR_BA_SHIFT			16
+#define CSPR_PORT_SIZE			0x00000180
+#define CSPR_PORT_SIZE_SHIFT		7
+#define CSPR_PORT_SIZE_8		0x00000080
+#define CSPR_PORT_SIZE_16		0x00000100
+#define CSPR_PORT_SIZE_32		0x00000180
+/* Write Protect */
+#define CSPR_WP				0x00000040
+#define CSPR_WP_SHIFT			6
+#define CSPR_MSEL			0x00000006
+#define CSPR_MSEL_SHIFT			1
+#define CSPR_MSEL_NOR			0x00000000
+#define CSPR_MSEL_NAND			0x00000002
+#define CSPR_MSEL_GPCM			0x00000004
+#define CSPR_V				0x00000001
+#define CSPR_V_SHIFT			0
+
+/* Convert an address into the right format for the CSPR Registers */
+#define CSPR_PHYS_ADDR(x)		(((uint64_t)x) & 0xffff0000)
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK			0xFFFF0000
+#define IFC_AMASK_SHIFT			16
+#define IFC_AMASK(n)			(IFC_AMASK_MASK << \
+					(ilog2(n) - IFC_AMASK_SHIFT))
+
+/*
+ * Chip Select Option Register IFC_NAND Machine
+ */
+#define CSOR_NAND_ECC_ENC_EN		0x80000000
+#define CSOR_NAND_ECC_MODE_MASK		0x30000000
+/* 4 bit correction per 520 Byte sector */
+#define CSOR_NAND_ECC_MODE_4		0x00000000
+/* 8 bit correction per 528 Byte sector */
+#define CSOR_NAND_ECC_MODE_8		0x10000000
+#define CSOR_NAND_ECC_DEC_EN		0x04000000
+/* Row Address Length */
+#define CSOR_NAND_RAL_MASK		0x01800000
+#define CSOR_NAND_RAL_SHIFT		20
+#define CSOR_NAND_RAL_1			0x00000000
+#define CSOR_NAND_RAL_2			0x00800000
+#define CSOR_NAND_RAL_3			0x01000000
+#define CSOR_NAND_RAL_4			0x01800000
+/* Page Size 512b, 2k, 4k */
+#define CSOR_NAND_PGS_MASK		0x00180000
+#define CSOR_NAND_PGS_SHIFT		16
+#define CSOR_NAND_PGS_512		0x00000000
+#define CSOR_NAND_PGS_2K		0x00080000
+#define CSOR_NAND_PGS_4K		0x00100000
+#define CSOR_NAND_PGS_8K		0x00180000
+/* Spare region Size */
+#define CSOR_NAND_SPRZ_MASK		0x0000E000
+#define CSOR_NAND_SPRZ_SHIFT		13
+#define CSOR_NAND_SPRZ_16		0x00000000
+#define CSOR_NAND_SPRZ_64		0x00002000
+#define CSOR_NAND_SPRZ_128		0x00004000
+#define CSOR_NAND_SPRZ_210		0x00006000
+#define CSOR_NAND_SPRZ_218		0x00008000
+#define CSOR_NAND_SPRZ_224		0x0000A000
+#define CSOR_NAND_SPRZ_CSOR_EXT	0x0000C000
+/* Pages Per Block */
+#define CSOR_NAND_PB_MASK		0x00000700
+#define CSOR_NAND_PB_SHIFT		8
+#define CSOR_NAND_PB(n)			((ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NAND_TRHZ_MASK		0x0000001C
+#define CSOR_NAND_TRHZ_SHIFT		2
+#define CSOR_NAND_TRHZ_20		0x00000000
+#define CSOR_NAND_TRHZ_40		0x00000004
+#define CSOR_NAND_TRHZ_60		0x00000008
+#define CSOR_NAND_TRHZ_80		0x0000000C
+#define CSOR_NAND_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_NAND_BCTLD			0x00000001
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+/* Enable Address shift Mode */
+#define CSOR_NOR_ADM_SHFT_MODE_EN	0x80000000
+/* Page Read Enable from NOR device */
+#define CSOR_NOR_PGRD_EN		0x10000000
+/* AVD Toggle Enable during Burst Program */
+#define CSOR_NOR_AVD_TGL_PGM_EN		0x01000000
+/* Address Data Multiplexing Shift */
+#define CSOR_NOR_ADM_MASK		0x0003E000
+#define CSOR_NOR_ADM_SHIFT_SHIFT	13
+#define CSOR_NOR_ADM_SHIFT(n)	((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
+/* Type of the NOR device hooked */
+#define CSOR_NOR_NOR_MODE_ASYNC_NOR	0x00000000
+#define CSOR_NOR_NOR_MODE_AVD_NOR	0x00000020
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NOR_TRHZ_MASK		0x0000001C
+#define CSOR_NOR_TRHZ_SHIFT		2
+#define CSOR_NOR_TRHZ_20		0x00000000
+#define CSOR_NOR_TRHZ_40		0x00000004
+#define CSOR_NOR_TRHZ_60		0x00000008
+#define CSOR_NOR_TRHZ_80		0x0000000C
+#define CSOR_NOR_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_NOR_BCTLD			0x00000001
+
+/*
+ * Flash Timing Registers (FTIM0 - FTIM2_CSn)
+ */
+/*
+ * FTIM0 - NAND Flash Mode
+ */
+#define FTIM0_NAND			0x7EFF3F3F
+#define FTIM0_NAND_TCCST_SHIFT		25
+#define FTIM0_NAND_TCCST(n)		((n) << FTIM0_NAND_TCCST_SHIFT)
+#define FTIM0_NAND_TWP_SHIFT	16
+#define FTIM0_NAND_TWP(n)	((n) << FTIM0_NAND_TWP_SHIFT)
+#define FTIM0_NAND_TWCHT_SHIFT	8
+#define FTIM0_NAND_TWCHT(n)	((n) << FTIM0_NAND_TWCHT_SHIFT)
+#define FTIM0_NAND_TWH_SHIFT	0
+#define FTIM0_NAND_TWH(n)	((n) << FTIM0_NAND_TWH_SHIFT)
+/*
+ * FTIM1 - NAND Flash Mode
+ */
+#define FTIM1_NAND			0xFFFF3FFF
+#define FTIM1_NAND_TADLE_SHIFT	24
+#define FTIM1_NAND_TADLE(n)	((n) << FTIM1_NAND_TADLE_SHIFT)
+#define FTIM1_NAND_TWBE_SHIFT	16
+#define FTIM1_NAND_TWBE(n)	((n) << FTIM1_NAND_TWBE_SHIFT)
+#define FTIM1_NAND_TRR_SHIFT	8
+#define FTIM1_NAND_TRR(n)	((n) << FTIM1_NAND_TRR_SHIFT)
+#define FTIM1_NAND_TRP_SHIFT	0
+#define FTIM1_NAND_TRP(n)	((n) << FTIM1_NAND_TRP_SHIFT)
+/*
+ * FTIM2 - NAND Flash Mode
+ */
+#define FTIM2_NAND			0x1FE1F8FF
+#define FTIM2_NAND_TRAD_SHIFT	21
+#define FTIM2_NAND_TRAD(n)	((n) << FTIM2_NAND_TRAD_SHIFT)
+#define FTIM2_NAND_TREH_SHIFT	11
+#define FTIM2_NAND_TREH(n)	((n) << FTIM2_NAND_TREH_SHIFT)
+#define FTIM2_NAND_TWHRE_SHIFT	0
+#define FTIM2_NAND_TWHRE(n)	((n) << FTIM2_NAND_TWHRE_SHIFT)
+/*
+ * FTIM0 - NOR Flash Mode
+ */
+#define FTIM0_NOR			0xF03F3F3F
+#define FTIM0_NOR_TACSE_SHIFT		28
+#define FTIM0_NOR_TACSE(n)		((n) << FTIM0_NOR_TACSE_SHIFT)
+#define FTIM0_NOR_TEADC_SHIFT		16
+#define FTIM0_NOR_TEADC(n)		((n) << FTIM0_NOR_TEADC_SHIFT)
+#define FTIM0_NOR_TAVDS_SHIFT		8
+#define FTIM0_NOR_TAVDS(n)		((n) << FTIM0_NOR_TAVDS_SHIFT)
+#define FTIM0_NOR_TEAHC_SHIFT		0
+#define FTIM0_NOR_TEAHC(n)		((n) << FTIM0_NOR_TEAHC_SHIFT)
+/*
+ * FTIM1 - NOR Flash Mode
+ */
+#define FTIM1_NOR			0xFF003F3F
+#define FTIM1_NOR_TACO_SHIFT		24
+#define FTIM1_NOR_TACO(n)		((n) << FTIM1_NOR_TACO_SHIFT)
+#define FTIM1_NOR_TRAD_NOR_SHIFT	8
+#define FTIM1_NOR_TRAD_NOR(n)		((n) << FTIM1_NOR_TRAD_NOR_SHIFT)
+#define FTIM1_NOR_TSEQRAD_NOR_SHIFT	0
+#define FTIM1_NOR_TSEQRAD_NOR(n)	((n) << FTIM1_NOR_TSEQRAD_NOR_SHIFT)
+/*
+ * FTIM2 - NOR Flash Mode
+ */
+#define FTIM2_NOR			0x0F3CFCFF
+#define FTIM2_NOR_TCS_SHIFT		24
+#define FTIM2_NOR_TCS(n)		((n) << FTIM2_NOR_TCS_SHIFT)
+#define FTIM2_NOR_TCH_SHIFT		18
+#define FTIM2_NOR_TCH(n)		((n) << FTIM2_NOR_TCH_SHIFT)
+#define FTIM2_NOR_TWPH_SHIFT		10
+#define FTIM2_NOR_TWPH(n)		((n) << FTIM2_NOR_TWPH_SHIFT)
+#define FTIM2_NOR_TWP_SHIFT		0
+#define FTIM2_NOR_TWP(n)		((n) << FTIM2_NOR_TWP_SHIFT)
+
+/*
+ * FTIM0 - Normal GPCM Mode
+ */
+#define FTIM0_GPCM			0xF03F3F3F
+#define FTIM0_GPCM_TACSE_SHIFT		28
+#define FTIM0_GPCM_TACSE(n)		((n) << FTIM0_GPCM_TACSE_SHIFT)
+#define FTIM0_GPCM_TEADC_SHIFT		16
+#define FTIM0_GPCM_TEADC(n)		((n) << FTIM0_GPCM_TEADC_SHIFT)
+#define FTIM0_GPCM_TAVDS_SHIFT		8
+#define FTIM0_GPCM_TAVDS(n)		((n) << FTIM0_GPCM_TAVDS_SHIFT)
+#define FTIM0_GPCM_TEAHC_SHIFT		0
+#define FTIM0_GPCM_TEAHC(n)		((n) << FTIM0_GPCM_TEAHC_SHIFT)
+/*
+ * FTIM1 - Normal GPCM Mode
+ */
+#define FTIM1_GPCM			0xFF003F00
+#define FTIM1_GPCM_TACO_SHIFT		24
+#define FTIM1_GPCM_TACO(n)		((n) << FTIM1_GPCM_TACO_SHIFT)
+#define FTIM1_GPCM_TRAD_SHIFT		8
+#define FTIM1_GPCM_TRAD(n)		((n) << FTIM1_GPCM_TRAD_SHIFT)
+/*
+ * FTIM2 - Normal GPCM Mode
+ */
+#define FTIM2_GPCM			0x0F3C00FF
+#define FTIM2_GPCM_TCS_SHIFT		24
+#define FTIM2_GPCM_TCS(n)		((n) << FTIM2_GPCM_TCS_SHIFT)
+#define FTIM2_GPCM_TCH_SHIFT		18
+#define FTIM2_GPCM_TCH(n)		((n) << FTIM2_GPCM_TCH_SHIFT)
+#define FTIM2_GPCM_TWP_SHIFT		0
+#define FTIM2_GPCM_TWP(n)		((n) << FTIM2_GPCM_TWP_SHIFT)
+
+/*
+ * General Control Register (GCR)
+ */
+#define IFC_GCR_MASK			0x8000F800
+/* reset all IFC hardware */
+#define IFC_GCR_SOFT_RST_ALL		0x80000000
+/* Turnaroud Time of external buffer */
+#define IFC_GCR_TBCTL_TRN_TIME		0x0000F800
+#define IFC_GCR_TBCTL_TRN_TIME_SHIFT	11
+
+/*
+ * Clock Control Register (CCR)
+ */
+#define IFC_CCR_MASK			0x0F0F8800
+/* Clock division ratio */
+#define IFC_CCR_CLK_DIV_MASK		0x0F000000
+#define IFC_CCR_CLK_DIV_SHIFT		24
+#define IFC_CCR_CLK_DIV(n)		((n-1) << IFC_CCR_CLK_DIV_SHIFT)
+/* IFC Clock Delay */
+#define IFC_CCR_CLK_DLY_MASK		0x000F0000
+#define IFC_CCR_CLK_DLY_SHIFT		16
+#define IFC_CCR_CLK_DLY(n)		((n) << IFC_CCR_CLK_DLY_SHIFT)
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+#define FSL_IFC_CSPRX(i)	(0x10 + ((i) * 0xc))
+#define FSL_IFC_CSORX(i)	(0x130 + ((i) * 0xc))
+#define FSL_IFC_CSORX_EXT(i)	(0x134 + ((i) * 0xc))
+#define FSL_IFC_AMASKX(i)	(0xa0 + ((i) * 0xc))
+#define FSL_IFC_CSX_FTIMY(i, j)	((0x1c0 + ((i) * 0x30)) + ((j) * 4))
+
+#define get_ifc_cspr(base, i) (ifc_in32(base + FSL_IFC_CSPRX(i)))
+#define get_ifc_csor(base, i) (ifc_in32(base + FSL_IFC_CSORX(i)))
+#define get_ifc_csor_ext(base, i) (ifc_in32(base + FSL_IFC_CSORX_EXT(i)))
+#define get_ifc_amask(base, i) (ifc_in32(base + FSL_IFC_AMASKX(i)))
+#define get_ifc_ftim(base, i, j) (ifc_in32(base + FSL_IFC_CSX_FTIMY(i, j)))
+
+#define set_ifc_cspr(base, i, v) (ifc_out32(base + FSL_IFC_CSPRX(i), v))
+#define set_ifc_csor(base, i, v) (ifc_out32(base + FSL_IFC_CSORX(i), v))
+#define set_ifc_csor_ext(base, i, v) (ifc_out32(base + FSL_IFC_CSORX_EXT(i),\
+				v))
+#define set_ifc_amask(base, i, v) (ifc_out32(base + FSL_IFC_AMASKX(i), v))
+#define set_ifc_ftim(base, i, j, v) \
+			(ifc_out32(base + FSL_IFC_CSX_FTIMY(i, j), v))
+
+#define FSL_IFC_GCR_OFFSET	0x40c
+#define FSL_IFC_CCR_OFFSET	0x44c
+
+enum ifc_chip_sel {
+	IFC_CS0,
+	IFC_CS1,
+	IFC_CS2,
+	IFC_CS3,
+	IFC_CS4,
+	IFC_CS5,
+	IFC_CS6,
+	IFC_CS7,
+};
+
+enum ifc_ftims {
+	IFC_FTIM0,
+	IFC_FTIM1,
+	IFC_FTIM2,
+	IFC_FTIM3,
+};
+
+#ifdef CONFIG_FSL_ERRATUM_IFC_A002769
+#undef CSPR_MSEL_NOR
+#define CSPR_MSEL_NOR	CSPR_MSEL_GPCM
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __FSL_IFC_H */
-- 
2.27.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:10 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:10 +0200
Subject: [PATCH v2 0/8] XN Support for reserved-memory areas
Message-ID: <20210803094418.475609-1-r.czerwinski@pengutronix.de>

This is v2 of a series to properly handle reserved memory areas with the
no-map property. This allows us to early load OP-TEE, while also
prohibiting the CPU from speculating into the OP-TEE area by mapping the
OP-TEE area as uncached and eXecute Never. We also parse the device tree
reserved memory areas from the DT passed into barebox proper, to also
remove no-map entries from the MMU there.

Rouven Czerwinski (8):
  of: reserve: add xn flag mem entries
  of: add of_get_reserve_map stub for !CONFIG_OFTREE
  ARM: mmu: use reserve mem entries to modify maps
  of: add flag to not create resmem DT entries
  of: add reserved_mem_read initcall
  pbl: fdt: add support to parse reserved mem
  ARM: mmu-early: map no-map entries XN & uncached
  PBL: enable LIBFDT for OP-TEE early loading

 arch/arm/cpu/mmu-early.c       |  13 +++++
 arch/arm/cpu/mmu.c             |  34 ++++++++++-
 arch/arm/cpu/sm.c              |   2 +-
 arch/arm/cpu/start.c           |   2 +-
 arch/arm/mach-layerscape/ppa.c |   2 +-
 common/Kconfig                 |   1 +
 common/bootm.c                 |   3 +-
 drivers/of/Makefile            |   1 +
 drivers/of/fdt.c               |  16 +++--
 drivers/of/reserved-mem.c      |  43 ++++++++++++++
 drivers/video/fb.c             |   3 +-
 drivers/video/simplefb-fixup.c |   2 +-
 fs/pstore/ram.c                |   3 +-
 include/of.h                   |  14 ++++-
 include/pbl.h                  |  25 ++++++++
 pbl/fdt.c                      | 103 ++++++++++++++++++++++++++++-----
 16 files changed, 237 insertions(+), 30 deletions(-)
 create mode 100644 drivers/of/reserved-mem.c

-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:12 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:12 +0200
Subject: [PATCH v2 2/8] of: add of_get_reserve_map stub for !CONFIG_OFTREE
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-3-r.czerwinski@pengutronix.de>

This allows us to unconditionally include of.h in files which did not
require CONFIG_OFTREE, required for the MMU code in later patches.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 include/of.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/of.h b/include/of.h
index 4844e800b4..36936ecd6e 100644
--- a/include/of.h
+++ b/include/of.h
@@ -62,7 +62,6 @@ struct of_reserve_map {
 
 int of_add_reserve_entry(resource_size_t start, resource_size_t end,
 		 int flags);
-struct of_reserve_map *of_get_reserve_map(void);
 void of_clean_reserve_map(void);
 void fdt_add_reserve_map(void *fdt);
 
@@ -120,6 +119,7 @@ struct device_node *of_unflatten_dtb_const(const void *infdt, int size);
 struct cdev;
 
 #ifdef CONFIG_OFTREE
+struct of_reserve_map *of_get_reserve_map(void);
 extern int of_bus_n_addr_cells(struct device_node *np);
 extern int of_n_addr_cells(struct device_node *np);
 extern int of_bus_n_size_cells(struct device_node *np);
@@ -821,6 +821,10 @@ static inline int of_autoenable_i2c_by_component(char *path)
 	return -ENODEV;
 }
 
+static inline struct of_reserve_map *of_get_reserve_map(void)
+{
+	return NULL;
+}
 
 #endif
 
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:13 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:13 +0200
Subject: [PATCH v2 3/8] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-4-r.czerwinski@pengutronix.de>

Use the information from the reserved memory entries to modify the
mapping of memory regions to mark them as uncachable and not-executable.
This also prevents the processor from speculating into these regions,
preventing hard to debug scenarios where boots fail for unknown reasons.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 arch/arm/cpu/mmu.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 6388e1bf14..73f4cf5b36 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -17,6 +17,7 @@
 #include <memory.h>
 #include <asm/system_info.h>
 #include <asm/sections.h>
+#include <of.h>
 
 #include "mmu.h"
 
@@ -407,6 +408,36 @@ static void vectors_init(void)
 	create_vector_table(ARM_LOW_VECTORS);
 }
 
+static void create_sections_with_intersect(struct memory_bank *bank)
+{
+	struct of_reserve_map *res_map;
+	unsigned long j_end;
+	unsigned long end;
+	unsigned long j;
+	u32 pmd_flags;
+	int i;
+
+	res_map = of_get_reserve_map();
+	if (!res_map)
+		return;
+
+	end = bank->start + bank->size - 1;
+
+	for (j = bank->start; j < end; j += PGDIR_SIZE) {
+		pmd_flags = PMD_SECT_DEF_CACHED;
+		j_end = j + PGDIR_SIZE - 1;
+
+		for (i = 0; i < res_map->num_entries; i++) {
+			if ((BIT(i) & res_map->xn) &&
+			    j_end >= res_map->start[i] &&
+			    j_end <= res_map->end[i])
+				pmd_flags = PMD_SECT_DEF_UNCACHED | PMD_SECT_XN;
+		}
+
+		create_sections(ttb, j, j_end, pmd_flags);
+	}
+}
+
 /*
  * Prepare MMU for usage enable it.
  */
@@ -468,8 +499,7 @@ void __mmu_init(bool mmu_on)
 	vectors_init();
 
 	for_each_memory_bank(bank) {
-		create_sections(ttb, bank->start, bank->start + bank->size - 1,
-				PMD_SECT_DEF_CACHED);
+		create_sections_with_intersect(bank);
 		__mmu_cache_flush();
 	}
 
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:11 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:11 +0200
Subject: [PATCH v2 1/8] of: reserve: add xn flag mem entries
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-2-r.czerwinski@pengutronix.de>

If the OF_RESERVE_ENTRY_FLAG_XN flag is passed while creating the
entry, a subsequent commit will use this information in the mmu to map
the area as non-executable.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 arch/arm/cpu/sm.c              | 2 +-
 arch/arm/cpu/start.c           | 2 +-
 arch/arm/mach-layerscape/ppa.c | 2 +-
 common/bootm.c                 | 3 ++-
 drivers/of/fdt.c               | 6 +++++-
 drivers/video/fb.c             | 3 ++-
 drivers/video/simplefb-fixup.c | 2 +-
 fs/pstore/ram.c                | 3 ++-
 include/of.h                   | 6 +++++-
 9 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/arch/arm/cpu/sm.c b/arch/arm/cpu/sm.c
index f5a1edbd4f..ebd5f76e14 100644
--- a/arch/arm/cpu/sm.c
+++ b/arch/arm/cpu/sm.c
@@ -203,7 +203,7 @@ static int of_secure_monitor_fixup(struct device_node *root, void *unused)
 	res_start = (unsigned long)_stext;
 	res_end = (unsigned long)__bss_stop;
 
-	of_add_reserve_entry(res_start, res_end);
+	of_add_reserve_entry(res_start, res_end, 0);
 
 	pr_debug("Reserved memory range from 0x%08lx to 0x%08lx\n", res_start, res_end);
 
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index c61db66865..10ac070fe3 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -227,7 +227,7 @@ __noreturn __no_sanitize_address void barebox_non_pbl_start(unsigned long membas
 	mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1);
 
 	if (IS_ENABLED(CONFIG_BOOTM_OPTEE))
-		of_add_reserve_entry(endmem - OPTEE_SIZE, endmem - 1);
+		of_add_reserve_entry(endmem - OPTEE_SIZE, endmem - 1, OF_RESERVE_ENTRY_FLAG_XN);
 
 	pr_debug("starting barebox...\n");
 
diff --git a/arch/arm/mach-layerscape/ppa.c b/arch/arm/mach-layerscape/ppa.c
index d962fba751..6e61766e54 100644
--- a/arch/arm/mach-layerscape/ppa.c
+++ b/arch/arm/mach-layerscape/ppa.c
@@ -130,7 +130,7 @@ int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size)
 	if (ret)
 		return ret;
 
-	of_add_reserve_entry(ppa_start, ppa_end);
+	of_add_reserve_entry(ppa_start, ppa_end, 0);
 
 	return 0;
 }
diff --git a/common/bootm.c b/common/bootm.c
index 89e3e93f2c..82f07b5139 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -411,7 +411,8 @@ void *bootm_get_devicetree(struct image_data *data)
 	if (data->initrd_res) {
 		of_add_initrd(data->of_root_node, data->initrd_res->start,
 				data->initrd_res->end);
-		of_add_reserve_entry(data->initrd_res->start, data->initrd_res->end);
+		of_add_reserve_entry(data->initrd_res->start,
+				     data->initrd_res->end, 0);
 	}
 
 	oftree = of_get_fixed_tree(data->of_root_node);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index f72f5e3a30..9356a92c5c 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -544,7 +544,8 @@ out_free:
 
 static struct of_reserve_map of_reserve_map;
 
-int of_add_reserve_entry(resource_size_t start, resource_size_t end)
+int of_add_reserve_entry(resource_size_t start, resource_size_t end,
+			 int flags)
 {
 	int e = of_reserve_map.num_entries;
 
@@ -555,6 +556,9 @@ int of_add_reserve_entry(resource_size_t start, resource_size_t end)
 	of_reserve_map.end[e] = end;
 	of_reserve_map.num_entries++;
 
+	if (flags & OF_RESERVE_ENTRY_FLAG_XN)
+		of_reserve_map.xn |= BIT(e);
+
 	return 0;
 }
 
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 113c1419a1..8aa4a77ef3 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -202,7 +202,8 @@ static int fb_of_reserve_fixup(struct device_node *root, void *context)
 		return 0;
 
 	of_add_reserve_entry((unsigned long)info->screen_base,
-			(unsigned long)info->screen_base + info->screen_size);
+			(unsigned long)info->screen_base + info->screen_size,
+			0);
 
 	return 0;
 }
diff --git a/drivers/video/simplefb-fixup.c b/drivers/video/simplefb-fixup.c
index a2c59de364..af7554d10f 100644
--- a/drivers/video/simplefb-fixup.c
+++ b/drivers/video/simplefb-fixup.c
@@ -131,7 +131,7 @@ static int simplefb_create_node(struct device_node *root,
 		return ret;
 
 	of_add_reserve_entry((u32)fbi->screen_base,
-			(u32)fbi->screen_base + fbi->screen_size);
+			(u32)fbi->screen_base + fbi->screen_size, 0);
 
 	return of_property_write_string(node, "status", "okay");
 }
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 958f46b0ea..e404187c83 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -639,7 +639,8 @@ static int ramoops_probe(struct device_d *dev)
 			  ramoops_ecc);
 		globalvar_add_simple("linux.bootargs.ramoops", kernelargs);
 	} else {
-		of_add_reserve_entry(cxt->phys_addr, cxt->phys_addr + mem_size);
+		of_add_reserve_entry(cxt->phys_addr, cxt->phys_addr + mem_size,
+				0);
 		of_register_fixup(ramoops_of_fixup, pdata);
 	}
 
diff --git a/include/of.h b/include/of.h
index f9c2b283de..4844e800b4 100644
--- a/include/of.h
+++ b/include/of.h
@@ -55,9 +55,13 @@ struct of_reserve_map {
 	uint64_t start[OF_MAX_RESERVE_MAP];
 	uint64_t end[OF_MAX_RESERVE_MAP];
 	int num_entries;
+	u16 xn;
 };
 
-int of_add_reserve_entry(resource_size_t start, resource_size_t end);
+#define OF_RESERVE_ENTRY_FLAG_XN		BIT(0)
+
+int of_add_reserve_entry(resource_size_t start, resource_size_t end,
+		 int flags);
 struct of_reserve_map *of_get_reserve_map(void);
 void of_clean_reserve_map(void);
 void fdt_add_reserve_map(void *fdt);
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:14 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:14 +0200
Subject: [PATCH v2 4/8] of: add flag to not create resmem DT entries
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-5-r.czerwinski@pengutronix.de>

If we are parsing entries from the /reserved-memory device tree path we
don't want to add them again as resmem blocks at the beginning of the
device tree. Therefore add another flag to indicate this.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 drivers/of/fdt.c | 10 +++++++---
 include/of.h     |  2 ++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 9356a92c5c..030f1233d5 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -559,6 +559,9 @@ int of_add_reserve_entry(resource_size_t start, resource_size_t end,
 	if (flags & OF_RESERVE_ENTRY_FLAG_XN)
 		of_reserve_map.xn |= BIT(e);
 
+	if (flags & OF_RESERVE_ENTRY_FLAG_NO_RESERVE)
+		of_reserve_map.noentry |= BIT(e);
+
 	return 0;
 }
 
@@ -601,9 +604,10 @@ void fdt_add_reserve_map(void *__fdt)
 	fdt_res += n;
 
 	for (i = 0; i < res->num_entries; i++) {
-		of_write_number(&fdt_res->address, res->start[i], 2);
-		of_write_number(&fdt_res->size, res->end[i] - res->start[i] + 1,
-				2);
+		if (!(res->noentry & BIT(i))) {
+			of_write_number(&fdt_res->address, res->start[i], 2);
+			of_write_number(&fdt_res->size, res->end[i] - res->start[i] + 1, 2);
+		}
 		fdt_res++;
 	}
 
diff --git a/include/of.h b/include/of.h
index 36936ecd6e..209d2898ae 100644
--- a/include/of.h
+++ b/include/of.h
@@ -56,9 +56,11 @@ struct of_reserve_map {
 	uint64_t end[OF_MAX_RESERVE_MAP];
 	int num_entries;
 	u16 xn;
+	u16 reserved_entry;
 };
 
 #define OF_RESERVE_ENTRY_FLAG_XN		BIT(0)
+#define OF_RESERVE_ENTRY_FLAG_NO_RESERVE	BIT(1)
 
 int of_add_reserve_entry(resource_size_t start, resource_size_t end,
 		 int flags);
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:15 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:15 +0200
Subject: [PATCH v2 5/8] of: add reserved_mem_read initcall
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-6-r.czerwinski@pengutronix.de>

Add a reserved_mem_read initcall which parses the reserved-memory
entries and adds barebox of reserve entries. Also remove the OP-TEE size
of reserve entry, since this is now parsed from the DT and does not need
to be statically configured any longer.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 drivers/of/Makefile       |  1 +
 drivers/of/reserved-mem.c | 43 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)
 create mode 100644 drivers/of/reserved-mem.c

diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index b6847752d2..b69cb84b99 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_OF_GPIO) += of_gpio.o
 obj-$(CONFIG_OF_PCI) += of_pci.o
 obj-y += partition.o
 obj-y += of_net.o
+obj-$(CONFIG_OFDEVICE) += reserved-mem.o
 obj-$(CONFIG_MTD) += of_mtd.o
 obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
 obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
diff --git a/drivers/of/reserved-mem.c b/drivers/of/reserved-mem.c
new file mode 100644
index 0000000000..8519a7e3dd
--- /dev/null
+++ b/drivers/of/reserved-mem.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2021 Rouven Czerwinski <r.czerwinski at pengutronix.de>, Pengutronix
+
+#define pr_fmt(fmt) "reserved-memory: " fmt
+
+#define DEBUG
+
+#include <common.h>
+#include <init.h>
+#include <of.h>
+#include <of_address.h>
+#include <malloc.h>
+#include <partition.h>
+
+static int reserved_mem_read(void)
+{
+	struct device_node *node, *child;
+	struct resource resource;
+	int flag;
+
+	node = of_find_node_by_path("/reserved-memory");
+	if (!node)
+		return 0;
+
+	for_each_child_of_node(node, child) {
+		flag = OF_RESERVE_ENTRY_FLAG_NO_RESERVE;
+
+		of_address_to_resource(child, 0, &resource);
+
+		pr_err("Res-Mem start: 0x%08x\n", resource.start);
+		pr_err("Res-Mem end: 0x%08x\n", resource.end);
+
+		if (of_find_property(child, "no-map", 0)) {
+			pr_debug("child %p: no-map\n", child);
+			flag |= OF_RESERVE_ENTRY_FLAG_XN;
+		}
+
+		of_add_reserve_entry(resource.start, resource.end, flag);
+	}
+
+	return 0;
+}
+postconsole_initcall(reserved_mem_read);
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:17 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:17 +0200
Subject: [PATCH v2 7/8] ARM: mmu-early: map no-map entries XN & uncached
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-8-r.czerwinski@pengutronix.de>

Ensure that reserved map entries with the no-map flag are marked as
uncached and non-execute during the early MMU initialization.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 arch/arm/cpu/mmu-early.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/cpu/mmu-early.c b/arch/arm/cpu/mmu-early.c
index b985aa455f..9c3f01326b 100644
--- a/arch/arm/cpu/mmu-early.c
+++ b/arch/arm/cpu/mmu-early.c
@@ -3,9 +3,11 @@
 #include <errno.h>
 #include <linux/sizes.h>
 #include <asm/memory.h>
+#include <asm-generic/memory_layout.h>
 #include <asm/system.h>
 #include <asm/cache.h>
 #include <asm-generic/sections.h>
+#include <pbl.h>
 
 #include "mmu.h"
 
@@ -24,7 +26,10 @@ static inline void map_region(unsigned long start, unsigned long size,
 void mmu_early_enable(unsigned long membase, unsigned long memsize,
 		      unsigned long _ttb)
 {
+	const struct pbl_reserved_memory *res_mem;
+	int i;
 	ttb = (uint32_t *)_ttb;
+	res_mem =  get_pbl_reserved_memory();
 
 	arm_set_cache_functions();
 
@@ -58,6 +63,14 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize,
 	/* maps main memory as cachable */
 	map_region(membase, memsize, PMD_SECT_DEF_CACHED);
 
+	for (i = 0; i < get_pbl_reserved_memory_num(); i++) {
+		if (res_mem->flags & FDT_RES_MEM_FLAG_NOMAP)
+			map_region(res_mem->base, res_mem->size,
+				   PMD_SECT_DEF_UNCACHED | PMD_SECT_XN);
+		res_mem++;
+	}
+
+
 	/*
 	 * With HAB enabled we call into the ROM code later in imx6_hab_get_status().
 	 * Map the ROM cached which has the effect that the XN bit is not set.
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:16 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:16 +0200
Subject: [PATCH v2 6/8] pbl: fdt: add support to parse reserved mem
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-7-r.czerwinski@pengutronix.de>

This allows the PBL to fill a reserved memory map which a subsequent
commit will use modify the early MMU mapping.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 include/pbl.h |  25 ++++++++++++
 pbl/fdt.c     | 103 ++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 113 insertions(+), 15 deletions(-)

diff --git a/include/pbl.h b/include/pbl.h
index f58daec735..03272879d7 100644
--- a/include/pbl.h
+++ b/include/pbl.h
@@ -42,5 +42,30 @@ struct fdt_device_id {
 const void *
 fdt_device_get_match_data(const void *fdt, const char *nodepath,
 			  const struct fdt_device_id ids[]);
+struct pbl_reserved_memory {
+	phys_addr_t			base;
+	phys_addr_t			size;
+	unsigned int			flags;
+};
+
+#define MAX_RESERVED_REGIONS	8
+
+#define FDT_RES_MEM_FLAG_NOMAP		BIT(0)
+
+void fdt_fill_reserve_mem(const void *fdt);
+
+#ifdef CONFIG_LIBFDT
+const struct pbl_reserved_memory *get_pbl_reserved_memory(void);
+int get_pbl_reserved_memory_num(void);
+#else
+static inline const struct pbl_reserved_memory *get_pbl_reserved_memory(void)
+{
+	return NULL;
+}
+static inline int get_pbl_reserved_memory_num(void)
+{
+	return 0;
+}
+#endif
 
 #endif /* __PBL_H__ */
diff --git a/pbl/fdt.c b/pbl/fdt.c
index 18ddb9f48a..383d0fec74 100644
--- a/pbl/fdt.c
+++ b/pbl/fdt.c
@@ -5,8 +5,8 @@
 
 void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsize)
 {
-	const __be32 *nap, *nsp, *reg;
-	uint32_t na, ns;
+	const __be32 *reg;
+	int na, ns;
 	uint64_t memsize64, membase64;
 	int node, size, i;
 
@@ -16,26 +16,17 @@ void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsiz
 		goto err;
 	}
 
-	/* Find the #address-cells and #size-cells properties */
-	node = fdt_path_offset(fdt, "/");
-	if (node < 0) {
-		pr_err("Cannot find root node\n");
-		goto err;
-	}
-
-	nap = fdt_getprop(fdt, node, "#address-cells", &size);
-	if (!nap || (size != 4)) {
+	na = fdt_address_cells(fdt, 0);
+	if (na < 0) {
 		pr_err("Cannot find #address-cells property");
 		goto err;
 	}
-	na = fdt32_to_cpu(*nap);
 
-	nsp = fdt_getprop(fdt, node, "#size-cells", &size);
-	if (!nsp || (size != 4)) {
+	ns = fdt_size_cells(fdt, 0);
+	if (ns < 0) {
 		pr_err("Cannot find #size-cells property");
 		goto err;
 	}
-	ns = fdt32_to_cpu(*nap);
 
 	/* Find the memory range */
 	node = fdt_node_offset_by_prop_value(fdt, -1, "device_type",
@@ -103,3 +94,85 @@ const void *fdt_device_get_match_data(const void *fdt, const char *nodepath,
 
 	return NULL;
 }
+
+static struct pbl_reserved_memory reserved_mem[MAX_RESERVED_REGIONS];
+static int reserved_mem_count;
+
+void fdt_fill_reserve_mem(const void *fdt)
+{
+	const __be32 *nap, *nsp, *reg;
+	uint32_t na, ns;
+	int node, size, i, parent;
+	const void *prop;
+	uint64_t memsize64, membase64;
+	bool nomap;
+
+	/* Make sure FDT blob is sane */
+	if (fdt_check_header(fdt) != 0) {
+		pr_err("Invalid device tree blob\n");
+		return;
+	}
+
+	parent = fdt_path_offset(fdt, "/reserved-memory");
+	if (parent < 0) {
+		pr_info("Cannot find reserved-memory node\n");
+		return;
+	}
+
+	nap = fdt_getprop(fdt, parent, "#address-cells", &size);
+	if (!nap || (size != 4)) {
+		pr_err("Cannot find #address-cells property");
+		return;
+	}
+	na = fdt32_to_cpu(*nap);
+
+	nsp = fdt_getprop(fdt, parent, "#size-cells", &size);
+	if (!nsp || (size != 4)) {
+		pr_err("Cannot find #size-cells property");
+		return;
+	}
+	ns = fdt32_to_cpu(*nap);
+
+	fdt_for_each_subnode(node, fdt, parent) {
+		nomap = true;
+		reg = fdt_getprop(fdt, node, "reg", &size);
+		if (size < (na + ns) * sizeof(u32)) {
+			pr_err("cannot get memory range\n");
+			return;
+		}
+
+		membase64 = 0;
+		for (i = 0; i < na; i++)
+			membase64 = (membase64 << 32) | fdt32_to_cpu(*reg++);
+
+		/* get the memsize and truncate it to under 4G on 32 bit machines */
+		memsize64 = 0;
+		for (i = 0; i < ns; i++)
+			memsize64 = (memsize64 << 32) | fdt32_to_cpu(*reg++);
+
+		prop = fdt_getprop(fdt, node, "nomap", NULL);
+		if (!prop)
+			nomap = false;
+
+		reserved_mem[reserved_mem_count].base = membase64;
+		reserved_mem[reserved_mem_count].size = memsize64;
+		if (nomap)
+			reserved_mem[reserved_mem_count].flags |= FDT_RES_MEM_FLAG_NOMAP;
+		reserved_mem_count++;
+	}
+
+	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
+		pr_err("Error while parsing reserved-memory nodes: %d\n", node);
+		return;
+	}
+}
+
+const struct pbl_reserved_memory *get_pbl_reserved_memory(void)
+{
+	return reserved_mem;
+}
+
+int get_pbl_reserved_memory_num(void)
+{
+	return reserved_mem_count;
+}
-- 
2.32.0



From r.czerwinski at pengutronix.de  Tue Aug  3 02:44:18 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue,  3 Aug 2021 11:44:18 +0200
Subject: [PATCH v2 8/8] PBL: enable LIBFDT for OP-TEE early loading
In-Reply-To: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
Message-ID: <20210803094418.475609-9-r.czerwinski@pengutronix.de>

This allows the OP-TEE early loaded board to add the reserved memory
entries for the correct MMU setup. This is done by including pbl/fdt.h
and using fdt_fill_reserve_mem().

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 common/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/Kconfig b/common/Kconfig
index a9feae2ae8..4f7a08bc8f 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1116,6 +1116,7 @@ config BOOTM_OPTEE
 
 config PBL_OPTEE
 	bool "Enable OP-TEE early start"
+	select LIBFDT
 	depends on ARM
 	depends on !THUMB2_BAREBOX
 	help
-- 
2.32.0



From a.fatoum at pengutronix.de  Tue Aug  3 09:59:36 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue,  3 Aug 2021 18:59:36 +0200
Subject: [PATCH 1/2] watchdog: imxwd: register explicit warm reset handler
Message-ID: <20210803165937.31608-1-a.fatoum@pengutronix.de>

With fsl,ext-reset-output and WDOG_B muxed correctly, the i.MX watchdog
will toggle an external signal to effect a PMIC reset.

That's good for normal use, but when exchanging information with the
BootROM over GPRs, a warm reset is required. This is needed e.g. to
set the reboot mode. Support this by defining a second, lower
priority, reset that will never toggle external lines.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/watchdog/imxwd.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 26c62b7bcb31..a109f6fee712 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -39,6 +39,7 @@ struct imx_wd {
 	struct device_d *dev;
 	const struct imx_wd_ops *ops;
 	struct restart_handler restart;
+	struct restart_handler restart_warm;
 	bool ext_reset;
 	bool bigendian;
 };
@@ -183,6 +184,14 @@ static void __noreturn imxwd_force_soc_reset(struct restart_handler *rst)
 	hang();
 }
 
+static void __noreturn imxwd_force_soc_reset_internal(struct restart_handler *rst)
+{
+	struct imx_wd *priv = container_of(rst, struct imx_wd, restart_warm);
+
+	priv->ext_reset = false;
+	imxwd_force_soc_reset(&priv->restart);
+}
+
 static void imx_watchdog_detect_reset_source(struct imx_wd *priv)
 {
 	u16 val = imxwd_read(priv, IMX21_WDOG_WSTR);
@@ -284,9 +293,16 @@ static int imx_wd_probe(struct device_d *dev)
 
 	priv->restart.name = "imxwd";
 	priv->restart.restart = imxwd_force_soc_reset;
+	priv->restart.priority = RESTART_DEFAULT_PRIORITY;
 
 	restart_handler_register(&priv->restart);
 
+	priv->restart_warm.name = "imxwd-warm";
+	priv->restart_warm.restart = imxwd_force_soc_reset_internal;
+	priv->restart_warm.priority = RESTART_DEFAULT_PRIORITY - 10;
+
+	restart_handler_register(&priv->restart_warm);
+
 	return 0;
 
 error_unregister:
-- 
2.30.2



From a.fatoum at pengutronix.de  Tue Aug  3 09:59:37 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue,  3 Aug 2021 18:59:37 +0200
Subject: [PATCH 2/2] ARM: i.MX8MM: add reboot to serial download mode
In-Reply-To: <20210803165937.31608-1-a.fatoum@pengutronix.de>
References: <20210803165937.31608-1-a.fatoum@pengutronix.de>
Message-ID: <20210803165937.31608-2-a.fatoum@pengutronix.de>

The i.MX8MM reference manual follows long established tradition in not
documenting BootROM magic reboot codes. For older i.MX variants, the
values can be seen in the bmode tables of Freescale's U-Boot patches.

There are no such patches for the i.MX8M, but testing shows that

	mw 0x30390094 0x10 ; mw 0x30390098 0x40000000

is one of the configurations that trigger serial download on next warm
reset on an i.MX8MM. Describe this in the device tree, so

	gpr.reboot_mode.next=serial reset -r imxwd-warm

does the right thing for that SoC.

This all might work for other i.MX8M variants as well, but the dtsi
can be genericized later on when tested.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
Cc: David Jander <david at protonic.nl>
Cc: Lucas Stach <l.stach at pengutronix.de>
---
 Documentation/boards/imx.rst   | 29 +++++++++++++++++++++++++++++
 arch/arm/dts/imx8mm-evk.dts    |  1 +
 arch/arm/dts/imx8mm-prt8mm.dts |  1 +
 arch/arm/dts/imx8mm.dtsi       | 18 ++++++++++++++++++
 4 files changed, 49 insertions(+)
 create mode 100644 arch/arm/dts/imx8mm.dtsi

diff --git a/Documentation/boards/imx.rst b/Documentation/boards/imx.rst
index 887b45c70881..4ce9d9808cc1 100644
--- a/Documentation/boards/imx.rst
+++ b/Documentation/boards/imx.rst
@@ -83,6 +83,35 @@ The images can also always be started as second stage on the target:
 
   barebox at Board Name:/ bootm /mnt/tftp/barebox-freescale-imx51-babbage.img
 
+BootROM Reboot mode codes (bmode)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For select SoCs, barebox supports communicating an alternative boot medium
+that BootROM should select after a warm reset::
+
+  barebox at FSL i.MX8MM EVK board:/ devinfo gpr.reboot_mode
+  Driver: syscon-reboot-mode
+  Bus: platform
+  Parent: 30390000.reset-controller at 30390000.of
+  Parameters:
+    next: normal (type: enum) (values: "normal", "serial")
+    prev: normal (type: enum) (values: "normal", "serial")
+  Device node: /soc at 0/bus at 30000000/reset-controller at 30390000/reboot-mode
+  reboot-mode {
+          compatible = "barebox,syscon-reboot-mode";
+          offset = <0x94 0x98>;
+          mask = <0xffffffff 0x40000000>;
+          mode-normal = <0x0 0x0>;
+          mode-serial = <0x10 0x40000000>;
+  };
+
+  barebox at FSL i.MX8MM EVK board:/ gpr.reboot_mode.next=serial reset -r imxwd-warm
+
+This will cause barebox to fall into serial download mode on an i.MX8MM.
+
+Different SoCs may have more possible reboot modes available.
+See the section on :ref:`Reboot modes<reboot_mode>` for more information.
+
 High Assurance Boot
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/arch/arm/dts/imx8mm-evk.dts b/arch/arm/dts/imx8mm-evk.dts
index 1e8619ccf584..304f150307a3 100644
--- a/arch/arm/dts/imx8mm-evk.dts
+++ b/arch/arm/dts/imx8mm-evk.dts
@@ -7,6 +7,7 @@
 /dts-v1/;
 
 #include <arm64/freescale/imx8mm-evk.dts>
+#include "imx8mm.dtsi"
 
 / {
 	chosen {
diff --git a/arch/arm/dts/imx8mm-prt8mm.dts b/arch/arm/dts/imx8mm-prt8mm.dts
index bdcdd0806243..abd758f2856e 100644
--- a/arch/arm/dts/imx8mm-prt8mm.dts
+++ b/arch/arm/dts/imx8mm-prt8mm.dts
@@ -7,6 +7,7 @@
 /dts-v1/;
 
 #include <arm64/freescale/imx8mm.dtsi>
+#include "imx8mm.dtsi"
 
 / {
 	model = "Protonic PRT8MM";
diff --git a/arch/arm/dts/imx8mm.dtsi b/arch/arm/dts/imx8mm.dtsi
new file mode 100644
index 000000000000..78bbacb2b1b2
--- /dev/null
+++ b/arch/arm/dts/imx8mm.dtsi
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/ {
+	aliases {
+		gpr.reboot_mode = &reboot_mode_gpr;
+	};
+};
+
+&src {
+	compatible = "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon", "simple-mfd";
+
+	reboot_mode_gpr: reboot-mode {
+		compatible = "barebox,syscon-reboot-mode";
+		offset = <0x94>, <0x98>; /* SRC_GPR{9,10} */
+		mask = <0xffffffff>, <0x40000000>;
+		mode-normal = <0>, <0>;
+		mode-serial = <0x00000010>, <0x40000000>;
+	};
+};
-- 
2.30.2



From r.czerwinski at pengutronix.de  Thu Aug  5 01:26:07 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Thu,  5 Aug 2021 10:26:07 +0200
Subject: [PATCH] mci: imx-esdhc-pbl: initialize fsl_esdhc_host
Message-ID: <20210805082607.1698733-1-r.czerwinski@pengutronix.de>

Since commit 56ca2c197e71 ("mci: sdhci: Get rid of many register ops")
the core checks whether there is an explicit write function for the
host. If the struct is not zero initialized, a bogus value is taken as
the function, resulting in an unbootable board. Zero initialize the
structs properly to let the PBL correctly load images. Fixes booting on
the i.MX8M* board, tested on i.MX8MP EVK.

Fixes: 56ca2c197e71 ("mci: sdhci: Get rid of many register ops")

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 drivers/mci/imx-esdhc-pbl.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index c3a8b377e..2e04c78fd 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -233,7 +233,7 @@ static int imx8m_esdhc_init(struct fsl_esdhc_host *host,
 int imx6_esdhc_start_image(int instance)
 {
 	struct esdhc_soc_data data;
-	struct fsl_esdhc_host host;
+	struct fsl_esdhc_host host = { 0 };
 
 	switch (instance) {
 	case 0:
@@ -272,7 +272,7 @@ int imx6_esdhc_start_image(int instance)
 int imx7_esdhc_start_image(int instance)
 {
 	struct esdhc_soc_data data;
-	struct fsl_esdhc_host host;
+	struct fsl_esdhc_host host = { 0 };
 
 	switch (instance) {
 	case 0:
@@ -309,7 +309,7 @@ int imx7_esdhc_start_image(int instance)
 int imx8m_esdhc_load_image(int instance, bool start)
 {
 	struct esdhc_soc_data data;
-	struct fsl_esdhc_host host;
+	struct fsl_esdhc_host host = { 0 };
 	int ret;
 
 	ret = imx8m_esdhc_init(&host, &data, instance);
@@ -337,7 +337,7 @@ int imx8m_esdhc_load_image(int instance, bool start)
 int imx8mp_esdhc_load_image(int instance, bool start)
 {
 	struct esdhc_soc_data data;
-	struct fsl_esdhc_host host;
+	struct fsl_esdhc_host host = { 0 };
 	int ret;
 
 	ret = imx8m_esdhc_init(&host, &data, instance);
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug  5 06:52:28 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 15:52:28 +0200
Subject: [PATCH] mci: imx-esdhc-pbl: initialize fsl_esdhc_host
In-Reply-To: <20210805082607.1698733-1-r.czerwinski@pengutronix.de>
References: <20210805082607.1698733-1-r.czerwinski@pengutronix.de>
Message-ID: <8879968f-3947-b754-1f07-935948e8f248@pengutronix.de>

On 05.08.21 10:26, Rouven Czerwinski wrote:
> Since commit 56ca2c197e71 ("mci: sdhci: Get rid of many register ops")
> the core checks whether there is an explicit write function for the
> host. If the struct is not zero initialized, a bogus value is taken as
> the function, resulting in an unbootable board. Zero initialize the
> structs properly to let the PBL correctly load images. Fixes booting on
> the i.MX8M* board, tested on i.MX8MP EVK.
> 
> Fixes: 56ca2c197e71 ("mci: sdhci: Get rid of many register ops")
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> ---
>  drivers/mci/imx-esdhc-pbl.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
> index c3a8b377e..2e04c78fd 100644
> --- a/drivers/mci/imx-esdhc-pbl.c
> +++ b/drivers/mci/imx-esdhc-pbl.c
> @@ -233,7 +233,7 @@ static int imx8m_esdhc_init(struct fsl_esdhc_host *host,
>  int imx6_esdhc_start_image(int instance)
>  {
>  	struct esdhc_soc_data data;
> -	struct fsl_esdhc_host host;
> +	struct fsl_esdhc_host host = { 0 };
>  
>  	switch (instance) {
>  	case 0:
> @@ -272,7 +272,7 @@ int imx6_esdhc_start_image(int instance)
>  int imx7_esdhc_start_image(int instance)
>  {
>  	struct esdhc_soc_data data;
> -	struct fsl_esdhc_host host;
> +	struct fsl_esdhc_host host = { 0 };
>  
>  	switch (instance) {
>  	case 0:
> @@ -309,7 +309,7 @@ int imx7_esdhc_start_image(int instance)
>  int imx8m_esdhc_load_image(int instance, bool start)
>  {
>  	struct esdhc_soc_data data;
> -	struct fsl_esdhc_host host;
> +	struct fsl_esdhc_host host = { 0 };
>  	int ret;
>  
>  	ret = imx8m_esdhc_init(&host, &data, instance);
> @@ -337,7 +337,7 @@ int imx8m_esdhc_load_image(int instance, bool start)
>  int imx8mp_esdhc_load_image(int instance, bool start)
>  {
>  	struct esdhc_soc_data data;
> -	struct fsl_esdhc_host host;
> +	struct fsl_esdhc_host host = { 0 };
>  	int ret;
>  
>  	ret = imx8m_esdhc_init(&host, &data, instance);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 06:53:33 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 15:53:33 +0200
Subject: [PATCH v2 8/8] PBL: enable LIBFDT for OP-TEE early loading
In-Reply-To: <20210803094418.475609-9-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-9-r.czerwinski@pengutronix.de>
Message-ID: <edee4bbe-ba6e-7356-5ce7-984a4009134d@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> This allows the OP-TEE early loaded board to add the reserved memory
> entries for the correct MMU setup. This is done by including pbl/fdt.h
> and using fdt_fill_reserve_mem().
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

Would be nice if we had a board upstream that made use of this.

> ---
>  common/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/common/Kconfig b/common/Kconfig
> index a9feae2ae8..4f7a08bc8f 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -1116,6 +1116,7 @@ config BOOTM_OPTEE
>  
>  config PBL_OPTEE
>  	bool "Enable OP-TEE early start"
> +	select LIBFDT
>  	depends on ARM
>  	depends on !THUMB2_BAREBOX
>  	help
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 06:54:01 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 15:54:01 +0200
Subject: [PATCH v2 1/8] of: reserve: add xn flag mem entries
In-Reply-To: <20210803094418.475609-2-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-2-r.czerwinski@pengutronix.de>
Message-ID: <1ed2d652-e8a1-46b6-4515-ca89d279088f@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> If the OF_RESERVE_ENTRY_FLAG_XN flag is passed while creating the
> entry, a subsequent commit will use this information in the mmu to map
> the area as non-executable.

A changelog would've been nice.

> diff --git a/arch/arm/mach-layerscape/ppa.c b/arch/arm/mach-layerscape/ppa.c
> index d962fba751..6e61766e54 100644
> --- a/arch/arm/mach-layerscape/ppa.c
> +++ b/arch/arm/mach-layerscape/ppa.c
> @@ -130,7 +130,7 @@ int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size)
>  	if (ret)
>  		return ret;
>  
> -	of_add_reserve_entry(ppa_start, ppa_end);
> +	of_add_reserve_entry(ppa_start, ppa_end, 0);

Same comment as last time. I believe this should be mapped _XN too,
but that should be tested first.

Thus:

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

If you respin the series, you may want to add a TODO comment here,
so it is not forgotten.

Cheers,
Ahmad

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 06:55:09 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 15:55:09 +0200
Subject: [PATCH v2 2/8] of: add of_get_reserve_map stub for !CONFIG_OFTREE
In-Reply-To: <20210803094418.475609-3-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-3-r.czerwinski@pengutronix.de>
Message-ID: <4a3d20df-d8f4-bf30-5286-77acc08e12d2@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> This allows us to unconditionally include of.h in files which did not
> require CONFIG_OFTREE, required for the MMU code in later patches.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> ---
>  include/of.h | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/include/of.h b/include/of.h
> index 4844e800b4..36936ecd6e 100644
> --- a/include/of.h
> +++ b/include/of.h
> @@ -62,7 +62,6 @@ struct of_reserve_map {
>  
>  int of_add_reserve_entry(resource_size_t start, resource_size_t end,
>  		 int flags);
> -struct of_reserve_map *of_get_reserve_map(void);
>  void of_clean_reserve_map(void);
>  void fdt_add_reserve_map(void *fdt);
>  
> @@ -120,6 +119,7 @@ struct device_node *of_unflatten_dtb_const(const void *infdt, int size);
>  struct cdev;
>  
>  #ifdef CONFIG_OFTREE
> +struct of_reserve_map *of_get_reserve_map(void);
>  extern int of_bus_n_addr_cells(struct device_node *np);
>  extern int of_n_addr_cells(struct device_node *np);
>  extern int of_bus_n_size_cells(struct device_node *np);
> @@ -821,6 +821,10 @@ static inline int of_autoenable_i2c_by_component(char *path)
>  	return -ENODEV;
>  }
>  
> +static inline struct of_reserve_map *of_get_reserve_map(void)
> +{
> +	return NULL;
> +}
>  
>  #endif
>  
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 07:06:42 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 16:06:42 +0200
Subject: [PATCH v2 3/8] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <20210803094418.475609-4-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-4-r.czerwinski@pengutronix.de>
Message-ID: <270994d8-2970-5095-2f82-f8cf29054629@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> Use the information from the reserved memory entries to modify the
> mapping of memory regions to mark them as uncachable and not-executable.
> This also prevents the processor from speculating into these regions,
> preventing hard to debug scenarios where boots fail for unknown reasons.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  arch/arm/cpu/mmu.c | 34 ++++++++++++++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
> index 6388e1bf14..73f4cf5b36 100644
> --- a/arch/arm/cpu/mmu.c
> +++ b/arch/arm/cpu/mmu.c
> @@ -17,6 +17,7 @@
>  #include <memory.h>
>  #include <asm/system_info.h>
>  #include <asm/sections.h>
> +#include <of.h>
>  
>  #include "mmu.h"
>  
> @@ -407,6 +408,36 @@ static void vectors_init(void)
>  	create_vector_table(ARM_LOW_VECTORS);
>  }
>  
> +static void create_sections_with_intersect(struct memory_bank *bank)
> +{
> +	struct of_reserve_map *res_map;
> +	unsigned long j_end;
> +	unsigned long end;
> +	unsigned long j;
> +	u32 pmd_flags;
> +	int i;
> +
> +	res_map = of_get_reserve_map();
> +	if (!res_map)
> +		return;

If there is no reserve map, you should still map the banks cached.
So this early exit is wrong.

> +
> +	end = bank->start + bank->size - 1;
> +
> +	for (j = bank->start; j < end; j += PGDIR_SIZE) {
> +		pmd_flags = PMD_SECT_DEF_CACHED;
> +		j_end = j + PGDIR_SIZE - 1;
> +
> +		for (i = 0; i < res_map->num_entries; i++) {
> +			if ((BIT(i) & res_map->xn) &&
> +			    j_end >= res_map->start[i] &&
> +			    j_end <= res_map->end[i])
> +				pmd_flags = PMD_SECT_DEF_UNCACHED | PMD_SECT_XN;
> +		}
> +
> +		create_sections(ttb, j, j_end, pmd_flags);
> +	}

Do we need the nested loop? Can't we create sections cached first
and then iterate once over the reserved map, deduce the sections containing
start and end and map those uncached?

See map_region in mmy-early.c for an example.
Am I missing something?

> +}
> +
>  /*
>   * Prepare MMU for usage enable it.
>   */
> @@ -468,8 +499,7 @@ void __mmu_init(bool mmu_on)
>  	vectors_init();
>  
>  	for_each_memory_bank(bank) {
> -		create_sections(ttb, bank->start, bank->start + bank->size - 1,
> -				PMD_SECT_DEF_CACHED);
> +		create_sections_with_intersect(bank);
>  		__mmu_cache_flush();
>  	}
>  
> 

Cheers,
Ahmad


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 07:09:56 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 16:09:56 +0200
Subject: [PATCH v2 4/8] of: add flag to not create resmem DT entries
In-Reply-To: <20210803094418.475609-5-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-5-r.czerwinski@pengutronix.de>
Message-ID: <f992a14d-0b7c-f6b2-ff60-c2c627f02e6b@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> If we are parsing entries from the /reserved-memory device tree path we
> don't want to add them again as resmem blocks at the beginning of the
> device tree. Therefore add another flag to indicate this.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  drivers/of/fdt.c | 10 +++++++---
>  include/of.h     |  2 ++
>  2 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 9356a92c5c..030f1233d5 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -559,6 +559,9 @@ int of_add_reserve_entry(resource_size_t start, resource_size_t end,
>  	if (flags & OF_RESERVE_ENTRY_FLAG_XN)
>  		of_reserve_map.xn |= BIT(e);
>  
> +	if (flags & OF_RESERVE_ENTRY_FLAG_NO_RESERVE)

Did I say before I dislike the name? Perhaps something like OF_RESERVE_ENTRY_FLAG_NO_FIXUP?

> +		of_reserve_map.noentry |= BIT(e);
> +
>  	return 0;
>  }
>  
> @@ -601,9 +604,10 @@ void fdt_add_reserve_map(void *__fdt)
>  	fdt_res += n;
>  
>  	for (i = 0; i < res->num_entries; i++) {
> -		of_write_number(&fdt_res->address, res->start[i], 2);
> -		of_write_number(&fdt_res->size, res->end[i] - res->start[i] + 1,
> -				2);
> +		if (!(res->noentry & BIT(i))) {

Nitpick: invert the condition and using continue is clearer IMO.

> +			of_write_number(&fdt_res->address, res->start[i], 2);
> +			of_write_number(&fdt_res->size, res->end[i] - res->start[i] + 1, 2);
> +		}
>  		fdt_res++;
>  	}
>  
> diff --git a/include/of.h b/include/of.h
> index 36936ecd6e..209d2898ae 100644
> --- a/include/of.h
> +++ b/include/of.h
> @@ -56,9 +56,11 @@ struct of_reserve_map {
>  	uint64_t end[OF_MAX_RESERVE_MAP];
>  	int num_entries;
>  	u16 xn;
> +	u16 reserved_entry;
>  };
>  
>  #define OF_RESERVE_ENTRY_FLAG_XN		BIT(0)
> +#define OF_RESERVE_ENTRY_FLAG_NO_RESERVE	BIT(1)
>  
>  int of_add_reserve_entry(resource_size_t start, resource_size_t end,
>  		 int flags);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 07:14:47 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 16:14:47 +0200
Subject: [PATCH v2 5/8] of: add reserved_mem_read initcall
In-Reply-To: <20210803094418.475609-6-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-6-r.czerwinski@pengutronix.de>
Message-ID: <dd763fc9-c984-9d39-8cee-ff5a736de663@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> Add a reserved_mem_read initcall which parses the reserved-memory
> entries and adds barebox of reserve entries. Also remove the OP-TEE size
> of reserve entry, since this is now parsed from the DT and does not need
> to be statically configured any longer.

Where do you do this OP-TEE size removal?

> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  drivers/of/Makefile       |  1 +
>  drivers/of/reserved-mem.c | 43 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 44 insertions(+)
>  create mode 100644 drivers/of/reserved-mem.c
> 
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index b6847752d2..b69cb84b99 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -4,6 +4,7 @@ obj-$(CONFIG_OF_GPIO) += of_gpio.o
>  obj-$(CONFIG_OF_PCI) += of_pci.o
>  obj-y += partition.o
>  obj-y += of_net.o
> +obj-$(CONFIG_OFDEVICE) += reserved-mem.o
>  obj-$(CONFIG_MTD) += of_mtd.o
>  obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
>  obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
> diff --git a/drivers/of/reserved-mem.c b/drivers/of/reserved-mem.c
> new file mode 100644
> index 0000000000..8519a7e3dd
> --- /dev/null
> +++ b/drivers/of/reserved-mem.c
> @@ -0,0 +1,43 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// SPDX-FileCopyrightText: 2021 Rouven Czerwinski <r.czerwinski at pengutronix.de>, Pengutronix
> +
> +#define pr_fmt(fmt) "reserved-memory: " fmt
> +
> +#define DEBUG

Left-over

> +
> +#include <common.h>
> +#include <init.h>
> +#include <of.h>
> +#include <of_address.h>
> +#include <malloc.h>
> +#include <partition.h>

Left-over?

> +
> +static int reserved_mem_read(void)
> +{
> +	struct device_node *node, *child;
> +	struct resource resource;
> +	int flag;
> +
> +	node = of_find_node_by_path("/reserved-memory");
> +	if (!node)
> +		return 0;
> +
> +	for_each_child_of_node(node, child) {
> +		flag = OF_RESERVE_ENTRY_FLAG_NO_RESERVE;

Why was this necessary again?

> +
> +		of_address_to_resource(child, 0, &resource);
> +
> +		pr_err("Res-Mem start: 0x%08x\n", resource.start);
> +		pr_err("Res-Mem end: 0x%08x\n", resource.end);

should be _dbg if at all. Preferably same line with child->name as prefix.

> +
> +		if (of_find_property(child, "no-map", 0)) {
> +			pr_debug("child %p: no-map\n", child);
> +			flag |= OF_RESERVE_ENTRY_FLAG_XN;
> +		}
> +
> +		of_add_reserve_entry(resource.start, resource.end, flag);
> +	}
> +
> +	return 0;
> +}
> +postconsole_initcall(reserved_mem_read);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 07:20:57 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 16:20:57 +0200
Subject: [PATCH v2 6/8] pbl: fdt: add support to parse reserved mem
In-Reply-To: <20210803094418.475609-7-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-7-r.czerwinski@pengutronix.de>
Message-ID: <9452a831-7497-962f-dca4-74638b3d3553@pengutronix.de>

Hello,

On 03.08.21 11:44, Rouven Czerwinski wrote:
> This allows the PBL to fill a reserved memory map which a subsequent
> commit will use modify the early MMU mapping.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  include/pbl.h |  25 ++++++++++++
>  pbl/fdt.c     | 103 ++++++++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 113 insertions(+), 15 deletions(-)
> 
> diff --git a/include/pbl.h b/include/pbl.h
> index f58daec735..03272879d7 100644
> --- a/include/pbl.h
> +++ b/include/pbl.h
> @@ -42,5 +42,30 @@ struct fdt_device_id {
>  const void *
>  fdt_device_get_match_data(const void *fdt, const char *nodepath,
>  			  const struct fdt_device_id ids[]);
> +struct pbl_reserved_memory {
> +	phys_addr_t			base;
> +	phys_addr_t			size;
> +	unsigned int			flags;
> +};
> +
> +#define MAX_RESERVED_REGIONS	8
> +
> +#define FDT_RES_MEM_FLAG_NOMAP		BIT(0)
> +
> +void fdt_fill_reserve_mem(const void *fdt);
> +
> +#ifdef CONFIG_LIBFDT
> +const struct pbl_reserved_memory *get_pbl_reserved_memory(void);
> +int get_pbl_reserved_memory_num(void);
> +#else
> +static inline const struct pbl_reserved_memory *get_pbl_reserved_memory(void)
> +{
> +	return NULL;
> +}
> +static inline int get_pbl_reserved_memory_num(void)
> +{
> +	return 0;
> +}
> +#endif
>  
>  #endif /* __PBL_H__ */
> diff --git a/pbl/fdt.c b/pbl/fdt.c
> index 18ddb9f48a..383d0fec74 100644
> --- a/pbl/fdt.c
> +++ b/pbl/fdt.c
> @@ -5,8 +5,8 @@
>  
>  void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsize)
>  {
> -	const __be32 *nap, *nsp, *reg;
> -	uint32_t na, ns;
> +	const __be32 *reg;
> +	int na, ns;
>  	uint64_t memsize64, membase64;
>  	int node, size, i;
>  
> @@ -16,26 +16,17 @@ void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsiz
>  		goto err;
>  	}
>  
> -	/* Find the #address-cells and #size-cells properties */
> -	node = fdt_path_offset(fdt, "/");
> -	if (node < 0) {
> -		pr_err("Cannot find root node\n");
> -		goto err;
> -	}
> -
> -	nap = fdt_getprop(fdt, node, "#address-cells", &size);
> -	if (!nap || (size != 4)) {
> +	na = fdt_address_cells(fdt, 0);
> +	if (na < 0) {
>  		pr_err("Cannot find #address-cells property");
>  		goto err;
>  	}
> -	na = fdt32_to_cpu(*nap);
>  
> -	nsp = fdt_getprop(fdt, node, "#size-cells", &size);
> -	if (!nsp || (size != 4)) {
> +	ns = fdt_size_cells(fdt, 0);
> +	if (ns < 0) {
>  		pr_err("Cannot find #size-cells property");
>  		goto err;
>  	}
> -	ns = fdt32_to_cpu(*nap);

I like the simplification, but it looks unrelated to the early reserved mem support..?
Perhaps split it up?

>  
>  	/* Find the memory range */
>  	node = fdt_node_offset_by_prop_value(fdt, -1, "device_type",
> @@ -103,3 +94,85 @@ const void *fdt_device_get_match_data(const void *fdt, const char *nodepath,
>  
>  	return NULL;
>  }
> +
> +static struct pbl_reserved_memory reserved_mem[MAX_RESERVED_REGIONS];
> +static int reserved_mem_count;
> +
> +void fdt_fill_reserve_mem(const void *fdt)
> +{
> +	const __be32 *nap, *nsp, *reg;
> +	uint32_t na, ns;
> +	int node, size, i, parent;
> +	const void *prop;
> +	uint64_t memsize64, membase64;
> +	bool nomap;
> +
> +	/* Make sure FDT blob is sane */
> +	if (fdt_check_header(fdt) != 0) {
> +		pr_err("Invalid device tree blob\n");
> +		return;
> +	}
> +
> +	parent = fdt_path_offset(fdt, "/reserved-memory");
> +	if (parent < 0) {
> +		pr_info("Cannot find reserved-memory node\n");
> +		return;
> +	}
> +
> +	nap = fdt_getprop(fdt, parent, "#address-cells", &size);
> +	if (!nap || (size != 4)) {
> +		pr_err("Cannot find #address-cells property");
> +		return;
> +	}
> +	na = fdt32_to_cpu(*nap);
> +
> +	nsp = fdt_getprop(fdt, parent, "#size-cells", &size);
> +	if (!nsp || (size != 4)) {
> +		pr_err("Cannot find #size-cells property");
> +		return;
> +	}
> +	ns = fdt32_to_cpu(*nap);

Oh, did you mean to use the cool fdt_address_cells and fdt_size_cells helper you found here
but fuzzily wrote your code? ^^'

> +
> +	fdt_for_each_subnode(node, fdt, parent) {
> +		nomap = true;
> +		reg = fdt_getprop(fdt, node, "reg", &size);
> +		if (size < (na + ns) * sizeof(u32)) {
> +			pr_err("cannot get memory range\n");
> +			return;
> +		}
> +
> +		membase64 = 0;
> +		for (i = 0; i < na; i++)
> +			membase64 = (membase64 << 32) | fdt32_to_cpu(*reg++);
> +
> +		/* get the memsize and truncate it to under 4G on 32 bit machines */
> +		memsize64 = 0;
> +		for (i = 0; i < ns; i++)
> +			memsize64 = (memsize64 << 32) | fdt32_to_cpu(*reg++);

Can you turn this into a helper and use that for both fdt_find_mem and fdt_fill_reserve_mem?

> +
> +		prop = fdt_getprop(fdt, node, "nomap", NULL);
> +		if (!prop)
> +			nomap = false;

Nitpick:

 if (fdt_getprop(fdt, node, "nomap", NULL))
	reserved_mem[reserved_mem_count].flags |= FDT_RES_MEM_FLAG_NOMAP;

would've worked too. Neither prop or nomap is strictly needed.

> +
> +		reserved_mem[reserved_mem_count].base = membase64;
> +		reserved_mem[reserved_mem_count].size = memsize64;
> +		if (nomap)
> +			reserved_mem[reserved_mem_count].flags |= FDT_RES_MEM_FLAG_NOMAP;
> +		reserved_mem_count++;
> +	}
> +
> +	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
> +		pr_err("Error while parsing reserved-memory nodes: %d\n", node);
> +		return;
> +	}
> +}
> +
> +const struct pbl_reserved_memory *get_pbl_reserved_memory(void)
> +{
> +	return reserved_mem;
> +}
> +
> +int get_pbl_reserved_memory_num(void)
> +{
> +	return reserved_mem_count;
> +}
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug  5 07:24:28 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 16:24:28 +0200
Subject: [PATCH v2 7/8] ARM: mmu-early: map no-map entries XN & uncached
In-Reply-To: <20210803094418.475609-8-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-8-r.czerwinski@pengutronix.de>
Message-ID: <086d5892-9ca1-84d3-05aa-fe16c5a6eccf@pengutronix.de>

On 03.08.21 11:44, Rouven Czerwinski wrote:
> Ensure that reserved map entries with the no-map flag are marked as
> uncached and non-execute during the early MMU initialization.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  arch/arm/cpu/mmu-early.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/arch/arm/cpu/mmu-early.c b/arch/arm/cpu/mmu-early.c
> index b985aa455f..9c3f01326b 100644
> --- a/arch/arm/cpu/mmu-early.c
> +++ b/arch/arm/cpu/mmu-early.c
> @@ -3,9 +3,11 @@
>  #include <errno.h>
>  #include <linux/sizes.h>
>  #include <asm/memory.h>
> +#include <asm-generic/memory_layout.h>
>  #include <asm/system.h>
>  #include <asm/cache.h>
>  #include <asm-generic/sections.h>
> +#include <pbl.h>
>  
>  #include "mmu.h"
>  
> @@ -24,7 +26,10 @@ static inline void map_region(unsigned long start, unsigned long size,
>  void mmu_early_enable(unsigned long membase, unsigned long memsize,
>  		      unsigned long _ttb)
>  {
> +	const struct pbl_reserved_memory *res_mem;
> +	int i;
>  	ttb = (uint32_t *)_ttb;
> +	res_mem =  get_pbl_reserved_memory();

Nitpick: could've been a single line.

>  
>  	arm_set_cache_functions();
>  
> @@ -58,6 +63,14 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize,
>  	/* maps main memory as cachable */
>  	map_region(membase, memsize, PMD_SECT_DEF_CACHED);
>  
> +	for (i = 0; i < get_pbl_reserved_memory_num(); i++) {
> +		if (res_mem->flags & FDT_RES_MEM_FLAG_NOMAP)
> +			map_region(res_mem->base, res_mem->size,
> +				   PMD_SECT_DEF_UNCACHED | PMD_SECT_XN);
> +		res_mem++;
> +	}
> +
> +

Looks good:

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

>  	/*
>  	 * With HAB enabled we call into the ROM code later in imx6_hab_get_status().
>  	 * Map the ROM cached which has the effect that the XN bit is not set.

Would be nice to make this HAB exception just an entry in the reserved map,
but that's out of scope for this patch.

Cheers,
Ahmad


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From u.kleine-koenig at pengutronix.de  Thu Aug  5 08:22:17 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Thu,  5 Aug 2021 17:22:17 +0200
Subject: [PATCH 1/2] arm/mvebu: sync barebox-arm-head.h to generic variant
Message-ID: <20210805152218.1901918-1-u.kleine-koenig@pengutronix.de>

En passant this adds support for PBL_BREAK. While there is no 64 bit
support available for mvebu, keeping the difference between
arch/arm/mach-mvebu/include/mach/barebox-arm-head.h and
arch/arm/include/asm/barebox-arm-head.h minimal is a good thing.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
Changes in this v2: Only some whitespace changes to reduce the diff
between the two headers even more.
---
 .../include/mach/barebox-arm-head.h           | 25 ++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h b/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h
index 3035f40ddf3b..723e2ab4c8b5 100644
--- a/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h
+++ b/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h
@@ -4,6 +4,7 @@
 static inline void __barebox_arm_head(void)
 {
 	__asm__ __volatile__ (
+#ifdef CONFIG_CPU_32
 #ifdef CONFIG_THUMB2_BAREBOX
 		".arm\n"
 		"adr r9, 1f + 1\n"
@@ -23,11 +24,23 @@ static inline void __barebox_arm_head(void)
 		"1: b 1b\n"
 		"1: b 1b\n"
 		"1: b 1b\n"
+#endif
+#else
+		"b 2f\n"
+		"nop\n"
+		"nop\n"
+		"nop\n"
+		"nop\n"
+		"nop\n"
 #endif
 		".asciz \"barebox\"\n"
+#ifdef CONFIG_CPU_32
 		".word _text\n"				/* text base. If copied there,
 							 * barebox can skip relocation
 							 */
+#else
+		".word 0xffffffff\n"
+#endif
 		".word _barebox_image_size\n"		/* image size to copy */
 
 		/*
@@ -42,9 +55,19 @@ static inline void __barebox_arm_head(void)
 		".word 0x55555555\n"
 		".endr\n"
 		"2:\n"
+#ifdef CONFIG_PBL_BREAK
+#ifdef CONFIG_CPU_V8
+		"brk #17\n"
+#else
+		"bkpt #17\n"
+#endif
+		"nop\n"
+#else
+		"nop\n"
+		"nop\n"
+#endif
 	);
 }
-
 static inline void barebox_arm_head(void)
 {
 	__barebox_arm_head();

base-commit: 72424fd057d135ec0e41139fe4cb5740471d33a5
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Thu Aug  5 08:22:18 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Thu,  5 Aug 2021 17:22:18 +0200
Subject: [PATCH 2/2] arm: mxs: Replace license and copyright boilerplate by
 SPDX identifiers
In-Reply-To: <20210805152218.1901918-1-u.kleine-koenig@pengutronix.de>
References: <20210805152218.1901918-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210805152218.1901918-2-u.kleine-koenig@pengutronix.de>

Converts the files that licensecheck can determine to be licensed under
GPL-2.0-only or GPL-2.0-or-later and also convert their copyright
statements to SPDX.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 arch/arm/mach-mxs/bcb.c                      | 10 +++-------
 arch/arm/mach-mxs/clocksource-imx23.c        | 16 ++-------------
 arch/arm/mach-mxs/clocksource-imx28.c        | 15 ++------------
 arch/arm/mach-mxs/imx.c                      | 16 ++-------------
 arch/arm/mach-mxs/include/mach/clock.h       | 16 ++-------------
 arch/arm/mach-mxs/include/mach/fb.h          | 12 +----------
 arch/arm/mach-mxs/include/mach/generic.h     | 16 ++-------------
 arch/arm/mach-mxs/include/mach/imx-regs.h    | 16 ++-------------
 arch/arm/mach-mxs/include/mach/imx23-regs.h  | 15 ++------------
 arch/arm/mach-mxs/include/mach/imx28-regs.h  | 12 +----------
 arch/arm/mach-mxs/include/mach/iomux-imx23.h | 14 ++-----------
 arch/arm/mach-mxs/include/mach/iomux-imx28.h | 12 +----------
 arch/arm/mach-mxs/include/mach/iomux.h       | 16 ++-------------
 arch/arm/mach-mxs/include/mach/mci.h         | 13 +-----------
 arch/arm/mach-mxs/include/mach/ssp.h         | 15 ++++----------
 arch/arm/mach-mxs/iomux-imx.c                | 16 ++-------------
 arch/arm/mach-mxs/ocotp.c                    | 17 +++++-----------
 arch/arm/mach-mxs/power.c                    | 17 ++++++----------
 arch/arm/mach-mxs/soc-imx23.c                | 19 ++++--------------
 arch/arm/mach-mxs/soc-imx28.c                | 19 ++++--------------
 arch/arm/mach-mxs/usb-imx23.c                | 20 +++++--------------
 arch/arm/mach-mxs/usb-imx28.c                | 21 +++++---------------
 22 files changed, 60 insertions(+), 283 deletions(-)

diff --git a/arch/arm/mach-mxs/bcb.c b/arch/arm/mach-mxs/bcb.c
index 860508bde7c5..749cf29af610 100644
--- a/arch/arm/mach-mxs/bcb.c
+++ b/arch/arm/mach-mxs/bcb.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2011 Wolfram Sang, Pengutronix e.K.
+
 /*
- * (C) Copyright 2011 Wolfram Sang, Pengutronix e.K.
- *
- * 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.
- *
  * Based on a similar function in Karo Electronics TX28-U-Boot (flash.c).
  * Probably written by Lothar Wa?mann (like tx28.c).
  */
diff --git a/arch/arm/mach-mxs/clocksource-imx23.c b/arch/arm/mach-mxs/clocksource-imx23.c
index 8279ee2f2df8..0a6716f87958 100644
--- a/arch/arm/mach-mxs/clocksource-imx23.c
+++ b/arch/arm/mach-mxs/clocksource-imx23.c
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix
 
 #include <common.h>
 #include <init.h>
diff --git a/arch/arm/mach-mxs/clocksource-imx28.c b/arch/arm/mach-mxs/clocksource-imx28.c
index 4f38af68b4a5..ea6d4b514630 100644
--- a/arch/arm/mach-mxs/clocksource-imx28.c
+++ b/arch/arm/mach-mxs/clocksource-imx28.c
@@ -1,16 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix <kernel at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix <kernel at pengutronix.de>
 
 #include <common.h>
 #include <init.h>
diff --git a/arch/arm/mach-mxs/imx.c b/arch/arm/mach-mxs/imx.c
index b7247b9b720a..5af9cca4e9fb 100644
--- a/arch/arm/mach-mxs/imx.c
+++ b/arch/arm/mach-mxs/imx.c
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix
 
 #include <common.h>
 #include <bootsource.h>
diff --git a/arch/arm/mach-mxs/include/mach/clock.h b/arch/arm/mach-mxs/include/mach/clock.h
index adbc3304f88e..2050b959133e 100644
--- a/arch/arm/mach-mxs/include/mach/clock.h
+++ b/arch/arm/mach-mxs/include/mach/clock.h
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
 
 #ifndef __MACH_CLOCK_H
 # define __MACH_CLOCK_H
diff --git a/arch/arm/mach-mxs/include/mach/fb.h b/arch/arm/mach-mxs/include/mach/fb.h
index ad28f79d57db..8fcfe8652067 100644
--- a/arch/arm/mach-mxs/include/mach/fb.h
+++ b/arch/arm/mach-mxs/include/mach/fb.h
@@ -1,14 +1,4 @@
-/*
- * 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.
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #ifndef __MACH_FB_H
 # define __MACH_FB_H
diff --git a/arch/arm/mach-mxs/include/mach/generic.h b/arch/arm/mach-mxs/include/mach/generic.h
index d63fa4825743..dc1b6ed4a008 100644
--- a/arch/arm/mach-mxs/include/mach/generic.h
+++ b/arch/arm/mach-mxs/include/mach/generic.h
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
 
 #ifdef CONFIG_ARCH_IMX23
 # define cpu_is_mx23()	(1)
diff --git a/arch/arm/mach-mxs/include/mach/imx-regs.h b/arch/arm/mach-mxs/include/mach/imx-regs.h
index f5abd8bf796b..4aede1bc9318 100644
--- a/arch/arm/mach-mxs/include/mach/imx-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx-regs.h
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
 
 #ifndef _IMX_REGS_H
 # define _IMX_REGS_H
diff --git a/arch/arm/mach-mxs/include/mach/imx23-regs.h b/arch/arm/mach-mxs/include/mach/imx23-regs.h
index 3fd2f3d15b94..a9a295fcbcd6 100644
--- a/arch/arm/mach-mxs/include/mach/imx23-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx23-regs.h
@@ -1,16 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
 
 #ifndef __ASM_ARCH_MX23_REGS_H
 #define __ASM_ARCH_MX23_REGS_H
diff --git a/arch/arm/mach-mxs/include/mach/imx28-regs.h b/arch/arm/mach-mxs/include/mach/imx28-regs.h
index 1a90ec2aa561..67e1009a9917 100644
--- a/arch/arm/mach-mxs/include/mach/imx28-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx28-regs.h
@@ -1,14 +1,4 @@
-/*
- * 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.
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #ifndef __ASM_ARCH_MX28_REGS_H
 #define __ASM_ARCH_MX28_REGS_H
diff --git a/arch/arm/mach-mxs/include/mach/iomux-imx23.h b/arch/arm/mach-mxs/include/mach/iomux-imx23.h
index 1e225f8fc51b..78a55a47b10d 100644
--- a/arch/arm/mach-mxs/include/mach/iomux-imx23.h
+++ b/arch/arm/mach-mxs/include/mach/iomux-imx23.h
@@ -1,15 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
 
 #ifndef __ASM_MACH_IOMUX_MX23_H
 #define __ASM_MACH_IOMUX_MX23_H
diff --git a/arch/arm/mach-mxs/include/mach/iomux-imx28.h b/arch/arm/mach-mxs/include/mach/iomux-imx28.h
index 6119f3caf98d..9fefe3a2af36 100644
--- a/arch/arm/mach-mxs/include/mach/iomux-imx28.h
+++ b/arch/arm/mach-mxs/include/mach/iomux-imx28.h
@@ -1,14 +1,4 @@
-/*
- * 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.
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #ifndef __MACH_IOMUX_IMX28_H
 #define __MACH_IOMUX_IMX28_H
diff --git a/arch/arm/mach-mxs/include/mach/iomux.h b/arch/arm/mach-mxs/include/mach/iomux.h
index 0091dbae1194..47e843e43f50 100644
--- a/arch/arm/mach-mxs/include/mach/iomux.h
+++ b/arch/arm/mach-mxs/include/mach/iomux.h
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix */
 
 #ifndef __ASM_MACH_IOMUX_H
 #define __ASM_MACH_IOMUX_H
diff --git a/arch/arm/mach-mxs/include/mach/mci.h b/arch/arm/mach-mxs/include/mach/mci.h
index c47c24cba831..3383635dfc13 100644
--- a/arch/arm/mach-mxs/include/mach/mci.h
+++ b/arch/arm/mach-mxs/include/mach/mci.h
@@ -1,15 +1,4 @@
-/*
- * 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.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #ifndef __MACH_MMC_H
 #define __MACH_MMC_H
diff --git a/arch/arm/mach-mxs/include/mach/ssp.h b/arch/arm/mach-mxs/include/mach/ssp.h
index 5eee5c010a02..b90a44820519 100644
--- a/arch/arm/mach-mxs/include/mach/ssp.h
+++ b/arch/arm/mach-mxs/include/mach/ssp.h
@@ -1,14 +1,7 @@
-/*
- * Freescale MXS SSP
- *
- * Copyright (C) 2013 Michael Grzeschik <mgr at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2013 Michael Grzeschik <mgr at pengutronix.de> */
+
+/* Freescale MXS SSP */
 
 #ifndef __SSP_H__
 #define __SSP_H__
diff --git a/arch/arm/mach-mxs/iomux-imx.c b/arch/arm/mach-mxs/iomux-imx.c
index 68a4e3cbd6cb..6b96fc4ed9c9 100644
--- a/arch/arm/mach-mxs/iomux-imx.c
+++ b/arch/arm/mach-mxs/iomux-imx.c
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2010 Juergen Beisert - Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix
 
 #include <common.h>
 #include <init.h>
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
index a4df39c2e902..5f78d9d773ec 100644
--- a/arch/arm/mach-mxs/ocotp.c
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -1,15 +1,8 @@
-/*
- * ocotp.c - barebox driver for the On-Chip One Time Programmable for MXS
- *
- * Copyright (C) 2012 by Wolfram Sang, Pengutronix e.K.
- * based on the kernel driver which is
- * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2012 Wolfram Sang, Pengutronix e.K.
+// SPDX-FileCopyrightText: 2010 Freescale Semiconductor, Inc.
+
+/* ocotp.c - barebox driver for the On-Chip One Time Programmable for MXS */
 
 #include <common.h>
 #include <init.h>
diff --git a/arch/arm/mach-mxs/power.c b/arch/arm/mach-mxs/power.c
index 6febf5dbaa52..342f7b0271c1 100644
--- a/arch/arm/mach-mxs/power.c
+++ b/arch/arm/mach-mxs/power.c
@@ -1,14 +1,9 @@
-/*
- * i.MX28 power related functions
- *
- * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
- * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
+// SPDX-FileCopyrightText: 2012 Wolfram Sang <w.sang at pengutronix.de>, Pengutronix
+
+/* i.MX28 power related functions */
+
 #include <common.h>
 #include <io.h>
 #include <stmp-device.h>
diff --git a/arch/arm/mach-mxs/soc-imx23.c b/arch/arm/mach-mxs/soc-imx23.c
index 8c47c766cc2b..16b1fda5ed95 100644
--- a/arch/arm/mach-mxs/soc-imx23.c
+++ b/arch/arm/mach-mxs/soc-imx23.c
@@ -1,18 +1,7 @@
-/*
- * (c) 2012 Juergen Beisert <kernel at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * Collection of some SoC specific functions
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2012 Juergen Beisert <kernel at pengutronix.de>
+
+/* Collection of some SoC specific functions */
 
 #include <common.h>
 #include <init.h>
diff --git a/arch/arm/mach-mxs/soc-imx28.c b/arch/arm/mach-mxs/soc-imx28.c
index a214e2b7a6d9..e3d3cb1c0a30 100644
--- a/arch/arm/mach-mxs/soc-imx28.c
+++ b/arch/arm/mach-mxs/soc-imx28.c
@@ -1,18 +1,7 @@
-/*
- * (c) 2012 Juergen Beisert <kernel at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * Collection of some SoC specific functions
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2012 Juergen Beisert <kernel at pengutronix.de>
+
+/* Collection of some SoC specific functions */
 
 #include <common.h>
 #include <init.h>
diff --git a/arch/arm/mach-mxs/usb-imx23.c b/arch/arm/mach-mxs/usb-imx23.c
index d9a54b66f89d..6acf1bb7866b 100644
--- a/arch/arm/mach-mxs/usb-imx23.c
+++ b/arch/arm/mach-mxs/usb-imx23.c
@@ -1,18 +1,8 @@
-/*
- * i.MX23 USBPHY setup
- *
- * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
+
+/* i.MX23 USBPHY setup */
+
 #include <common.h>
 #include <io.h>
 #include <mach/imx23-regs.h>
diff --git a/arch/arm/mach-mxs/usb-imx28.c b/arch/arm/mach-mxs/usb-imx28.c
index a4e1bdb2802e..3793169b5985 100644
--- a/arch/arm/mach-mxs/usb-imx28.c
+++ b/arch/arm/mach-mxs/usb-imx28.c
@@ -1,19 +1,8 @@
-/*
- * i.MX28 USBPHY setup
- *
- * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
+
+/* i.MX28 USBPHY setup */
+
 #include <common.h>
 #include <io.h>
 #include <errno.h>
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Thu Aug  5 08:22:51 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Thu,  5 Aug 2021 17:22:51 +0200
Subject: [PATCH 2/2] imx-usb-loader: Add support for i.MX8MP
In-Reply-To: <20210805152251.1902158-1-u.kleine-koenig@pengutronix.de>
References: <20210805152251.1902158-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210805152251.1902158-2-u.kleine-koenig@pengutronix.de>

From: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>

The i.MX8MP uses a protocol similar to the MXS. The relevant differences
are:

 - Maximal transfer size is 1020
 - HID reports must be sent to EP1 instead of using a control transfer
 - The FW_DOWNLOAD command must not be send.

Signed-off-by: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
---
 scripts/imx/imx-usb-loader.c | 65 +++++++++++++++++++++++-------------
 1 file changed, 42 insertions(+), 23 deletions(-)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 3e96c86f2f29..40a85ee26105 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -71,6 +71,7 @@ struct mach_id {
 #define DEV_IMX		0
 #define DEV_MXS		1
 	unsigned char dev_type;
+	unsigned char hid_endpoint;
 };
 
 struct usb_work {
@@ -177,6 +178,13 @@ static const struct mach_id imx_ids[] = {
 		.header_type = HDR_MX53,
 		.mode = MODE_HID,
 		.max_transfer = 1024,
+	}, {
+		.vid = 0x1fc9,
+		.pid = 0x0146,
+		.name = "i.MX8MP",
+		.max_transfer = 1020,
+		.dev_type = DEV_MXS,
+		.hid_endpoint = 1,
 	}, {
 		.vid = 0x1fc9,
 		.pid = 0x012b,
@@ -522,15 +530,24 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
 
 		if (report < 3) {
 			memcpy(&tmp[1], p, cnt);
-			err = libusb_control_transfer(usb_dev_handle,
-					CTRL_OUT,
-					HID_SET_REPORT,
-					(HID_REPORT_TYPE_OUTPUT << 8) | report,
-					0,
-					tmp, cnt + 1, 1000);
-			*last_trans = (err > 0) ? err - 1 : 0;
-			if (err > 0)
-				err = 0;
+			if (mach_id->hid_endpoint) {
+				int trans;
+				err = libusb_interrupt_transfer(usb_dev_handle,
+						mach_id->hid_endpoint, tmp, cnt + 1, &trans, 1000);
+				if (err == 0 && last_trans)
+					*last_trans = trans - 1;
+			} else {
+				err = libusb_control_transfer(usb_dev_handle,
+						CTRL_OUT,
+						HID_SET_REPORT,
+						(HID_REPORT_TYPE_OUTPUT << 8) | report,
+						0,
+						tmp, cnt + 1, 1000);
+				if (err > 0) {
+					*last_trans = err - 1;
+					err = 0;
+				}
+			}
 		} else {
 			*last_trans = 0;
 			memset(&tmp[1], 0, cnt);
@@ -1507,20 +1524,22 @@ static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size)
 	void *p;
 	int cnt;
 
-	dl_command.sign = htonl(0x424c5443); /* Signature: BLTC */
-	dl_command.tag = htonl(0x1);
-	dl_command.size = htonl(size);
-	dl_command.flags = 0;
-	dl_command.rsvd[0] = 0;
-	dl_command.rsvd[1] = 0;
-	dl_command.cmd = MXS_CMD_FW_DOWNLOAD;
-	dl_command.dw_size = htonl(size);
-
-	err = transfer(1, (unsigned char *) &dl_command, 20, &last_trans);
-	if (err) {
-		printf("transfer error at init step: err=%i, last_trans=%i\n",
-		       err, last_trans);
-		return err;
+	if (!mach_id->hid_endpoint) {
+		dl_command.sign = htonl(0x424c5443); /* Signature: BLTC */
+		dl_command.tag = htonl(0x1);
+		dl_command.size = htonl(size);
+		dl_command.flags = 0;
+		dl_command.rsvd[0] = 0;
+		dl_command.rsvd[1] = 0;
+		dl_command.cmd = MXS_CMD_FW_DOWNLOAD;
+		dl_command.dw_size = htonl(size);
+
+		err = transfer(1, (unsigned char *) &dl_command, 20, &last_trans);
+		if (err) {
+			printf("transfer error at init step: err=%i, last_trans=%i\n",
+					err, last_trans);
+			return err;
+		}
 	}
 
 	p = data;
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Thu Aug  5 08:22:50 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Thu,  5 Aug 2021 17:22:50 +0200
Subject: [PATCH 1/2] imx-usb-loader: Drop nearly unused struct usb_id
Message-ID: <20210805152251.1902158-1-u.kleine-koenig@pengutronix.de>

From: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>

Only one of the two members of struct usb_id is actually used. So
replace struct usb_id by a struct mach_id.

Signed-off-by: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
---
 scripts/imx/imx-usb-loader.c | 51 ++++++++++++------------------------
 1 file changed, 17 insertions(+), 34 deletions(-)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index cff77f27f264..3e96c86f2f29 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -52,7 +52,7 @@
 
 int verbose;
 static struct libusb_device_handle *usb_dev_handle;
-static struct usb_id *usb_id;
+static const struct mach_id *mach_id;
 
 struct mach_id {
 	struct mach_id * next;
@@ -79,11 +79,6 @@ struct usb_work {
 	unsigned char plug;
 };
 
-struct usb_id {
-	const struct mach_id *mach_id;
-	struct usb_work *work;
-};
-
 static const struct mach_id imx_ids[] = {
 	{
 		.vid = 0x066f,
@@ -507,8 +502,8 @@ static int read_file(const char *name, unsigned char **buffer, unsigned *size)
 static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
 {
 	int err;
-	if (cnt > usb_id->mach_id->max_transfer)
-		cnt = usb_id->mach_id->max_transfer;
+	if (cnt > mach_id->max_transfer)
+		cnt = mach_id->max_transfer;
 
 	if (verbose > 4) {
 		printf("report=%i\n", report);
@@ -516,7 +511,7 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
 			dump_bytes(p, cnt, 0);
 	}
 
-	if (usb_id->mach_id->mode == MODE_BULK) {
+	if (mach_id->mode == MODE_BULK) {
 		*last_trans = 0;
 		err = libusb_bulk_transfer(usb_dev_handle,
 					   (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
@@ -602,7 +597,7 @@ static int do_status(void)
 			break;
 	}
 
-	if (usb_id->mach_id->mode == MODE_HID) {
+	if (mach_id->mode == MODE_HID) {
 		err = transfer(4, tmp, sizeof(tmp), &last_trans);
 		if (err)
 			printf("4 in err=%i, last_trans=%i  %02x %02x %02x %02x\n",
@@ -810,7 +805,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
 
 	retry = 0;
 
-	if (usb_id->mach_id->mode == MODE_BULK) {
+	if (mach_id->mode == MODE_BULK) {
 		err = transfer(3, tmp, sizeof(tmp), &last_trans);
 		if (err)
 			printf("in err=%i, last_trans=%i  %02x %02x %02x %02x\n",
@@ -821,7 +816,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
 	cnt = len;
 
 	while (1) {
-		int now = get_min(cnt, usb_id->mach_id->max_transfer);
+		int now = get_min(cnt, mach_id->max_transfer);
 
 		if (!now)
 			break;
@@ -839,7 +834,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
 	if (mode_barebox)
 		return transfer_size;
 
-	if (usb_id->mach_id->mode == MODE_HID) {
+	if (mach_id->mode == MODE_HID) {
 		err = transfer(3, tmp, sizeof(tmp), &last_trans);
 		if (err)
 			printf("3 in err=%i, last_trans=%i  %02x %02x %02x %02x\n",
@@ -1233,7 +1228,7 @@ static int is_header(const unsigned char *p)
 	const struct imx_flash_header_v2 *hdr =
 		(const struct imx_flash_header_v2 *)p;
 
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 		if (ohdr->app_code_barker == 0xb1)
 			return 1;
@@ -1253,7 +1248,7 @@ static int perform_dcd(unsigned char *p, const unsigned char *file_start,
 	struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
 	int ret = 0;
 
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 		ret = write_dcd_table_old(ohdr, file_start, cnt);
 		ohdr->dcd_block_len = 0;
@@ -1274,7 +1269,7 @@ static int get_dl_start(const unsigned char *p, const unsigned char *file_start,
 		unsigned *header_addr)
 {
 	const unsigned char *file_end = file_start + cnt;
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 	{
 		struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
@@ -1315,7 +1310,7 @@ static int get_payload_start(const unsigned char *p, uint32_t *ofs)
 {
 	struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
 
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 		return -EINVAL;
 
@@ -1430,7 +1425,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
 
 		memcpy(verify_buffer, image, 64);
 
-		if ((type == FT_APP) && (usb_id->mach_id->mode != MODE_HID)) {
+		if ((type == FT_APP) && (mach_id->mode != MODE_HID)) {
 			type = FT_LOAD_ONLY;
 			verify = 2;
 		}
@@ -1469,7 +1464,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
 		}
 	}
 
-	if (usb_id->mach_id->mode == MODE_HID && type == FT_APP) {
+	if (mach_id->mode == MODE_HID && type == FT_APP) {
 		printf("jumping to 0x%08x\n", header_addr);
 
 		ret = sdp_jump_address(header_addr);
@@ -1532,7 +1527,7 @@ static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size)
 	cnt = size;
 
 	while (1) {
-		int now = get_min(cnt, usb_id->mach_id->max_transfer);
+		int now = get_min(cnt, mach_id->max_transfer);
 
 		if (!now)
 			break;
@@ -1591,7 +1586,6 @@ static void usage(const char *prgname)
 
 int main(int argc, char *argv[])
 {
-	const struct mach_id *mach;
 	libusb_device **devs;
 	libusb_device *dev;
 	int r;
@@ -1663,7 +1657,7 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
-	dev = find_imx_dev(devs, &mach, devpath, devtype);
+	dev = find_imx_dev(devs, &mach_id, devpath, devtype);
 	if (!dev) {
 		fprintf(stderr, "no supported device found\n");
 		goto out;
@@ -1682,15 +1676,7 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
-	usb_id = malloc(sizeof(*usb_id));
-	if (!usb_id) {
-		perror("malloc");
-		exit(1);
-	}
-
-	usb_id->mach_id = mach;
-
-	if (mach->dev_type == DEV_MXS) {
+	if (mach_id->dev_type == DEV_MXS) {
 		ret = mxs_work(&w);
 		goto out;
 	}
@@ -1715,9 +1701,6 @@ int main(int argc, char *argv[])
 
 	ret = 0;
 out:
-	if (usb_id)
-		free(usb_id);
-
 	if (usb_dev_handle)
 		libusb_close(usb_dev_handle);
 

base-commit: 72424fd057d135ec0e41139fe4cb5740471d33a5
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug  5 08:32:01 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 5 Aug 2021 17:32:01 +0200
Subject: [PATCH 2/2] ARM: i.MX8MM: add reboot to serial download mode
In-Reply-To: <20210803165937.31608-2-a.fatoum@pengutronix.de>
References: <20210803165937.31608-1-a.fatoum@pengutronix.de>
 <20210803165937.31608-2-a.fatoum@pengutronix.de>
Message-ID: <7a0b3298-2fe4-13d3-e6ef-28814a8831c2@pengutronix.de>

Hello Uwe,

On 03.08.21 18:59, Ahmad Fatoum wrote:
> The i.MX8MM reference manual follows long established tradition in not
> documenting BootROM magic reboot codes. For older i.MX variants, the
> values can be seen in the bmode tables of Freescale's U-Boot patches.
> 
> There are no such patches for the i.MX8M, but testing shows that
> 
> 	mw 0x30390094 0x10 ; mw 0x30390098 0x40000000
> 
> is one of the configurations that trigger serial download on next warm
> reset on an i.MX8MM. Describe this in the device tree, so
> 
> 	gpr.reboot_mode.next=serial reset -r imxwd-warm
> 
> does the right thing for that SoC.

As you are currently doing i.MX8MP serial boot work, could you apply this
series, boot barebox containing it (and the i.MX watchdog driver)
from eMMC and try out:

	mw 0x30390094 0x10 ; mw 0x30390098 0x40000000
	reset -r imxwd-warm

If the 8MP is similar enough to the 8MM in this respect, the BootROM
should fall into serial download mode despite being strapped for
eMMC.

Thanks!
Ahmad


> 
> This all might work for other i.MX8M variants as well, but the dtsi
> can be genericized later on when tested.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
> Cc: David Jander <david at protonic.nl>
> Cc: Lucas Stach <l.stach at pengutronix.de>
> ---
>  Documentation/boards/imx.rst   | 29 +++++++++++++++++++++++++++++
>  arch/arm/dts/imx8mm-evk.dts    |  1 +
>  arch/arm/dts/imx8mm-prt8mm.dts |  1 +
>  arch/arm/dts/imx8mm.dtsi       | 18 ++++++++++++++++++
>  4 files changed, 49 insertions(+)
>  create mode 100644 arch/arm/dts/imx8mm.dtsi
> 
> diff --git a/Documentation/boards/imx.rst b/Documentation/boards/imx.rst
> index 887b45c70881..4ce9d9808cc1 100644
> --- a/Documentation/boards/imx.rst
> +++ b/Documentation/boards/imx.rst
> @@ -83,6 +83,35 @@ The images can also always be started as second stage on the target:
>  
>    barebox at Board Name:/ bootm /mnt/tftp/barebox-freescale-imx51-babbage.img
>  
> +BootROM Reboot mode codes (bmode)
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +For select SoCs, barebox supports communicating an alternative boot medium
> +that BootROM should select after a warm reset::
> +
> +  barebox at FSL i.MX8MM EVK board:/ devinfo gpr.reboot_mode
> +  Driver: syscon-reboot-mode
> +  Bus: platform
> +  Parent: 30390000.reset-controller at 30390000.of
> +  Parameters:
> +    next: normal (type: enum) (values: "normal", "serial")
> +    prev: normal (type: enum) (values: "normal", "serial")
> +  Device node: /soc at 0/bus at 30000000/reset-controller at 30390000/reboot-mode
> +  reboot-mode {
> +          compatible = "barebox,syscon-reboot-mode";
> +          offset = <0x94 0x98>;
> +          mask = <0xffffffff 0x40000000>;
> +          mode-normal = <0x0 0x0>;
> +          mode-serial = <0x10 0x40000000>;
> +  };
> +
> +  barebox at FSL i.MX8MM EVK board:/ gpr.reboot_mode.next=serial reset -r imxwd-warm
> +
> +This will cause barebox to fall into serial download mode on an i.MX8MM.
> +
> +Different SoCs may have more possible reboot modes available.
> +See the section on :ref:`Reboot modes<reboot_mode>` for more information.
> +
>  High Assurance Boot
>  ^^^^^^^^^^^^^^^^^^^
>  
> diff --git a/arch/arm/dts/imx8mm-evk.dts b/arch/arm/dts/imx8mm-evk.dts
> index 1e8619ccf584..304f150307a3 100644
> --- a/arch/arm/dts/imx8mm-evk.dts
> +++ b/arch/arm/dts/imx8mm-evk.dts
> @@ -7,6 +7,7 @@
>  /dts-v1/;
>  
>  #include <arm64/freescale/imx8mm-evk.dts>
> +#include "imx8mm.dtsi"
>  
>  / {
>  	chosen {
> diff --git a/arch/arm/dts/imx8mm-prt8mm.dts b/arch/arm/dts/imx8mm-prt8mm.dts
> index bdcdd0806243..abd758f2856e 100644
> --- a/arch/arm/dts/imx8mm-prt8mm.dts
> +++ b/arch/arm/dts/imx8mm-prt8mm.dts
> @@ -7,6 +7,7 @@
>  /dts-v1/;
>  
>  #include <arm64/freescale/imx8mm.dtsi>
> +#include "imx8mm.dtsi"
>  
>  / {
>  	model = "Protonic PRT8MM";
> diff --git a/arch/arm/dts/imx8mm.dtsi b/arch/arm/dts/imx8mm.dtsi
> new file mode 100644
> index 000000000000..78bbacb2b1b2
> --- /dev/null
> +++ b/arch/arm/dts/imx8mm.dtsi
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/ {
> +	aliases {
> +		gpr.reboot_mode = &reboot_mode_gpr;
> +	};
> +};
> +
> +&src {
> +	compatible = "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon", "simple-mfd";
> +
> +	reboot_mode_gpr: reboot-mode {
> +		compatible = "barebox,syscon-reboot-mode";
> +		offset = <0x94>, <0x98>; /* SRC_GPR{9,10} */
> +		mask = <0xffffffff>, <0x40000000>;
> +		mode-normal = <0>, <0>;
> +		mode-serial = <0x00000010>, <0x40000000>;
> +	};
> +};
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From u.kleine-koenig at pengutronix.de  Fri Aug  6 01:40:54 2021
From: u.kleine-koenig at pengutronix.de (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Fri, 6 Aug 2021 10:40:54 +0200
Subject: [PATCH 1/2] arm/mvebu: sync barebox-arm-head.h to generic variant
In-Reply-To: <20210805152218.1901918-1-u.kleine-koenig@pengutronix.de>
References: <20210805152218.1901918-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210806084054.7ko3rubp5rcrqkba@pengutronix.de>

Hello,

please disregard this series. The patches are already on the list in
their own threads. This was just me git-send-emailing the wrong branch
...

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210806/2fb7ba26/attachment.sig>

From m.felsch at pengutronix.de  Fri Aug  6 02:33:37 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Fri,  6 Aug 2021 11:33:37 +0200
Subject: [PATCH] scripts: bareboxenv: add erase hint if build as host-tool
Message-ID: <20210806093337.10153-1-m.felsch@pengutronix.de>

The bareboxenv behviour is different if used as host-tool. As host-tool
the erase is skipped which can confuse the user. Add a help note as hot
fix. In the long term we should add the host-tool erase support as well.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 scripts/bareboxenv.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index bdff644335..f1706a5e17 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -98,6 +98,12 @@ static void usage(char *prgname)
 	printf( "Usage : %s [OPTION] DIRECTORY FILE\n"
 		"Load a barebox environment sector into a directory or\n"
 		"save a directory into a barebox environment sector\n"
+#ifndef __BAREBOX__
+		"\n"
+		"Attention:\n"
+		"Depending on your environment backend storage you need to\n"
+		"erase FILE before you save the new environment.\n"
+#endif
 		"\n"
 		"options:\n"
 		"  -s        save (directory -> environment sector)\n"
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Aug  9 03:40:31 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 9 Aug 2021 12:40:31 +0200
Subject: [PATCH 2/2] ARM: i.MX8MM: add reboot to serial download mode
In-Reply-To: <7a0b3298-2fe4-13d3-e6ef-28814a8831c2@pengutronix.de>
References: <20210803165937.31608-1-a.fatoum@pengutronix.de>
 <20210803165937.31608-2-a.fatoum@pengutronix.de>
 <7a0b3298-2fe4-13d3-e6ef-28814a8831c2@pengutronix.de>
Message-ID: <aa57423e-2141-12a9-cc9d-845730e0190b@pengutronix.de>

On 05.08.21 17:32, Ahmad Fatoum wrote:
> On 03.08.21 18:59, Ahmad Fatoum wrote:
>> The i.MX8MM reference manual follows long established tradition in not
>> documenting BootROM magic reboot codes. For older i.MX variants, the
>> values can be seen in the bmode tables of Freescale's U-Boot patches.
>>
>> There are no such patches for the i.MX8M, but testing shows that
>>
>> 	mw 0x30390094 0x10 ; mw 0x30390098 0x40000000
>>
>> is one of the configurations that trigger serial download on next warm
>> reset on an i.MX8MM. Describe this in the device tree, so
>>
>> 	gpr.reboot_mode.next=serial reset -r imxwd-warm
>>
>> does the right thing for that SoC.
> 
> As you are currently doing i.MX8MP serial boot work, could you apply this
> series, boot barebox containing it (and the i.MX watchdog driver)
> from eMMC and try out:
> 
> 	mw 0x30390094 0x10 ; mw 0x30390098 0x40000000
> 	reset -r imxwd-warm
> 
> If the 8MP is similar enough to the 8MM in this respect, the BootROM
> should fall into serial download mode despite being strapped for
> eMMC.

FTR: The same sequence doesn't work on a 8MP.

> 
> Thanks!
> Ahmad
> 
> 
>>
>> This all might work for other i.MX8M variants as well, but the dtsi
>> can be genericized later on when tested.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>> ---
>> Cc: David Jander <david at protonic.nl>
>> Cc: Lucas Stach <l.stach at pengutronix.de>
>> ---
>>  Documentation/boards/imx.rst   | 29 +++++++++++++++++++++++++++++
>>  arch/arm/dts/imx8mm-evk.dts    |  1 +
>>  arch/arm/dts/imx8mm-prt8mm.dts |  1 +
>>  arch/arm/dts/imx8mm.dtsi       | 18 ++++++++++++++++++
>>  4 files changed, 49 insertions(+)
>>  create mode 100644 arch/arm/dts/imx8mm.dtsi
>>
>> diff --git a/Documentation/boards/imx.rst b/Documentation/boards/imx.rst
>> index 887b45c70881..4ce9d9808cc1 100644
>> --- a/Documentation/boards/imx.rst
>> +++ b/Documentation/boards/imx.rst
>> @@ -83,6 +83,35 @@ The images can also always be started as second stage on the target:
>>  
>>    barebox at Board Name:/ bootm /mnt/tftp/barebox-freescale-imx51-babbage.img
>>  
>> +BootROM Reboot mode codes (bmode)
>> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> +
>> +For select SoCs, barebox supports communicating an alternative boot medium
>> +that BootROM should select after a warm reset::
>> +
>> +  barebox at FSL i.MX8MM EVK board:/ devinfo gpr.reboot_mode
>> +  Driver: syscon-reboot-mode
>> +  Bus: platform
>> +  Parent: 30390000.reset-controller at 30390000.of
>> +  Parameters:
>> +    next: normal (type: enum) (values: "normal", "serial")
>> +    prev: normal (type: enum) (values: "normal", "serial")
>> +  Device node: /soc at 0/bus at 30000000/reset-controller at 30390000/reboot-mode
>> +  reboot-mode {
>> +          compatible = "barebox,syscon-reboot-mode";
>> +          offset = <0x94 0x98>;
>> +          mask = <0xffffffff 0x40000000>;
>> +          mode-normal = <0x0 0x0>;
>> +          mode-serial = <0x10 0x40000000>;
>> +  };
>> +
>> +  barebox at FSL i.MX8MM EVK board:/ gpr.reboot_mode.next=serial reset -r imxwd-warm
>> +
>> +This will cause barebox to fall into serial download mode on an i.MX8MM.
>> +
>> +Different SoCs may have more possible reboot modes available.
>> +See the section on :ref:`Reboot modes<reboot_mode>` for more information.
>> +
>>  High Assurance Boot
>>  ^^^^^^^^^^^^^^^^^^^
>>  
>> diff --git a/arch/arm/dts/imx8mm-evk.dts b/arch/arm/dts/imx8mm-evk.dts
>> index 1e8619ccf584..304f150307a3 100644
>> --- a/arch/arm/dts/imx8mm-evk.dts
>> +++ b/arch/arm/dts/imx8mm-evk.dts
>> @@ -7,6 +7,7 @@
>>  /dts-v1/;
>>  
>>  #include <arm64/freescale/imx8mm-evk.dts>
>> +#include "imx8mm.dtsi"
>>  
>>  / {
>>  	chosen {
>> diff --git a/arch/arm/dts/imx8mm-prt8mm.dts b/arch/arm/dts/imx8mm-prt8mm.dts
>> index bdcdd0806243..abd758f2856e 100644
>> --- a/arch/arm/dts/imx8mm-prt8mm.dts
>> +++ b/arch/arm/dts/imx8mm-prt8mm.dts
>> @@ -7,6 +7,7 @@
>>  /dts-v1/;
>>  
>>  #include <arm64/freescale/imx8mm.dtsi>
>> +#include "imx8mm.dtsi"
>>  
>>  / {
>>  	model = "Protonic PRT8MM";
>> diff --git a/arch/arm/dts/imx8mm.dtsi b/arch/arm/dts/imx8mm.dtsi
>> new file mode 100644
>> index 000000000000..78bbacb2b1b2
>> --- /dev/null
>> +++ b/arch/arm/dts/imx8mm.dtsi
>> @@ -0,0 +1,18 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/ {
>> +	aliases {
>> +		gpr.reboot_mode = &reboot_mode_gpr;
>> +	};
>> +};
>> +
>> +&src {
>> +	compatible = "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon", "simple-mfd";
>> +
>> +	reboot_mode_gpr: reboot-mode {
>> +		compatible = "barebox,syscon-reboot-mode";
>> +		offset = <0x94>, <0x98>; /* SRC_GPR{9,10} */
>> +		mask = <0xffffffff>, <0x40000000>;
>> +		mode-normal = <0>, <0>;
>> +		mode-serial = <0x00000010>, <0x40000000>;
>> +	};
>> +};
>>
> 
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Aug  9 03:49:37 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 9 Aug 2021 12:49:37 +0200
Subject: [PATCH 3/3] ls1046ardb: enable IFC NAND.
In-Reply-To: <1627900804-15814-4-git-send-email-renaud.barbier@abaco.com>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
 <1627900804-15814-4-git-send-email-renaud.barbier@abaco.com>
Message-ID: <471e6659-459f-f6e6-7abf-9b6141e6c7a3@pengutronix.de>

Hello Renaud,

On 02.08.21 12:40, Renaud Barbier wrote:
> Set the NAND timings and enable the IFC NAND driver.
> 
> Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
> ---
>  arch/arm/boards/ls1046ardb/board.c    | 42 +++++++++++++++++++++++++++
>  arch/arm/configs/layerscape_defconfig | 11 +++++++
>  2 files changed, 53 insertions(+)
> 
> diff --git a/arch/arm/boards/ls1046ardb/board.c b/arch/arm/boards/ls1046ardb/board.c
> index ef68e9c7f9..b2cfba58a8 100644
> --- a/arch/arm/boards/ls1046ardb/board.c
> +++ b/arch/arm/boards/ls1046ardb/board.c
> @@ -8,10 +8,12 @@
>  #include <fs.h>
>  #include <envfs.h>
>  #include <libfile.h>
> +#include <of_address.h>
>  #include <asm/memory.h>
>  #include <linux/sizes.h>
>  #include <linux/clk.h>
>  #include <linux/clkdev.h>
> +#include <linux/fsl_ifc.h>
>  #include <asm/system.h>
>  #include <mach/layerscape.h>
>  #include <mach/bbu.h>
> @@ -35,6 +37,11 @@ struct nxid {
>  	u32 crc;          /* 0xfc - 0xff CRC32 checksum */
>  } __packed;
>  
> +static const struct of_device_id fsl_ifc_of_ids[] = {
> +	{ .compatible = "fsl,ifc", },
> +	{ },
> +};
> +
>  static int nxid_is_valid(struct nxid *nxid)
>  {
>  	unsigned char id[] = { 'N', 'X', 'I', 'D' };
> @@ -161,3 +168,38 @@ static int rdb_postcore_init(void)
>  }
>  
>  postcore_initcall(rdb_postcore_init);
> +
> +static int rdb_nand_init(void)
> +{
> +	struct device_node *np;
> +	void __iomem *ifc;
> +

If you think this configuration should be done for _all_ boards,
you should move it to arch/arm/mach-layerscape. If you intend it
to be done only for this specific board, you should check the
board compatible, otherwise this function is called even for
boards that don't have NAND physically. Throwing an error
there is inappropriate. If this is board-specific, please add:


	if (!of_machine_is_compatible("fsl,ls1046a-rdb"))

		return 0;

> +	np = of_find_matching_node(NULL, fsl_ifc_of_ids);

You can use of_find_compatible_node, which lets you drop the struct.

> +	if (!np)
> +		return -EINVAL;
> +
> +	ifc = of_iomap(np, 0);
> +	if (!ifc)
> +		return -EINVAL;
> +
> +	set_ifc_cspr(ifc, IFC_CS0, CSPR_PHYS_ADDR(0x7e800000) |
> +			CSPR_PORT_SIZE_8 | CSPR_MSEL_NAND | CSPR_V);
> +	set_ifc_csor(ifc, IFC_CS0, CSOR_NAND_ECC_ENC_EN | CSOR_NAND_ECC_DEC_EN |
> +			CSOR_NAND_ECC_MODE_8 |
> +			CSOR_NAND_RAL_3 | CSOR_NAND_PGS_4K |
> +			CSOR_NAND_SPRZ_224 |  CSOR_NAND_PB(64) |
> +			CSOR_NAND_TRHZ_20);
> +	set_ifc_amask(ifc, IFC_CS0, IFC_AMASK(64*1024));
> +	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM0, FTIM0_NAND_TCCST(0x07) |
> +			FTIM0_NAND_TWP(0x18) | FTIM0_NAND_TWCHT(0x07) |
> +			FTIM0_NAND_TWH(0x0a));
> +	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM1, FTIM1_NAND_TADLE(0x32) |
> +			FTIM1_NAND_TWBE(0x39) | FTIM1_NAND_TRR(0x0e)|
> +			FTIM1_NAND_TRP(0x18));
> +	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM2, FTIM2_NAND_TRAD(0xf) |
> +			FTIM2_NAND_TREH(0xa) | FTIM2_NAND_TWHRE(0x1e));
> +	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM3, 0);
> +
> +	return 0;
> +}
> +postcore_initcall(rdb_nand_init);
> diff --git a/arch/arm/configs/layerscape_defconfig b/arch/arm/configs/layerscape_defconfig
> index 394cd95c98..fb8e885353 100644
> --- a/arch/arm/configs/layerscape_defconfig
> +++ b/arch/arm/configs/layerscape_defconfig
> @@ -34,6 +34,10 @@ CONFIG_CMD_GO=y
>  CONFIG_CMD_RESET=y
>  CONFIG_CMD_UIMAGE=y
>  CONFIG_CMD_PARTITION=y
> +CONFIG_CMD_MOUNT=y
> +CONFIG_CMD_UBI=y
> +CONFIG_CMD_UBIFORMAT=y
> +CONFIG_CMD_UMOUNT=y
>  CONFIG_CMD_EXPORT=y
>  CONFIG_CMD_LOADENV=y
>  CONFIG_CMD_PRINTENV=y
> @@ -69,6 +73,7 @@ CONFIG_CMD_GPIO=y
>  CONFIG_CMD_I2C=y
>  CONFIG_CMD_LED=y
>  CONFIG_CMD_SPI=y
> +CONFIG_CMD_NAND=y
>  CONFIG_CMD_LED_TRIGGER=y
>  CONFIG_CMD_WD=y
>  CONFIG_CMD_BAREBOX_UPDATE=y
> @@ -85,6 +90,10 @@ CONFIG_DP83867_PHY=y
>  CONFIG_REALTEK_PHY=y
>  CONFIG_NET_DSA_MV88E6XXX=y
>  CONFIG_DRIVER_SPI_FSL_QUADSPI=y
> +CONFIG_NAND=y
> +CONFIG_NAND_FSL_IFC=y
> +CONFIG_MTD_UBI=y
> +CONFIG_MTD_UBI_BEB_LIMIT=20
>  CONFIG_I2C=y
>  CONFIG_I2C_IMX=y
>  CONFIG_I2C_MUX=y
> @@ -112,5 +121,7 @@ CONFIG_FS_NFS=y
>  CONFIG_FS_FAT=y
>  CONFIG_FS_FAT_WRITE=y
>  CONFIG_FS_FAT_LFN=y
> +CONFIG_FS_UBIFS=y
> +CONFIG_FS_UBIFS_COMPRESSION_LZO=y
>  CONFIG_ZLIB=y
>  CONFIG_LZO_DECOMPRESS=y
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Aug  9 03:54:47 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 9 Aug 2021 12:54:47 +0200
Subject: Not successful if statements returning error code
In-Reply-To: <d5905da7db8e8f867e0a9e2c0a3c58e48eea7a8f.camel@diehl.com>
References: <4e1aa199-a5fa-2ad5-80cb-ef3cf86fd174@norik.com>
 <2c7807b2-e709-8042-1945-bf4d06f77f28@pengutronix.de>
 <eb2c7cc52d5a68cccaa64642ca909acf7cf25c94.camel@diehl.com>
 <1e471a43-3b6c-f632-1359-6f44a06f8c54@pengutronix.de>
 <d5905da7db8e8f867e0a9e2c0a3c58e48eea7a8f.camel@diehl.com>
Message-ID: <11ebc3d6-33d7-baaa-e3f5-bffccde285f7@pengutronix.de>

Hi,

On 29.07.21 11:48, Denis Osterland-Heim wrote:
> Hi,
> 
> Am Donnerstag, den 29.07.2021, 11:22 +0200 schrieb Ahmad Fatoum:
>> On 28.07.21 11:38, Denis Osterland-Heim wrote:
>>> Hi,
>>>
>>> Am Mittwoch, den 28.07.2021, 10:56 +0200 schrieb Ahmad Fatoum:
>>>
>>>> I talked with Sascha once before (off-list) about a similar issue. Missing error handling
>>>> results in
>>>>
>>>>   [ x1 -eq x2 ] && echo yes || echo no
>>>>
>>>> printing yes.
>>>>
>>>> We agreed that it's ok to break scripts relying on clear hush bugs like this.
>>>>
>>>> I'd thus recommend you to send a patch to fix hush instead of working around it.
>>>
>>> shellcheck says:
>>>
>>> SC2015: Note that A && B || C is not if-then-else. C may run when A is true.
>>>
>>> So I would think that B is maybe allowed to run before A, too.
>>> But, I do not know if Hush specifies execution order here.
>>
>> An option-less barebox echo can't fail, so it should never
>> print both yes and no, but thanks for the reference. I'll keep
>> an eye on it in future shell code.
>>
>> This wasn't what I meant to show though, I meant that x1 and x2
>> are both non-integers and -eq which compares integers returns
>> true when comparing them unlike what a POSIX shell does.
> Oh. Now I got your point ;-)
> 
> https://git.pengutronix.de/cgit/barebox/tree/commands/test.c#n182
> error handling is missing here.
> It is very likely that simple_strtol() returns the same value in case of error,
> which results in a successfully compare.

Yes. I noted this because of the similarity to Andrej's problem:
A bug leads to clearly bogus shell behavior. It can be ok to fix such bugs
despite them not being 100% backwards compatible.

> 
> Regards, Denis
> 
>>
>> Cheers,
>> Ahmad
>>
>>
>>>
>>> Regards, Denis
>>>
>>>>
>>>> Cheers,
>>>> Ahmad
>>>>
>>>>>
>>>>> Thank you for your answer.
>>>>>
>>>>> Best regards,
>>>>> Andrej
>>>>>
>>>>> _______________________________________________
>>>>> barebox mailing list
>>>>> barebox at lists.infradead.org
>>>>> http://lists.infradead.org/mailman/listinfo/barebox
>>>>>
>>>>
>>>>
>>>
>>> Diehl Connectivity Solutions GmbH
>>> Gesch?ftsf?hrung: Horst Leonberger
>>> Sitz der Gesellschaft: N?rnberg - Registergericht: Amtsgericht
>>> N?rnberg: HRB 32315
>>>
>>> ________________________________
>>>
>>> Der Inhalt der vorstehenden E-Mail ist nicht rechtlich bindend. Diese E-Mail enthaelt vertrauliche und/oder rechtlich geschuetzte Informationen.
>>> Informieren Sie uns bitte, wenn Sie diese E-Mail faelschlicherweise erhalten haben. Bitte loeschen Sie in diesem Fall die Nachricht.
>>> Jede unerlaubte Form der Reproduktion, Bekanntgabe, Aenderung, Verteilung und/oder Publikation dieser E-Mail ist strengstens untersagt.
>>>
>>> - Informationen zum Datenschutz, insbesondere zu Ihren Rechten, erhalten Sie unter:
>>>
>>> https://www.diehl.com/group/de/transparenz-und-informationspflichten/
>>>
>>> The contents of the above mentioned e-mail is not legally binding. This e-mail contains confidential and/or legally protected information. Please inform us if you have received this e-mail by
>>> mistake and delete it in such a case. Each unauthorized reproduction, disclosure, alteration, distribution and/or publication of this e-mail is strictly prohibited.
>>>
>>> - For general information on data protection and your respective rights please visit:
>>>
>>> https://www.diehl.com/group/en/transparency-and-information-obligations/
>>>
>>>
>>> _______________________________________________
>>> barebox mailing list
>>> barebox at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/barebox
>>>
>>
>>
> Diehl Connectivity Solutions GmbH
> Gesch?ftsf?hrung: Horst Leonberger
> Sitz der Gesellschaft: N?rnberg - Registergericht: Amtsgericht
> N?rnberg: HRB 32315
> 
> ________________________________
> 
> Der Inhalt der vorstehenden E-Mail ist nicht rechtlich bindend. Diese E-Mail enthaelt vertrauliche und/oder rechtlich geschuetzte Informationen.
> Informieren Sie uns bitte, wenn Sie diese E-Mail faelschlicherweise erhalten haben. Bitte loeschen Sie in diesem Fall die Nachricht.
> Jede unerlaubte Form der Reproduktion, Bekanntgabe, Aenderung, Verteilung und/oder Publikation dieser E-Mail ist strengstens untersagt.
> 
> - Informationen zum Datenschutz, insbesondere zu Ihren Rechten, erhalten Sie unter:
> 
> https://www.diehl.com/group/de/transparenz-und-informationspflichten/
> 
> The contents of the above mentioned e-mail is not legally binding. This e-mail contains confidential and/or legally protected information. Please inform us if you have received this e-mail by
> mistake and delete it in such a case. Each unauthorized reproduction, disclosure, alteration, distribution and/or publication of this e-mail is strictly prohibited.
> 
> - For general information on data protection and your respective rights please visit:
> 
> https://www.diehl.com/group/en/transparency-and-information-obligations/
> 
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Aug  9 04:01:07 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 9 Aug 2021 13:01:07 +0200
Subject: [PATCH 1/3] ARM: atomic.h: add 64-bit counter support
In-Reply-To: <1627900804-15814-2-git-send-email-renaud.barbier@abaco.com>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
 <1627900804-15814-2-git-send-email-renaud.barbier@abaco.com>
Message-ID: <5f511429-45c0-0a69-0690-24562bd93f69@pengutronix.de>

On 02.08.21 12:40, Renaud Barbier wrote:
> In preparation for the introduction of the FSL IFC nand driver
> for the layerscape CPU, add 64-bit counter support.
> 
> Remove functions calling undefined functions.
> 
> Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
> ---
>  include/asm-generic/atomic-long.h | 63 -------------------------------
>  include/asm-generic/atomic.h      | 49 ++++++++++++++++++++++++
>  2 files changed, 49 insertions(+), 63 deletions(-)
> 
> diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
> index 322d510f38..fd1fdad20f 100644
> --- a/include/asm-generic/atomic-long.h
> +++ b/include/asm-generic/atomic-long.h
> @@ -66,69 +66,6 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
>  	atomic64_sub(i, v);
>  }
>  
> -static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return atomic64_sub_and_test(i, v);
> -}
> -
> -static inline int atomic_long_dec_and_test(atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return atomic64_dec_and_test(v);
> -}
> -
> -static inline int atomic_long_inc_and_test(atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return atomic64_inc_and_test(v);
> -}
> -
> -static inline int atomic_long_add_negative(long i, atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return atomic64_add_negative(i, v);
> -}
> -
> -static inline long atomic_long_add_return(long i, atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return (long)atomic64_add_return(i, v);
> -}
> -
> -static inline long atomic_long_sub_return(long i, atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return (long)atomic64_sub_return(i, v);
> -}
> -
> -static inline long atomic_long_inc_return(atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return (long)atomic64_inc_return(v);
> -}
> -
> -static inline long atomic_long_dec_return(atomic_long_t *l)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return (long)atomic64_dec_return(v);
> -}
> -
> -static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
> -{
> -	atomic64_t *v = (atomic64_t *)l;
> -
> -	return (long)atomic64_add_unless(v, a, u);
> -}
> -

No one is using the deleted atomic_long_ functions. So that's ok.

>  #define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
>  
>  #define atomic_long_cmpxchg(l, old, new) \
> diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
> index 449cecaabc..6e63b8e8e7 100644
> --- a/include/asm-generic/atomic.h
> +++ b/include/asm-generic/atomic.h
> @@ -11,7 +11,55 @@
>  #ifdef CONFIG_SMP
>  #error SMP not supported
>  #endif
> +#define ATOMIC_INIT(i)	{ (i) }
> +
> +#ifdef CONFIG_64BIT
> +typedef struct { s64 counter; } atomic64_t;
> +
> +#define atomic64_read(v)	((v)->counter)
> +#define atomic64_set(v, i)	(((v)->counter) = (i))
> +
> +static inline void atomic64_add(s64 i, volatile atomic64_t *v)
> +{
> +	v->counter += i;
> +}
> +
> +static inline void atomic64_sub(s64 i, volatile atomic64_t *v)
> +{
> +	v->counter -= i;
> +}
> +
> +static inline void atomic64_inc(volatile atomic64_t *v)
> +{
> +	v->counter += 1;
> +}
> +
> +static inline void atomic64_dec(volatile atomic64_t *v)
> +{
> +	v->counter -= 1;
> +}
> +
> +static inline int atomic64_dec_and_test(volatile atomic64_t *v)
> +{
> +	s64 val;
> +
> +	val = v->counter;
> +	v->counter = val -= 1;
> +
> +	return val == 0;

That's a very awkward way to write

return --v->counter == 0;

But I see you just copied the 32 bit variants, so:

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> +}
>  
> +static inline int atomic64_add_negative(s64 i, volatile atomic64_t *v)
> +{
> +	s64 val;
> +
> +	val = v->counter;
> +	v->counter = val += i;
> +
> +	return val < 0;
> +}
> +
> +#else
>  typedef struct { volatile int counter; } atomic_t;
>  
>  #define ATOMIC_INIT(i)	{ (i) }
> @@ -63,6 +111,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
>  {
>  	*addr &= ~mask;
>  }
> +#endif
>  
>  /* Atomic operations are already serializing on ARM */
>  #define smp_mb__before_atomic_dec()	barrier()
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 10:56:56 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 19:56:56 +0200
Subject: [PATCH] scripts: bareboxenv: add erase hint if build as host-tool
In-Reply-To: <20210806093337.10153-1-m.felsch@pengutronix.de>
References: <20210806093337.10153-1-m.felsch@pengutronix.de>
Message-ID: <20210809175656.GA11515@pengutronix.de>

On Fri, Aug 06, 2021 at 11:33:37AM +0200, Marco Felsch wrote:
> The bareboxenv behviour is different if used as host-tool. As host-tool
> the erase is skipped which can confuse the user. Add a help note as hot
> fix. In the long term we should add the host-tool erase support as well.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  scripts/bareboxenv.c | 6 ++++++
>  1 file changed, 6 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
> index bdff644335..f1706a5e17 100644
> --- a/scripts/bareboxenv.c
> +++ b/scripts/bareboxenv.c
> @@ -98,6 +98,12 @@ static void usage(char *prgname)
>  	printf( "Usage : %s [OPTION] DIRECTORY FILE\n"
>  		"Load a barebox environment sector into a directory or\n"
>  		"save a directory into a barebox environment sector\n"
> +#ifndef __BAREBOX__
> +		"\n"
> +		"Attention:\n"
> +		"Depending on your environment backend storage you need to\n"
> +		"erase FILE before you save the new environment.\n"
> +#endif
>  		"\n"
>  		"options:\n"
>  		"  -s        save (directory -> environment sector)\n"
> -- 
> 2.30.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:08:42 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:08:42 +0200
Subject: [PATCH 2/2] imx-usb-loader: Add support for i.MX8MP
In-Reply-To: <20210805152251.1902158-2-u.kleine-koenig@pengutronix.de>
References: <20210805152251.1902158-1-u.kleine-koenig@pengutronix.de>
 <20210805152251.1902158-2-u.kleine-koenig@pengutronix.de>
Message-ID: <20210809180842.GB11515@pengutronix.de>

On Thu, Aug 05, 2021 at 05:22:51PM +0200, Uwe Kleine-K?nig wrote:
> From: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
> 
> The i.MX8MP uses a protocol similar to the MXS. The relevant differences
> are:
> 
>  - Maximal transfer size is 1020
>  - HID reports must be sent to EP1 instead of using a control transfer
>  - The FW_DOWNLOAD command must not be send.
> 
> Signed-off-by: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
> ---
>  scripts/imx/imx-usb-loader.c | 65 +++++++++++++++++++++++-------------
>  1 file changed, 42 insertions(+), 23 deletions(-)
> 
> diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
> index 3e96c86f2f29..40a85ee26105 100644
> --- a/scripts/imx/imx-usb-loader.c
> +++ b/scripts/imx/imx-usb-loader.c
> @@ -71,6 +71,7 @@ struct mach_id {
>  #define DEV_IMX		0
>  #define DEV_MXS		1
>  	unsigned char dev_type;
> +	unsigned char hid_endpoint;
>  };
>  
>  struct usb_work {
> @@ -177,6 +178,13 @@ static const struct mach_id imx_ids[] = {
>  		.header_type = HDR_MX53,
>  		.mode = MODE_HID,
>  		.max_transfer = 1024,
> +	}, {
> +		.vid = 0x1fc9,
> +		.pid = 0x0146,
> +		.name = "i.MX8MP",
> +		.max_transfer = 1020,
> +		.dev_type = DEV_MXS,
> +		.hid_endpoint = 1,
>  	}, {
>  		.vid = 0x1fc9,
>  		.pid = 0x012b,
> @@ -522,15 +530,24 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
>  
>  		if (report < 3) {
>  			memcpy(&tmp[1], p, cnt);
> -			err = libusb_control_transfer(usb_dev_handle,
> -					CTRL_OUT,
> -					HID_SET_REPORT,
> -					(HID_REPORT_TYPE_OUTPUT << 8) | report,
> -					0,
> -					tmp, cnt + 1, 1000);
> -			*last_trans = (err > 0) ? err - 1 : 0;
> -			if (err > 0)
> -				err = 0;
> +			if (mach_id->hid_endpoint) {
> +				int trans;
> +				err = libusb_interrupt_transfer(usb_dev_handle,
> +						mach_id->hid_endpoint, tmp, cnt + 1, &trans, 1000);
> +				if (err == 0 && last_trans)

last_trans is assumed to be non NULL throughout this function, so there
shouldn't be a need to check it here.

> +					*last_trans = trans - 1;
> +			} else {
> +				err = libusb_control_transfer(usb_dev_handle,
> +						CTRL_OUT,
> +						HID_SET_REPORT,
> +						(HID_REPORT_TYPE_OUTPUT << 8) | report,
> +						0,
> +						tmp, cnt + 1, 1000);
> +				if (err > 0) {
> +					*last_trans = err - 1;
> +					err = 0;
> +				}

Previously *last_trans was set unconditionally, with this patch you only
set it when err > 0. I don't know if this makes a difference, but I
would expect this change in a separate patch.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:10:21 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:10:21 +0200
Subject: [PATCH] mci: imx-esdhc-pbl: initialize fsl_esdhc_host
In-Reply-To: <20210805082607.1698733-1-r.czerwinski@pengutronix.de>
References: <20210805082607.1698733-1-r.czerwinski@pengutronix.de>
Message-ID: <20210809181021.GC11515@pengutronix.de>

On Thu, Aug 05, 2021 at 10:26:07AM +0200, Rouven Czerwinski wrote:
> Since commit 56ca2c197e71 ("mci: sdhci: Get rid of many register ops")
> the core checks whether there is an explicit write function for the
> host. If the struct is not zero initialized, a bogus value is taken as
> the function, resulting in an unbootable board. Zero initialize the
> structs properly to let the PBL correctly load images. Fixes booting on
> the i.MX8M* board, tested on i.MX8MP EVK.
> 
> Fixes: 56ca2c197e71 ("mci: sdhci: Get rid of many register ops")
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  drivers/mci/imx-esdhc-pbl.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Applied to master, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:18:05 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:18:05 +0200
Subject: [PATCH 1/2] watchdog: imxwd: register explicit warm reset handler
In-Reply-To: <20210803165937.31608-1-a.fatoum@pengutronix.de>
References: <20210803165937.31608-1-a.fatoum@pengutronix.de>
Message-ID: <20210809181805.GD11515@pengutronix.de>

On Tue, Aug 03, 2021 at 06:59:36PM +0200, Ahmad Fatoum wrote:
> With fsl,ext-reset-output and WDOG_B muxed correctly, the i.MX watchdog
> will toggle an external signal to effect a PMIC reset.
> 
> That's good for normal use, but when exchanging information with the
> BootROM over GPRs, a warm reset is required. This is needed e.g. to
> set the reboot mode. Support this by defining a second, lower
> priority, reset that will never toggle external lines.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/watchdog/imxwd.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
> index 26c62b7bcb31..a109f6fee712 100644
> --- a/drivers/watchdog/imxwd.c
> +++ b/drivers/watchdog/imxwd.c
> @@ -39,6 +39,7 @@ struct imx_wd {
>  	struct device_d *dev;
>  	const struct imx_wd_ops *ops;
>  	struct restart_handler restart;
> +	struct restart_handler restart_warm;
>  	bool ext_reset;
>  	bool bigendian;
>  };
> @@ -183,6 +184,14 @@ static void __noreturn imxwd_force_soc_reset(struct restart_handler *rst)
>  	hang();
>  }
>  
> +static void __noreturn imxwd_force_soc_reset_internal(struct restart_handler *rst)
> +{
> +	struct imx_wd *priv = container_of(rst, struct imx_wd, restart_warm);
> +
> +	priv->ext_reset = false;
> +	imxwd_force_soc_reset(&priv->restart);
> +}
> +
>  static void imx_watchdog_detect_reset_source(struct imx_wd *priv)
>  {
>  	u16 val = imxwd_read(priv, IMX21_WDOG_WSTR);
> @@ -284,9 +293,16 @@ static int imx_wd_probe(struct device_d *dev)
>  
>  	priv->restart.name = "imxwd";
>  	priv->restart.restart = imxwd_force_soc_reset;
> +	priv->restart.priority = RESTART_DEFAULT_PRIORITY;
>  
>  	restart_handler_register(&priv->restart);
>  
> +	priv->restart_warm.name = "imxwd-warm";
> +	priv->restart_warm.restart = imxwd_force_soc_reset_internal;
> +	priv->restart_warm.priority = RESTART_DEFAULT_PRIORITY - 10;
> +
> +	restart_handler_register(&priv->restart_warm);
> +
>  	return 0;
>  
>  error_unregister:
> -- 
> 2.30.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:26:36 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:26:36 +0200
Subject: [PATCH v2 1/8] of: reserve: add xn flag mem entries
In-Reply-To: <20210803094418.475609-2-r.czerwinski@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-2-r.czerwinski@pengutronix.de>
Message-ID: <20210809182636.GE11515@pengutronix.de>

On Tue, Aug 03, 2021 at 11:44:11AM +0200, Rouven Czerwinski wrote:
> If the OF_RESERVE_ENTRY_FLAG_XN flag is passed while creating the
> entry, a subsequent commit will use this information in the mmu to map
> the area as non-executable.

Do we need this flag at all? I can't find any place changed in this
patch where the reserved memory should be mapped executable.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:30:42 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:30:42 +0200
Subject: [PATCH v2 3/8] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <270994d8-2970-5095-2f82-f8cf29054629@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-4-r.czerwinski@pengutronix.de>
 <270994d8-2970-5095-2f82-f8cf29054629@pengutronix.de>
Message-ID: <20210809183042.GF11515@pengutronix.de>

On Thu, Aug 05, 2021 at 04:06:42PM +0200, Ahmad Fatoum wrote:
> On 03.08.21 11:44, Rouven Czerwinski wrote:
> > Use the information from the reserved memory entries to modify the
> > mapping of memory regions to mark them as uncachable and not-executable.
> > This also prevents the processor from speculating into these regions,
> > preventing hard to debug scenarios where boots fail for unknown reasons.
> > 
> > Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> > ---
> >  arch/arm/cpu/mmu.c | 34 ++++++++++++++++++++++++++++++++--
> >  1 file changed, 32 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
> > index 6388e1bf14..73f4cf5b36 100644
> > --- a/arch/arm/cpu/mmu.c
> > +++ b/arch/arm/cpu/mmu.c
> > @@ -17,6 +17,7 @@
> >  #include <memory.h>
> >  #include <asm/system_info.h>
> >  #include <asm/sections.h>
> > +#include <of.h>
> >  
> >  #include "mmu.h"
> >  
> > @@ -407,6 +408,36 @@ static void vectors_init(void)
> >  	create_vector_table(ARM_LOW_VECTORS);
> >  }
> >  
> > +static void create_sections_with_intersect(struct memory_bank *bank)
> > +{
> > +	struct of_reserve_map *res_map;
> > +	unsigned long j_end;
> > +	unsigned long end;
> > +	unsigned long j;
> > +	u32 pmd_flags;
> > +	int i;
> > +
> > +	res_map = of_get_reserve_map();
> > +	if (!res_map)
> > +		return;
> 
> If there is no reserve map, you should still map the banks cached.
> So this early exit is wrong.
> 
> > +
> > +	end = bank->start + bank->size - 1;
> > +
> > +	for (j = bank->start; j < end; j += PGDIR_SIZE) {
> > +		pmd_flags = PMD_SECT_DEF_CACHED;
> > +		j_end = j + PGDIR_SIZE - 1;
> > +
> > +		for (i = 0; i < res_map->num_entries; i++) {
> > +			if ((BIT(i) & res_map->xn) &&
> > +			    j_end >= res_map->start[i] &&
> > +			    j_end <= res_map->end[i])
> > +				pmd_flags = PMD_SECT_DEF_UNCACHED | PMD_SECT_XN;
> > +		}
> > +
> > +		create_sections(ttb, j, j_end, pmd_flags);
> > +	}
> 
> Do we need the nested loop? Can't we create sections cached first
> and then iterate once over the reserved map, deduce the sections containing
> start and end and map those uncached?

Wouldn't that open a window to speculate into the areas we want to avoid
speculating into in the first place?

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:35:57 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:35:57 +0200
Subject: [PATCH v2] arm/mvebu: sync barebox-arm-head.h to generic variant
In-Reply-To: <20210730070001.1441742-1-u.kleine-koenig@pengutronix.de>
References: <20210518091644.2519581-1-u.kleine-koenig@pengutronix.de>
 <20210730070001.1441742-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210809183557.GG11515@pengutronix.de>

On Fri, Jul 30, 2021 at 09:00:01AM +0200, Uwe Kleine-K?nig wrote:
> En passant this adds support for PBL_BREAK. While there is no 64 bit
> support available for mvebu, keeping the difference between
> arch/arm/mach-mvebu/include/mach/barebox-arm-head.h and
> arch/arm/include/asm/barebox-arm-head.h minimal is a good thing.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---
> Changes in this v2: Only some whitespace changes to reduce the diff
> between the two headers even more.
> ---
>  .../include/mach/barebox-arm-head.h           | 25 ++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:36:34 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:36:34 +0200
Subject: [PATCH] arm: mxs: Replace license and copyright boilerplate by
 SPDX identifiers
In-Reply-To: <20210730192802.1457345-1-u.kleine-koenig@pengutronix.de>
References: <20210730192802.1457345-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210809183634.GH11515@pengutronix.de>

On Fri, Jul 30, 2021 at 09:28:02PM +0200, Uwe Kleine-K?nig wrote:
> Converts the files that licensecheck can determine to be licensed under
> GPL-2.0-only or GPL-2.0-or-later and also convert their copyright
> statements to SPDX.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:37:27 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:37:27 +0200
Subject: [PATCH master] ARM: at91: fix building samad2 images without
 sama5d3
In-Reply-To: <20210722124137.7431-1-a.fatoum@pengutronix.de>
References: <20210722124137.7431-1-a.fatoum@pengutronix.de>
Message-ID: <20210809183726.GI11515@pengutronix.de>

On Thu, Jul 22, 2021 at 02:41:37PM +0200, Ahmad Fatoum wrote:
> Addition of first stage support for SAMA5D3 added a dependency
> between sama5d2 and sama5d3 first stages: They both needed to be
> enabled to generate images for either. Break up this dependency
> to fix build failures for configs that e.g. only build one SoC.
> 
> Fixes: e30fb46597d3 ("ARM: at91: xload-mmc: add sama5d3_atmci_start_image() helper")
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  arch/arm/mach-at91/Kconfig | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:48:34 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:48:34 +0200
Subject: [PATCH 2/2] fastboot: use file_list_parse_null()
In-Reply-To: <7938608bfc1f8ec8f460de95d065b6352f50eff8.camel@pengutronix.de>
References: <20210721084017.401081-1-r.czerwinski@pengutronix.de>
 <20210721084017.401081-2-r.czerwinski@pengutronix.de>
 <7938608bfc1f8ec8f460de95d065b6352f50eff8.camel@pengutronix.de>
Message-ID: <20210809184834.GJ11515@pengutronix.de>

On Wed, Jul 21, 2021 at 10:43:04AM +0200, Rouven Czerwinski wrote:
> On Wed, 2021-07-21 at 10:40 +0200, Rouven Czerwinski wrote:
> > In case an invalid file list is passed to file_list_parse(), it will
> > return an error, i.e. by passing "/dev/mmc1(emmc) /dev/mmc1.1(root)",
> > the error here being that the entries are not comma separated and
> > file_list_parse will try to parse ' ' as a flag. The fastboot code
> > didn't handle this, leading to the following error:
> > 
> >   ERROR: file_list: Unknown flag ' '
> >   ERROR: file_list: parse error
> >   unable to handle paging request at address 0xfffffff2
> >   pc : [<8fe26a20>]    lr : [<8fe0f965>]
> >   sp : 8ffeff50  ip : 8ffef714  fp : 00079bda
> >   r10: 001b9ff8  r9 : 8fea7eec  r8 : 00000001
> >   r7 : 00000000  r6 : 00000001  r5 : 00000000  r4 : 8813eab0
> >   r3 : ffffffea  r2 : 00020000  r1 : 00000001  r0 : 8813eab0
> >   Flags: nzCv  IRQs off  FIQs off  Mode SVC_32
> >   WARNING: [<8fe26a20>] (usb_multi_count_functions+0xc/0x2a) from [<8fe0f965>] (usbgadget_register+0x79/0xf4)
> >   WARNING: [<8fe0f965>] (usbgadget_register+0x79/0xf4) from [<8fe0fa13>] (usbgadget_autostart_set+0x33/0x4c)
> >   WARNING: [<8fe0fa13>] (usbgadget_autostart_set+0x33/0x4c) from [<8fe4d437>] (param_int_set+0x4b/0xb0)
> >   WARNING: [<8fe4d437>] (param_int_set+0x4b/0xb0) from [<8fe4d899>] (dev_set_param+0x4d/0x64)
> >   WARNING: [<8fe4d899>] (dev_set_param+0x4d/0x64) from [<8fe066f1>] (globalvar_add_bool+0x49/0x54)
> >   WARNING: [<8fe066f1>] (globalvar_add_bool+0x49/0x54) from [<8fe0f8dd>] (usbgadget_autostart_init+0x15/0x24)
> >   WARNING: [<8fe0f8dd>] (usbgadget_autostart_init+0x15/0x24) from [<8fe01081>] (start_barebox+0x35/0x6c)
> >   WARNING: [<8fe01081>] (start_barebox+0x35/0x6c) from [<8fe62ed9>] (barebox_non_pbl_start+0x121/0x164)
> >   WARNING: [<8fe62ed9>] (barebox_non_pbl_start+0x121/0x164) from [<8fe00005>] (__bare_init_start+0x1/0xc)
> > 
> >   WARNING: [<8fe64e3d>] (unwind_backtrace+0x1/0x78) from [<8fe01385>] (panic+0x1d/0x34)
> >   WARNING: [<8fe01385>] (panic+0x1d/0x34) from [<8fe62723>] (do_exception+0xf/0x14)
> >   WARNING: [<8fe62723>] (do_exception+0xf/0x14) from [<8fe62791>] (do_data_abort+0x21/0x34)
> >   WARNING: [<8fe62791>] (do_data_abort+0x21/0x34) from [<8fe624d4>] (do_abort_6+0x48/0x54)
> > 
> > Use file_list_parse_null instead of file_list_parse to get a NULL
> > pointer if there is a parse error.
> > 
> > Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> > ---
> >  common/fastboot.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/common/fastboot.c b/common/fastboot.c
> > index 75f6691b08..00a50813a7 100644
> > --- a/common/fastboot.c
> > +++ b/common/fastboot.c
> > @@ -918,8 +918,9 @@ bool get_fastboot_bbu(void)
> >  
> >  struct file_list *get_fastboot_partitions(void)
> >  {
> > -	if (fastboot_partitions && *fastboot_partitions)
> > -		return file_list_parse(fastboot_partitions);
> > +	if (fastboot_partitions && *fastboot_partitions) {
> > +		return file_list_parse_null(fastboot_partitions);
> > +	}
> 
> I missed the no longer required braces, do you want to fixup locally or
> should I send a v2?

I would clean this up locally, but the series doesn't apply on current
master, so could you resend a v2?

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:51:02 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:51:02 +0200
Subject: [PATCH v2] arm: rockchip-rk3568-evb: add hardware id detection
In-Reply-To: <20210705160457.7346-1-michael.riesch@wolfvision.net>
References: <20210705160457.7346-1-michael.riesch@wolfvision.net>
Message-ID: <20210809185102.GK11515@pengutronix.de>

On Mon, Jul 05, 2021 at 06:04:57PM +0200, Michael Riesch wrote:
> The RK3568 EVB uses a voltage divider to determine the hardware ID of
> the board. At the moment, the voltage levels for seven EVB variants are
> defined. This commit adds a late_initcall to the board code that reads
> out the voltage and populates the hardware ID as environment variable.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
> v2:
> - add compatible check
> - return early in case the voltage cannot be read
> - populate hardware ID as environment variable
> 
>  arch/arm/boards/rockchip-rk3568-evb/board.c | 56 +++++++++++++++++++++
>  1 file changed, 56 insertions(+)

Applied with Ahmads fixup, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 11:52:08 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 20:52:08 +0200
Subject: [PATCH] scripts: socfpga_import_preloader: make sdk optional
In-Reply-To: <20210611080233.15141-1-s.trumtrar@pengutronix.de>
References: <20210611080233.15141-1-s.trumtrar@pengutronix.de>
Message-ID: <20210809185208.GA24834@pengutronix.de>

On Fri, Jun 11, 2021 at 10:02:33AM +0200, Steffen Trumtrar wrote:
> The commit a9b2e6089d82686564220013f14e9f0ffcc725e2 allowed generating
> everything needed in one step. This was however a bit too ambitious.
> The script now requires that the Altera Embedded SDK is always
> installed. There are situations where this is unwanted.
> 
> Beef up the code a little bit to allow having the SDK as an optional
> argument and make the other input parameters location independent.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  Documentation/boards/socfpga.rst |  2 +-
>  scripts/socfpga_import_preloader | 88 ++++++++++++++++++++++++++++----
>  2 files changed, 78 insertions(+), 12 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug  9 12:16:25 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 9 Aug 2021 21:16:25 +0200
Subject: [PATCH 2/3] nand: add NXP IFC nand driver
In-Reply-To: <1627900804-15814-3-git-send-email-renaud.barbier@abaco.com>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
 <1627900804-15814-3-git-send-email-renaud.barbier@abaco.com>
Message-ID: <20210809191625.GB24834@pengutronix.de>

Hi Renaud,

On Mon, Aug 02, 2021 at 11:40:03AM +0100, Renaud Barbier wrote:
> Add the NXP IFC nand driver support. This driver
> can be used with the NXP QorIQ cores.

Could you leave a few words here which base you used for the driver? Is
it based on Linux or U-Boot, which version?

> +static void fsl_ifc_ctrl_init(void)
> +{
> +	struct fsl_ifc_ctrl *ctrl;
> +	struct device_node *np;
> +
> +	np = of_find_compatible_node(NULL, NULL, "fsl,ifc");
> +	if (!np)
> +		return;

Looks like this function can fail, it should return an error.

> +		while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
> +			ifc_ctrl->nand_stat =
> +				ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
> +
> +			if (!(ifc_ctrl->nand_stat & IFC_NAND_SRAM_INIT_EN))
> +				return 0;
> +		}
> +		pr_err("fsl-ifc: Failed to Initialise SRAM\n");
> +		return 1;

It would be better to return an error code here and propagate that.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From r.czerwinski at pengutronix.de  Mon Aug  9 22:29:28 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue, 10 Aug 2021 07:29:28 +0200
Subject: [PATCH v2 2/2] fastboot: use file_list_parse_null()
In-Reply-To: <20210810052928.101783-1-r.czerwinski@pengutronix.de>
References: <20210810052928.101783-1-r.czerwinski@pengutronix.de>
Message-ID: <20210810052928.101783-2-r.czerwinski@pengutronix.de>

In case an invalid file list is passed to file_list_parse(), it will
return an error, i.e. by passing "/dev/mmc1(emmc) /dev/mmc1.1(root)",
the error here being that the entries are not comma separated and
file_list_parse will try to parse ' ' as a flag. The fastboot code
didn't handle this, leading to the following error:

  ERROR: file_list: Unknown flag ' '
  ERROR: file_list: parse error
  unable to handle paging request at address 0xfffffff2
  pc : [<8fe26a20>]    lr : [<8fe0f965>]
  sp : 8ffeff50  ip : 8ffef714  fp : 00079bda
  r10: 001b9ff8  r9 : 8fea7eec  r8 : 00000001
  r7 : 00000000  r6 : 00000001  r5 : 00000000  r4 : 8813eab0
  r3 : ffffffea  r2 : 00020000  r1 : 00000001  r0 : 8813eab0
  Flags: nzCv  IRQs off  FIQs off  Mode SVC_32
  WARNING: [<8fe26a20>] (usb_multi_count_functions+0xc/0x2a) from [<8fe0f965>] (usbgadget_register+0x79/0xf4)
  WARNING: [<8fe0f965>] (usbgadget_register+0x79/0xf4) from [<8fe0fa13>] (usbgadget_autostart_set+0x33/0x4c)
  WARNING: [<8fe0fa13>] (usbgadget_autostart_set+0x33/0x4c) from [<8fe4d437>] (param_int_set+0x4b/0xb0)
  WARNING: [<8fe4d437>] (param_int_set+0x4b/0xb0) from [<8fe4d899>] (dev_set_param+0x4d/0x64)
  WARNING: [<8fe4d899>] (dev_set_param+0x4d/0x64) from [<8fe066f1>] (globalvar_add_bool+0x49/0x54)
  WARNING: [<8fe066f1>] (globalvar_add_bool+0x49/0x54) from [<8fe0f8dd>] (usbgadget_autostart_init+0x15/0x24)
  WARNING: [<8fe0f8dd>] (usbgadget_autostart_init+0x15/0x24) from [<8fe01081>] (start_barebox+0x35/0x6c)
  WARNING: [<8fe01081>] (start_barebox+0x35/0x6c) from [<8fe62ed9>] (barebox_non_pbl_start+0x121/0x164)
  WARNING: [<8fe62ed9>] (barebox_non_pbl_start+0x121/0x164) from [<8fe00005>] (__bare_init_start+0x1/0xc)

  WARNING: [<8fe64e3d>] (unwind_backtrace+0x1/0x78) from [<8fe01385>] (panic+0x1d/0x34)
  WARNING: [<8fe01385>] (panic+0x1d/0x34) from [<8fe62723>] (do_exception+0xf/0x14)
  WARNING: [<8fe62723>] (do_exception+0xf/0x14) from [<8fe62791>] (do_data_abort+0x21/0x34)
  WARNING: [<8fe62791>] (do_data_abort+0x21/0x34) from [<8fe624d4>] (do_abort_6+0x48/0x54)

Use file_list_parse_null instead of file_list_parse to get a NULL
pointer if there is a parse error.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>

---
v2: remove left over braces
---
 common/fastboot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/fastboot.c b/common/fastboot.c
index 75f6691b08..04a8573b4a 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -919,7 +919,7 @@ bool get_fastboot_bbu(void)
 struct file_list *get_fastboot_partitions(void)
 {
 	if (fastboot_partitions && *fastboot_partitions)
-		return file_list_parse(fastboot_partitions);
+		return file_list_parse_null(fastboot_partitions);
 	if (!system_partitions_empty())
 		return system_partitions_get();
 	return NULL;
-- 
2.32.0



From r.czerwinski at pengutronix.de  Mon Aug  9 22:29:27 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue, 10 Aug 2021 07:29:27 +0200
Subject: [PATCH v2 1/2] file_list: add file_list_parse_null()
Message-ID: <20210810052928.101783-1-r.czerwinski@pengutronix.de>

Move the usbgadget parse() function to file_list and rename it to
file_list_parse_null() which will return a NULL pointer instead of an
error. Also adjust the callers in the usbgadget code.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>

---
v2: rebase on master to fix USB mass storage conflict
---
 common/file-list.c  | 16 ++++++++++++++++
 common/usbgadget.c  | 24 ++++--------------------
 include/file-list.h |  1 +
 3 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/common/file-list.c b/common/file-list.c
index 05f44514fb..407b312833 100644
--- a/common/file-list.c
+++ b/common/file-list.c
@@ -158,6 +158,22 @@ out:
 	return ERR_PTR(ret);
 }
 
+struct file_list *file_list_parse_null(const char *files)
+{
+	struct file_list *list;
+
+	if (!files)
+		return NULL;
+
+	list = file_list_parse(files);
+	if (IS_ERR(list)) {
+		pr_err("Parsing file list \"%s\" failed: %pe\n", files, list);
+		return NULL;
+	}
+
+	return list;
+}
+
 void file_list_free(struct file_list *files)
 {
 	struct file_list_entry *entry, *tmp;
diff --git a/common/usbgadget.c b/common/usbgadget.c
index 34a685234b..e8c9f7d236 100644
--- a/common/usbgadget.c
+++ b/common/usbgadget.c
@@ -23,26 +23,10 @@ static int autostart;
 static int acm;
 static char *dfu_function;
 
-static struct file_list *parse(const char *files)
-{
-	struct file_list *list;
-
-	if (!files)
-		return NULL;
-
-	list = file_list_parse(files);
-	if (IS_ERR(list)) {
-		pr_err("Parsing file list \"%s\" failed: %pe\n", files, list);
-		return NULL;
-	}
-
-	return list;
-}
-
 static inline struct file_list *get_dfu_function(void)
 {
 	if (dfu_function && *dfu_function)
-		return file_list_parse(dfu_function);
+		return file_list_parse_null(dfu_function);
 	if (!system_partitions_empty())
 		return system_partitions_get();
 	return NULL;
@@ -59,7 +43,7 @@ int usbgadget_register(const struct usbgadget_funcs *funcs)
 	opts->release = usb_multi_opts_release;
 
 	if (flags & USBGADGET_DFU) {
-		opts->dfu_opts.files = parse(funcs->dfu_opts);
+		opts->dfu_opts.files = file_list_parse_null(funcs->dfu_opts);
 		if (IS_ENABLED(CONFIG_USB_GADGET_DFU) && file_list_empty(opts->dfu_opts.files)) {
 			file_list_free(opts->dfu_opts.files);
 			opts->dfu_opts.files = get_dfu_function();
@@ -67,7 +51,7 @@ int usbgadget_register(const struct usbgadget_funcs *funcs)
 	}
 
 	if (flags & USBGADGET_MASS_STORAGE) {
-		opts->ums_opts.files = parse(funcs->ums_opts);
+		opts->ums_opts.files = file_list_parse_null(funcs->ums_opts);
 		if (IS_ENABLED(CONFIG_USB_GADGET_MASS_STORAGE) && file_list_empty(opts->ums_opts.files)) {
 			file_list_free(opts->ums_opts.files);
 			opts->ums_opts.files = system_partitions_get();
@@ -75,7 +59,7 @@ int usbgadget_register(const struct usbgadget_funcs *funcs)
 	}
 
 	if (flags & USBGADGET_FASTBOOT) {
-		opts->fastboot_opts.files = parse(funcs->fastboot_opts);
+		opts->fastboot_opts.files = file_list_parse_null(funcs->fastboot_opts);
 		if (IS_ENABLED(CONFIG_FASTBOOT_BASE) && file_list_empty(opts->fastboot_opts.files)) {
 			file_list_free(opts->fastboot_opts.files);
 			opts->fastboot_opts.files = get_fastboot_partitions();
diff --git a/include/file-list.h b/include/file-list.h
index 7e2a4d9205..5090313739 100644
--- a/include/file-list.h
+++ b/include/file-list.h
@@ -22,6 +22,7 @@ struct file_list {
 };
 
 struct file_list *file_list_parse(const char *str);
+struct file_list *file_list_parse_null(const char *str);
 char *file_list_to_str(const struct file_list *files);
 void file_list_free(struct file_list *);
 
-- 
2.32.0



From andrej.picej at norik.com  Mon Aug  9 22:47:12 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Tue, 10 Aug 2021 07:47:12 +0200
Subject: [PATCH] hush: fix conditional statements exit code
Message-ID: <20210810054712.1547433-1-andrej.picej@norik.com>

Fix conditional statements ("if" , "elif", "while" and "until") exit
code when used in scripts. Before the change, when conditional statement
evaluated false just before the end of the script, script's exit code
would have been 1 (instead of 0), which implies error condition. This is
not expected nor desired behavior, so correct it by handling such cases
and passing exit code 0 (SUCCESS) instead in such situations.

Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
This problem/bug was previously discussed on barebox mailing list.
Although a simple workaround was found (explicit exit 0 at the end of
scripts), a decision for fixing Hush was encouraged.
---
 common/hush.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/common/hush.c b/common/hush.c
index 047540132..d80df7a18 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -854,7 +854,7 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 	struct pipe *rpipe;
 	int flag_rep = 0;
 	int rcode=0, flag_skip=1;
-	int flag_restore = 0;
+	int flag_restore = 0, flag_conditional = 0;
 	int if_code=0, next_if_code=0;  /* need double-buffer to handle elif */
 	reserved_style rmode, skip_more_in_this_rmode = RES_XXXX;
 
@@ -966,6 +966,20 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 			return rcode;	/* exit */
 		}
 
+		/* Conditional statements like "if", "elif", "while" and "until"
+		 * return 1 if conditional is not met. This is standard behavior.
+		 * However this does not mean that this value (1) should be
+		 * returned as exit code, as it suggests generic error code.
+		 * Catch this by raising a flag and check it later on.
+		 */
+		if (rcode == 1) {
+			if (rmode == RES_IF || rmode == RES_ELIF ||
+				rmode == RES_WHILE || rmode == RES_UNTIL)
+				flag_conditional = 1;
+			else
+				flag_conditional = 0;
+		}
+
 		last_return_code = rcode;
 
 		if (rmode == RES_IF || rmode == RES_ELIF )
@@ -981,6 +995,13 @@ static int run_list_real(struct p_context *ctx, struct pipe *pi)
 		     (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) )
 			skip_more_in_this_rmode = rmode;
 	}
+
+	/* Substitute exit code in case flag_conditional is set. */
+	if (flag_conditional == 1 && last_return_code == 1) {
+		last_return_code = 0;
+		rcode = 0;
+	}
+
 	return rcode;
 }
 
-- 
2.25.1



From renaud.barbier at abaco.com  Tue Aug 10 01:33:42 2021
From: renaud.barbier at abaco.com (Barbier, Renaud)
Date: Tue, 10 Aug 2021 08:33:42 +0000
Subject: [PATCH 2/3] nand: add NXP IFC nand driver
In-Reply-To: <20210809191625.GB24834@pengutronix.de>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
 <1627900804-15814-3-git-send-email-renaud.barbier@abaco.com>
 <20210809191625.GB24834@pengutronix.de>
Message-ID: <MN2PR16MB31353E5032A5C1D316AFA71191F79@MN2PR16MB3135.namprd16.prod.outlook.com>

I first ported this driver in 2015. It was derived from U-boot (2015-10) commit cce573e and had a few updates over the years.


-----Original Message-----
From: Sascha Hauer <sha at pengutronix.de> 
Sent: 09 August 2021 20:16
To: Barbier, Renaud <renaud.barbier at abaco.com>
Cc: barebox at lists.infradead.org
Subject: Re: [PATCH 2/3] nand: add NXP IFC nand driver



[**EXTERNAL SOURCE**]:Please verify the source before clicking link or opening attachment.

Hi Renaud,

On Mon, Aug 02, 2021 at 11:40:03AM +0100, Renaud Barbier wrote:
> Add the NXP IFC nand driver support. This driver can be used with the 
> NXP QorIQ cores.

Could you leave a few words here which base you used for the driver? Is it based on Linux or U-Boot, which version?

> +static void fsl_ifc_ctrl_init(void)
> +{
> +     struct fsl_ifc_ctrl *ctrl;
> +     struct device_node *np;
> +
> +     np = of_find_compatible_node(NULL, NULL, "fsl,ifc");
> +     if (!np)
> +             return;

Looks like this function can fail, it should return an error.

> +             while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
> +                     ifc_ctrl->nand_stat =
> +                             ifc_in32(ctrl->rregs + 
> + FSL_IFC_NAND_EVTER_STAT);
> +
> +                     if (!(ifc_ctrl->nand_stat & IFC_NAND_SRAM_INIT_EN))
> +                             return 0;
> +             }
> +             pr_err("fsl-ifc: Failed to Initialise SRAM\n");
> +             return 1;

It would be better to return an error code here and propagate that.

Sascha

--
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix.de%2F&amp;data=04%7C01%7Crenaud.barbier%40abaco.com%7C5542b21e348444c35e0908d95b6a2fd6%7Ce6f27451899d4d0db8fa88baafa551a7%7C0%7C0%7C637641333904496165%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=eBdLLjmiSrNN%2F2VJjk6sRWhCgnPKOZUpkzYkePKh%2Fuk%3D&amp;reserved=0  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From renaud.barbier at abaco.com  Tue Aug 10 03:33:09 2021
From: renaud.barbier at abaco.com (Barbier, Renaud)
Date: Tue, 10 Aug 2021 10:33:09 +0000
Subject: [PATCH 3/3] ls1046ardb: enable IFC NAND.
In-Reply-To: <471e6659-459f-f6e6-7abf-9b6141e6c7a3@pengutronix.de>
References: <1627900804-15814-1-git-send-email-renaud.barbier@abaco.com>
 <1627900804-15814-4-git-send-email-renaud.barbier@abaco.com>
 <471e6659-459f-f6e6-7abf-9b6141e6c7a3@pengutronix.de>
Message-ID: <MN2PR16MB3135A7F2C63FD29126B4122091F79@MN2PR16MB3135.namprd16.prod.outlook.com>



> diff --git a/arch/arm/boards/ls1046ardb/board.c 
> b/arch/arm/boards/ls1046ardb/board.c
> index ef68e9c7f9..b2cfba58a8 100644
> --- a/arch/arm/boards/ls1046ardb/board.c
> +++ b/arch/arm/boards/ls1046ardb/board.c
> @@ -8,10 +8,12 @@
>  #include <fs.h>
>  #include <envfs.h>
>  #include <libfile.h>
> +#include <of_address.h>
>  #include <asm/memory.h>
>  #include <linux/sizes.h>
>  #include <linux/clk.h>
>  #include <linux/clkdev.h>
> +#include <linux/fsl_ifc.h>
>  #include <asm/system.h>
>  #include <mach/layerscape.h>
>  #include <mach/bbu.h>
> @@ -35,6 +37,11 @@ struct nxid {
>       u32 crc;          /* 0xfc - 0xff CRC32 checksum */
>  } __packed;
>
> +static const struct of_device_id fsl_ifc_of_ids[] = {
> +     { .compatible = "fsl,ifc", },
> +     { },
> +};
> +
>  static int nxid_is_valid(struct nxid *nxid)  {
>       unsigned char id[] = { 'N', 'X', 'I', 'D' }; @@ -161,3 +168,38 
> @@ static int rdb_postcore_init(void)  }
>
>  postcore_initcall(rdb_postcore_init);
> +
> +static int rdb_nand_init(void)
> +{
> +     struct device_node *np;
> +     void __iomem *ifc;
> +

If you think this configuration should be done for _all_ boards, you should move it to arch/arm/mach-layerscape. If you intend it to be done only for this specific board, you should check the board compatible, otherwise this function is called even for boards that don't have NAND physically. Throwing an error there is inappropriate. If this is board-specific, please add:


        if (!of_machine_is_compatible("fsl,ls1046a-rdb"))

                return 0;

> +     np = of_find_matching_node(NULL, fsl_ifc_of_ids);

You can use of_find_compatible_node, which lets you drop the struct.



Indeed, this makes sense as we are going to have our own board support in a few months.


From a.fatoum at pengutronix.de  Wed Aug 11 01:52:53 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 11 Aug 2021 10:52:53 +0200
Subject: [PATCH v3 00/10] RISC-V: add LiteX SoC support; resurrect nmon
In-Reply-To: <20210525071952.18045-1-antonynpavlov@gmail.com>
References: <20210525071952.18045-1-antonynpavlov@gmail.com>
Message-ID: <32db3d61-f04c-5940-600c-fb2435808beb@pengutronix.de>

Hello Antony,

On 25.05.21 09:19, Antony Pavlov wrote:
> Changes since v2:
> 
>   * rebase on top of master branch (f873c7ff2497) +
>     "RISC-V: extend multi-image to support both S- and M-Mode"
>     (http://lists.infradead.org/pipermail/barebox/2021-May/036086.html).
>   * "litex serial: add setbrg callback" patch by Marek Czerski is added
>     for review;
>   * fix "clocksource: timer-riscv: select CSR from device tree" patch;
>   * change gpio IP-block base addresses in litex dts;
>   * gpio-74xx-mmio uses device_get_match_data() now.
> 
> Changes since v1:
> 
>   * rebased on top of next branch;
>   * new patches are introduced:
>     * clocksource: timer-riscv: select CSR from device tree
>     * RISC-V: make RISCV_SBI and RISCV_M_MODE explicitly mutually exclusive
>     * RISC-V: make it possible to build RV32I multi-image with DEBUG_LL=n
>   * almost all of Ahmad's notes are fixed (e.g. unused header files inclusions are dropped);
>   * NOT FIXED: gpio-74xx-mmio still uses dev_get_drvdata(), not device_get_match_data()
> 
> Antony Pavlov (9):
>   clocksource: timer-riscv: select CSR from device tree
>   RISC-V: make it possible to run nmon from PBL C code
>   RISC-V: boards: erizo: make it possible to use nmon
>   serial: add litex UART driver
>   gpio: add driver for 74xx-ICs with MMIO access
>   spi: add litex spiflash driver
>   net: add LiteEth driver
>   RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
>   RISC-V: add litex_linux_defconfig
> 
> Marek Czerski (1):
>   litex serial: add setbrg callback

I'd like to give this a try eventually while following:
https://github.com/enjoy-digital/litex/wiki/Use-LiteX-on-the-Acorn-CLE-215

Do you intend to submit a new revision soon? Is it ok for you if I respin
this series?

Cheers,
Ahmad

>  arch/riscv/Kconfig.socs                  |  14 +
>  arch/riscv/boards/Makefile               |   1 +
>  arch/riscv/boards/erizo/lowlevel.c       |   4 +
>  arch/riscv/boards/litex-linux/Makefile   |   3 +
>  arch/riscv/boards/litex-linux/lowlevel.c |  22 ++
>  arch/riscv/boot/Makefile                 |   1 +
>  arch/riscv/boot/nmon_entry.S             |  13 +
>  arch/riscv/configs/litex_linux_defconfig |  76 +++++
>  arch/riscv/dts/Makefile                  |   1 +
>  arch/riscv/dts/erizo.dtsi                |   2 +
>  arch/riscv/dts/litex-linux.dts           |  92 ++++++
>  arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++
>  arch/riscv/include/asm/debug_ll.h        |   3 +
>  arch/riscv/include/asm/debug_ll_litex.h  | 123 ++++++++
>  arch/riscv/include/asm/riscv_nmon.h      |  49 ++-
>  common/Kconfig                           |   4 +
>  drivers/clocksource/timer-riscv.c        |  24 +-
>  drivers/gpio/Kconfig                     |  14 +
>  drivers/gpio/Makefile                    |   1 +
>  drivers/gpio/gpio-74xx-mmio.c            | 165 ++++++++++
>  drivers/net/Kconfig                      |   8 +
>  drivers/net/Makefile                     |   1 +
>  drivers/net/liteeth.c                    | 376 +++++++++++++++++++++++
>  drivers/serial/Makefile                  |   1 +
>  drivers/serial/serial_litex.c            | 103 +++++++
>  drivers/spi/Kconfig                      |   3 +
>  drivers/spi/Makefile                     |   1 +
>  drivers/spi/litex_spiflash.c             | 241 +++++++++++++++
>  images/Makefile.riscv                    |   4 +
>  29 files changed, 1370 insertions(+), 29 deletions(-)
>  create mode 100644 arch/riscv/boards/litex-linux/Makefile
>  create mode 100644 arch/riscv/boards/litex-linux/lowlevel.c
>  create mode 100644 arch/riscv/boot/nmon_entry.S
>  create mode 100644 arch/riscv/configs/litex_linux_defconfig
>  create mode 100644 arch/riscv/dts/litex-linux.dts
>  create mode 100644 arch/riscv/dts/litex_soc_linux.dtsi
>  create mode 100644 arch/riscv/include/asm/debug_ll_litex.h
>  create mode 100644 drivers/gpio/gpio-74xx-mmio.c
>  create mode 100644 drivers/net/liteeth.c
>  create mode 100644 drivers/serial/serial_litex.c
>  create mode 100644 drivers/spi/litex_spiflash.c
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Wed Aug 11 10:25:04 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 11 Aug 2021 19:25:04 +0200
Subject: [PATCH] fastboot net: add global.fastboot.net.autostart early
Message-ID: <20210811172504.11396-1-m.felsch@pengutronix.de>

Split adding the fastboot.net.autostart to the global device and make
use of it. With this change it is possible to set it e.g. during
environment_initcall() and the later on followed fastboot_on_boot() can
use it to start fastboot it automatically during boot.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 net/fastboot.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/net/fastboot.c b/net/fastboot.c
index df388adc89..a5a7caf526 100644
--- a/net/fastboot.c
+++ b/net/fastboot.c
@@ -547,12 +547,16 @@ fail_generic_init:
 static struct fastboot_net *fastboot_net_obj;
 static int fastboot_net_autostart;
 
-static int fastboot_on_boot(void)
+static int fastboot_net_globalvars_init(void)
 {
-	struct fastboot_net *fbn;
-
 	globalvar_add_simple_bool("fastboot.net.autostart",
 				  &fastboot_net_autostart);
+	return 0;
+}
+
+static int fastboot_on_boot(void)
+{
+	struct fastboot_net *fbn;
 
 	if (!fastboot_net_autostart)
 		return 0;
@@ -573,6 +577,7 @@ static void fastboot_net_exit(void)
 		fastboot_net_free(fastboot_net_obj);
 }
 
+device_initcall(fastboot_net_globalvars_init);
 postenvironment_initcall(fastboot_on_boot);
 predevshutdown_exitcall(fastboot_net_exit);
 
-- 
2.30.2



From m.felsch at pengutronix.de  Wed Aug 11 10:36:24 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 11 Aug 2021 19:36:24 +0200
Subject: [PATCH] ARM: i.MX6: boot: detect USB serial downloader more reliable
Message-ID: <20210811173624.28061-1-m.felsch@pengutronix.de>

The problem with the BootROM is that the SCR registers are not set
accordingly in case of a failed primary boot. E.g. if the device is
configured to boot from an eMMC and the eMMC is empty or image is
corrupt, the BootROM goes into 'recovery boot mode' (reference manual
Figure 8-1) and the last possible recovery option is the serial
downloader. In such case the SRC registers still indicate that the
device was booted from an eMMC instead of serial-download.

This commit ports the U-Boot commit [1] with slightly adaptions suggested
by Ahmad to Barebox. Also we need to reorder the imx6_init() else we
reset the otg-controller to early.

[1] https://source.denx.de/u-boot/u-boot/-/commit/e203dcf23e9eabc2e4f3d0b079457cd1516f2081

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/mach-imx/boot.c  | 27 +++++++++++++++++++++++++++
 arch/arm/mach-imx/imx6.c  |  4 ++--
 include/soc/fsl/fsl_udc.h | 11 +++++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 2b66bbf71e..fcb3c10064 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -8,6 +8,7 @@
 #include <magicvar.h>
 
 #include <io.h>
+#include <mach/clock-imx6.h>
 #include <mach/generic.h>
 #include <mach/imx25-regs.h>
 #include <mach/imx27-regs.h>
@@ -23,6 +24,7 @@
 #include <mach/imx8mq.h>
 #include <mach/imx6.h>
 
+#include <soc/fsl/fsl_udc.h>
 
 static void
 imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
@@ -397,6 +399,11 @@ static u32 imx6_get_src_boot_mode(void __iomem *src_base)
 	return readl(src_base + IMX6_SRC_SBMR1);
 }
 
+static inline bool imx6_usboh3_clk_active(void)
+{
+	return (readl(MXC_CCM_CCGR6) & 0x3) == 0x3;
+}
+
 void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
@@ -410,6 +417,26 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 
 	bootsrc = imx53_bootsource_internal(bootmode);
 
+	/*
+	 * imx6_bootsource_serial() can't detect cases where the boot ROM
+	 * decided to use the serial downloader as a fall back (primary
+	 * boot source failed).
+	 *
+	 * Infer that the boot ROM used the USB serial downloader by
+	 * checking whether both the UDC and the clock enabling access
+	 * to its MMIO region are currently active...
+	 * This assumes:
+	 * - On fresh boots, PBL doesn't itself start a stopped UDC
+	 * - In barebox proper, boot source is saved before the UDC driver
+	 *   may enable the UDC
+	 */
+
+	if (imx6_usboh3_clk_active() &&
+	    is_chipidea_udc_running(IOMEM(MX6_OTG_BASE_ADDR))) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
+
 	if (imx6_bootsource_serial(sbmr2) ||
 	    imx6_bootsource_serial_forced(bootsrc)) {
 		*src = BOOTSOURCE_SERIAL;
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 9ccb391384..fa4cb093c3 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -205,10 +205,10 @@ int imx6_init(void)
 	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
 	u64 mx6_uid;
 
-	imx6_init_lowlevel();
-
 	imx6_boot_save_loc();
 
+	imx6_init_lowlevel();
+
 	mx6_silicon_revision = imx6_cpu_revision();
 	mx6_uid = imx6_uid();
 
diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
index b983f714c5..0b409a9f6b 100644
--- a/include/soc/fsl/fsl_udc.h
+++ b/include/soc/fsl/fsl_udc.h
@@ -1,6 +1,9 @@
 #ifndef __FSL_UDC_H
 #define __FSL_UDC_H
 
+#include <linux/types.h>
+#include <io.h>
+
 /* USB DR device mode registers (Little Endian) */
 struct usb_dr_device {
 	/* Capability register */
@@ -380,4 +383,12 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest);
 int imx8mm_barebox_load_usb(void *dest);
 int imx8mm_barebox_start_usb(void *dest);
 
+static inline bool is_chipidea_udc_running(void __iomem *dr)
+{
+	struct usb_dr_device __iomem *dr_regs = dr;
+
+	return (readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_DEVICE)
+		&& (readl(&dr_regs->usbcmd) & USB_CMD_RUN_STOP);
+}
+
 #endif /* __FSL_UDC_H */
-- 
2.30.2



From a.fatoum at pengutronix.de  Wed Aug 11 11:22:15 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 11 Aug 2021 20:22:15 +0200
Subject: [PATCH] fastboot net: add global.fastboot.net.autostart early
In-Reply-To: <20210811172504.11396-1-m.felsch@pengutronix.de>
References: <20210811172504.11396-1-m.felsch@pengutronix.de>
Message-ID: <9e266302-92a1-a577-d38c-fc240177b169@pengutronix.de>

On 11.08.21 19:25, Marco Felsch wrote:
> Split adding the fastboot.net.autostart to the global device and make
> use of it. With this change it is possible to set it e.g. during
> environment_initcall() and the later on followed fastboot_on_boot() can
> use it to start fastboot it automatically during boot.

So what you fix here is use of global fastboot.net.autostart from within
init scripts, or what is your use case?

> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  net/fastboot.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/net/fastboot.c b/net/fastboot.c
> index df388adc89..a5a7caf526 100644
> --- a/net/fastboot.c
> +++ b/net/fastboot.c
> @@ -547,12 +547,16 @@ fail_generic_init:
>  static struct fastboot_net *fastboot_net_obj;
>  static int fastboot_net_autostart;
>  
> -static int fastboot_on_boot(void)
> +static int fastboot_net_globalvars_init(void)
>  {
> -	struct fastboot_net *fbn;
> -
>  	globalvar_add_simple_bool("fastboot.net.autostart",
>  				  &fastboot_net_autostart);
> +	return 0;
> +}
> +
> +static int fastboot_on_boot(void)
> +{
> +	struct fastboot_net *fbn;
>  
>  	if (!fastboot_net_autostart)
>  		return 0;
> @@ -573,6 +577,7 @@ static void fastboot_net_exit(void)
>  		fastboot_net_free(fastboot_net_obj);
>  }
>  
> +device_initcall(fastboot_net_globalvars_init);
>  postenvironment_initcall(fastboot_on_boot);
>  predevshutdown_exitcall(fastboot_net_exit);
>  
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Wed Aug 11 11:30:53 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 11 Aug 2021 20:30:53 +0200
Subject: [PATCH] ARM: i.MX6: boot: detect USB serial downloader more
 reliable
In-Reply-To: <20210811173624.28061-1-m.felsch@pengutronix.de>
References: <20210811173624.28061-1-m.felsch@pengutronix.de>
Message-ID: <241f3046-fdaf-ccd9-bc43-8c6879da75d8@pengutronix.de>

On 11.08.21 19:36, Marco Felsch wrote:
> The problem with the BootROM is that the SCR registers are not set

s/SCR/SRC/ ?

> accordingly in case of a failed primary boot. E.g. if the device is
> configured to boot from an eMMC and the eMMC is empty or image is
> corrupt, the BootROM goes into 'recovery boot mode' (reference manual
> Figure 8-1) and the last possible recovery option is the serial
> downloader. In such case the SRC registers still indicate that the
> device was booted from an eMMC instead of serial-download.
> 
> This commit ports the U-Boot commit [1] with slightly adaptions suggested
> by Ahmad to Barebox. Also we need to reorder the imx6_init() else we
> reset the otg-controller to early.
> 
> [1] https://source.denx.de/u-boot/u-boot/-/commit/e203dcf23e9eabc2e4f3d0b079457cd1516f2081
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  arch/arm/mach-imx/boot.c  | 27 +++++++++++++++++++++++++++
>  arch/arm/mach-imx/imx6.c  |  4 ++--
>  include/soc/fsl/fsl_udc.h | 11 +++++++++++
>  3 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> index 2b66bbf71e..fcb3c10064 100644
> --- a/arch/arm/mach-imx/boot.c
> +++ b/arch/arm/mach-imx/boot.c
> @@ -8,6 +8,7 @@
>  #include <magicvar.h>
>  
>  #include <io.h>
> +#include <mach/clock-imx6.h>
>  #include <mach/generic.h>
>  #include <mach/imx25-regs.h>
>  #include <mach/imx27-regs.h>
> @@ -23,6 +24,7 @@
>  #include <mach/imx8mq.h>
>  #include <mach/imx6.h>
>  
> +#include <soc/fsl/fsl_udc.h>
>  
>  static void
>  imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
> @@ -397,6 +399,11 @@ static u32 imx6_get_src_boot_mode(void __iomem *src_base)
>  	return readl(src_base + IMX6_SRC_SBMR1);
>  }
>  
> +static inline bool imx6_usboh3_clk_active(void)
> +{
> +	return (readl(MXC_CCM_CCGR6) & 0x3) == 0x3;
> +}
> +
>  void imx6_get_boot_source(enum bootsource *src, int *instance)
>  {
>  	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
> @@ -410,6 +417,26 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
>  
>  	bootsrc = imx53_bootsource_internal(bootmode);
>  
> +	/*
> +	 * imx6_bootsource_serial() can't detect cases where the boot ROM
> +	 * decided to use the serial downloader as a fall back (primary
> +	 * boot source failed).
> +	 *
> +	 * Infer that the boot ROM used the USB serial downloader by
> +	 * checking whether both the UDC and the clock enabling access
> +	 * to its MMIO region are currently active...
> +	 * This assumes:
> +	 * - On fresh boots, PBL doesn't itself start a stopped UDC
> +	 * - In barebox proper, boot source is saved before the UDC driver
> +	 *   may enable the UDC
> +	 */
> +
> +	if (imx6_usboh3_clk_active() &&
> +	    is_chipidea_udc_running(IOMEM(MX6_OTG_BASE_ADDR))) {
> +		*src = BOOTSOURCE_SERIAL;
> +		return;
> +	}
> +
>  	if (imx6_bootsource_serial(sbmr2) ||
>  	    imx6_bootsource_serial_forced(bootsrc)) {
>  		*src = BOOTSOURCE_SERIAL;
> diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
> index 9ccb391384..fa4cb093c3 100644
> --- a/arch/arm/mach-imx/imx6.c
> +++ b/arch/arm/mach-imx/imx6.c
> @@ -205,10 +205,10 @@ int imx6_init(void)
>  	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
>  	u64 mx6_uid;
>  
> -	imx6_init_lowlevel();
> -
>  	imx6_boot_save_loc();
>  
> +	imx6_init_lowlevel();

A comment inside imx6_init_lowlevel hinting at the dependency w.r.t 
imx6_boot_save_loc would be nice.

Apart from these nitpicks:

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> +
>  	mx6_silicon_revision = imx6_cpu_revision();
>  	mx6_uid = imx6_uid();
>  
> diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
> index b983f714c5..0b409a9f6b 100644
> --- a/include/soc/fsl/fsl_udc.h
> +++ b/include/soc/fsl/fsl_udc.h
> @@ -1,6 +1,9 @@
>  #ifndef __FSL_UDC_H
>  #define __FSL_UDC_H
>  
> +#include <linux/types.h>
> +#include <io.h>
> +
>  /* USB DR device mode registers (Little Endian) */
>  struct usb_dr_device {
>  	/* Capability register */
> @@ -380,4 +383,12 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest);
>  int imx8mm_barebox_load_usb(void *dest);
>  int imx8mm_barebox_start_usb(void *dest);
>  
> +static inline bool is_chipidea_udc_running(void __iomem *dr)
> +{
> +	struct usb_dr_device __iomem *dr_regs = dr;
> +
> +	return (readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_DEVICE)
> +		&& (readl(&dr_regs->usbcmd) & USB_CMD_RUN_STOP);
> +}
> +
>  #endif /* __FSL_UDC_H */
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Thu Aug 12 00:35:34 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Thu, 12 Aug 2021 09:35:34 +0200
Subject: [PATCH] fastboot net: add global.fastboot.net.autostart early
In-Reply-To: <9e266302-92a1-a577-d38c-fc240177b169@pengutronix.de>
References: <20210811172504.11396-1-m.felsch@pengutronix.de>
 <9e266302-92a1-a577-d38c-fc240177b169@pengutronix.de>
Message-ID: <20210812073534.fg5f2cucub4rr3kv@pengutronix.de>

Hi Ahmad,

On 21-08-11 20:22, Ahmad Fatoum wrote:
> On 11.08.21 19:25, Marco Felsch wrote:
> > Split adding the fastboot.net.autostart to the global device and make
> > use of it. With this change it is possible to set it e.g. during
> > environment_initcall() and the later on followed fastboot_on_boot() can
> > use it to start fastboot it automatically during boot.
> 
> So what you fix here is use of global fastboot.net.autostart from within
> init scripts, or what is your use case?

Yes something like this. I have a custom board which calls
sentenv("global.fastboot.net.autostart", "1") during the
environment_initcall step.

But also I didn't get the logic behind: adding a global var in the same
function which checks that var to start the network interface.

Regards,
  Marco

> > Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> > ---
> >  net/fastboot.c | 11 ++++++++---
> >  1 file changed, 8 insertions(+), 3 deletions(-)
> > 
> > diff --git a/net/fastboot.c b/net/fastboot.c
> > index df388adc89..a5a7caf526 100644
> > --- a/net/fastboot.c
> > +++ b/net/fastboot.c
> > @@ -547,12 +547,16 @@ fail_generic_init:
> >  static struct fastboot_net *fastboot_net_obj;
> >  static int fastboot_net_autostart;
> >  
> > -static int fastboot_on_boot(void)
> > +static int fastboot_net_globalvars_init(void)
> >  {
> > -	struct fastboot_net *fbn;
> > -
> >  	globalvar_add_simple_bool("fastboot.net.autostart",
> >  				  &fastboot_net_autostart);
> > +	return 0;
> > +}
> > +
> > +static int fastboot_on_boot(void)
> > +{
> > +	struct fastboot_net *fbn;
> >  
> >  	if (!fastboot_net_autostart)
> >  		return 0;
> > @@ -573,6 +577,7 @@ static void fastboot_net_exit(void)
> >  		fastboot_net_free(fastboot_net_obj);
> >  }
> >  
> > +device_initcall(fastboot_net_globalvars_init);
> >  postenvironment_initcall(fastboot_on_boot);
> >  predevshutdown_exitcall(fastboot_net_exit);
> >  
> > 
> 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Thu Aug 12 00:38:19 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Thu, 12 Aug 2021 09:38:19 +0200
Subject: [PATCH] ARM: i.MX6: boot: detect USB serial downloader more
 reliable
In-Reply-To: <241f3046-fdaf-ccd9-bc43-8c6879da75d8@pengutronix.de>
References: <20210811173624.28061-1-m.felsch@pengutronix.de>
 <241f3046-fdaf-ccd9-bc43-8c6879da75d8@pengutronix.de>
Message-ID: <20210812073819.okshc336zsntsim7@pengutronix.de>

On 21-08-11 20:30, Ahmad Fatoum wrote:
> On 11.08.21 19:36, Marco Felsch wrote:
> > The problem with the BootROM is that the SCR registers are not set
> 
> s/SCR/SRC/ ?

of course :)

> > accordingly in case of a failed primary boot. E.g. if the device is
> > configured to boot from an eMMC and the eMMC is empty or image is
> > corrupt, the BootROM goes into 'recovery boot mode' (reference manual
> > Figure 8-1) and the last possible recovery option is the serial
> > downloader. In such case the SRC registers still indicate that the
> > device was booted from an eMMC instead of serial-download.
> > 
> > This commit ports the U-Boot commit [1] with slightly adaptions suggested
> > by Ahmad to Barebox. Also we need to reorder the imx6_init() else we
> > reset the otg-controller to early.
> > 
> > [1] https://source.denx.de/u-boot/u-boot/-/commit/e203dcf23e9eabc2e4f3d0b079457cd1516f2081
> > 
> > Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> > ---
> >  arch/arm/mach-imx/boot.c  | 27 +++++++++++++++++++++++++++
> >  arch/arm/mach-imx/imx6.c  |  4 ++--
> >  include/soc/fsl/fsl_udc.h | 11 +++++++++++
> >  3 files changed, 40 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> > index 2b66bbf71e..fcb3c10064 100644
> > --- a/arch/arm/mach-imx/boot.c
> > +++ b/arch/arm/mach-imx/boot.c
> > @@ -8,6 +8,7 @@
> >  #include <magicvar.h>
> >  
> >  #include <io.h>
> > +#include <mach/clock-imx6.h>
> >  #include <mach/generic.h>
> >  #include <mach/imx25-regs.h>
> >  #include <mach/imx27-regs.h>
> > @@ -23,6 +24,7 @@
> >  #include <mach/imx8mq.h>
> >  #include <mach/imx6.h>
> >  
> > +#include <soc/fsl/fsl_udc.h>
> >  
> >  static void
> >  imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
> > @@ -397,6 +399,11 @@ static u32 imx6_get_src_boot_mode(void __iomem *src_base)
> >  	return readl(src_base + IMX6_SRC_SBMR1);
> >  }
> >  
> > +static inline bool imx6_usboh3_clk_active(void)
> > +{
> > +	return (readl(MXC_CCM_CCGR6) & 0x3) == 0x3;
> > +}
> > +
> >  void imx6_get_boot_source(enum bootsource *src, int *instance)
> >  {
> >  	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
> > @@ -410,6 +417,26 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
> >  
> >  	bootsrc = imx53_bootsource_internal(bootmode);
> >  
> > +	/*
> > +	 * imx6_bootsource_serial() can't detect cases where the boot ROM
> > +	 * decided to use the serial downloader as a fall back (primary
> > +	 * boot source failed).
> > +	 *
> > +	 * Infer that the boot ROM used the USB serial downloader by
> > +	 * checking whether both the UDC and the clock enabling access
> > +	 * to its MMIO region are currently active...
> > +	 * This assumes:
> > +	 * - On fresh boots, PBL doesn't itself start a stopped UDC
> > +	 * - In barebox proper, boot source is saved before the UDC driver
> > +	 *   may enable the UDC
> > +	 */
> > +
> > +	if (imx6_usboh3_clk_active() &&
> > +	    is_chipidea_udc_running(IOMEM(MX6_OTG_BASE_ADDR))) {
> > +		*src = BOOTSOURCE_SERIAL;
> > +		return;
> > +	}
> > +
> >  	if (imx6_bootsource_serial(sbmr2) ||
> >  	    imx6_bootsource_serial_forced(bootsrc)) {
> >  		*src = BOOTSOURCE_SERIAL;
> > diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
> > index 9ccb391384..fa4cb093c3 100644
> > --- a/arch/arm/mach-imx/imx6.c
> > +++ b/arch/arm/mach-imx/imx6.c
> > @@ -205,10 +205,10 @@ int imx6_init(void)
> >  	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
> >  	u64 mx6_uid;
> >  
> > -	imx6_init_lowlevel();
> > -
> >  	imx6_boot_save_loc();
> >  
> > +	imx6_init_lowlevel();
> 
> A comment inside imx6_init_lowlevel hinting at the dependency w.r.t 
> imx6_boot_save_loc would be nice.

Make sense.

Regards,
  Marco

> Apart from these nitpicks:
> 
> Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> 
> > +
> >  	mx6_silicon_revision = imx6_cpu_revision();
> >  	mx6_uid = imx6_uid();
> >  
> > diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
> > index b983f714c5..0b409a9f6b 100644
> > --- a/include/soc/fsl/fsl_udc.h
> > +++ b/include/soc/fsl/fsl_udc.h
> > @@ -1,6 +1,9 @@
> >  #ifndef __FSL_UDC_H
> >  #define __FSL_UDC_H
> >  
> > +#include <linux/types.h>
> > +#include <io.h>
> > +
> >  /* USB DR device mode registers (Little Endian) */
> >  struct usb_dr_device {
> >  	/* Capability register */
> > @@ -380,4 +383,12 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest);
> >  int imx8mm_barebox_load_usb(void *dest);
> >  int imx8mm_barebox_start_usb(void *dest);
> >  
> > +static inline bool is_chipidea_udc_running(void __iomem *dr)
> > +{
> > +	struct usb_dr_device __iomem *dr_regs = dr;
> > +
> > +	return (readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_DEVICE)
> > +		&& (readl(&dr_regs->usbcmd) & USB_CMD_RUN_STOP);
> > +}
> > +
> >  #endif /* __FSL_UDC_H */
> > 
> 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Thu Aug 12 01:36:51 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Thu, 12 Aug 2021 10:36:51 +0200
Subject: [PATCH v2] ARM: i.MX6: boot: detect USB serial downloader more
 reliable
Message-ID: <20210812083651.3576-1-m.felsch@pengutronix.de>

The problem with the BootROM is that the SRC registers are not set
accordingly in case of a failed primary boot. E.g. if the device is
configured to boot from an eMMC and the eMMC is empty or image is
corrupt, the BootROM goes into 'recovery boot mode' (reference manual
Figure 8-1) and the last possible recovery option is the serial
downloader. In such case the SRC registers still indicate that the
device was booted from an eMMC instead of serial-download.

This commit ports the U-Boot commit [1] with slightly adaptions suggested
by Ahmad to Barebox. Also we need to reorder the imx6_init() else we
reset the otg-controller to early.

[1] https://source.denx.de/u-boot/u-boot/-/commit/e203dcf23e9eabc2e4f3d0b079457cd1516f2081

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/mach-imx/boot.c  | 27 +++++++++++++++++++++++++++
 arch/arm/mach-imx/imx6.c  |  9 +++++++--
 include/soc/fsl/fsl_udc.h | 11 +++++++++++
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 2b66bbf71e..fcb3c10064 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -8,6 +8,7 @@
 #include <magicvar.h>
 
 #include <io.h>
+#include <mach/clock-imx6.h>
 #include <mach/generic.h>
 #include <mach/imx25-regs.h>
 #include <mach/imx27-regs.h>
@@ -23,6 +24,7 @@
 #include <mach/imx8mq.h>
 #include <mach/imx6.h>
 
+#include <soc/fsl/fsl_udc.h>
 
 static void
 imx_boot_save_loc(void (*get_boot_source)(enum bootsource *, int *))
@@ -397,6 +399,11 @@ static u32 imx6_get_src_boot_mode(void __iomem *src_base)
 	return readl(src_base + IMX6_SRC_SBMR1);
 }
 
+static inline bool imx6_usboh3_clk_active(void)
+{
+	return (readl(MXC_CCM_CCGR6) & 0x3) == 0x3;
+}
+
 void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
 	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
@@ -410,6 +417,26 @@ void imx6_get_boot_source(enum bootsource *src, int *instance)
 
 	bootsrc = imx53_bootsource_internal(bootmode);
 
+	/*
+	 * imx6_bootsource_serial() can't detect cases where the boot ROM
+	 * decided to use the serial downloader as a fall back (primary
+	 * boot source failed).
+	 *
+	 * Infer that the boot ROM used the USB serial downloader by
+	 * checking whether both the UDC and the clock enabling access
+	 * to its MMIO region are currently active...
+	 * This assumes:
+	 * - On fresh boots, PBL doesn't itself start a stopped UDC
+	 * - In barebox proper, boot source is saved before the UDC driver
+	 *   may enable the UDC
+	 */
+
+	if (imx6_usboh3_clk_active() &&
+	    is_chipidea_udc_running(IOMEM(MX6_OTG_BASE_ADDR))) {
+		*src = BOOTSOURCE_SERIAL;
+		return;
+	}
+
 	if (imx6_bootsource_serial(sbmr2) ||
 	    imx6_bootsource_serial_forced(bootsrc)) {
 		*src = BOOTSOURCE_SERIAL;
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 9ccb391384..3ee42fd966 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -43,6 +43,11 @@ static void imx6_init_lowlevel(void)
 	uint32_t periph_sel_2;
 	uint32_t reg;
 
+	/*
+	 * Before reset the controller imx6_boot_save_loc() must be called to
+	 * detect serial-downloader fall back boots. For further information
+	 * check the comment in imx6_get_boot_source().
+	 */
 	if ((readl(MXC_CCM_CCGR6) & 0x3))
 		imx_reset_otg_controller(IOMEM(MX6_OTG_BASE_ADDR));
 
@@ -205,10 +210,10 @@ int imx6_init(void)
 	void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR);
 	u64 mx6_uid;
 
-	imx6_init_lowlevel();
-
 	imx6_boot_save_loc();
 
+	imx6_init_lowlevel();
+
 	mx6_silicon_revision = imx6_cpu_revision();
 	mx6_uid = imx6_uid();
 
diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
index b983f714c5..0b409a9f6b 100644
--- a/include/soc/fsl/fsl_udc.h
+++ b/include/soc/fsl/fsl_udc.h
@@ -1,6 +1,9 @@
 #ifndef __FSL_UDC_H
 #define __FSL_UDC_H
 
+#include <linux/types.h>
+#include <io.h>
+
 /* USB DR device mode registers (Little Endian) */
 struct usb_dr_device {
 	/* Capability register */
@@ -380,4 +383,12 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest);
 int imx8mm_barebox_load_usb(void *dest);
 int imx8mm_barebox_start_usb(void *dest);
 
+static inline bool is_chipidea_udc_running(void __iomem *dr)
+{
+	struct usb_dr_device __iomem *dr_regs = dr;
+
+	return (readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_DEVICE)
+		&& (readl(&dr_regs->usbcmd) & USB_CMD_RUN_STOP);
+}
+
 #endif /* __FSL_UDC_H */
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 12 01:54:34 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 10:54:34 +0200
Subject: [PATCH] fastboot net: add global.fastboot.net.autostart early
In-Reply-To: <20210812073534.fg5f2cucub4rr3kv@pengutronix.de>
References: <20210811172504.11396-1-m.felsch@pengutronix.de>
 <9e266302-92a1-a577-d38c-fc240177b169@pengutronix.de>
 <20210812073534.fg5f2cucub4rr3kv@pengutronix.de>
Message-ID: <89bf6b5f-8a05-5dc6-f08f-0e9f4d7b865f@pengutronix.de>

Hello Marco,

On 12.08.21 09:35, Marco Felsch wrote:
> Hi Ahmad,
> 
> On 21-08-11 20:22, Ahmad Fatoum wrote:
>> On 11.08.21 19:25, Marco Felsch wrote:
>>> Split adding the fastboot.net.autostart to the global device and make
>>> use of it. With this change it is possible to set it e.g. during
>>> environment_initcall() and the later on followed fastboot_on_boot() can
>>> use it to start fastboot it automatically during boot.
>>
>> So what you fix here is use of global fastboot.net.autostart from within
>> init scripts, or what is your use case?
> 
> Yes something like this. I have a custom board which calls
> sentenv("global.fastboot.net.autostart", "1") during the
> environment_initcall step.
> 
> But also I didn't get the logic behind: adding a global var in the same
> function which checks that var to start the network interface.

Global variables are synced with nv on creation, so they can be
added postenvironment and still have a different value from
the default.

I was asking because I had earlier moved global.usbgadget.autostart in
common/usbgadget.c to postenvironment, so I wondered what use case that
might have broken. To recap:

 - nv works with and without your change, because sync happens
   at globalvar add time

 - setting the variable from an environment_initcall won't work,
   without your change, as they are not registered yet that early

 - init scripts setting won't work with or without your change,

   because no one cares about fastboot_net_autostart after the

   initcalls are over


I think you should turn fastboot.net.autostart into a non
simple globalvar and enable it in the setter, just like is done
for global.usbgadget.autostart.

This allows you to set it an arbitrary time after postenvironment
and it would work. You can use it from late_initcall, in an init
script depending on whether a variable is set or from the
interactive shell.

(Maybe you could even turn the conditional in your board code into
 an init script that way)

Cheers,
Ahmad


> 
> Regards,
>   Marco
> 
>>> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
>>> ---
>>>  net/fastboot.c | 11 ++++++++---
>>>  1 file changed, 8 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/net/fastboot.c b/net/fastboot.c
>>> index df388adc89..a5a7caf526 100644
>>> --- a/net/fastboot.c
>>> +++ b/net/fastboot.c
>>> @@ -547,12 +547,16 @@ fail_generic_init:
>>>  static struct fastboot_net *fastboot_net_obj;
>>>  static int fastboot_net_autostart;
>>>  
>>> -static int fastboot_on_boot(void)
>>> +static int fastboot_net_globalvars_init(void)
>>>  {
>>> -	struct fastboot_net *fbn;
>>> -
>>>  	globalvar_add_simple_bool("fastboot.net.autostart",
>>>  				  &fastboot_net_autostart);
>>> +	return 0;
>>> +}
>>> +
>>> +static int fastboot_on_boot(void)
>>> +{
>>> +	struct fastboot_net *fbn;
>>>  
>>>  	if (!fastboot_net_autostart)
>>>  		return 0;
>>> @@ -573,6 +577,7 @@ static void fastboot_net_exit(void)
>>>  		fastboot_net_free(fastboot_net_obj);
>>>  }
>>>  
>>> +device_initcall(fastboot_net_globalvars_init);
>>>  postenvironment_initcall(fastboot_on_boot);
>>>  predevshutdown_exitcall(fastboot_net_exit);
>>>  
>>>
>>
>>
>> -- 
>> Pengutronix e.K.                           |                             |
>> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
>> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
>> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>>
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Thu Aug 12 05:19:43 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 14:19:43 +0200
Subject: [PATCH 4/5] x86: define phys_to_virt and virt_to_phys
In-Reply-To: <20210812121944.4419-1-a.fatoum@pengutronix.de>
References: <20210812121944.4419-1-a.fatoum@pengutronix.de>
Message-ID: <20210812121944.4419-4-a.fatoum@pengutronix.de>

Some PCI drivers use those, so provide 1:1 implementations.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/x86/include/asm/io.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 5d19679b5064..0971727bc63d 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -82,6 +82,16 @@ static inline void io_delay(void)
 	inb(0x80);
 }
 
+static inline void *phys_to_virt(unsigned long phys)
+{
+	return (void *)phys;
+}
+
+static inline unsigned long virt_to_phys(volatile void *mem)
+{
+	return (unsigned long)mem;
+}
+
 #include <asm-generic/io.h>
 
 #endif	/* __ASM_X86_IO_H */
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 12 05:19:40 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 14:19:40 +0200
Subject: [PATCH 1/5] net: drop Calxeda Highbank xgmac driver support
Message-ID: <20210812121944.4419-1-a.fatoum@pengutronix.de>

Support for MACH_HIGHBANK was removed in f0f96c3322d5
("ARM: remove Calxeda Highbank support"). There are no device trees
either barebox or upstream using this network controller, so remove
the driver as well.

Fixes: f0f96c3322d5 ("ARM: remove Calxeda Highbank support")
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/net/Kconfig  |   4 -
 drivers/net/Makefile |   1 -
 drivers/net/xgmac.c  | 734 -------------------------------------------
 3 files changed, 739 deletions(-)
 delete mode 100644 drivers/net/xgmac.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 802169a86e8c..4a290bebbd75 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -39,10 +39,6 @@ config DRIVER_NET_AT91_ETHER
 	depends on HAS_AT91_ETHER
 	select PHYLIB
 
-config DRIVER_NET_CALXEDA_XGMAC
-	bool "Calxeda xgmac"
-	depends on HAS_DMA
-
 config DRIVER_NET_CS8900
 	bool "cs8900 ethernet driver"
 	depends on HAS_CS8900 || COMPILE_TEST
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fb3e3bdee46a..e5eede634e63 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -4,7 +4,6 @@ obj-$(CONFIG_NET_USB)			+= usb/
 obj-$(CONFIG_DRIVER_NET_AR231X)		+= ar231x.o
 obj-$(CONFIG_DRIVER_NET_ARC_EMAC)	+= arc_emac.o
 obj-$(CONFIG_DRIVER_NET_AT91_ETHER)	+= at91_ether.o
-obj-$(CONFIG_DRIVER_NET_CALXEDA_XGMAC)	+= xgmac.o
 obj-$(CONFIG_DRIVER_NET_CS8900)		+= cs8900.o
 obj-$(CONFIG_DRIVER_NET_CPSW)		+= cpsw.o
 obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC)	+= davinci_emac.o
diff --git a/drivers/net/xgmac.c b/drivers/net/xgmac.c
deleted file mode 100644
index 136d78804349..000000000000
--- a/drivers/net/xgmac.c
+++ /dev/null
@@ -1,734 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2010-2011 Calxeda, Inc.
- */
-
-#include <common.h>
-#include <dma.h>
-#include <net.h>
-#include <clock.h>
-#include <malloc.h>
-#include <xfuncs.h>
-#include <init.h>
-#include <errno.h>
-#include <io.h>
-#include <linux/err.h>
-
-#define TX_NUM_DESC			1
-#define RX_NUM_DESC			32
-
-#define ETH_BUF_SZ			2048
-#define TX_BUF_SZ			(ETH_BUF_SZ * TX_NUM_DESC)
-#define RX_BUF_SZ			(ETH_BUF_SZ * RX_NUM_DESC)
-
-/* XGMAC Register definitions */
-#define XGMAC_CONTROL		0x00000000	/* MAC Configuration */
-#define XGMAC_FRAME_FILTER	0x00000004	/* MAC Frame Filter */
-#define XGMAC_FLOW_CTRL		0x00000018	/* MAC Flow Control */
-#define XGMAC_VLAN_TAG		0x0000001C	/* VLAN Tags */
-#define XGMAC_VERSION		0x00000020	/* Version */
-#define XGMAC_VLAN_INCL		0x00000024	/* VLAN tag for tx frames */
-#define XGMAC_LPI_CTRL		0x00000028	/* LPI Control and Status */
-#define XGMAC_LPI_TIMER		0x0000002C	/* LPI Timers Control */
-#define XGMAC_TX_PACE		0x00000030	/* Transmit Pace and Stretch */
-#define XGMAC_VLAN_HASH		0x00000034	/* VLAN Hash Table */
-#define XGMAC_DEBUG		0x00000038	/* Debug */
-#define XGMAC_INT_STAT		0x0000003C	/* Interrupt and Control */
-#define XGMAC_ADDR_HIGH(reg)	(0x00000040 + ((reg) * 8))
-#define XGMAC_ADDR_LOW(reg)	(0x00000044 + ((reg) * 8))
-#define XGMAC_HASH(n)		(0x00000300 + (n) * 4) /* HASH table regs */
-#define XGMAC_NUM_HASH		16
-#define XGMAC_OMR		0x00000400
-#define XGMAC_REMOTE_WAKE	0x00000700	/* Remote Wake-Up Frm Filter */
-#define XGMAC_PMT		0x00000704	/* PMT Control and Status */
-#define XGMAC_MMC_CTRL		0x00000800	/* XGMAC MMC Control */
-#define XGMAC_MMC_INTR_RX	0x00000804	/* Recieve Interrupt */
-#define XGMAC_MMC_INTR_TX	0x00000808	/* Transmit Interrupt */
-#define XGMAC_MMC_INTR_MASK_RX	0x0000080c	/* Recieve Interrupt Mask */
-#define XGMAC_MMC_INTR_MASK_TX	0x00000810	/* Transmit Interrupt Mask */
-
-
-/* Hardware TX Statistics Counters */
-#define XGMAC_MMC_TXOCTET_GB_LO	0x00000814
-#define XGMAC_MMC_TXOCTET_GB_HI	0x00000818
-#define XGMAC_MMC_TXFRAME_GB_LO	0x0000081C
-#define XGMAC_MMC_TXFRAME_GB_HI	0x00000820
-#define XGMAC_MMC_TXBCFRAME_G	0x00000824
-#define XGMAC_MMC_TXMCFRAME_G	0x0000082C
-#define XGMAC_MMC_TXUCFRAME_GB	0x00000864
-#define XGMAC_MMC_TXMCFRAME_GB	0x0000086C
-#define XGMAC_MMC_TXBCFRAME_GB	0x00000874
-#define XGMAC_MMC_TXUNDERFLOW	0x0000087C
-#define XGMAC_MMC_TXOCTET_G_LO	0x00000884
-#define XGMAC_MMC_TXOCTET_G_HI	0x00000888
-#define XGMAC_MMC_TXFRAME_G_LO	0x0000088C
-#define XGMAC_MMC_TXFRAME_G_HI	0x00000890
-#define XGMAC_MMC_TXPAUSEFRAME	0x00000894
-#define XGMAC_MMC_TXVLANFRAME	0x0000089C
-
-/* Hardware RX Statistics Counters */
-#define XGMAC_MMC_RXFRAME_GB_LO	0x00000900
-#define XGMAC_MMC_RXFRAME_GB_HI	0x00000904
-#define XGMAC_MMC_RXOCTET_GB_LO	0x00000908
-#define XGMAC_MMC_RXOCTET_GB_HI	0x0000090C
-#define XGMAC_MMC_RXOCTET_G_LO	0x00000910
-#define XGMAC_MMC_RXOCTET_G_HI	0x00000914
-#define XGMAC_MMC_RXBCFRAME_G	0x00000918
-#define XGMAC_MMC_RXMCFRAME_G	0x00000920
-#define XGMAC_MMC_RXCRCERR	0x00000928
-#define XGMAC_MMC_RXRUNT	0x00000930
-#define XGMAC_MMC_RXJABBER	0x00000934
-#define XGMAC_MMC_RXUCFRAME_G	0x00000970
-#define XGMAC_MMC_RXLENGTHERR	0x00000978
-#define XGMAC_MMC_RXPAUSEFRAME	0x00000988
-#define XGMAC_MMC_RXOVERFLOW	0x00000990
-#define XGMAC_MMC_RXVLANFRAME	0x00000998
-#define XGMAC_MMC_RXWATCHDOG	0x000009a0
-
-/* DMA Control and Status Registers */
-#define XGMAC_DMA_BUS_MODE	0x00000f00	/* Bus Mode */
-#define XGMAC_DMA_TX_POLL	0x00000f04	/* Transmit Poll Demand */
-#define XGMAC_DMA_RX_POLL	0x00000f08	/* Received Poll Demand */
-#define XGMAC_DMA_RX_BASE_ADDR	0x00000f0c	/* Receive List Base */
-#define XGMAC_DMA_TX_BASE_ADDR	0x00000f10	/* Transmit List Base */
-#define XGMAC_DMA_STATUS	0x00000f14	/* Status Register */
-#define XGMAC_DMA_CONTROL	0x00000f18	/* Ctrl (Operational Mode) */
-#define XGMAC_DMA_INTR_ENA	0x00000f1c	/* Interrupt Enable */
-#define XGMAC_DMA_MISS_FRAME_CTR 0x00000f20	/* Missed Frame Counter */
-#define XGMAC_DMA_RI_WDOG_TIMER	0x00000f24	/* RX Intr Watchdog Timer */
-#define XGMAC_DMA_AXI_BUS	0x00000f28	/* AXI Bus Mode */
-#define XGMAC_DMA_AXI_STATUS	0x00000f2C	/* AXI Status */
-#define XGMAC_DMA_HW_FEATURE	0x00000f58	/* Enabled Hardware Features */
-
-#define XGMAC_ADDR_AE		0x80000000
-#define XGMAC_MAX_FILTER_ADDR	31
-
-/* PMT Control and Status */
-#define XGMAC_PMT_POINTER_RESET	0x80000000
-#define XGMAC_PMT_GLBL_UNICAST	0x00000200
-#define XGMAC_PMT_WAKEUP_RX_FRM	0x00000040
-#define XGMAC_PMT_MAGIC_PKT	0x00000020
-#define XGMAC_PMT_WAKEUP_FRM_EN	0x00000004
-#define XGMAC_PMT_MAGIC_PKT_EN	0x00000002
-#define XGMAC_PMT_POWERDOWN	0x00000001
-
-#define XGMAC_CONTROL_SPD	0x40000000	/* Speed control */
-#define XGMAC_CONTROL_SPD_MASK	0x60000000
-#define XGMAC_CONTROL_SPD_1G	0x60000000
-#define XGMAC_CONTROL_SPD_2_5G	0x40000000
-#define XGMAC_CONTROL_SPD_10G	0x00000000
-#define XGMAC_CONTROL_SARC	0x10000000	/* Source Addr Insert/Replace */
-#define XGMAC_CONTROL_SARK_MASK	0x18000000
-#define XGMAC_CONTROL_CAR	0x04000000	/* CRC Addition/Replacement */
-#define XGMAC_CONTROL_CAR_MASK	0x06000000
-#define XGMAC_CONTROL_DP	0x01000000	/* Disable Padding */
-#define XGMAC_CONTROL_WD	0x00800000	/* Disable Watchdog on rx */
-#define XGMAC_CONTROL_JD	0x00400000	/* Jabber disable */
-#define XGMAC_CONTROL_JE	0x00100000	/* Jumbo frame */
-#define XGMAC_CONTROL_LM	0x00001000	/* Loop-back mode */
-#define XGMAC_CONTROL_IPC	0x00000400	/* Checksum Offload */
-#define XGMAC_CONTROL_ACS	0x00000080	/* Automatic Pad/FCS Strip */
-#define XGMAC_CONTROL_DDIC	0x00000010	/* Disable Deficit Idle Count */
-#define XGMAC_CONTROL_TE	0x00000008	/* Transmitter Enable */
-#define XGMAC_CONTROL_RE	0x00000004	/* Receiver Enable */
-
-/* XGMAC Frame Filter defines */
-#define XGMAC_FRAME_FILTER_PR	0x00000001	/* Promiscuous Mode */
-#define XGMAC_FRAME_FILTER_HUC	0x00000002	/* Hash Unicast */
-#define XGMAC_FRAME_FILTER_HMC	0x00000004	/* Hash Multicast */
-#define XGMAC_FRAME_FILTER_DAIF	0x00000008	/* DA Inverse Filtering */
-#define XGMAC_FRAME_FILTER_PM	0x00000010	/* Pass all multicast */
-#define XGMAC_FRAME_FILTER_DBF	0x00000020	/* Disable Broadcast frames */
-#define XGMAC_FRAME_FILTER_SAIF	0x00000100	/* Inverse Filtering */
-#define XGMAC_FRAME_FILTER_SAF	0x00000200	/* Source Address Filter */
-#define XGMAC_FRAME_FILTER_HPF	0x00000400	/* Hash or perfect Filter */
-#define XGMAC_FRAME_FILTER_VHF	0x00000800	/* VLAN Hash Filter */
-#define XGMAC_FRAME_FILTER_VPF	0x00001000	/* VLAN Perfect Filter */
-#define XGMAC_FRAME_FILTER_RA	0x80000000	/* Receive all mode */
-
-#define FIFO_MINUS_1K			0x0
-#define FIFO_MINUS_2K			0x1
-#define FIFO_MINUS_3K			0x2
-#define FIFO_MINUS_4K			0x3
-#define FIFO_MINUS_6K			0x4
-#define FIFO_MINUS_8K			0x5
-#define FIFO_MINUS_12K			0x6
-#define FIFO_MINUS_16K			0x7
-
-/* XGMAC FLOW CTRL defines */
-#define XGMAC_FLOW_CTRL_PT_MASK	0xffff0000	/* Pause Time Mask */
-#define XGMAC_FLOW_CTRL_PT_SHIFT	16
-#define XGMAC_FLOW_CTRL_DZQP	0x00000080	/* Disable Zero-Quanta Phase */
-#define XGMAC_FLOW_CTRL_PLT	0x00000020	/* Pause Low Threshhold */
-#define XGMAC_FLOW_CTRL_PLT_SHIFT	4
-#define XGMAC_FLOW_CTRL_PLT_MASK 0x00000030	/* PLT MASK */
-#define XGMAC_FLOW_CTRL_UP	0x00000008	/* Unicast Pause Frame Detect */
-#define XGMAC_FLOW_CTRL_RFE	0x00000004	/* Rx Flow Control Enable */
-#define XGMAC_FLOW_CTRL_TFE	0x00000002	/* Tx Flow Control Enable */
-#define XGMAC_FLOW_CTRL_FCB_BPA	0x00000001	/* Flow Control Busy ... */
-
-/* XGMAC_INT_STAT reg */
-#define XGMAC_INT_STAT_PMT	0x0080		/* PMT Interrupt Status */
-#define XGMAC_INT_STAT_LPI	0x0040		/* LPI Interrupt Status */
-
-/* DMA Bus Mode register defines */
-#define DMA_BUS_MODE_SFT_RESET	0x00000001	/* Software Reset */
-#define DMA_BUS_MODE_DSL_MASK	0x0000007c	/* Descriptor Skip Length */
-#define DMA_BUS_MODE_DSL_SHIFT	2		/* (in DWORDS) */
-#define DMA_BUS_MODE_ATDS	0x00000080	/* Alternate Descriptor Size */
-
-/* Programmable burst length */
-#define DMA_BUS_MODE_PBL_MASK	0x00003f00	/* Programmable Burst Len */
-#define DMA_BUS_MODE_PBL_SHIFT	8
-#define DMA_BUS_MODE_FB		0x00010000	/* Fixed burst */
-#define DMA_BUS_MODE_RPBL_MASK	0x003e0000	/* Rx-Programmable Burst Len */
-#define DMA_BUS_MODE_RPBL_SHIFT	17
-#define DMA_BUS_MODE_USP	0x00800000
-#define DMA_BUS_MODE_8PBL	0x01000000
-#define DMA_BUS_MODE_AAL	0x02000000
-
-#define DMA_AXIMODE_ENLPI	0x80000000
-#define DMA_AXIMODE_MGK		0x40000000
-#define DMA_AXIMODE_WROSR	0x00100000
-#define DMA_AXIMODE_WROSR_MASK	0x00F00000
-#define DMA_AXIMODE_WROSR_SHIFT	20
-#define DMA_AXIMODE_RDOSR	0x00010000
-#define DMA_AXIMODE_RDOSR_MASK	0x000F0000
-#define DMA_AXIMODE_RDOSR_SHIFT	16
-#define DMA_AXIMODE_AAL		0x00001000
-#define DMA_AXIMODE_BLEN256	0x00000080
-#define DMA_AXIMODE_BLEN128	0x00000040
-#define DMA_AXIMODE_BLEN64	0x00000020
-#define DMA_AXIMODE_BLEN32	0x00000010
-#define DMA_AXIMODE_BLEN16	0x00000008
-#define DMA_AXIMODE_BLEN8	0x00000004
-#define DMA_AXIMODE_BLEN4	0x00000002
-#define DMA_AXIMODE_UNDEF	0x00000001
-
-/* DMA Bus Mode register defines */
-#define DMA_BUS_PR_RATIO_MASK	0x0000c000	/* Rx/Tx priority ratio */
-#define DMA_BUS_PR_RATIO_SHIFT	14
-#define DMA_BUS_FB		0x00010000	/* Fixed Burst */
-
-/* DMA Control register defines */
-#define DMA_CONTROL_ST		0x00002000	/* Start/Stop Transmission */
-#define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
-#define DMA_CONTROL_DFF		0x01000000	/* Disable flush of rx frames */
-
-/* DMA Normal interrupt */
-#define DMA_INTR_ENA_NIE	0x00010000	/* Normal Summary */
-#define DMA_INTR_ENA_AIE	0x00008000	/* Abnormal Summary */
-#define DMA_INTR_ENA_ERE	0x00004000	/* Early Receive */
-#define DMA_INTR_ENA_FBE	0x00002000	/* Fatal Bus Error */
-#define DMA_INTR_ENA_ETE	0x00000400	/* Early Transmit */
-#define DMA_INTR_ENA_RWE	0x00000200	/* Receive Watchdog */
-#define DMA_INTR_ENA_RSE	0x00000100	/* Receive Stopped */
-#define DMA_INTR_ENA_RUE	0x00000080	/* Receive Buffer Unavailable */
-#define DMA_INTR_ENA_RIE	0x00000040	/* Receive Interrupt */
-#define DMA_INTR_ENA_UNE	0x00000020	/* Tx Underflow */
-#define DMA_INTR_ENA_OVE	0x00000010	/* Receive Overflow */
-#define DMA_INTR_ENA_TJE	0x00000008	/* Transmit Jabber */
-#define DMA_INTR_ENA_TUE	0x00000004	/* Transmit Buffer Unavail */
-#define DMA_INTR_ENA_TSE	0x00000002	/* Transmit Stopped */
-#define DMA_INTR_ENA_TIE	0x00000001	/* Transmit Interrupt */
-
-#define DMA_INTR_NORMAL		(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
-				 DMA_INTR_ENA_TUE)
-
-#define DMA_INTR_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
-				 DMA_INTR_ENA_RWE | DMA_INTR_ENA_RSE | \
-				 DMA_INTR_ENA_RUE | DMA_INTR_ENA_UNE | \
-				 DMA_INTR_ENA_OVE | DMA_INTR_ENA_TJE | \
-				 DMA_INTR_ENA_TSE)
-
-/* DMA default interrupt mask */
-#define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
-
-/* DMA Status register defines */
-#define DMA_STATUS_GMI		0x08000000	/* MMC interrupt */
-#define DMA_STATUS_GLI		0x04000000	/* GMAC Line interface int */
-#define DMA_STATUS_EB_MASK	0x00380000	/* Error Bits Mask */
-#define DMA_STATUS_EB_TX_ABORT	0x00080000	/* Error Bits - TX Abort */
-#define DMA_STATUS_EB_RX_ABORT	0x00100000	/* Error Bits - RX Abort */
-#define DMA_STATUS_TS_MASK	0x00700000	/* Transmit Process State */
-#define DMA_STATUS_TS_SHIFT	20
-#define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
-#define DMA_STATUS_RS_SHIFT	17
-#define DMA_STATUS_NIS		0x00010000	/* Normal Interrupt Summary */
-#define DMA_STATUS_AIS		0x00008000	/* Abnormal Interrupt Summary */
-#define DMA_STATUS_ERI		0x00004000	/* Early Receive Interrupt */
-#define DMA_STATUS_FBI		0x00002000	/* Fatal Bus Error Interrupt */
-#define DMA_STATUS_ETI		0x00000400	/* Early Transmit Interrupt */
-#define DMA_STATUS_RWT		0x00000200	/* Receive Watchdog Timeout */
-#define DMA_STATUS_RPS		0x00000100	/* Receive Process Stopped */
-#define DMA_STATUS_RU		0x00000080	/* Receive Buffer Unavailable */
-#define DMA_STATUS_RI		0x00000040	/* Receive Interrupt */
-#define DMA_STATUS_UNF		0x00000020	/* Transmit Underflow */
-#define DMA_STATUS_OVF		0x00000010	/* Receive Overflow */
-#define DMA_STATUS_TJT		0x00000008	/* Transmit Jabber Timeout */
-#define DMA_STATUS_TU		0x00000004	/* Transmit Buffer Unavail */
-#define DMA_STATUS_TPS		0x00000002	/* Transmit Process Stopped */
-#define DMA_STATUS_TI		0x00000001	/* Transmit Interrupt */
-
-/* Common MAC defines */
-#define MAC_ENABLE_TX		0x00000008	/* Transmitter Enable */
-#define MAC_ENABLE_RX		0x00000004	/* Receiver Enable */
-
-/* XGMAC Operation Mode Register */
-#define XGMAC_OMR_TSF		0x00200000	/* TX FIFO Store and Forward */
-#define XGMAC_OMR_FTF		0x00100000	/* Flush Transmit FIFO */
-#define XGMAC_OMR_TTC		0x00020000	/* Transmit Threshhold Ctrl */
-#define XGMAC_OMR_TTC_SHIFT	16
-#define XGMAC_OMR_TTC_MASK	0x00030000
-#define XGMAC_OMR_RFD		0x00006000	/* FC Deactivation Threshhold */
-#define XGMAC_OMR_RFD_SHIFT	12
-#define XGMAC_OMR_RFD_MASK	0x00007000	/* FC Deact Threshhold MASK */
-#define XGMAC_OMR_RFA		0x00000600	/* FC Activation Threshhold */
-#define XGMAC_OMR_RFA_SHIFT	9
-#define XGMAC_OMR_RFA_MASK	0x00000E00	/* FC Act Threshhold MASK */
-#define XGMAC_OMR_EFC		0x00000100	/* Enable Hardware FC */
-#define XGMAC_OMR_FEF		0x00000080	/* Forward Error Frames */
-#define XGMAC_OMR_DT		0x00000040	/* Drop TCP/IP csum Errors */
-#define XGMAC_OMR_RSF		0x00000020	/* RX FIFO Store and Forward */
-#define XGMAC_OMR_RTC_256	0x00000018	/* RX Threshhold Ctrl */
-#define XGMAC_OMR_RTC_MASK	0x00000018	/* RX Threshhold Ctrl MASK */
-
-/* XGMAC HW Features Register */
-#define DMA_HW_FEAT_TXCOESEL	0x00010000	/* TX Checksum offload */
-
-#define XGMAC_MMC_CTRL_CNT_FRZ	0x00000008
-
-/* XGMAC Descriptor Defines */
-#define MAX_DESC_BUF_SZ		(0x2000 - 8)
-
-#define RXDESC_EXT_STATUS	0x00000001
-#define RXDESC_CRC_ERR		0x00000002
-#define RXDESC_RX_ERR		0x00000008
-#define RXDESC_RX_WDOG		0x00000010
-#define RXDESC_FRAME_TYPE	0x00000020
-#define RXDESC_GIANT_FRAME	0x00000080
-#define RXDESC_LAST_SEG		0x00000100
-#define RXDESC_FIRST_SEG	0x00000200
-#define RXDESC_VLAN_FRAME	0x00000400
-#define RXDESC_OVERFLOW_ERR	0x00000800
-#define RXDESC_LENGTH_ERR	0x00001000
-#define RXDESC_SA_FILTER_FAIL	0x00002000
-#define RXDESC_DESCRIPTOR_ERR	0x00004000
-#define RXDESC_ERROR_SUMMARY	0x00008000
-#define RXDESC_FRAME_LEN_OFFSET	16
-#define RXDESC_FRAME_LEN_MASK	0x3fff0000
-#define RXDESC_DA_FILTER_FAIL	0x40000000
-
-#define RXDESC1_END_RING	0x00008000
-
-#define RXDESC_IP_PAYLOAD_MASK	0x00000003
-#define RXDESC_IP_PAYLOAD_UDP	0x00000001
-#define RXDESC_IP_PAYLOAD_TCP	0x00000002
-#define RXDESC_IP_PAYLOAD_ICMP	0x00000003
-#define RXDESC_IP_HEADER_ERR	0x00000008
-#define RXDESC_IP_PAYLOAD_ERR	0x00000010
-#define RXDESC_IPV4_PACKET	0x00000040
-#define RXDESC_IPV6_PACKET	0x00000080
-#define TXDESC_UNDERFLOW_ERR	0x00000001
-#define TXDESC_JABBER_TIMEOUT	0x00000002
-#define TXDESC_LOCAL_FAULT	0x00000004
-#define TXDESC_REMOTE_FAULT	0x00000008
-#define TXDESC_VLAN_FRAME	0x00000010
-#define TXDESC_FRAME_FLUSHED	0x00000020
-#define TXDESC_IP_HEADER_ERR	0x00000040
-#define TXDESC_PAYLOAD_CSUM_ERR	0x00000080
-#define TXDESC_ERROR_SUMMARY	0x00008000
-#define TXDESC_SA_CTRL_INSERT	0x00040000
-#define TXDESC_SA_CTRL_REPLACE	0x00080000
-#define TXDESC_2ND_ADDR_CHAINED	0x00100000
-#define TXDESC_END_RING		0x00200000
-#define TXDESC_CSUM_IP		0x00400000
-#define TXDESC_CSUM_IP_PAYLD	0x00800000
-#define TXDESC_CSUM_ALL		0x00C00000
-#define TXDESC_CRC_EN_REPLACE	0x01000000
-#define TXDESC_CRC_EN_APPEND	0x02000000
-#define TXDESC_DISABLE_PAD	0x04000000
-#define TXDESC_FIRST_SEG	0x10000000
-#define TXDESC_LAST_SEG		0x20000000
-#define TXDESC_INTERRUPT	0x40000000
-
-#define DESC_OWN		0x80000000
-#define DESC_BUFFER1_SZ_MASK	0x00001fff
-#define DESC_BUFFER2_SZ_MASK	0x1fff0000
-#define DESC_BUFFER2_SZ_OFFSET	16
-
-struct xgmac_dma_desc {
-	__le32 flags;
-	__le32 buf_size;
-	__le32 buf1_addr;		/* Buffer 1 Address Pointer */
-	__le32 buf2_addr;		/* Buffer 2 Address Pointer */
-	__le32 ext_status;
-	__le32 res[3];
-};
-
-struct xgmac_priv {
-	struct xgmac_dma_desc *rx_chain;
-	struct xgmac_dma_desc *tx_chain;
-	char *rxbuffer;
-
-	u32 tx_currdesc;
-	u32 rx_currdesc;
-
-	void __iomem *base;
-
-	struct eth_device edev;
-	struct device_d *dev;
-};
-
-/* XGMAC Descriptor Access Helpers */
-static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
-{
-	if (buf_sz > MAX_DESC_BUF_SZ)
-		p->buf_size = cpu_to_le32(MAX_DESC_BUF_SZ |
-			(buf_sz - MAX_DESC_BUF_SZ) << DESC_BUFFER2_SZ_OFFSET);
-	else
-		p->buf_size = cpu_to_le32(buf_sz);
-}
-
-static inline int desc_get_buf_len(struct xgmac_dma_desc *p)
-{
-	u32 len = le32_to_cpu(p->buf_size);
-	return (len & DESC_BUFFER1_SZ_MASK) +
-		((len & DESC_BUFFER2_SZ_MASK) >> DESC_BUFFER2_SZ_OFFSET);
-}
-
-static inline void desc_init_rx_desc(struct xgmac_dma_desc *p, int ring_size,
-				     int buf_sz)
-{
-	struct xgmac_dma_desc *end = p + ring_size - 1;
-
-	memset(p, 0, sizeof(*p) * ring_size);
-
-	for (; p <= end; p++)
-		desc_set_buf_len(p, buf_sz);
-
-	end->buf_size |= cpu_to_le32(RXDESC1_END_RING);
-}
-
-static inline void desc_init_tx_desc(struct xgmac_dma_desc *p, u32 ring_size)
-{
-	memset(p, 0, sizeof(*p) * ring_size);
-	p[ring_size - 1].flags = cpu_to_le32(TXDESC_END_RING);
-}
-
-static inline int desc_get_owner(struct xgmac_dma_desc *p)
-{
-	return le32_to_cpu(p->flags) & DESC_OWN;
-}
-
-static inline void desc_set_rx_owner(struct xgmac_dma_desc *p)
-{
-	/* Clear all fields and set the owner */
-	p->flags = cpu_to_le32(DESC_OWN);
-}
-
-static inline void desc_set_tx_owner(struct xgmac_dma_desc *p, u32 flags)
-{
-	u32 tmpflags = le32_to_cpu(p->flags);
-	tmpflags &= TXDESC_END_RING;
-	tmpflags |= flags | DESC_OWN;
-	p->flags = cpu_to_le32(tmpflags);
-}
-
-static inline void *desc_get_buf_addr(struct xgmac_dma_desc *p)
-{
-	return (void *)le32_to_cpu(p->buf1_addr);
-}
-
-static inline void desc_set_buf_addr(struct xgmac_dma_desc *p,
-				     void *paddr, int len)
-{
-	p->buf1_addr = cpu_to_le32(paddr);
-	if (len > MAX_DESC_BUF_SZ)
-		p->buf2_addr = cpu_to_le32(paddr + MAX_DESC_BUF_SZ);
-}
-
-static inline void desc_set_buf_addr_and_size(struct xgmac_dma_desc *p,
-					      void *paddr, int len)
-{
-	desc_set_buf_len(p, len);
-	desc_set_buf_addr(p, paddr, len);
-}
-
-static inline int desc_get_rx_frame_len(struct xgmac_dma_desc *p)
-{
-	u32 data = le32_to_cpu(p->flags);
-	u32 len = (data & RXDESC_FRAME_LEN_MASK) >> RXDESC_FRAME_LEN_OFFSET;
-	if (data & RXDESC_FRAME_TYPE)
-		len -= 4;
-
-	return len;
-}
-
-/*
- * Initialize a descriptor ring.  Calxeda XGMAC is configured to use
- * advanced descriptors.
- */
-
-static void init_rx_desc(struct xgmac_priv *priv)
-{
-	struct xgmac_dma_desc *rxdesc = priv->rx_chain;
-	void *rxbuffer = priv->rxbuffer;
-	int i;
-
-	desc_init_rx_desc(rxdesc, RX_NUM_DESC, ETH_BUF_SZ);
-	writel((ulong)rxdesc, priv->base + XGMAC_DMA_RX_BASE_ADDR);
-
-	for (i = 0; i < RX_NUM_DESC; i++) {
-		desc_set_buf_addr(rxdesc + i, rxbuffer + (i * ETH_BUF_SZ),
-				  ETH_BUF_SZ);
-		desc_set_rx_owner(rxdesc + i);
-	}
-}
-
-static void init_tx_desc(struct xgmac_priv *priv)
-{
-	desc_init_tx_desc(priv->tx_chain, TX_NUM_DESC);
-	writel((ulong)priv->tx_chain, priv->base + XGMAC_DMA_TX_BASE_ADDR);
-}
-
-static int xgmac_reset(struct eth_device *dev)
-{
-	struct xgmac_priv *priv = dev->priv;
-	int ret;
-	u32 value;
-
-	value = readl(priv->base + XGMAC_CONTROL) & XGMAC_CONTROL_SPD_MASK;
-
-	writel(DMA_BUS_MODE_SFT_RESET, priv->base + XGMAC_DMA_BUS_MODE);
-
-	ret = wait_on_timeout(100 * MSECOND,
-		!(readl(priv->base + XGMAC_DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
-
-	writel(value, priv->base + XGMAC_CONTROL);
-
-	return ret;
-}
-
-static int xgmac_open(struct eth_device *edev)
-{
-	struct xgmac_priv *priv = edev->priv;
-	int value;
-	int ret;
-
-	ret = xgmac_reset(edev);
-	if (ret)
-		return ret;
-
-	/* set the AXI bus modes */
-	value = DMA_BUS_MODE_ATDS |
-		(16 << DMA_BUS_MODE_PBL_SHIFT) |
-		DMA_BUS_MODE_FB | DMA_BUS_MODE_AAL;
-	writel(value, priv->base + XGMAC_DMA_BUS_MODE);
-
-	value = DMA_AXIMODE_AAL | DMA_AXIMODE_BLEN16 |
-		DMA_AXIMODE_BLEN8 | DMA_AXIMODE_BLEN4;
-	writel(value, priv->base + XGMAC_DMA_AXI_BUS);
-
-	/* set flow control parameters and store and forward mode */
-	value = (FIFO_MINUS_12K << XGMAC_OMR_RFD_SHIFT) |
-		(FIFO_MINUS_4K << XGMAC_OMR_RFA_SHIFT) |
-		XGMAC_OMR_EFC | XGMAC_OMR_TSF | XGMAC_OMR_RSF;
-	writel(value, priv->base + XGMAC_OMR);
-
-	/* enable pause frames */
-	value = (1024 << XGMAC_FLOW_CTRL_PT_SHIFT) |
-		(1 << XGMAC_FLOW_CTRL_PLT_SHIFT) |
-		XGMAC_FLOW_CTRL_UP | XGMAC_FLOW_CTRL_RFE | XGMAC_FLOW_CTRL_TFE;
-	writel(value, priv->base + XGMAC_FLOW_CTRL);
-
-	/* Initialize the descriptor chains */
-	init_rx_desc(priv);
-	init_tx_desc(priv);
-
-	/* must set to 0, or when started up will cause issues */
-	priv->tx_currdesc = 0;
-	priv->rx_currdesc = 0;
-
-	/* set default core values */
-	value = readl(priv->base + XGMAC_CONTROL);
-	value &= XGMAC_CONTROL_SPD_MASK;
-	value |= XGMAC_CONTROL_DDIC | XGMAC_CONTROL_ACS |
-		XGMAC_CONTROL_IPC | XGMAC_CONTROL_CAR;
-
-	/* Everything is ready enable both mac and DMA */
-	value |= XGMAC_CONTROL_RE | XGMAC_CONTROL_TE;
-	writel(value, priv->base + XGMAC_CONTROL);
-
-	value = readl(priv->base + XGMAC_DMA_CONTROL);
-	value |= DMA_CONTROL_SR | DMA_CONTROL_ST;
-	writel(value, priv->base + XGMAC_DMA_CONTROL);
-
-	return 0;
-}
-
-static int xgmac_send(struct eth_device *edev, void *packet, int length)
-{
-	struct xgmac_priv *priv = edev->priv;
-	u32 currdesc = priv->tx_currdesc;
-	struct xgmac_dma_desc *txdesc = &priv->tx_chain[currdesc];
-	int ret;
-
-	dma_sync_single_for_device((unsigned long)packet, length, DMA_TO_DEVICE);
-	desc_set_buf_addr_and_size(txdesc, packet, length);
-	desc_set_tx_owner(txdesc, TXDESC_FIRST_SEG |
-		TXDESC_LAST_SEG | TXDESC_CRC_EN_APPEND);
-
-	/* write poll demand */
-	writel(1, priv->base + XGMAC_DMA_TX_POLL);
-
-	ret = wait_on_timeout(1 * SECOND, !desc_get_owner(txdesc));
-	dma_sync_single_for_cpu((unsigned long)packet, length, DMA_TO_DEVICE);
-	if (ret) {
-		dev_err(priv->dev, "TX timeout\n");
-		return ret;
-	}
-
-	priv->tx_currdesc = (currdesc + 1) & (TX_NUM_DESC - 1);
-	return 0;
-}
-
-static int xgmac_recv(struct eth_device *edev)
-{
-	struct xgmac_priv *priv = edev->priv;
-	u32 currdesc = priv->rx_currdesc;
-	struct xgmac_dma_desc *rxdesc = &priv->rx_chain[currdesc];
-	int length = 0;
-	void *buf_addr;
-
-	/* check if the host has the desc */
-	if (desc_get_owner(rxdesc))
-		return -1; /* something bad happened */
-
-	length = desc_get_rx_frame_len(rxdesc);
-	buf_addr = desc_get_buf_addr(rxdesc);
-
-	dma_sync_single_for_cpu((unsigned long)buf_addr, length, DMA_FROM_DEVICE);
-	net_receive(edev, buf_addr, length);
-	dma_sync_single_for_device((unsigned long)buf_addr, length,
-				   DMA_FROM_DEVICE);
-
-	/* set descriptor back to owned by XGMAC */
-	desc_set_rx_owner(rxdesc);
-	writel(1, priv->base + XGMAC_DMA_RX_POLL);
-
-	priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
-
-	return length;
-}
-
-static void xgmac_halt(struct eth_device *edev)
-{
-	struct xgmac_priv *priv = edev->priv;
-	int value;
-
-	/* Disable TX/RX */
-	value = readl(priv->base + XGMAC_CONTROL);
-	value &= ~(XGMAC_CONTROL_RE | XGMAC_CONTROL_TE);
-	writel(value, priv->base + XGMAC_CONTROL);
-
-	/* Disable DMA */
-	value = readl(priv->base + XGMAC_DMA_CONTROL);
-	value &= ~(DMA_CONTROL_SR | DMA_CONTROL_ST);
-	writel(value, priv->base + XGMAC_DMA_CONTROL);
-
-	/* must set to 0, or when started up will cause issues */
-	priv->tx_currdesc = 0;
-	priv->rx_currdesc = 0;
-}
-
-static int xgmac_get_ethaddr(struct eth_device *edev, unsigned char *addr)
-{
-	struct xgmac_priv *priv = edev->priv;
-	u32 hi_addr, lo_addr;
-
-	/* Read the MAC address from the hardware */
-	hi_addr = readl(priv->base + XGMAC_ADDR_HIGH(0));
-	lo_addr = readl(priv->base + XGMAC_ADDR_LOW(0));
-
-	/* Extract the MAC address from the high and low words */
-	addr[0] = lo_addr & 0xff;
-	addr[1] = (lo_addr >> 8) & 0xff;
-	addr[2] = (lo_addr >> 16) & 0xff;
-	addr[3] = (lo_addr >> 24) & 0xff;
-	addr[4] = hi_addr & 0xff;
-	addr[5] = (hi_addr >> 8) & 0xff;
-
-	return 0;
-}
-
-static int xgmac_set_ethaddr(struct eth_device *dev, const unsigned char *addr)
-{
-	struct xgmac_priv *priv = dev->priv;
-	u32 data;
-
-	data = (addr[5] << 8) | addr[4];
-	writel(data, priv->base + XGMAC_ADDR_HIGH(0));
-	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
-	writel(data, priv->base + XGMAC_ADDR_LOW(0));
-
-	return 0;
-}
-
-static int hb_xgmac_probe(struct device_d *dev)
-{
-	struct resource *iores;
-	struct eth_device *edev;
-	struct xgmac_priv *priv;
-	void __iomem *base;
-
-	iores = dev_request_mem_resource(dev, 0);
-	if (IS_ERR(iores))
-		return PTR_ERR(iores);
-	base = IOMEM(iores->start);
-
-	/* check hardware version */
-	if (readl(base + XGMAC_VERSION) != 0x1012)
-		return -EINVAL;
-
-	priv = xzalloc(sizeof(*priv));
-
-	priv->dev = dev;
-	priv->base = base;
-
-	priv->rxbuffer = dma_alloc_coherent(RX_BUF_SZ, DMA_ADDRESS_BROKEN);
-	priv->rx_chain = dma_alloc_coherent(RX_NUM_DESC * sizeof(struct xgmac_dma_desc),
-					    DMA_ADDRESS_BROKEN);
-	priv->tx_chain = dma_alloc_coherent(TX_NUM_DESC * sizeof(struct xgmac_dma_desc),
-					    DMA_ADDRESS_BROKEN);
-
-	edev = &priv->edev;
-	edev->priv = priv;
-
-	edev->open = xgmac_open;
-	edev->send = xgmac_send;
-	edev->recv = xgmac_recv;
-	edev->halt = xgmac_halt;
-	edev->get_ethaddr = xgmac_get_ethaddr;
-	edev->set_ethaddr = xgmac_set_ethaddr;
-	edev->parent = dev;
-
-	eth_register(edev);
-
-	return 0;
-}
-
-static __maybe_unused struct of_device_id xgmac_dt_ids[] = {
-	{
-		.compatible = "calxeda,hb-xgmac",
-	}, {
-		/* sentinel */
-	}
-};
-
-static struct driver_d hb_xgmac_driver = {
-	.name  = "hb-xgmac",
-	.probe = hb_xgmac_probe,
-	.of_compatible = DRV_OF_COMPAT(xgmac_dt_ids),
-};
-device_platform_driver(hb_xgmac_driver);
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 12 05:19:44 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 14:19:44 +0200
Subject: [PATCH 5/5] net: e1000: split EEPROM and barebox MTD wrapper into
 separate files
In-Reply-To: <20210812121944.4419-1-a.fatoum@pengutronix.de>
References: <20210812121944.4419-1-a.fatoum@pengutronix.de>
Message-ID: <20210812121944.4419-5-a.fatoum@pengutronix.de>

With the addition of the EFI PCI bus driver, e1000 can now be built for
x86 as well. This only works when CONFIG_MTD=y, because otherwise
add_mtd_device is not defined leading to a link error.

This doesn't happen with other platforms, because linker garbage
collection, which is not used for the EFI platform.

Fix this issue by separating the generic EEPROM parts from the
barebox-specific MTD parts and compiling the MTD parts conditionally.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/net/Makefile       |   2 +-
 drivers/net/e1000/Makefile |   3 +
 drivers/net/e1000/eeprom.c | 814 ------------------------------------
 drivers/net/e1000/mtd.c    | 835 +++++++++++++++++++++++++++++++++++++
 4 files changed, 839 insertions(+), 815 deletions(-)
 create mode 100644 drivers/net/e1000/Makefile
 create mode 100644 drivers/net/e1000/mtd.c

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e5eede634e63..b1aa9571fc72 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP) += designware_rockchip.o
 obj-$(CONFIG_DRIVER_NET_DM9K)		+= dm9k.o
-obj-$(CONFIG_DRIVER_NET_E1000)		+= e1000/regio.o e1000/main.o e1000/eeprom.o
+obj-$(CONFIG_DRIVER_NET_E1000)		+= e1000/
 obj-$(CONFIG_DRIVER_NET_ENC28J60)	+= enc28j60.o
 obj-$(CONFIG_DRIVER_NET_EP93XX)		+= ep93xx.o
 obj-$(CONFIG_DRIVER_NET_ETHOC)		+= ethoc.o
diff --git a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile
new file mode 100644
index 000000000000..91ef11cbe356
--- /dev/null
+++ b/drivers/net/e1000/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y			+= regio.o main.o eeprom.o
+obj-$(CONFIG_MTD)	+= mtd.o
diff --git a/drivers/net/e1000/eeprom.c b/drivers/net/e1000/eeprom.c
index 5a7d8675cecd..6bdf9db5532e 100644
--- a/drivers/net/e1000/eeprom.c
+++ b/drivers/net/e1000/eeprom.c
@@ -731,250 +731,6 @@ static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw)
 	return E1000_SUCCESS;
 }
 
-static int e1000_flash_mode_wait_for_idle(struct e1000_hw *hw)
-{
-	const int ret = e1000_poll_reg(hw, E1000_FLSWCTL, E1000_FLSWCTL_DONE,
-				       E1000_FLSWCTL_DONE, SECOND);
-	if (ret < 0)
-		dev_err(hw->dev,
-			"Timeout waiting for FLSWCTL.DONE to be set (wait)\n");
-	return ret;
-}
-
-static int e1000_flash_mode_check_command_valid(struct e1000_hw *hw)
-{
-	const uint32_t flswctl = e1000_read_reg(hw, E1000_FLSWCTL);
-	if (!(flswctl & E1000_FLSWCTL_CMDV)) {
-		dev_err(hw->dev, "FLSWCTL.CMDV was cleared\n");
-		return -EIO;
-	}
-
-	return E1000_SUCCESS;
-}
-
-static void e1000_flash_cmd(struct e1000_hw *hw,
-			    uint32_t cmd, uint32_t offset)
-{
-	uint32_t flswctl = e1000_read_reg(hw, E1000_FLSWCTL);
-	flswctl &= ~E1000_FLSWCTL_CMD_ADDR_MASK;
-	flswctl |= E1000_FLSWCTL_CMD(cmd) | E1000_FLSWCTL_ADDR(offset);
-	e1000_write_reg(hw, E1000_FLSWCTL, flswctl);
-}
-
-static int e1000_flash_mode_read_chunk(struct e1000_hw *hw, loff_t offset,
-				       size_t size, void *data)
-{
-	int ret;
-	size_t chunk, residue = size;
-	uint32_t flswdata;
-
-	DEBUGFUNC();
-
-	if (size > SZ_4K ||
-	    E1000_FLSWCTL_ADDR(offset) != offset)
-		return -EINVAL;
-
-	ret = e1000_flash_mode_wait_for_idle(hw);
-	if (ret < 0)
-		return ret;
-
-	e1000_write_reg(hw, E1000_FLSWCNT, size);
-	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_READ, offset);
-
-	do {
-		ret = e1000_flash_mode_check_command_valid(hw);
-		if (ret < 0)
-			return -EIO;
-
-		chunk = min(sizeof(flswdata), residue);
-
-		ret = e1000_poll_reg(hw, E1000_FLSWCTL,
-				     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
-				     SECOND);
-		if (ret < 0) {
-			dev_err(hw->dev,
-				"Timeout waiting for FLSWCTL.DONE to be set (read)\n");
-			return ret;
-		}
-
-		flswdata = e1000_read_reg(hw, E1000_FLSWDATA);
-		/*
-		 * Readl does le32_to_cpu, so we need to undo that
-		 */
-		flswdata = cpu_to_le32(flswdata);
-		memcpy(data, &flswdata, chunk);
-
-		data += chunk;
-		residue -= chunk;
-	} while (residue);
-
-	return E1000_SUCCESS;
-}
-
-static int e1000_flash_mode_write_chunk(struct e1000_hw *hw, loff_t offset,
-					size_t size, const void *data)
-{
-	int ret;
-	size_t chunk, residue = size;
-	uint32_t flswdata;
-
-	if (size > 256 ||
-	    E1000_FLSWCTL_ADDR(offset) != offset)
-		return -EINVAL;
-
-	ret = e1000_flash_mode_wait_for_idle(hw);
-	if (ret < 0)
-		return ret;
-
-
-	e1000_write_reg(hw, E1000_FLSWCNT, size);
-	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_WRITE, offset);
-
-	do {
-		chunk = min(sizeof(flswdata), residue);
-		memcpy(&flswdata, data, chunk);
-		/*
-		 * writel does cpu_to_le32, so we do the inverse in
-		 * order to account for that
-		 */
-		flswdata = le32_to_cpu(flswdata);
-		e1000_write_reg(hw, E1000_FLSWDATA, flswdata);
-
-		ret = e1000_flash_mode_check_command_valid(hw);
-		if (ret < 0)
-			return -EIO;
-
-		ret = e1000_poll_reg(hw, E1000_FLSWCTL,
-				     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
-				     SECOND);
-		if (ret < 0) {
-			dev_err(hw->dev,
-				"Timeout waiting for FLSWCTL.DONE to be set (write)\n");
-			return ret;
-		}
-
-		data += chunk;
-		residue -= chunk;
-
-	} while (residue);
-
-	return E1000_SUCCESS;
-}
-
-
-static int e1000_flash_mode_erase_chunk(struct e1000_hw *hw, loff_t offset,
-					size_t size)
-{
-	int ret;
-
-	ret = e1000_flash_mode_wait_for_idle(hw);
-	if (ret < 0)
-		return ret;
-
-	if (!size && !offset)
-		e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_ERASE_DEVICE, 0);
-	else
-		e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_ERASE_SECTOR, offset);
-
-	ret = e1000_flash_mode_check_command_valid(hw);
-	if (ret < 0)
-		return -EIO;
-
-	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
-			     E1000_FLSWCTL_DONE | E1000_FLSWCTL_FLBUSY,
-			     E1000_FLSWCTL_DONE,
-			     40 * SECOND);
-	if (ret < 0) {
-		dev_err(hw->dev,
-			"Timeout waiting for FLSWCTL.DONE to be set (erase)\n");
-		return ret;
-	}
-
-	return E1000_SUCCESS;
-}
-
-enum {
-	E1000_FLASH_MODE_OP_READ = 0,
-	E1000_FLASH_MODE_OP_WRITE = 1,
-	E1000_FLASH_MODE_OP_ERASE = 2,
-};
-
-
-static int e1000_flash_mode_io(struct e1000_hw *hw, int op, size_t granularity,
-			       loff_t offset, size_t size, void *data)
-{
-	int ret;
-	size_t residue = size;
-
-	do {
-		const size_t chunk = min(granularity, residue);
-
-		switch (op) {
-		case E1000_FLASH_MODE_OP_READ:
-			ret = e1000_flash_mode_read_chunk(hw, offset,
-							  chunk, data);
-			break;
-		case E1000_FLASH_MODE_OP_WRITE:
-			ret = e1000_flash_mode_write_chunk(hw, offset,
-							   chunk, data);
-			break;
-		case E1000_FLASH_MODE_OP_ERASE:
-			ret = e1000_flash_mode_erase_chunk(hw, offset,
-							   chunk);
-			break;
-		default:
-			return -ENOTSUPP;
-		}
-
-		if (ret < 0)
-			return ret;
-
-		offset += chunk;
-		residue -= chunk;
-		data += chunk;
-	} while (residue);
-
-	return E1000_SUCCESS;
-}
-
-
-static int e1000_flash_mode_read(struct e1000_hw *hw, loff_t offset,
-				 size_t size, void *data)
-{
-	return e1000_flash_mode_io(hw,
-				   E1000_FLASH_MODE_OP_READ, SZ_4K,
-				   offset, size, data);
-}
-
-static int e1000_flash_mode_write(struct e1000_hw *hw, loff_t offset,
-				  size_t size, const void *data)
-{
-	int ret;
-
-	ret = e1000_flash_mode_io(hw,
-				  E1000_FLASH_MODE_OP_WRITE, 256,
-				  offset, size, (void *)data);
-	if (ret < 0)
-		return ret;
-
-	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
-			     E1000_FLSWCTL_FLBUSY,
-			     0,  SECOND);
-	if (ret < 0)
-		dev_err(hw->dev, "Timout while waiting for FLSWCTL.FLBUSY\n");
-
-	return ret;
-}
-
-static int e1000_flash_mode_erase(struct e1000_hw *hw, loff_t offset,
-				  size_t size)
-{
-	return e1000_flash_mode_io(hw,
-				   E1000_FLASH_MODE_OP_ERASE, SZ_4K,
-				   offset, size, NULL);
-}
-
-
 /******************************************************************************
  * Reads a 16 bit word from the EEPROM.
  *
@@ -1066,484 +822,6 @@ int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
 	return -E1000_ERR_EEPROM;
 }
 
-static ssize_t e1000_invm_cdev_read(struct cdev *cdev, void *buf,
-				    size_t count, loff_t offset, unsigned long flags)
-{
-	uint8_t n, bnr;
-	uint32_t line;
-	size_t chunk, residue = count;
-	struct e1000_hw *hw = container_of(cdev, struct e1000_hw, invm.cdev);
-
-	n = offset / sizeof(line);
-	if (n > E1000_INVM_DATA_MAX_N)
-		return -EINVAL;
-
-	bnr = offset % sizeof(line);
-	if (bnr) {
-		/*
-		 * if bnr in not zero it means we have a non 4-byte
-		 * aligned start and need to do a partial read
-		 */
-		const uint8_t *bptr;
-
-		bptr  = (uint8_t *)&line + bnr;
-		chunk = min(bnr - sizeof(line), count);
-		line  = e1000_read_reg(hw, E1000_INVM_DATA(n));
-		line  = cpu_to_le32(line); /* to account for readl */
-		memcpy(buf, bptr, chunk);
-
-		goto start_adjusted;
-	}
-
-	do {
-		if (n > E1000_INVM_DATA_MAX_N)
-			return -EINVAL;
-
-		chunk = min(sizeof(line), residue);
-		line = e1000_read_reg(hw, E1000_INVM_DATA(n));
-		line = cpu_to_le32(line); /* to account for readl */
-
-		/*
-		 * by using memcpy in conjunction with min should get
-		 * dangling tail reads as well as aligned reads
-		 */
-		memcpy(buf, &line, chunk);
-
-	start_adjusted:
-		residue -= chunk;
-		buf += chunk;
-		n++;
-	} while (residue);
-
-	return count;
-}
-
-static int e1000_invm_program(struct e1000_hw *hw, u32 offset, u32 value,
-			      unsigned int delay)
-{
-	int retries = 400;
-	do {
-		if ((e1000_read_reg(hw, offset) & value) == value)
-			return E1000_SUCCESS;
-
-		e1000_write_reg(hw, offset, value);
-
-		if (delay) {
-			udelay(delay);
-		} else {
-			int ret;
-
-			if (e1000_read_reg(hw, E1000_INVM_PROTECT) &
-			    E1000_INVM_PROTECT_WRITE_ERROR) {
-				dev_err(hw->dev, "Error while writing to %x\n", offset);
-				return -EIO;
-			}
-
-			ret = e1000_poll_reg(hw, E1000_INVM_PROTECT,
-					     E1000_INVM_PROTECT_BUSY,
-					     0,  SECOND);
-			if (ret < 0) {
-				dev_err(hw->dev,
-					"Timeout while waiting for INVM_PROTECT.BUSY\n");
-				return ret;
-			}
-		}
-	} while (retries--);
-
-	return -ETIMEDOUT;
-}
-
-static int e1000_invm_set_lock(struct param_d *param, void *priv)
-{
-	struct e1000_hw *hw = priv;
-
-	if (hw->invm.line > 31)
-		return -EINVAL;
-
-	return e1000_invm_program(hw,
-				  E1000_INVM_LOCK(hw->invm.line),
-				  E1000_INVM_LOCK_BIT,
-				  10);
-}
-
-static int e1000_invm_unlock(struct e1000_hw *hw)
-{
-	e1000_write_reg(hw, E1000_INVM_PROTECT, E1000_INVM_PROTECT_CODE);
-	/*
-	 * If we were successful at unlocking iNVM for programming we
-	 * should see ALLOW_WRITE bit toggle to 1
-	 */
-	if (!(e1000_read_reg(hw, E1000_INVM_PROTECT) &
-	      E1000_INVM_PROTECT_ALLOW_WRITE))
-		return -EIO;
-	else
-		return E1000_SUCCESS;
-}
-
-static void e1000_invm_lock(struct e1000_hw *hw)
-{
-	e1000_write_reg(hw, E1000_INVM_PROTECT, 0);
-}
-
-static int e1000_invm_write_prepare(struct e1000_hw *hw)
-{
-	int ret;
-	/*
-	 * This needs to be done accorging to the datasheet p. 541 and
-	 * p. 79
-	*/
-	e1000_write_reg(hw, E1000_PCIEMISC,
-			E1000_PCIEMISC_RESERVED_PATTERN1 |
-			E1000_PCIEMISC_DMA_IDLE          |
-			E1000_PCIEMISC_RESERVED_PATTERN2);
-
-	/*
-	 * Needed for programming iNVM on devices with Flash with valid
-	 * contents attached
-	 */
-	ret = e1000_poll_reg(hw, E1000_EEMNGCTL,
-			     E1000_EEMNGCTL_CFG_DONE,
-			     E1000_EEMNGCTL_CFG_DONE, SECOND);
-	if (ret < 0) {
-		dev_err(hw->dev,
-			"Timeout while waiting for EEMNGCTL.CFG_DONE\n");
-		return ret;
-	}
-
-	udelay(15);
-
-	return E1000_SUCCESS;
-}
-
-static ssize_t e1000_invm_cdev_write(struct cdev *cdev, const void *buf,
-				     size_t count, loff_t offset, unsigned long flags)
-{
-	int ret;
-	uint8_t n, bnr;
-	uint32_t line;
-	size_t chunk, residue = count;
-	struct e1000_hw *hw = container_of(cdev, struct e1000_hw, invm.cdev);
-
-	ret = e1000_invm_write_prepare(hw);
-	if (ret < 0)
-		return ret;
-
-	ret = e1000_invm_unlock(hw);
-	if (ret < 0)
-		goto exit;
-
-	n = offset / sizeof(line);
-	if (n > E1000_INVM_DATA_MAX_N) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	bnr = offset % sizeof(line);
-	if (bnr) {
-		uint8_t *bptr;
-		/*
-		 * if bnr in not zero it means we have a non 4-byte
-		 * aligned start and need to do a read-modify-write
-		 * sequence
-		 */
-
-		/* Read */
-		line = e1000_read_reg(hw, E1000_INVM_DATA(n));
-
-		/* Modify */
-		/*
-		 * We need to ensure that line is LE32 in order for
-		 * memcpy to copy byte from least significant to most
-		 * significant, since that's how i210 will write the
-		 * 32-bit word out to OTP
-		 */
-		line = cpu_to_le32(line);
-		bptr  = (uint8_t *)&line + bnr;
-		chunk = min(sizeof(line) - bnr, count);
-		memcpy(bptr, buf, chunk);
-		line = le32_to_cpu(line);
-
-		/* Jumping inside of the loop to take care of the
-		 * Write */
-		goto start_adjusted;
-	}
-
-	do {
-		if (n > E1000_INVM_DATA_MAX_N) {
-			ret = -EINVAL;
-			goto exit;
-		}
-
-		chunk = min(sizeof(line), residue);
-		if (chunk != sizeof(line)) {
-			/*
-			 * If chunk is smaller that sizeof(line), which
-			 * should be 4 bytes, we have a "dangling"
-			 * chunk and we should read the unchanged
-			 * portion of the 4-byte word from iNVM and do
-			 * a read-modify-write sequence
-			 */
-			line = e1000_read_reg(hw, E1000_INVM_DATA(n));
-		}
-
-		line = cpu_to_le32(line);
-		memcpy(&line, buf, chunk);
-		line = le32_to_cpu(line);
-
-	start_adjusted:
-		/*
-		 * iNVM is organized in 32 64-bit lines and each of
-		 * those lines can be locked to prevent any further
-		 * modification, so for every i-th 32-bit word we need
-		 * to check INVM_LINE[i/2] register to see if that word
-		 * can be modified
-		 */
-		if (e1000_read_reg(hw, E1000_INVM_LOCK(n / 2)) &
-		    E1000_INVM_LOCK_BIT) {
-			dev_err(hw->dev, "line %d is locked\n", n / 2);
-			ret = -EIO;
-			goto exit;
-		}
-
-		ret = e1000_invm_program(hw,
-					 E1000_INVM_DATA(n),
-					 line,
-					 0);
-		if (ret < 0)
-			goto exit;
-
-		residue -= chunk;
-		buf += chunk;
-		n++;
-	} while (residue);
-
-	ret = E1000_SUCCESS;
-exit:
-	e1000_invm_lock(hw);
-	return ret;
-}
-
-static struct cdev_operations e1000_invm_ops = {
-	.read	= e1000_invm_cdev_read,
-	.write	= e1000_invm_cdev_write,
-};
-
-static ssize_t e1000_eeprom_cdev_read(struct cdev *cdev, void *buf,
-				      size_t count, loff_t offset, unsigned long flags)
-{
-	struct e1000_hw *hw = container_of(cdev, struct e1000_hw, eepromcdev);
-	int32_t ret;
-
-	/*
-	 * The eeprom interface works on 16 bit words which gives a nice excuse
-	 * for being lazy and not implementing unaligned reads.
-	 */
-	if (offset & 1 || count == 1)
-		return -EIO;
-
-	ret = e1000_read_eeprom(hw, offset / 2, count / 2, buf);
-	if (ret)
-		return -EIO;
-	else
-		return (count / 2) * 2;
-};
-
-static struct cdev_operations e1000_eeprom_ops = {
-	.read = e1000_eeprom_cdev_read,
-};
-
-static int e1000_mtd_read_or_write(bool read,
-				   struct mtd_info *mtd, loff_t off, size_t len,
-				   size_t *retlen, u_char *buf)
-{
-	int ret;
-	struct e1000_hw *hw = container_of(mtd, struct e1000_hw, mtd);
-
-	DEBUGFUNC();
-
-	if (e1000_acquire_eeprom(hw) == E1000_SUCCESS) {
-		if (read)
-			ret = e1000_flash_mode_read(hw, off,
-						    len, buf);
-		else
-			ret = e1000_flash_mode_write(hw, off,
-						     len, buf);
-		if (ret == E1000_SUCCESS)
-			*retlen = len;
-
-		e1000_release_eeprom(hw);
-	} else {
-		ret = -E1000_ERR_EEPROM;
-	}
-
-	return ret;
-
-}
-
-static int e1000_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
-				 size_t *retlen, u_char *buf)
-{
-	return e1000_mtd_read_or_write(true,
-				       mtd, from, len, retlen, buf);
-}
-
-static int e1000_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
-			   size_t *retlen, const u_char *buf)
-{
-	return e1000_mtd_read_or_write(false,
-				       mtd, to, len, retlen, (u_char *)buf);
-}
-
-static int e1000_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	uint32_t rem;
-	struct e1000_hw *hw = container_of(mtd, struct e1000_hw, mtd);
-	int ret;
-
-	div_u64_rem(instr->len, mtd->erasesize, &rem);
-	if (rem)
-		return -EINVAL;
-
-	ret = e1000_acquire_eeprom(hw);
-	if (ret != E1000_SUCCESS)
-		goto fail;
-
-	/*
-	 * If mtd->size is 4096 it means we are dealing with
-	 * unprogrammed flash and we don't really know its size to
-	 * make an informed decision wheither to erase the whole chip or
-	 * just a number of its sectors
-	 */
-	if (mtd->size > SZ_4K &&
-	    instr->len == mtd->size)
-		ret = e1000_flash_mode_erase(hw, 0, 0);
-	else
-		ret = e1000_flash_mode_erase(hw,
-					     instr->addr, instr->len);
-
-	e1000_release_eeprom(hw);
-
-	if (ret < 0)
-		goto fail;
-
-	return 0;
-
-fail:
-	return ret;
-}
-
-static int e1000_mtd_sr_rmw(struct mtd_info *mtd, u8 mask, u8 val)
-{
-	struct e1000_hw *hw = container_of(mtd, struct e1000_hw, mtd);
-	uint32_t flswdata;
-	int ret;
-
-	ret = e1000_flash_mode_wait_for_idle(hw);
-	if (ret < 0)
-		return ret;
-
-	e1000_write_reg(hw, E1000_FLSWCNT, 1);
-	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_RDSR, 0);
-
-	ret = e1000_flash_mode_check_command_valid(hw);
-	if (ret < 0)
-		return -EIO;
-
-	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
-			     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
-			     SECOND);
-	if (ret < 0) {
-		dev_err(hw->dev,
-			"Timeout waiting for FLSWCTL.DONE to be set (RDSR)\n");
-		return ret;
-	}
-
-	flswdata = e1000_read_reg(hw, E1000_FLSWDATA);
-
-	flswdata = (flswdata & ~mask) | val;
-
-	e1000_write_reg(hw, E1000_FLSWCNT, 1);
-	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_WRSR, 0);
-
-	ret = e1000_flash_mode_check_command_valid(hw);
-	if (ret < 0)
-		return -EIO;
-
-	e1000_write_reg(hw, E1000_FLSWDATA, flswdata);
-
-	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
-			     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
-			     SECOND);
-	if (ret < 0) {
-		dev_err(hw->dev,
-			"Timeout waiting for FLSWCTL.DONE to be set (WRSR)\n");
-	}
-
-	return ret;
-}
-
-/*
- * The available spi nor devices are very different in how the block protection
- * bits affect which sectors to be protected. So take the simple approach and
- * only use BP[012] = b000 (unprotected) and BP[012] = b111 (protected).
- */
-#define SR_BPALL (SR_BP0 | SR_BP1 | SR_BP2)
-
-static int e1000_mtd_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-	return e1000_mtd_sr_rmw(mtd, SR_BPALL, SR_BPALL);
-}
-
-static int e1000_mtd_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-	return e1000_mtd_sr_rmw(mtd, SR_BPALL, 0x0);
-}
-
-static int e1000_register_invm(struct e1000_hw *hw)
-{
-	int ret;
-	u16 word;
-	struct param_d *p;
-
-	if (e1000_eeprom_valid(hw)) {
-		ret = e1000_read_eeprom(hw, 0x0a, 1, &word);
-		if (ret < 0)
-			return ret;
-
-		if (word & (1 << 15))
-			dev_warn(hw->dev, "iNVM lockout mechanism is active\n");
-	}
-
-	hw->invm.cdev.dev = hw->dev;
-	hw->invm.cdev.ops = &e1000_invm_ops;
-	hw->invm.cdev.priv = hw;
-	hw->invm.cdev.name = xasprintf("e1000-invm%d", hw->dev->id);
-	hw->invm.cdev.size = 4 * (E1000_INVM_DATA_MAX_N + 1);
-
-	ret = devfs_create(&hw->invm.cdev);
-	if (ret < 0)
-		return ret;
-
-	dev_set_name(&hw->invm.dev, "invm");
-	hw->invm.dev.id = hw->dev->id;
-	hw->invm.dev.parent = hw->dev;
-	ret = register_device(&hw->invm.dev);
-	if (ret < 0) {
-		devfs_remove(&hw->invm.cdev);
-		return ret;
-	}
-
-	p = dev_add_param_int(&hw->invm.dev, "lock", e1000_invm_set_lock,
-			      NULL, &hw->invm.line, "%u", hw);
-	if (IS_ERR(p)) {
-		unregister_device(&hw->invm.dev);
-		devfs_remove(&hw->invm.cdev);
-		ret = PTR_ERR(p);
-	}
-
-	return ret;
-}
-
 int e1000_eeprom_valid(struct e1000_hw *hw)
 {
 	uint32_t valid_mask = E1000_EECD_FLASH_IN_USE |
@@ -1562,95 +840,3 @@ int e1000_eeprom_valid(struct e1000_hw *hw)
 
 	return 1;
 }
-
-/*
- * This function has a wrong name for historic reasons, it doesn't add an
- * eeprom, but the flash (if available) that is used to simulate the eeprom.
- * Also a device that represents the invm is registered here (if available).
- */
-int e1000_register_eeprom(struct e1000_hw *hw)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	uint32_t eecd;
-	int ret;
-
-	if (hw->mac_type != e1000_igb)
-		return E1000_SUCCESS;
-
-	eecd = e1000_read_reg(hw, E1000_EECD);
-
-	if (eecd & E1000_EECD_AUTO_RD) {
-		if (eecd & E1000_EECD_EE_PRES) {
-			if (eecd & E1000_EECD_FLASH_IN_USE) {
-				uint32_t fla = e1000_read_reg(hw, E1000_FLA);
-				dev_info(hw->dev,
-					 "Hardware programmed from flash (%ssecure)\n",
-					 fla & E1000_FLA_LOCKED ? "" : "un");
-			} else {
-				dev_info(hw->dev, "Hardware programmed from iNVM\n");
-			}
-		} else {
-			dev_warn(hw->dev, "Shadow RAM invalid\n");
-		}
-	} else {
-		/*
-		 * I never saw this case in practise and I'm unsure how
-		 * to handle that. Maybe just wait until the hardware is
-		 * up enough that this bit is set?
-		 */
-		dev_err(hw->dev, "Flash Auto-Read not done\n");
-	}
-
-	if (e1000_eeprom_valid(hw)) {
-		hw->eepromcdev.dev = hw->dev;
-		hw->eepromcdev.ops = &e1000_eeprom_ops;
-		hw->eepromcdev.name = xasprintf("e1000-eeprom%d",
-						hw->dev->id);
-		hw->eepromcdev.size = 0x1000;
-
-		ret = devfs_create(&hw->eepromcdev);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (eecd & E1000_EECD_I210_FLASH_DETECTED) {
-		hw->mtd.dev.parent = hw->dev;
-		hw->mtd._read = e1000_mtd_read;
-		hw->mtd._write = e1000_mtd_write;
-		hw->mtd._erase = e1000_mtd_erase;
-		hw->mtd._lock = e1000_mtd_lock;
-		hw->mtd._unlock = e1000_mtd_unlock;
-		hw->mtd.size = eeprom->word_size * 2;
-		hw->mtd.writesize = 1;
-		hw->mtd.subpage_sft = 0;
-
-		hw->mtd.eraseregions = xzalloc(sizeof(struct mtd_erase_region_info));
-		hw->mtd.erasesize = SZ_4K;
-		hw->mtd.eraseregions[0].erasesize = SZ_4K;
-		hw->mtd.eraseregions[0].numblocks = hw->mtd.size / SZ_4K;
-		hw->mtd.numeraseregions = 1;
-
-		hw->mtd.flags = MTD_CAP_NORFLASH;
-		hw->mtd.type = MTD_NORFLASH;
-
-		ret = add_mtd_device(&hw->mtd, "e1000-nor",
-				     DEVICE_ID_DYNAMIC);
-		if (ret)
-			goto out_eeprom;
-	}
-
-	ret = e1000_register_invm(hw);
-	if (ret < 0)
-		goto out_mtd;
-
-	return E1000_SUCCESS;
-
-out_mtd:
-	if (eecd & E1000_EECD_I210_FLASH_DETECTED)
-		del_mtd_device(&hw->mtd);
-out_eeprom:
-	if (e1000_eeprom_valid(hw))
-		devfs_remove(&hw->eepromcdev);
-
-	return ret;
-}
diff --git a/drivers/net/e1000/mtd.c b/drivers/net/e1000/mtd.c
new file mode 100644
index 000000000000..93595cc88d24
--- /dev/null
+++ b/drivers/net/e1000/mtd.c
@@ -0,0 +1,835 @@
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <linux/math64.h>
+#include <linux/sizes.h>
+#include <of_device.h>
+#include <linux/pci.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "e1000.h"
+
+static int32_t e1000_acquire_eeprom(struct e1000_hw *hw)
+{
+	if (hw->eeprom.acquire)
+		return hw->eeprom.acquire(hw);
+	else
+		return E1000_SUCCESS;
+}
+
+static void e1000_release_eeprom(struct e1000_hw *hw)
+{
+	if (hw->eeprom.release)
+		hw->eeprom.release(hw);
+}
+
+static int e1000_flash_mode_wait_for_idle(struct e1000_hw *hw)
+{
+	const int ret = e1000_poll_reg(hw, E1000_FLSWCTL, E1000_FLSWCTL_DONE,
+				       E1000_FLSWCTL_DONE, SECOND);
+	if (ret < 0)
+		dev_err(hw->dev,
+			"Timeout waiting for FLSWCTL.DONE to be set (wait)\n");
+	return ret;
+}
+
+static int e1000_flash_mode_check_command_valid(struct e1000_hw *hw)
+{
+	const uint32_t flswctl = e1000_read_reg(hw, E1000_FLSWCTL);
+	if (!(flswctl & E1000_FLSWCTL_CMDV)) {
+		dev_err(hw->dev, "FLSWCTL.CMDV was cleared\n");
+		return -EIO;
+	}
+
+	return E1000_SUCCESS;
+}
+
+static void e1000_flash_cmd(struct e1000_hw *hw,
+			    uint32_t cmd, uint32_t offset)
+{
+	uint32_t flswctl = e1000_read_reg(hw, E1000_FLSWCTL);
+	flswctl &= ~E1000_FLSWCTL_CMD_ADDR_MASK;
+	flswctl |= E1000_FLSWCTL_CMD(cmd) | E1000_FLSWCTL_ADDR(offset);
+	e1000_write_reg(hw, E1000_FLSWCTL, flswctl);
+}
+
+static int e1000_flash_mode_read_chunk(struct e1000_hw *hw, loff_t offset,
+				       size_t size, void *data)
+{
+	int ret;
+	size_t chunk, residue = size;
+	uint32_t flswdata;
+
+	DEBUGFUNC();
+
+	if (size > SZ_4K ||
+	    E1000_FLSWCTL_ADDR(offset) != offset)
+		return -EINVAL;
+
+	ret = e1000_flash_mode_wait_for_idle(hw);
+	if (ret < 0)
+		return ret;
+
+	e1000_write_reg(hw, E1000_FLSWCNT, size);
+	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_READ, offset);
+
+	do {
+		ret = e1000_flash_mode_check_command_valid(hw);
+		if (ret < 0)
+			return -EIO;
+
+		chunk = min(sizeof(flswdata), residue);
+
+		ret = e1000_poll_reg(hw, E1000_FLSWCTL,
+				     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
+				     SECOND);
+		if (ret < 0) {
+			dev_err(hw->dev,
+				"Timeout waiting for FLSWCTL.DONE to be set (read)\n");
+			return ret;
+		}
+
+		flswdata = e1000_read_reg(hw, E1000_FLSWDATA);
+		/*
+		 * Readl does le32_to_cpu, so we need to undo that
+		 */
+		flswdata = cpu_to_le32(flswdata);
+		memcpy(data, &flswdata, chunk);
+
+		data += chunk;
+		residue -= chunk;
+	} while (residue);
+
+	return E1000_SUCCESS;
+}
+
+static int e1000_flash_mode_write_chunk(struct e1000_hw *hw, loff_t offset,
+					size_t size, const void *data)
+{
+	int ret;
+	size_t chunk, residue = size;
+	uint32_t flswdata;
+
+	if (size > 256 ||
+	    E1000_FLSWCTL_ADDR(offset) != offset)
+		return -EINVAL;
+
+	ret = e1000_flash_mode_wait_for_idle(hw);
+	if (ret < 0)
+		return ret;
+
+
+	e1000_write_reg(hw, E1000_FLSWCNT, size);
+	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_WRITE, offset);
+
+	do {
+		chunk = min(sizeof(flswdata), residue);
+		memcpy(&flswdata, data, chunk);
+		/*
+		 * writel does cpu_to_le32, so we do the inverse in
+		 * order to account for that
+		 */
+		flswdata = le32_to_cpu(flswdata);
+		e1000_write_reg(hw, E1000_FLSWDATA, flswdata);
+
+		ret = e1000_flash_mode_check_command_valid(hw);
+		if (ret < 0)
+			return -EIO;
+
+		ret = e1000_poll_reg(hw, E1000_FLSWCTL,
+				     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
+				     SECOND);
+		if (ret < 0) {
+			dev_err(hw->dev,
+				"Timeout waiting for FLSWCTL.DONE to be set (write)\n");
+			return ret;
+		}
+
+		data += chunk;
+		residue -= chunk;
+
+	} while (residue);
+
+	return E1000_SUCCESS;
+}
+
+static int e1000_flash_mode_erase_chunk(struct e1000_hw *hw, loff_t offset,
+					size_t size)
+{
+	int ret;
+
+	ret = e1000_flash_mode_wait_for_idle(hw);
+	if (ret < 0)
+		return ret;
+
+	if (!size && !offset)
+		e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_ERASE_DEVICE, 0);
+	else
+		e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_ERASE_SECTOR, offset);
+
+	ret = e1000_flash_mode_check_command_valid(hw);
+	if (ret < 0)
+		return -EIO;
+
+	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
+			     E1000_FLSWCTL_DONE | E1000_FLSWCTL_FLBUSY,
+			     E1000_FLSWCTL_DONE,
+			     40 * SECOND);
+	if (ret < 0) {
+		dev_err(hw->dev,
+			"Timeout waiting for FLSWCTL.DONE to be set (erase)\n");
+		return ret;
+	}
+
+	return E1000_SUCCESS;
+}
+
+enum {
+	E1000_FLASH_MODE_OP_READ = 0,
+	E1000_FLASH_MODE_OP_WRITE = 1,
+	E1000_FLASH_MODE_OP_ERASE = 2,
+};
+
+
+static int e1000_flash_mode_io(struct e1000_hw *hw, int op, size_t granularity,
+			       loff_t offset, size_t size, void *data)
+{
+	int ret;
+	size_t residue = size;
+
+	do {
+		const size_t chunk = min(granularity, residue);
+
+		switch (op) {
+		case E1000_FLASH_MODE_OP_READ:
+			ret = e1000_flash_mode_read_chunk(hw, offset,
+							  chunk, data);
+			break;
+		case E1000_FLASH_MODE_OP_WRITE:
+			ret = e1000_flash_mode_write_chunk(hw, offset,
+							   chunk, data);
+			break;
+		case E1000_FLASH_MODE_OP_ERASE:
+			ret = e1000_flash_mode_erase_chunk(hw, offset,
+							   chunk);
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+
+		if (ret < 0)
+			return ret;
+
+		offset += chunk;
+		residue -= chunk;
+		data += chunk;
+	} while (residue);
+
+	return E1000_SUCCESS;
+}
+
+static int e1000_flash_mode_read(struct e1000_hw *hw, loff_t offset,
+				 size_t size, void *data)
+{
+	return e1000_flash_mode_io(hw,
+				   E1000_FLASH_MODE_OP_READ, SZ_4K,
+				   offset, size, data);
+}
+
+static int e1000_flash_mode_write(struct e1000_hw *hw, loff_t offset,
+				  size_t size, const void *data)
+{
+	int ret;
+
+	ret = e1000_flash_mode_io(hw,
+				  E1000_FLASH_MODE_OP_WRITE, 256,
+				  offset, size, (void *)data);
+	if (ret < 0)
+		return ret;
+
+	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
+			     E1000_FLSWCTL_FLBUSY,
+			     0,  SECOND);
+	if (ret < 0)
+		dev_err(hw->dev, "Timout while waiting for FLSWCTL.FLBUSY\n");
+
+	return ret;
+}
+
+static int e1000_flash_mode_erase(struct e1000_hw *hw, loff_t offset,
+				  size_t size)
+{
+	return e1000_flash_mode_io(hw,
+				   E1000_FLASH_MODE_OP_ERASE, SZ_4K,
+				   offset, size, NULL);
+}
+
+static ssize_t e1000_invm_cdev_read(struct cdev *cdev, void *buf,
+				    size_t count, loff_t offset, unsigned long flags)
+{
+	uint8_t n, bnr;
+	uint32_t line;
+	size_t chunk, residue = count;
+	struct e1000_hw *hw = container_of(cdev, struct e1000_hw, invm.cdev);
+
+	n = offset / sizeof(line);
+	if (n > E1000_INVM_DATA_MAX_N)
+		return -EINVAL;
+
+	bnr = offset % sizeof(line);
+	if (bnr) {
+		/*
+		 * if bnr in not zero it means we have a non 4-byte
+		 * aligned start and need to do a partial read
+		 */
+		const uint8_t *bptr;
+
+		bptr  = (uint8_t *)&line + bnr;
+		chunk = min(bnr - sizeof(line), count);
+		line  = e1000_read_reg(hw, E1000_INVM_DATA(n));
+		line  = cpu_to_le32(line); /* to account for readl */
+		memcpy(buf, bptr, chunk);
+
+		goto start_adjusted;
+	}
+
+	do {
+		if (n > E1000_INVM_DATA_MAX_N)
+			return -EINVAL;
+
+		chunk = min(sizeof(line), residue);
+		line = e1000_read_reg(hw, E1000_INVM_DATA(n));
+		line = cpu_to_le32(line); /* to account for readl */
+
+		/*
+		 * by using memcpy in conjunction with min should get
+		 * dangling tail reads as well as aligned reads
+		 */
+		memcpy(buf, &line, chunk);
+
+	start_adjusted:
+		residue -= chunk;
+		buf += chunk;
+		n++;
+	} while (residue);
+
+	return count;
+}
+
+static int e1000_invm_program(struct e1000_hw *hw, u32 offset, u32 value,
+			      unsigned int delay)
+{
+	int retries = 400;
+	do {
+		if ((e1000_read_reg(hw, offset) & value) == value)
+			return E1000_SUCCESS;
+
+		e1000_write_reg(hw, offset, value);
+
+		if (delay) {
+			udelay(delay);
+		} else {
+			int ret;
+
+			if (e1000_read_reg(hw, E1000_INVM_PROTECT) &
+			    E1000_INVM_PROTECT_WRITE_ERROR) {
+				dev_err(hw->dev, "Error while writing to %x\n", offset);
+				return -EIO;
+			}
+
+			ret = e1000_poll_reg(hw, E1000_INVM_PROTECT,
+					     E1000_INVM_PROTECT_BUSY,
+					     0,  SECOND);
+			if (ret < 0) {
+				dev_err(hw->dev,
+					"Timeout while waiting for INVM_PROTECT.BUSY\n");
+				return ret;
+			}
+		}
+	} while (retries--);
+
+	return -ETIMEDOUT;
+}
+
+static int e1000_invm_set_lock(struct param_d *param, void *priv)
+{
+	struct e1000_hw *hw = priv;
+
+	if (hw->invm.line > 31)
+		return -EINVAL;
+
+	return e1000_invm_program(hw,
+				  E1000_INVM_LOCK(hw->invm.line),
+				  E1000_INVM_LOCK_BIT,
+				  10);
+}
+
+static int e1000_invm_unlock(struct e1000_hw *hw)
+{
+	e1000_write_reg(hw, E1000_INVM_PROTECT, E1000_INVM_PROTECT_CODE);
+	/*
+	 * If we were successful at unlocking iNVM for programming we
+	 * should see ALLOW_WRITE bit toggle to 1
+	 */
+	if (!(e1000_read_reg(hw, E1000_INVM_PROTECT) &
+	      E1000_INVM_PROTECT_ALLOW_WRITE))
+		return -EIO;
+	else
+		return E1000_SUCCESS;
+}
+
+static void e1000_invm_lock(struct e1000_hw *hw)
+{
+	e1000_write_reg(hw, E1000_INVM_PROTECT, 0);
+}
+
+static int e1000_invm_write_prepare(struct e1000_hw *hw)
+{
+	int ret;
+	/*
+	 * This needs to be done accorging to the datasheet p. 541 and
+	 * p. 79
+	*/
+	e1000_write_reg(hw, E1000_PCIEMISC,
+			E1000_PCIEMISC_RESERVED_PATTERN1 |
+			E1000_PCIEMISC_DMA_IDLE          |
+			E1000_PCIEMISC_RESERVED_PATTERN2);
+
+	/*
+	 * Needed for programming iNVM on devices with Flash with valid
+	 * contents attached
+	 */
+	ret = e1000_poll_reg(hw, E1000_EEMNGCTL,
+			     E1000_EEMNGCTL_CFG_DONE,
+			     E1000_EEMNGCTL_CFG_DONE, SECOND);
+	if (ret < 0) {
+		dev_err(hw->dev,
+			"Timeout while waiting for EEMNGCTL.CFG_DONE\n");
+		return ret;
+	}
+
+	udelay(15);
+
+	return E1000_SUCCESS;
+}
+
+static ssize_t e1000_invm_cdev_write(struct cdev *cdev, const void *buf,
+				     size_t count, loff_t offset, unsigned long flags)
+{
+	int ret;
+	uint8_t n, bnr;
+	uint32_t line;
+	size_t chunk, residue = count;
+	struct e1000_hw *hw = container_of(cdev, struct e1000_hw, invm.cdev);
+
+	ret = e1000_invm_write_prepare(hw);
+	if (ret < 0)
+		return ret;
+
+	ret = e1000_invm_unlock(hw);
+	if (ret < 0)
+		goto exit;
+
+	n = offset / sizeof(line);
+	if (n > E1000_INVM_DATA_MAX_N) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	bnr = offset % sizeof(line);
+	if (bnr) {
+		uint8_t *bptr;
+		/*
+		 * if bnr in not zero it means we have a non 4-byte
+		 * aligned start and need to do a read-modify-write
+		 * sequence
+		 */
+
+		/* Read */
+		line = e1000_read_reg(hw, E1000_INVM_DATA(n));
+
+		/* Modify */
+		/*
+		 * We need to ensure that line is LE32 in order for
+		 * memcpy to copy byte from least significant to most
+		 * significant, since that's how i210 will write the
+		 * 32-bit word out to OTP
+		 */
+		line = cpu_to_le32(line);
+		bptr  = (uint8_t *)&line + bnr;
+		chunk = min(sizeof(line) - bnr, count);
+		memcpy(bptr, buf, chunk);
+		line = le32_to_cpu(line);
+
+		/* Jumping inside of the loop to take care of the
+		 * Write */
+		goto start_adjusted;
+	}
+
+	do {
+		if (n > E1000_INVM_DATA_MAX_N) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		chunk = min(sizeof(line), residue);
+		if (chunk != sizeof(line)) {
+			/*
+			 * If chunk is smaller that sizeof(line), which
+			 * should be 4 bytes, we have a "dangling"
+			 * chunk and we should read the unchanged
+			 * portion of the 4-byte word from iNVM and do
+			 * a read-modify-write sequence
+			 */
+			line = e1000_read_reg(hw, E1000_INVM_DATA(n));
+		}
+
+		line = cpu_to_le32(line);
+		memcpy(&line, buf, chunk);
+		line = le32_to_cpu(line);
+
+	start_adjusted:
+		/*
+		 * iNVM is organized in 32 64-bit lines and each of
+		 * those lines can be locked to prevent any further
+		 * modification, so for every i-th 32-bit word we need
+		 * to check INVM_LINE[i/2] register to see if that word
+		 * can be modified
+		 */
+		if (e1000_read_reg(hw, E1000_INVM_LOCK(n / 2)) &
+		    E1000_INVM_LOCK_BIT) {
+			dev_err(hw->dev, "line %d is locked\n", n / 2);
+			ret = -EIO;
+			goto exit;
+		}
+
+		ret = e1000_invm_program(hw,
+					 E1000_INVM_DATA(n),
+					 line,
+					 0);
+		if (ret < 0)
+			goto exit;
+
+		residue -= chunk;
+		buf += chunk;
+		n++;
+	} while (residue);
+
+	ret = E1000_SUCCESS;
+exit:
+	e1000_invm_lock(hw);
+	return ret;
+}
+
+static struct cdev_operations e1000_invm_ops = {
+	.read	= e1000_invm_cdev_read,
+	.write	= e1000_invm_cdev_write,
+};
+
+static ssize_t e1000_eeprom_cdev_read(struct cdev *cdev, void *buf,
+				      size_t count, loff_t offset, unsigned long flags)
+{
+	struct e1000_hw *hw = container_of(cdev, struct e1000_hw, eepromcdev);
+	int32_t ret;
+
+	/*
+	 * The eeprom interface works on 16 bit words which gives a nice excuse
+	 * for being lazy and not implementing unaligned reads.
+	 */
+	if (offset & 1 || count == 1)
+		return -EIO;
+
+	ret = e1000_read_eeprom(hw, offset / 2, count / 2, buf);
+	if (ret)
+		return -EIO;
+	else
+		return (count / 2) * 2;
+};
+
+static struct cdev_operations e1000_eeprom_ops = {
+	.read = e1000_eeprom_cdev_read,
+};
+
+static int e1000_mtd_read_or_write(bool read,
+				   struct mtd_info *mtd, loff_t off, size_t len,
+				   size_t *retlen, u_char *buf)
+{
+	int ret;
+	struct e1000_hw *hw = container_of(mtd, struct e1000_hw, mtd);
+
+	DEBUGFUNC();
+
+	if (e1000_acquire_eeprom(hw) == E1000_SUCCESS) {
+		if (read)
+			ret = e1000_flash_mode_read(hw, off,
+						    len, buf);
+		else
+			ret = e1000_flash_mode_write(hw, off,
+						     len, buf);
+		if (ret == E1000_SUCCESS)
+			*retlen = len;
+
+		e1000_release_eeprom(hw);
+	} else {
+		ret = -E1000_ERR_EEPROM;
+	}
+
+	return ret;
+
+}
+
+static int e1000_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
+				 size_t *retlen, u_char *buf)
+{
+	return e1000_mtd_read_or_write(true,
+				       mtd, from, len, retlen, buf);
+}
+
+static int e1000_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
+			   size_t *retlen, const u_char *buf)
+{
+	return e1000_mtd_read_or_write(false,
+				       mtd, to, len, retlen, (u_char *)buf);
+}
+
+static int e1000_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	uint32_t rem;
+	struct e1000_hw *hw = container_of(mtd, struct e1000_hw, mtd);
+	int ret;
+
+	div_u64_rem(instr->len, mtd->erasesize, &rem);
+	if (rem)
+		return -EINVAL;
+
+	ret = e1000_acquire_eeprom(hw);
+	if (ret != E1000_SUCCESS)
+		goto fail;
+
+	/*
+	 * If mtd->size is 4096 it means we are dealing with
+	 * unprogrammed flash and we don't really know its size to
+	 * make an informed decision wheither to erase the whole chip or
+	 * just a number of its sectors
+	 */
+	if (mtd->size > SZ_4K &&
+	    instr->len == mtd->size)
+		ret = e1000_flash_mode_erase(hw, 0, 0);
+	else
+		ret = e1000_flash_mode_erase(hw,
+					     instr->addr, instr->len);
+
+	e1000_release_eeprom(hw);
+
+	if (ret < 0)
+		goto fail;
+
+	return 0;
+
+fail:
+	return ret;
+}
+
+static int e1000_mtd_sr_rmw(struct mtd_info *mtd, u8 mask, u8 val)
+{
+	struct e1000_hw *hw = container_of(mtd, struct e1000_hw, mtd);
+	uint32_t flswdata;
+	int ret;
+
+	ret = e1000_flash_mode_wait_for_idle(hw);
+	if (ret < 0)
+		return ret;
+
+	e1000_write_reg(hw, E1000_FLSWCNT, 1);
+	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_RDSR, 0);
+
+	ret = e1000_flash_mode_check_command_valid(hw);
+	if (ret < 0)
+		return -EIO;
+
+	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
+			     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
+			     SECOND);
+	if (ret < 0) {
+		dev_err(hw->dev,
+			"Timeout waiting for FLSWCTL.DONE to be set (RDSR)\n");
+		return ret;
+	}
+
+	flswdata = e1000_read_reg(hw, E1000_FLSWDATA);
+
+	flswdata = (flswdata & ~mask) | val;
+
+	e1000_write_reg(hw, E1000_FLSWCNT, 1);
+	e1000_flash_cmd(hw, E1000_FLSWCTL_CMD_WRSR, 0);
+
+	ret = e1000_flash_mode_check_command_valid(hw);
+	if (ret < 0)
+		return -EIO;
+
+	e1000_write_reg(hw, E1000_FLSWDATA, flswdata);
+
+	ret = e1000_poll_reg(hw, E1000_FLSWCTL,
+			     E1000_FLSWCTL_DONE, E1000_FLSWCTL_DONE,
+			     SECOND);
+	if (ret < 0) {
+		dev_err(hw->dev,
+			"Timeout waiting for FLSWCTL.DONE to be set (WRSR)\n");
+	}
+
+	return ret;
+}
+
+/*
+ * The available spi nor devices are very different in how the block protection
+ * bits affect which sectors to be protected. So take the simple approach and
+ * only use BP[012] = b000 (unprotected) and BP[012] = b111 (protected).
+ */
+#define SR_BPALL (SR_BP0 | SR_BP1 | SR_BP2)
+
+static int e1000_mtd_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	return e1000_mtd_sr_rmw(mtd, SR_BPALL, SR_BPALL);
+}
+
+static int e1000_mtd_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	return e1000_mtd_sr_rmw(mtd, SR_BPALL, 0x0);
+}
+
+static int e1000_register_invm(struct e1000_hw *hw)
+{
+	int ret;
+	u16 word;
+	struct param_d *p;
+
+	if (e1000_eeprom_valid(hw)) {
+		ret = e1000_read_eeprom(hw, 0x0a, 1, &word);
+		if (ret < 0)
+			return ret;
+
+		if (word & (1 << 15))
+			dev_warn(hw->dev, "iNVM lockout mechanism is active\n");
+	}
+
+	hw->invm.cdev.dev = hw->dev;
+	hw->invm.cdev.ops = &e1000_invm_ops;
+	hw->invm.cdev.priv = hw;
+	hw->invm.cdev.name = xasprintf("e1000-invm%d", hw->dev->id);
+	hw->invm.cdev.size = 4 * (E1000_INVM_DATA_MAX_N + 1);
+
+	ret = devfs_create(&hw->invm.cdev);
+	if (ret < 0)
+		return ret;
+
+	dev_set_name(&hw->invm.dev, "invm");
+	hw->invm.dev.id = hw->dev->id;
+	hw->invm.dev.parent = hw->dev;
+	ret = register_device(&hw->invm.dev);
+	if (ret < 0) {
+		devfs_remove(&hw->invm.cdev);
+		return ret;
+	}
+
+	p = dev_add_param_int(&hw->invm.dev, "lock", e1000_invm_set_lock,
+			      NULL, &hw->invm.line, "%u", hw);
+	if (IS_ERR(p)) {
+		unregister_device(&hw->invm.dev);
+		devfs_remove(&hw->invm.cdev);
+		ret = PTR_ERR(p);
+	}
+
+	return ret;
+}
+
+/*
+ * This function has a wrong name for historic reasons, it doesn't add an
+ * eeprom, but the flash (if available) that is used to simulate the eeprom.
+ * Also a device that represents the invm is registered here (if available).
+ */
+int e1000_register_eeprom(struct e1000_hw *hw)
+{
+	struct e1000_eeprom_info *eeprom = &hw->eeprom;
+	uint32_t eecd;
+	int ret;
+
+	if (hw->mac_type != e1000_igb)
+		return E1000_SUCCESS;
+
+	eecd = e1000_read_reg(hw, E1000_EECD);
+
+	if (eecd & E1000_EECD_AUTO_RD) {
+		if (eecd & E1000_EECD_EE_PRES) {
+			if (eecd & E1000_EECD_FLASH_IN_USE) {
+				uint32_t fla = e1000_read_reg(hw, E1000_FLA);
+				dev_info(hw->dev,
+					 "Hardware programmed from flash (%ssecure)\n",
+					 fla & E1000_FLA_LOCKED ? "" : "un");
+			} else {
+				dev_info(hw->dev, "Hardware programmed from iNVM\n");
+			}
+		} else {
+			dev_warn(hw->dev, "Shadow RAM invalid\n");
+		}
+	} else {
+		/*
+		 * I never saw this case in practise and I'm unsure how
+		 * to handle that. Maybe just wait until the hardware is
+		 * up enough that this bit is set?
+		 */
+		dev_err(hw->dev, "Flash Auto-Read not done\n");
+	}
+
+	if (e1000_eeprom_valid(hw)) {
+		hw->eepromcdev.dev = hw->dev;
+		hw->eepromcdev.ops = &e1000_eeprom_ops;
+		hw->eepromcdev.name = xasprintf("e1000-eeprom%d",
+						hw->dev->id);
+		hw->eepromcdev.size = 0x1000;
+
+		ret = devfs_create(&hw->eepromcdev);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (eecd & E1000_EECD_I210_FLASH_DETECTED) {
+		hw->mtd.dev.parent = hw->dev;
+		hw->mtd._read = e1000_mtd_read;
+		hw->mtd._write = e1000_mtd_write;
+		hw->mtd._erase = e1000_mtd_erase;
+		hw->mtd._lock = e1000_mtd_lock;
+		hw->mtd._unlock = e1000_mtd_unlock;
+		hw->mtd.size = eeprom->word_size * 2;
+		hw->mtd.writesize = 1;
+		hw->mtd.subpage_sft = 0;
+
+		hw->mtd.eraseregions = xzalloc(sizeof(struct mtd_erase_region_info));
+		hw->mtd.erasesize = SZ_4K;
+		hw->mtd.eraseregions[0].erasesize = SZ_4K;
+		hw->mtd.eraseregions[0].numblocks = hw->mtd.size / SZ_4K;
+		hw->mtd.numeraseregions = 1;
+
+		hw->mtd.flags = MTD_CAP_NORFLASH;
+		hw->mtd.type = MTD_NORFLASH;
+
+		ret = add_mtd_device(&hw->mtd, "e1000-nor",
+				     DEVICE_ID_DYNAMIC);
+		if (ret)
+			goto out_eeprom;
+	}
+
+	ret = e1000_register_invm(hw);
+	if (ret < 0)
+		goto out_mtd;
+
+	return E1000_SUCCESS;
+
+out_mtd:
+	if (eecd & E1000_EECD_I210_FLASH_DETECTED)
+		del_mtd_device(&hw->mtd);
+out_eeprom:
+	if (e1000_eeprom_valid(hw))
+		devfs_remove(&hw->eepromcdev);
+
+	return ret;
+}
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 12 05:19:42 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 14:19:42 +0200
Subject: [PATCH 3/5] asm-generic: include bitio.h from io.h
In-Reply-To: <20210812121944.4419-1-a.fatoum@pengutronix.de>
References: <20210812121944.4419-1-a.fatoum@pengutronix.de>
Message-ID: <20210812121944.4419-3-a.fatoum@pengutronix.de>

This is currently used on ARM and sandbox, but it's relevant for
other platforms like x86 as well if driver code wants to make use
of the functions defined within.

MIPS and PowerPC already defines the symbols, but that's ok because
<bitio.h> doesn't override existing macros. This works for MIPS, but
not PowerPC, where those aren't macros. Fix that up.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/include/asm/io.h     |  1 -
 arch/powerpc/include/asm/io.h | 10 ++++++++++
 arch/sandbox/include/asm/io.h |  1 -
 include/asm-generic/io.h      |  2 ++
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index b442a37b9c1d..0507db1a9cf8 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -8,7 +8,6 @@
 #define memset_io memset_io
 
 #include <asm-generic/io.h>
-#include <asm-generic/bitio.h>
 
 /*
  * String version of IO memory access ops:
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 8488c36f6558..30d098702380 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -132,6 +132,7 @@ static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
 /*
  * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
  */
+#define in_8 in_8
 static inline u8 in_8(const volatile u8 __iomem *addr)
 {
 	u8 ret;
@@ -141,11 +142,13 @@ static inline u8 in_8(const volatile u8 __iomem *addr)
 	return ret;
 }
 
+#define out_8 out_8
 static inline void out_8(volatile u8 __iomem *addr, u8 val)
 {
 	__asm__ __volatile__("sync;stb%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
 }
 
+#define in_le16 in_le16
 static inline u16 in_le16(const volatile u16 __iomem *addr)
 {
 	u16 ret;
@@ -155,6 +158,7 @@ static inline u16 in_le16(const volatile u16 __iomem *addr)
 	return ret;
 }
 
+#define in_be16 in_be16
 static inline u16 in_be16(const volatile u16 __iomem *addr)
 {
 	u16 ret;
@@ -164,17 +168,20 @@ static inline u16 in_be16(const volatile u16 __iomem *addr)
 	return ret;
 }
 
+#define out_le16 out_le16
 static inline void out_le16(volatile u16 __iomem *addr, u16 val)
 {
 	__asm__ __volatile__("sync; sthbrx %1,0,%2"
 			: "=m" (*addr) : "r" (val), "r" (addr));
 }
 
+#define out_be16 out_be16
 static inline void out_be16(volatile u16 __iomem *addr, u16 val)
 {
 	__asm__ __volatile__("sync;sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
 }
 
+#define in_le32 in_le32
 static inline u32 in_le32(const volatile u32 __iomem *addr)
 {
 	u32 ret;
@@ -184,6 +191,7 @@ static inline u32 in_le32(const volatile u32 __iomem *addr)
 	return ret;
 }
 
+#define in_be32 in_be32
 static inline u32 in_be32(const volatile u32 __iomem *addr)
 {
 	u32 ret;
@@ -193,12 +201,14 @@ static inline u32 in_be32(const volatile u32 __iomem *addr)
 	return ret;
 }
 
+#define out_le32 out_le32
 static inline void out_le32(volatile u32 __iomem *addr, u32 val)
 {
 	__asm__ __volatile__("sync; stwbrx %1,0,%2"
 			: "=m" (*addr) : "r" (val), "r" (addr));
 }
 
+#define out_be32 out_be32
 static inline void out_be32(volatile u32 __iomem *addr, u32 val)
 {
 	__asm__ __volatile__("sync;stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 9f9cd3a42ab1..3e5c0580bc5a 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -8,7 +8,6 @@
 extern unsigned char __pci_iobase[IO_SPACE_LIMIT];
 
 #include <asm-generic/io.h>
-#include <asm-generic/bitio.h>
 
 static inline void *phys_to_virt(unsigned long phys)
 {
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index a4b0dc4b4337..47f8c3ec1be6 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -479,4 +479,6 @@ static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer,
 }
 #endif
 
+#include <asm-generic/bitio.h>
+
 #endif /* __ASM_GENERIC_IO_H */
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 12 05:19:41 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 14:19:41 +0200
Subject: [PATCH 2/5] net: make ARC MAC driver 32-bit only
In-Reply-To: <20210812121944.4419-1-a.fatoum@pengutronix.de>
References: <20210812121944.4419-1-a.fatoum@pengutronix.de>
Message-ID: <20210812121944.4419-2-a.fatoum@pengutronix.de>

The driver assumes 32-bit pointers and only matches against 32-bit
rockchip device trees. Make this official in the kconfig, so it's
not selectable on 64 bit, where it would issue build warnings and
probably not work anyway.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/net/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4a290bebbd75..397164f3f175 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -28,7 +28,7 @@ config DRIVER_NET_AR231X
 
 config DRIVER_NET_ARC_EMAC
 	bool "ARC Ethernet MAC driver"
-	depends on HAS_DMA
+	depends on HAS_DMA && 32BIT
 	select PHYLIB
 	help
 	  This option enables support for the ARC EMAC ethernet
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 12 06:03:09 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 12 Aug 2021 15:03:09 +0200
Subject: [PATCH 1/5] net: drop Calxeda Highbank xgmac driver support
In-Reply-To: <20210812121944.4419-1-a.fatoum@pengutronix.de>
References: <20210812121944.4419-1-a.fatoum@pengutronix.de>
Message-ID: <1864c8ce-96c1-b6fe-2390-ef67a6089f23@pengutronix.de>

On 12.08.21 14:19, Ahmad Fatoum wrote:
> Support for MACH_HIGHBANK was removed in f0f96c3322d5
> ("ARM: remove Calxeda Highbank support"). There are no device trees
> either barebox or upstream using this network controller, so remove
> the driver as well.
> 
> Fixes: f0f96c3322d5 ("ARM: remove Calxeda Highbank support")
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

Should've added a cover letter. With the recent virtio/dma and PCI
additions for x86, many network drivers can now be newly enabled
on x86, yielding different warnings/errors.

This series fixes that up.

> ---
>  drivers/net/Kconfig  |   4 -
>  drivers/net/Makefile |   1 -
>  drivers/net/xgmac.c  | 734 -------------------------------------------
>  3 files changed, 739 deletions(-)
>  delete mode 100644 drivers/net/xgmac.c
> 
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 802169a86e8c..4a290bebbd75 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -39,10 +39,6 @@ config DRIVER_NET_AT91_ETHER
>  	depends on HAS_AT91_ETHER
>  	select PHYLIB
>  
> -config DRIVER_NET_CALXEDA_XGMAC
> -	bool "Calxeda xgmac"
> -	depends on HAS_DMA
> -
>  config DRIVER_NET_CS8900
>  	bool "cs8900 ethernet driver"
>  	depends on HAS_CS8900 || COMPILE_TEST
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index fb3e3bdee46a..e5eede634e63 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -4,7 +4,6 @@ obj-$(CONFIG_NET_USB)			+= usb/
>  obj-$(CONFIG_DRIVER_NET_AR231X)		+= ar231x.o
>  obj-$(CONFIG_DRIVER_NET_ARC_EMAC)	+= arc_emac.o
>  obj-$(CONFIG_DRIVER_NET_AT91_ETHER)	+= at91_ether.o
> -obj-$(CONFIG_DRIVER_NET_CALXEDA_XGMAC)	+= xgmac.o
>  obj-$(CONFIG_DRIVER_NET_CS8900)		+= cs8900.o
>  obj-$(CONFIG_DRIVER_NET_CPSW)		+= cpsw.o
>  obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC)	+= davinci_emac.o
> diff --git a/drivers/net/xgmac.c b/drivers/net/xgmac.c
> deleted file mode 100644
> index 136d78804349..000000000000
> --- a/drivers/net/xgmac.c
> +++ /dev/null
> @@ -1,734 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-or-later
> -/*
> - * Copyright 2010-2011 Calxeda, Inc.
> - */
> -
> -#include <common.h>
> -#include <dma.h>
> -#include <net.h>
> -#include <clock.h>
> -#include <malloc.h>
> -#include <xfuncs.h>
> -#include <init.h>
> -#include <errno.h>
> -#include <io.h>
> -#include <linux/err.h>
> -
> -#define TX_NUM_DESC			1
> -#define RX_NUM_DESC			32
> -
> -#define ETH_BUF_SZ			2048
> -#define TX_BUF_SZ			(ETH_BUF_SZ * TX_NUM_DESC)
> -#define RX_BUF_SZ			(ETH_BUF_SZ * RX_NUM_DESC)
> -
> -/* XGMAC Register definitions */
> -#define XGMAC_CONTROL		0x00000000	/* MAC Configuration */
> -#define XGMAC_FRAME_FILTER	0x00000004	/* MAC Frame Filter */
> -#define XGMAC_FLOW_CTRL		0x00000018	/* MAC Flow Control */
> -#define XGMAC_VLAN_TAG		0x0000001C	/* VLAN Tags */
> -#define XGMAC_VERSION		0x00000020	/* Version */
> -#define XGMAC_VLAN_INCL		0x00000024	/* VLAN tag for tx frames */
> -#define XGMAC_LPI_CTRL		0x00000028	/* LPI Control and Status */
> -#define XGMAC_LPI_TIMER		0x0000002C	/* LPI Timers Control */
> -#define XGMAC_TX_PACE		0x00000030	/* Transmit Pace and Stretch */
> -#define XGMAC_VLAN_HASH		0x00000034	/* VLAN Hash Table */
> -#define XGMAC_DEBUG		0x00000038	/* Debug */
> -#define XGMAC_INT_STAT		0x0000003C	/* Interrupt and Control */
> -#define XGMAC_ADDR_HIGH(reg)	(0x00000040 + ((reg) * 8))
> -#define XGMAC_ADDR_LOW(reg)	(0x00000044 + ((reg) * 8))
> -#define XGMAC_HASH(n)		(0x00000300 + (n) * 4) /* HASH table regs */
> -#define XGMAC_NUM_HASH		16
> -#define XGMAC_OMR		0x00000400
> -#define XGMAC_REMOTE_WAKE	0x00000700	/* Remote Wake-Up Frm Filter */
> -#define XGMAC_PMT		0x00000704	/* PMT Control and Status */
> -#define XGMAC_MMC_CTRL		0x00000800	/* XGMAC MMC Control */
> -#define XGMAC_MMC_INTR_RX	0x00000804	/* Recieve Interrupt */
> -#define XGMAC_MMC_INTR_TX	0x00000808	/* Transmit Interrupt */
> -#define XGMAC_MMC_INTR_MASK_RX	0x0000080c	/* Recieve Interrupt Mask */
> -#define XGMAC_MMC_INTR_MASK_TX	0x00000810	/* Transmit Interrupt Mask */
> -
> -
> -/* Hardware TX Statistics Counters */
> -#define XGMAC_MMC_TXOCTET_GB_LO	0x00000814
> -#define XGMAC_MMC_TXOCTET_GB_HI	0x00000818
> -#define XGMAC_MMC_TXFRAME_GB_LO	0x0000081C
> -#define XGMAC_MMC_TXFRAME_GB_HI	0x00000820
> -#define XGMAC_MMC_TXBCFRAME_G	0x00000824
> -#define XGMAC_MMC_TXMCFRAME_G	0x0000082C
> -#define XGMAC_MMC_TXUCFRAME_GB	0x00000864
> -#define XGMAC_MMC_TXMCFRAME_GB	0x0000086C
> -#define XGMAC_MMC_TXBCFRAME_GB	0x00000874
> -#define XGMAC_MMC_TXUNDERFLOW	0x0000087C
> -#define XGMAC_MMC_TXOCTET_G_LO	0x00000884
> -#define XGMAC_MMC_TXOCTET_G_HI	0x00000888
> -#define XGMAC_MMC_TXFRAME_G_LO	0x0000088C
> -#define XGMAC_MMC_TXFRAME_G_HI	0x00000890
> -#define XGMAC_MMC_TXPAUSEFRAME	0x00000894
> -#define XGMAC_MMC_TXVLANFRAME	0x0000089C
> -
> -/* Hardware RX Statistics Counters */
> -#define XGMAC_MMC_RXFRAME_GB_LO	0x00000900
> -#define XGMAC_MMC_RXFRAME_GB_HI	0x00000904
> -#define XGMAC_MMC_RXOCTET_GB_LO	0x00000908
> -#define XGMAC_MMC_RXOCTET_GB_HI	0x0000090C
> -#define XGMAC_MMC_RXOCTET_G_LO	0x00000910
> -#define XGMAC_MMC_RXOCTET_G_HI	0x00000914
> -#define XGMAC_MMC_RXBCFRAME_G	0x00000918
> -#define XGMAC_MMC_RXMCFRAME_G	0x00000920
> -#define XGMAC_MMC_RXCRCERR	0x00000928
> -#define XGMAC_MMC_RXRUNT	0x00000930
> -#define XGMAC_MMC_RXJABBER	0x00000934
> -#define XGMAC_MMC_RXUCFRAME_G	0x00000970
> -#define XGMAC_MMC_RXLENGTHERR	0x00000978
> -#define XGMAC_MMC_RXPAUSEFRAME	0x00000988
> -#define XGMAC_MMC_RXOVERFLOW	0x00000990
> -#define XGMAC_MMC_RXVLANFRAME	0x00000998
> -#define XGMAC_MMC_RXWATCHDOG	0x000009a0
> -
> -/* DMA Control and Status Registers */
> -#define XGMAC_DMA_BUS_MODE	0x00000f00	/* Bus Mode */
> -#define XGMAC_DMA_TX_POLL	0x00000f04	/* Transmit Poll Demand */
> -#define XGMAC_DMA_RX_POLL	0x00000f08	/* Received Poll Demand */
> -#define XGMAC_DMA_RX_BASE_ADDR	0x00000f0c	/* Receive List Base */
> -#define XGMAC_DMA_TX_BASE_ADDR	0x00000f10	/* Transmit List Base */
> -#define XGMAC_DMA_STATUS	0x00000f14	/* Status Register */
> -#define XGMAC_DMA_CONTROL	0x00000f18	/* Ctrl (Operational Mode) */
> -#define XGMAC_DMA_INTR_ENA	0x00000f1c	/* Interrupt Enable */
> -#define XGMAC_DMA_MISS_FRAME_CTR 0x00000f20	/* Missed Frame Counter */
> -#define XGMAC_DMA_RI_WDOG_TIMER	0x00000f24	/* RX Intr Watchdog Timer */
> -#define XGMAC_DMA_AXI_BUS	0x00000f28	/* AXI Bus Mode */
> -#define XGMAC_DMA_AXI_STATUS	0x00000f2C	/* AXI Status */
> -#define XGMAC_DMA_HW_FEATURE	0x00000f58	/* Enabled Hardware Features */
> -
> -#define XGMAC_ADDR_AE		0x80000000
> -#define XGMAC_MAX_FILTER_ADDR	31
> -
> -/* PMT Control and Status */
> -#define XGMAC_PMT_POINTER_RESET	0x80000000
> -#define XGMAC_PMT_GLBL_UNICAST	0x00000200
> -#define XGMAC_PMT_WAKEUP_RX_FRM	0x00000040
> -#define XGMAC_PMT_MAGIC_PKT	0x00000020
> -#define XGMAC_PMT_WAKEUP_FRM_EN	0x00000004
> -#define XGMAC_PMT_MAGIC_PKT_EN	0x00000002
> -#define XGMAC_PMT_POWERDOWN	0x00000001
> -
> -#define XGMAC_CONTROL_SPD	0x40000000	/* Speed control */
> -#define XGMAC_CONTROL_SPD_MASK	0x60000000
> -#define XGMAC_CONTROL_SPD_1G	0x60000000
> -#define XGMAC_CONTROL_SPD_2_5G	0x40000000
> -#define XGMAC_CONTROL_SPD_10G	0x00000000
> -#define XGMAC_CONTROL_SARC	0x10000000	/* Source Addr Insert/Replace */
> -#define XGMAC_CONTROL_SARK_MASK	0x18000000
> -#define XGMAC_CONTROL_CAR	0x04000000	/* CRC Addition/Replacement */
> -#define XGMAC_CONTROL_CAR_MASK	0x06000000
> -#define XGMAC_CONTROL_DP	0x01000000	/* Disable Padding */
> -#define XGMAC_CONTROL_WD	0x00800000	/* Disable Watchdog on rx */
> -#define XGMAC_CONTROL_JD	0x00400000	/* Jabber disable */
> -#define XGMAC_CONTROL_JE	0x00100000	/* Jumbo frame */
> -#define XGMAC_CONTROL_LM	0x00001000	/* Loop-back mode */
> -#define XGMAC_CONTROL_IPC	0x00000400	/* Checksum Offload */
> -#define XGMAC_CONTROL_ACS	0x00000080	/* Automatic Pad/FCS Strip */
> -#define XGMAC_CONTROL_DDIC	0x00000010	/* Disable Deficit Idle Count */
> -#define XGMAC_CONTROL_TE	0x00000008	/* Transmitter Enable */
> -#define XGMAC_CONTROL_RE	0x00000004	/* Receiver Enable */
> -
> -/* XGMAC Frame Filter defines */
> -#define XGMAC_FRAME_FILTER_PR	0x00000001	/* Promiscuous Mode */
> -#define XGMAC_FRAME_FILTER_HUC	0x00000002	/* Hash Unicast */
> -#define XGMAC_FRAME_FILTER_HMC	0x00000004	/* Hash Multicast */
> -#define XGMAC_FRAME_FILTER_DAIF	0x00000008	/* DA Inverse Filtering */
> -#define XGMAC_FRAME_FILTER_PM	0x00000010	/* Pass all multicast */
> -#define XGMAC_FRAME_FILTER_DBF	0x00000020	/* Disable Broadcast frames */
> -#define XGMAC_FRAME_FILTER_SAIF	0x00000100	/* Inverse Filtering */
> -#define XGMAC_FRAME_FILTER_SAF	0x00000200	/* Source Address Filter */
> -#define XGMAC_FRAME_FILTER_HPF	0x00000400	/* Hash or perfect Filter */
> -#define XGMAC_FRAME_FILTER_VHF	0x00000800	/* VLAN Hash Filter */
> -#define XGMAC_FRAME_FILTER_VPF	0x00001000	/* VLAN Perfect Filter */
> -#define XGMAC_FRAME_FILTER_RA	0x80000000	/* Receive all mode */
> -
> -#define FIFO_MINUS_1K			0x0
> -#define FIFO_MINUS_2K			0x1
> -#define FIFO_MINUS_3K			0x2
> -#define FIFO_MINUS_4K			0x3
> -#define FIFO_MINUS_6K			0x4
> -#define FIFO_MINUS_8K			0x5
> -#define FIFO_MINUS_12K			0x6
> -#define FIFO_MINUS_16K			0x7
> -
> -/* XGMAC FLOW CTRL defines */
> -#define XGMAC_FLOW_CTRL_PT_MASK	0xffff0000	/* Pause Time Mask */
> -#define XGMAC_FLOW_CTRL_PT_SHIFT	16
> -#define XGMAC_FLOW_CTRL_DZQP	0x00000080	/* Disable Zero-Quanta Phase */
> -#define XGMAC_FLOW_CTRL_PLT	0x00000020	/* Pause Low Threshhold */
> -#define XGMAC_FLOW_CTRL_PLT_SHIFT	4
> -#define XGMAC_FLOW_CTRL_PLT_MASK 0x00000030	/* PLT MASK */
> -#define XGMAC_FLOW_CTRL_UP	0x00000008	/* Unicast Pause Frame Detect */
> -#define XGMAC_FLOW_CTRL_RFE	0x00000004	/* Rx Flow Control Enable */
> -#define XGMAC_FLOW_CTRL_TFE	0x00000002	/* Tx Flow Control Enable */
> -#define XGMAC_FLOW_CTRL_FCB_BPA	0x00000001	/* Flow Control Busy ... */
> -
> -/* XGMAC_INT_STAT reg */
> -#define XGMAC_INT_STAT_PMT	0x0080		/* PMT Interrupt Status */
> -#define XGMAC_INT_STAT_LPI	0x0040		/* LPI Interrupt Status */
> -
> -/* DMA Bus Mode register defines */
> -#define DMA_BUS_MODE_SFT_RESET	0x00000001	/* Software Reset */
> -#define DMA_BUS_MODE_DSL_MASK	0x0000007c	/* Descriptor Skip Length */
> -#define DMA_BUS_MODE_DSL_SHIFT	2		/* (in DWORDS) */
> -#define DMA_BUS_MODE_ATDS	0x00000080	/* Alternate Descriptor Size */
> -
> -/* Programmable burst length */
> -#define DMA_BUS_MODE_PBL_MASK	0x00003f00	/* Programmable Burst Len */
> -#define DMA_BUS_MODE_PBL_SHIFT	8
> -#define DMA_BUS_MODE_FB		0x00010000	/* Fixed burst */
> -#define DMA_BUS_MODE_RPBL_MASK	0x003e0000	/* Rx-Programmable Burst Len */
> -#define DMA_BUS_MODE_RPBL_SHIFT	17
> -#define DMA_BUS_MODE_USP	0x00800000
> -#define DMA_BUS_MODE_8PBL	0x01000000
> -#define DMA_BUS_MODE_AAL	0x02000000
> -
> -#define DMA_AXIMODE_ENLPI	0x80000000
> -#define DMA_AXIMODE_MGK		0x40000000
> -#define DMA_AXIMODE_WROSR	0x00100000
> -#define DMA_AXIMODE_WROSR_MASK	0x00F00000
> -#define DMA_AXIMODE_WROSR_SHIFT	20
> -#define DMA_AXIMODE_RDOSR	0x00010000
> -#define DMA_AXIMODE_RDOSR_MASK	0x000F0000
> -#define DMA_AXIMODE_RDOSR_SHIFT	16
> -#define DMA_AXIMODE_AAL		0x00001000
> -#define DMA_AXIMODE_BLEN256	0x00000080
> -#define DMA_AXIMODE_BLEN128	0x00000040
> -#define DMA_AXIMODE_BLEN64	0x00000020
> -#define DMA_AXIMODE_BLEN32	0x00000010
> -#define DMA_AXIMODE_BLEN16	0x00000008
> -#define DMA_AXIMODE_BLEN8	0x00000004
> -#define DMA_AXIMODE_BLEN4	0x00000002
> -#define DMA_AXIMODE_UNDEF	0x00000001
> -
> -/* DMA Bus Mode register defines */
> -#define DMA_BUS_PR_RATIO_MASK	0x0000c000	/* Rx/Tx priority ratio */
> -#define DMA_BUS_PR_RATIO_SHIFT	14
> -#define DMA_BUS_FB		0x00010000	/* Fixed Burst */
> -
> -/* DMA Control register defines */
> -#define DMA_CONTROL_ST		0x00002000	/* Start/Stop Transmission */
> -#define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
> -#define DMA_CONTROL_DFF		0x01000000	/* Disable flush of rx frames */
> -
> -/* DMA Normal interrupt */
> -#define DMA_INTR_ENA_NIE	0x00010000	/* Normal Summary */
> -#define DMA_INTR_ENA_AIE	0x00008000	/* Abnormal Summary */
> -#define DMA_INTR_ENA_ERE	0x00004000	/* Early Receive */
> -#define DMA_INTR_ENA_FBE	0x00002000	/* Fatal Bus Error */
> -#define DMA_INTR_ENA_ETE	0x00000400	/* Early Transmit */
> -#define DMA_INTR_ENA_RWE	0x00000200	/* Receive Watchdog */
> -#define DMA_INTR_ENA_RSE	0x00000100	/* Receive Stopped */
> -#define DMA_INTR_ENA_RUE	0x00000080	/* Receive Buffer Unavailable */
> -#define DMA_INTR_ENA_RIE	0x00000040	/* Receive Interrupt */
> -#define DMA_INTR_ENA_UNE	0x00000020	/* Tx Underflow */
> -#define DMA_INTR_ENA_OVE	0x00000010	/* Receive Overflow */
> -#define DMA_INTR_ENA_TJE	0x00000008	/* Transmit Jabber */
> -#define DMA_INTR_ENA_TUE	0x00000004	/* Transmit Buffer Unavail */
> -#define DMA_INTR_ENA_TSE	0x00000002	/* Transmit Stopped */
> -#define DMA_INTR_ENA_TIE	0x00000001	/* Transmit Interrupt */
> -
> -#define DMA_INTR_NORMAL		(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
> -				 DMA_INTR_ENA_TUE)
> -
> -#define DMA_INTR_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
> -				 DMA_INTR_ENA_RWE | DMA_INTR_ENA_RSE | \
> -				 DMA_INTR_ENA_RUE | DMA_INTR_ENA_UNE | \
> -				 DMA_INTR_ENA_OVE | DMA_INTR_ENA_TJE | \
> -				 DMA_INTR_ENA_TSE)
> -
> -/* DMA default interrupt mask */
> -#define DMA_INTR_DEFAULT_MASK	(DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
> -
> -/* DMA Status register defines */
> -#define DMA_STATUS_GMI		0x08000000	/* MMC interrupt */
> -#define DMA_STATUS_GLI		0x04000000	/* GMAC Line interface int */
> -#define DMA_STATUS_EB_MASK	0x00380000	/* Error Bits Mask */
> -#define DMA_STATUS_EB_TX_ABORT	0x00080000	/* Error Bits - TX Abort */
> -#define DMA_STATUS_EB_RX_ABORT	0x00100000	/* Error Bits - RX Abort */
> -#define DMA_STATUS_TS_MASK	0x00700000	/* Transmit Process State */
> -#define DMA_STATUS_TS_SHIFT	20
> -#define DMA_STATUS_RS_MASK	0x000e0000	/* Receive Process State */
> -#define DMA_STATUS_RS_SHIFT	17
> -#define DMA_STATUS_NIS		0x00010000	/* Normal Interrupt Summary */
> -#define DMA_STATUS_AIS		0x00008000	/* Abnormal Interrupt Summary */
> -#define DMA_STATUS_ERI		0x00004000	/* Early Receive Interrupt */
> -#define DMA_STATUS_FBI		0x00002000	/* Fatal Bus Error Interrupt */
> -#define DMA_STATUS_ETI		0x00000400	/* Early Transmit Interrupt */
> -#define DMA_STATUS_RWT		0x00000200	/* Receive Watchdog Timeout */
> -#define DMA_STATUS_RPS		0x00000100	/* Receive Process Stopped */
> -#define DMA_STATUS_RU		0x00000080	/* Receive Buffer Unavailable */
> -#define DMA_STATUS_RI		0x00000040	/* Receive Interrupt */
> -#define DMA_STATUS_UNF		0x00000020	/* Transmit Underflow */
> -#define DMA_STATUS_OVF		0x00000010	/* Receive Overflow */
> -#define DMA_STATUS_TJT		0x00000008	/* Transmit Jabber Timeout */
> -#define DMA_STATUS_TU		0x00000004	/* Transmit Buffer Unavail */
> -#define DMA_STATUS_TPS		0x00000002	/* Transmit Process Stopped */
> -#define DMA_STATUS_TI		0x00000001	/* Transmit Interrupt */
> -
> -/* Common MAC defines */
> -#define MAC_ENABLE_TX		0x00000008	/* Transmitter Enable */
> -#define MAC_ENABLE_RX		0x00000004	/* Receiver Enable */
> -
> -/* XGMAC Operation Mode Register */
> -#define XGMAC_OMR_TSF		0x00200000	/* TX FIFO Store and Forward */
> -#define XGMAC_OMR_FTF		0x00100000	/* Flush Transmit FIFO */
> -#define XGMAC_OMR_TTC		0x00020000	/* Transmit Threshhold Ctrl */
> -#define XGMAC_OMR_TTC_SHIFT	16
> -#define XGMAC_OMR_TTC_MASK	0x00030000
> -#define XGMAC_OMR_RFD		0x00006000	/* FC Deactivation Threshhold */
> -#define XGMAC_OMR_RFD_SHIFT	12
> -#define XGMAC_OMR_RFD_MASK	0x00007000	/* FC Deact Threshhold MASK */
> -#define XGMAC_OMR_RFA		0x00000600	/* FC Activation Threshhold */
> -#define XGMAC_OMR_RFA_SHIFT	9
> -#define XGMAC_OMR_RFA_MASK	0x00000E00	/* FC Act Threshhold MASK */
> -#define XGMAC_OMR_EFC		0x00000100	/* Enable Hardware FC */
> -#define XGMAC_OMR_FEF		0x00000080	/* Forward Error Frames */
> -#define XGMAC_OMR_DT		0x00000040	/* Drop TCP/IP csum Errors */
> -#define XGMAC_OMR_RSF		0x00000020	/* RX FIFO Store and Forward */
> -#define XGMAC_OMR_RTC_256	0x00000018	/* RX Threshhold Ctrl */
> -#define XGMAC_OMR_RTC_MASK	0x00000018	/* RX Threshhold Ctrl MASK */
> -
> -/* XGMAC HW Features Register */
> -#define DMA_HW_FEAT_TXCOESEL	0x00010000	/* TX Checksum offload */
> -
> -#define XGMAC_MMC_CTRL_CNT_FRZ	0x00000008
> -
> -/* XGMAC Descriptor Defines */
> -#define MAX_DESC_BUF_SZ		(0x2000 - 8)
> -
> -#define RXDESC_EXT_STATUS	0x00000001
> -#define RXDESC_CRC_ERR		0x00000002
> -#define RXDESC_RX_ERR		0x00000008
> -#define RXDESC_RX_WDOG		0x00000010
> -#define RXDESC_FRAME_TYPE	0x00000020
> -#define RXDESC_GIANT_FRAME	0x00000080
> -#define RXDESC_LAST_SEG		0x00000100
> -#define RXDESC_FIRST_SEG	0x00000200
> -#define RXDESC_VLAN_FRAME	0x00000400
> -#define RXDESC_OVERFLOW_ERR	0x00000800
> -#define RXDESC_LENGTH_ERR	0x00001000
> -#define RXDESC_SA_FILTER_FAIL	0x00002000
> -#define RXDESC_DESCRIPTOR_ERR	0x00004000
> -#define RXDESC_ERROR_SUMMARY	0x00008000
> -#define RXDESC_FRAME_LEN_OFFSET	16
> -#define RXDESC_FRAME_LEN_MASK	0x3fff0000
> -#define RXDESC_DA_FILTER_FAIL	0x40000000
> -
> -#define RXDESC1_END_RING	0x00008000
> -
> -#define RXDESC_IP_PAYLOAD_MASK	0x00000003
> -#define RXDESC_IP_PAYLOAD_UDP	0x00000001
> -#define RXDESC_IP_PAYLOAD_TCP	0x00000002
> -#define RXDESC_IP_PAYLOAD_ICMP	0x00000003
> -#define RXDESC_IP_HEADER_ERR	0x00000008
> -#define RXDESC_IP_PAYLOAD_ERR	0x00000010
> -#define RXDESC_IPV4_PACKET	0x00000040
> -#define RXDESC_IPV6_PACKET	0x00000080
> -#define TXDESC_UNDERFLOW_ERR	0x00000001
> -#define TXDESC_JABBER_TIMEOUT	0x00000002
> -#define TXDESC_LOCAL_FAULT	0x00000004
> -#define TXDESC_REMOTE_FAULT	0x00000008
> -#define TXDESC_VLAN_FRAME	0x00000010
> -#define TXDESC_FRAME_FLUSHED	0x00000020
> -#define TXDESC_IP_HEADER_ERR	0x00000040
> -#define TXDESC_PAYLOAD_CSUM_ERR	0x00000080
> -#define TXDESC_ERROR_SUMMARY	0x00008000
> -#define TXDESC_SA_CTRL_INSERT	0x00040000
> -#define TXDESC_SA_CTRL_REPLACE	0x00080000
> -#define TXDESC_2ND_ADDR_CHAINED	0x00100000
> -#define TXDESC_END_RING		0x00200000
> -#define TXDESC_CSUM_IP		0x00400000
> -#define TXDESC_CSUM_IP_PAYLD	0x00800000
> -#define TXDESC_CSUM_ALL		0x00C00000
> -#define TXDESC_CRC_EN_REPLACE	0x01000000
> -#define TXDESC_CRC_EN_APPEND	0x02000000
> -#define TXDESC_DISABLE_PAD	0x04000000
> -#define TXDESC_FIRST_SEG	0x10000000
> -#define TXDESC_LAST_SEG		0x20000000
> -#define TXDESC_INTERRUPT	0x40000000
> -
> -#define DESC_OWN		0x80000000
> -#define DESC_BUFFER1_SZ_MASK	0x00001fff
> -#define DESC_BUFFER2_SZ_MASK	0x1fff0000
> -#define DESC_BUFFER2_SZ_OFFSET	16
> -
> -struct xgmac_dma_desc {
> -	__le32 flags;
> -	__le32 buf_size;
> -	__le32 buf1_addr;		/* Buffer 1 Address Pointer */
> -	__le32 buf2_addr;		/* Buffer 2 Address Pointer */
> -	__le32 ext_status;
> -	__le32 res[3];
> -};
> -
> -struct xgmac_priv {
> -	struct xgmac_dma_desc *rx_chain;
> -	struct xgmac_dma_desc *tx_chain;
> -	char *rxbuffer;
> -
> -	u32 tx_currdesc;
> -	u32 rx_currdesc;
> -
> -	void __iomem *base;
> -
> -	struct eth_device edev;
> -	struct device_d *dev;
> -};
> -
> -/* XGMAC Descriptor Access Helpers */
> -static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
> -{
> -	if (buf_sz > MAX_DESC_BUF_SZ)
> -		p->buf_size = cpu_to_le32(MAX_DESC_BUF_SZ |
> -			(buf_sz - MAX_DESC_BUF_SZ) << DESC_BUFFER2_SZ_OFFSET);
> -	else
> -		p->buf_size = cpu_to_le32(buf_sz);
> -}
> -
> -static inline int desc_get_buf_len(struct xgmac_dma_desc *p)
> -{
> -	u32 len = le32_to_cpu(p->buf_size);
> -	return (len & DESC_BUFFER1_SZ_MASK) +
> -		((len & DESC_BUFFER2_SZ_MASK) >> DESC_BUFFER2_SZ_OFFSET);
> -}
> -
> -static inline void desc_init_rx_desc(struct xgmac_dma_desc *p, int ring_size,
> -				     int buf_sz)
> -{
> -	struct xgmac_dma_desc *end = p + ring_size - 1;
> -
> -	memset(p, 0, sizeof(*p) * ring_size);
> -
> -	for (; p <= end; p++)
> -		desc_set_buf_len(p, buf_sz);
> -
> -	end->buf_size |= cpu_to_le32(RXDESC1_END_RING);
> -}
> -
> -static inline void desc_init_tx_desc(struct xgmac_dma_desc *p, u32 ring_size)
> -{
> -	memset(p, 0, sizeof(*p) * ring_size);
> -	p[ring_size - 1].flags = cpu_to_le32(TXDESC_END_RING);
> -}
> -
> -static inline int desc_get_owner(struct xgmac_dma_desc *p)
> -{
> -	return le32_to_cpu(p->flags) & DESC_OWN;
> -}
> -
> -static inline void desc_set_rx_owner(struct xgmac_dma_desc *p)
> -{
> -	/* Clear all fields and set the owner */
> -	p->flags = cpu_to_le32(DESC_OWN);
> -}
> -
> -static inline void desc_set_tx_owner(struct xgmac_dma_desc *p, u32 flags)
> -{
> -	u32 tmpflags = le32_to_cpu(p->flags);
> -	tmpflags &= TXDESC_END_RING;
> -	tmpflags |= flags | DESC_OWN;
> -	p->flags = cpu_to_le32(tmpflags);
> -}
> -
> -static inline void *desc_get_buf_addr(struct xgmac_dma_desc *p)
> -{
> -	return (void *)le32_to_cpu(p->buf1_addr);
> -}
> -
> -static inline void desc_set_buf_addr(struct xgmac_dma_desc *p,
> -				     void *paddr, int len)
> -{
> -	p->buf1_addr = cpu_to_le32(paddr);
> -	if (len > MAX_DESC_BUF_SZ)
> -		p->buf2_addr = cpu_to_le32(paddr + MAX_DESC_BUF_SZ);
> -}
> -
> -static inline void desc_set_buf_addr_and_size(struct xgmac_dma_desc *p,
> -					      void *paddr, int len)
> -{
> -	desc_set_buf_len(p, len);
> -	desc_set_buf_addr(p, paddr, len);
> -}
> -
> -static inline int desc_get_rx_frame_len(struct xgmac_dma_desc *p)
> -{
> -	u32 data = le32_to_cpu(p->flags);
> -	u32 len = (data & RXDESC_FRAME_LEN_MASK) >> RXDESC_FRAME_LEN_OFFSET;
> -	if (data & RXDESC_FRAME_TYPE)
> -		len -= 4;
> -
> -	return len;
> -}
> -
> -/*
> - * Initialize a descriptor ring.  Calxeda XGMAC is configured to use
> - * advanced descriptors.
> - */
> -
> -static void init_rx_desc(struct xgmac_priv *priv)
> -{
> -	struct xgmac_dma_desc *rxdesc = priv->rx_chain;
> -	void *rxbuffer = priv->rxbuffer;
> -	int i;
> -
> -	desc_init_rx_desc(rxdesc, RX_NUM_DESC, ETH_BUF_SZ);
> -	writel((ulong)rxdesc, priv->base + XGMAC_DMA_RX_BASE_ADDR);
> -
> -	for (i = 0; i < RX_NUM_DESC; i++) {
> -		desc_set_buf_addr(rxdesc + i, rxbuffer + (i * ETH_BUF_SZ),
> -				  ETH_BUF_SZ);
> -		desc_set_rx_owner(rxdesc + i);
> -	}
> -}
> -
> -static void init_tx_desc(struct xgmac_priv *priv)
> -{
> -	desc_init_tx_desc(priv->tx_chain, TX_NUM_DESC);
> -	writel((ulong)priv->tx_chain, priv->base + XGMAC_DMA_TX_BASE_ADDR);
> -}
> -
> -static int xgmac_reset(struct eth_device *dev)
> -{
> -	struct xgmac_priv *priv = dev->priv;
> -	int ret;
> -	u32 value;
> -
> -	value = readl(priv->base + XGMAC_CONTROL) & XGMAC_CONTROL_SPD_MASK;
> -
> -	writel(DMA_BUS_MODE_SFT_RESET, priv->base + XGMAC_DMA_BUS_MODE);
> -
> -	ret = wait_on_timeout(100 * MSECOND,
> -		!(readl(priv->base + XGMAC_DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
> -
> -	writel(value, priv->base + XGMAC_CONTROL);
> -
> -	return ret;
> -}
> -
> -static int xgmac_open(struct eth_device *edev)
> -{
> -	struct xgmac_priv *priv = edev->priv;
> -	int value;
> -	int ret;
> -
> -	ret = xgmac_reset(edev);
> -	if (ret)
> -		return ret;
> -
> -	/* set the AXI bus modes */
> -	value = DMA_BUS_MODE_ATDS |
> -		(16 << DMA_BUS_MODE_PBL_SHIFT) |
> -		DMA_BUS_MODE_FB | DMA_BUS_MODE_AAL;
> -	writel(value, priv->base + XGMAC_DMA_BUS_MODE);
> -
> -	value = DMA_AXIMODE_AAL | DMA_AXIMODE_BLEN16 |
> -		DMA_AXIMODE_BLEN8 | DMA_AXIMODE_BLEN4;
> -	writel(value, priv->base + XGMAC_DMA_AXI_BUS);
> -
> -	/* set flow control parameters and store and forward mode */
> -	value = (FIFO_MINUS_12K << XGMAC_OMR_RFD_SHIFT) |
> -		(FIFO_MINUS_4K << XGMAC_OMR_RFA_SHIFT) |
> -		XGMAC_OMR_EFC | XGMAC_OMR_TSF | XGMAC_OMR_RSF;
> -	writel(value, priv->base + XGMAC_OMR);
> -
> -	/* enable pause frames */
> -	value = (1024 << XGMAC_FLOW_CTRL_PT_SHIFT) |
> -		(1 << XGMAC_FLOW_CTRL_PLT_SHIFT) |
> -		XGMAC_FLOW_CTRL_UP | XGMAC_FLOW_CTRL_RFE | XGMAC_FLOW_CTRL_TFE;
> -	writel(value, priv->base + XGMAC_FLOW_CTRL);
> -
> -	/* Initialize the descriptor chains */
> -	init_rx_desc(priv);
> -	init_tx_desc(priv);
> -
> -	/* must set to 0, or when started up will cause issues */
> -	priv->tx_currdesc = 0;
> -	priv->rx_currdesc = 0;
> -
> -	/* set default core values */
> -	value = readl(priv->base + XGMAC_CONTROL);
> -	value &= XGMAC_CONTROL_SPD_MASK;
> -	value |= XGMAC_CONTROL_DDIC | XGMAC_CONTROL_ACS |
> -		XGMAC_CONTROL_IPC | XGMAC_CONTROL_CAR;
> -
> -	/* Everything is ready enable both mac and DMA */
> -	value |= XGMAC_CONTROL_RE | XGMAC_CONTROL_TE;
> -	writel(value, priv->base + XGMAC_CONTROL);
> -
> -	value = readl(priv->base + XGMAC_DMA_CONTROL);
> -	value |= DMA_CONTROL_SR | DMA_CONTROL_ST;
> -	writel(value, priv->base + XGMAC_DMA_CONTROL);
> -
> -	return 0;
> -}
> -
> -static int xgmac_send(struct eth_device *edev, void *packet, int length)
> -{
> -	struct xgmac_priv *priv = edev->priv;
> -	u32 currdesc = priv->tx_currdesc;
> -	struct xgmac_dma_desc *txdesc = &priv->tx_chain[currdesc];
> -	int ret;
> -
> -	dma_sync_single_for_device((unsigned long)packet, length, DMA_TO_DEVICE);
> -	desc_set_buf_addr_and_size(txdesc, packet, length);
> -	desc_set_tx_owner(txdesc, TXDESC_FIRST_SEG |
> -		TXDESC_LAST_SEG | TXDESC_CRC_EN_APPEND);
> -
> -	/* write poll demand */
> -	writel(1, priv->base + XGMAC_DMA_TX_POLL);
> -
> -	ret = wait_on_timeout(1 * SECOND, !desc_get_owner(txdesc));
> -	dma_sync_single_for_cpu((unsigned long)packet, length, DMA_TO_DEVICE);
> -	if (ret) {
> -		dev_err(priv->dev, "TX timeout\n");
> -		return ret;
> -	}
> -
> -	priv->tx_currdesc = (currdesc + 1) & (TX_NUM_DESC - 1);
> -	return 0;
> -}
> -
> -static int xgmac_recv(struct eth_device *edev)
> -{
> -	struct xgmac_priv *priv = edev->priv;
> -	u32 currdesc = priv->rx_currdesc;
> -	struct xgmac_dma_desc *rxdesc = &priv->rx_chain[currdesc];
> -	int length = 0;
> -	void *buf_addr;
> -
> -	/* check if the host has the desc */
> -	if (desc_get_owner(rxdesc))
> -		return -1; /* something bad happened */
> -
> -	length = desc_get_rx_frame_len(rxdesc);
> -	buf_addr = desc_get_buf_addr(rxdesc);
> -
> -	dma_sync_single_for_cpu((unsigned long)buf_addr, length, DMA_FROM_DEVICE);
> -	net_receive(edev, buf_addr, length);
> -	dma_sync_single_for_device((unsigned long)buf_addr, length,
> -				   DMA_FROM_DEVICE);
> -
> -	/* set descriptor back to owned by XGMAC */
> -	desc_set_rx_owner(rxdesc);
> -	writel(1, priv->base + XGMAC_DMA_RX_POLL);
> -
> -	priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
> -
> -	return length;
> -}
> -
> -static void xgmac_halt(struct eth_device *edev)
> -{
> -	struct xgmac_priv *priv = edev->priv;
> -	int value;
> -
> -	/* Disable TX/RX */
> -	value = readl(priv->base + XGMAC_CONTROL);
> -	value &= ~(XGMAC_CONTROL_RE | XGMAC_CONTROL_TE);
> -	writel(value, priv->base + XGMAC_CONTROL);
> -
> -	/* Disable DMA */
> -	value = readl(priv->base + XGMAC_DMA_CONTROL);
> -	value &= ~(DMA_CONTROL_SR | DMA_CONTROL_ST);
> -	writel(value, priv->base + XGMAC_DMA_CONTROL);
> -
> -	/* must set to 0, or when started up will cause issues */
> -	priv->tx_currdesc = 0;
> -	priv->rx_currdesc = 0;
> -}
> -
> -static int xgmac_get_ethaddr(struct eth_device *edev, unsigned char *addr)
> -{
> -	struct xgmac_priv *priv = edev->priv;
> -	u32 hi_addr, lo_addr;
> -
> -	/* Read the MAC address from the hardware */
> -	hi_addr = readl(priv->base + XGMAC_ADDR_HIGH(0));
> -	lo_addr = readl(priv->base + XGMAC_ADDR_LOW(0));
> -
> -	/* Extract the MAC address from the high and low words */
> -	addr[0] = lo_addr & 0xff;
> -	addr[1] = (lo_addr >> 8) & 0xff;
> -	addr[2] = (lo_addr >> 16) & 0xff;
> -	addr[3] = (lo_addr >> 24) & 0xff;
> -	addr[4] = hi_addr & 0xff;
> -	addr[5] = (hi_addr >> 8) & 0xff;
> -
> -	return 0;
> -}
> -
> -static int xgmac_set_ethaddr(struct eth_device *dev, const unsigned char *addr)
> -{
> -	struct xgmac_priv *priv = dev->priv;
> -	u32 data;
> -
> -	data = (addr[5] << 8) | addr[4];
> -	writel(data, priv->base + XGMAC_ADDR_HIGH(0));
> -	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
> -	writel(data, priv->base + XGMAC_ADDR_LOW(0));
> -
> -	return 0;
> -}
> -
> -static int hb_xgmac_probe(struct device_d *dev)
> -{
> -	struct resource *iores;
> -	struct eth_device *edev;
> -	struct xgmac_priv *priv;
> -	void __iomem *base;
> -
> -	iores = dev_request_mem_resource(dev, 0);
> -	if (IS_ERR(iores))
> -		return PTR_ERR(iores);
> -	base = IOMEM(iores->start);
> -
> -	/* check hardware version */
> -	if (readl(base + XGMAC_VERSION) != 0x1012)
> -		return -EINVAL;
> -
> -	priv = xzalloc(sizeof(*priv));
> -
> -	priv->dev = dev;
> -	priv->base = base;
> -
> -	priv->rxbuffer = dma_alloc_coherent(RX_BUF_SZ, DMA_ADDRESS_BROKEN);
> -	priv->rx_chain = dma_alloc_coherent(RX_NUM_DESC * sizeof(struct xgmac_dma_desc),
> -					    DMA_ADDRESS_BROKEN);
> -	priv->tx_chain = dma_alloc_coherent(TX_NUM_DESC * sizeof(struct xgmac_dma_desc),
> -					    DMA_ADDRESS_BROKEN);
> -
> -	edev = &priv->edev;
> -	edev->priv = priv;
> -
> -	edev->open = xgmac_open;
> -	edev->send = xgmac_send;
> -	edev->recv = xgmac_recv;
> -	edev->halt = xgmac_halt;
> -	edev->get_ethaddr = xgmac_get_ethaddr;
> -	edev->set_ethaddr = xgmac_set_ethaddr;
> -	edev->parent = dev;
> -
> -	eth_register(edev);
> -
> -	return 0;
> -}
> -
> -static __maybe_unused struct of_device_id xgmac_dt_ids[] = {
> -	{
> -		.compatible = "calxeda,hb-xgmac",
> -	}, {
> -		/* sentinel */
> -	}
> -};
> -
> -static struct driver_d hb_xgmac_driver = {
> -	.name  = "hb-xgmac",
> -	.probe = hb_xgmac_probe,
> -	.of_compatible = DRV_OF_COMPAT(xgmac_dt_ids),
> -};
> -device_platform_driver(hb_xgmac_driver);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From renaud.barbier at abaco.com  Fri Aug 13 01:16:45 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Fri, 13 Aug 2021 09:16:45 +0100
Subject: [PATCH v3 0/3] NXP IFC nand driver
Message-ID: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>

This version 3 of the patch addresses the follwoing comments:
	* Move the NAND timings initialisation to the mach-layerscape machine
	* fsl_chip_ctrl_init returns errors.
	* NAND commit message specifies from where the driver is derived from.


Renaud Barbier (3):
  ARM: atomic.h: add 64-bit counter support
  nand: add NXP IFC nand driver
  ls1046ardb: enable IFC NAND.

 arch/arm/configs/layerscape_defconfig |   11 +
 arch/arm/mach-layerscape/Makefile     |    1 +
 arch/arm/mach-layerscape/nand.c       |   44 ++
 drivers/mtd/nand/Kconfig              |    7 +
 drivers/mtd/nand/Makefile             |    1 +
 drivers/mtd/nand/fsl_ifc.h            |  116 +++
 drivers/mtd/nand/nand_fsl_ifc.c       | 1038 +++++++++++++++++++++++++
 include/asm-generic/atomic-long.h     |   63 --
 include/asm-generic/atomic.h          |   49 ++
 include/linux/fsl_ifc.h               |  305 ++++++++
 10 files changed, 1572 insertions(+), 63 deletions(-)
 create mode 100644 arch/arm/mach-layerscape/nand.c
 create mode 100644 drivers/mtd/nand/fsl_ifc.h
 create mode 100644 drivers/mtd/nand/nand_fsl_ifc.c
 create mode 100644 include/linux/fsl_ifc.h

-- 
2.27.0



From renaud.barbier at abaco.com  Fri Aug 13 01:16:48 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Fri, 13 Aug 2021 09:16:48 +0100
Subject: [PATCH 3/3] ls1046ardb: enable IFC NAND.
In-Reply-To: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
References: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
Message-ID: <1628842608-17031-4-git-send-email-renaud.barbier@abaco.com>

Set the NAND timings and enable the IFC NAND driver.

Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
---
 arch/arm/configs/layerscape_defconfig | 11 +++++++
 arch/arm/mach-layerscape/Makefile     |  1 +
 arch/arm/mach-layerscape/nand.c       | 44 +++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)
 create mode 100644 arch/arm/mach-layerscape/nand.c

diff --git a/arch/arm/configs/layerscape_defconfig b/arch/arm/configs/layerscape_defconfig
index 394cd95c98..fb8e885353 100644
--- a/arch/arm/configs/layerscape_defconfig
+++ b/arch/arm/configs/layerscape_defconfig
@@ -34,6 +34,10 @@ CONFIG_CMD_GO=y
 CONFIG_CMD_RESET=y
 CONFIG_CMD_UIMAGE=y
 CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UBI=y
+CONFIG_CMD_UBIFORMAT=y
+CONFIG_CMD_UMOUNT=y
 CONFIG_CMD_EXPORT=y
 CONFIG_CMD_LOADENV=y
 CONFIG_CMD_PRINTENV=y
@@ -69,6 +73,7 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_LED=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_NAND=y
 CONFIG_CMD_LED_TRIGGER=y
 CONFIG_CMD_WD=y
 CONFIG_CMD_BAREBOX_UPDATE=y
@@ -85,6 +90,10 @@ CONFIG_DP83867_PHY=y
 CONFIG_REALTEK_PHY=y
 CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_DRIVER_SPI_FSL_QUADSPI=y
+CONFIG_NAND=y
+CONFIG_NAND_FSL_IFC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=20
 CONFIG_I2C=y
 CONFIG_I2C_IMX=y
 CONFIG_I2C_MUX=y
@@ -112,5 +121,7 @@ CONFIG_FS_NFS=y
 CONFIG_FS_FAT=y
 CONFIG_FS_FAT_WRITE=y
 CONFIG_FS_FAT_LFN=y
+CONFIG_FS_UBIFS=y
+CONFIG_FS_UBIFS_COMPRESSION_LZO=y
 CONFIG_ZLIB=y
 CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/mach-layerscape/Makefile b/arch/arm/mach-layerscape/Makefile
index 854a327c91..99da7b2af0 100644
--- a/arch/arm/mach-layerscape/Makefile
+++ b/arch/arm/mach-layerscape/Makefile
@@ -6,3 +6,4 @@ obj-pbl-y += boot.o
 pbl-y += xload-qspi.o xload.o
 obj-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa.o ppa-entry.o
 obj-$(CONFIG_BOOTM) += pblimage.o
+obj-$(CONFIG_NAND_FSL_IFC) += nand.o
diff --git a/arch/arm/mach-layerscape/nand.c b/arch/arm/mach-layerscape/nand.c
new file mode 100644
index 0000000000..b36c6b3c46
--- /dev/null
+++ b/arch/arm/mach-layerscape/nand.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <init.h>
+#include <of_address.h>
+#include <linux/fsl_ifc.h>
+
+static int rdb_nand_init(void)
+{
+	struct device_node *np;
+	void __iomem *ifc;
+
+	if (!of_machine_is_compatible("fsl,ls1046a-rdb"))
+		return 0;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,ifc");
+	if (!np)
+		return -EINVAL;
+
+	ifc = of_iomap(np, 0);
+	if (!ifc)
+		return -EINVAL;
+
+	set_ifc_cspr(ifc, IFC_CS0, CSPR_PHYS_ADDR(0x7e800000) |
+			CSPR_PORT_SIZE_8 | CSPR_MSEL_NAND | CSPR_V);
+	set_ifc_csor(ifc, IFC_CS0, CSOR_NAND_ECC_ENC_EN | CSOR_NAND_ECC_DEC_EN |
+			CSOR_NAND_ECC_MODE_8 |
+			CSOR_NAND_RAL_3 | CSOR_NAND_PGS_4K |
+			CSOR_NAND_SPRZ_224 |  CSOR_NAND_PB(64) |
+			CSOR_NAND_TRHZ_20);
+	set_ifc_amask(ifc, IFC_CS0, IFC_AMASK(64*1024));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM0, FTIM0_NAND_TCCST(0x07) |
+			FTIM0_NAND_TWP(0x18) | FTIM0_NAND_TWCHT(0x07) |
+			FTIM0_NAND_TWH(0x0a));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM1, FTIM1_NAND_TADLE(0x32) |
+			FTIM1_NAND_TWBE(0x39) | FTIM1_NAND_TRR(0x0e)|
+			FTIM1_NAND_TRP(0x18));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM2, FTIM2_NAND_TRAD(0xf) |
+			FTIM2_NAND_TREH(0xa) | FTIM2_NAND_TWHRE(0x1e));
+	set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM3, 0);
+
+	return 0;
+}
+postcore_initcall(rdb_nand_init);
-- 
2.27.0



From renaud.barbier at abaco.com  Fri Aug 13 01:16:46 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Fri, 13 Aug 2021 09:16:46 +0100
Subject: [PATCH 1/3] ARM: atomic.h: add 64-bit counter support
In-Reply-To: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
References: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
Message-ID: <1628842608-17031-2-git-send-email-renaud.barbier@abaco.com>

In preparation for the introduction of the FSL IFC nand driver
for the layerscape CPU, add 64-bit counter support.

Remove functions calling undefined functions.

Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
---
 include/asm-generic/atomic-long.h | 63 -------------------------------
 include/asm-generic/atomic.h      | 49 ++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 63 deletions(-)

diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index 322d510f38..fd1fdad20f 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -66,69 +66,6 @@ static inline void atomic_long_sub(long i, atomic_long_t *l)
 	atomic64_sub(i, v);
 }
 
-static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_sub_and_test(i, v);
-}
-
-static inline int atomic_long_dec_and_test(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_dec_and_test(v);
-}
-
-static inline int atomic_long_inc_and_test(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_inc_and_test(v);
-}
-
-static inline int atomic_long_add_negative(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return atomic64_add_negative(i, v);
-}
-
-static inline long atomic_long_add_return(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_add_return(i, v);
-}
-
-static inline long atomic_long_sub_return(long i, atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_sub_return(i, v);
-}
-
-static inline long atomic_long_inc_return(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_inc_return(v);
-}
-
-static inline long atomic_long_dec_return(atomic_long_t *l)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_dec_return(v);
-}
-
-static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
-{
-	atomic64_t *v = (atomic64_t *)l;
-
-	return (long)atomic64_add_unless(v, a, u);
-}
-
 #define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
 
 #define atomic_long_cmpxchg(l, old, new) \
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 449cecaabc..6e63b8e8e7 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -11,7 +11,55 @@
 #ifdef CONFIG_SMP
 #error SMP not supported
 #endif
+#define ATOMIC_INIT(i)	{ (i) }
+
+#ifdef CONFIG_64BIT
+typedef struct { s64 counter; } atomic64_t;
+
+#define atomic64_read(v)	((v)->counter)
+#define atomic64_set(v, i)	(((v)->counter) = (i))
+
+static inline void atomic64_add(s64 i, volatile atomic64_t *v)
+{
+	v->counter += i;
+}
+
+static inline void atomic64_sub(s64 i, volatile atomic64_t *v)
+{
+	v->counter -= i;
+}
+
+static inline void atomic64_inc(volatile atomic64_t *v)
+{
+	v->counter += 1;
+}
+
+static inline void atomic64_dec(volatile atomic64_t *v)
+{
+	v->counter -= 1;
+}
+
+static inline int atomic64_dec_and_test(volatile atomic64_t *v)
+{
+	s64 val;
+
+	val = v->counter;
+	v->counter = val -= 1;
+
+	return val == 0;
+}
 
+static inline int atomic64_add_negative(s64 i, volatile atomic64_t *v)
+{
+	s64 val;
+
+	val = v->counter;
+	v->counter = val += i;
+
+	return val < 0;
+}
+
+#else
 typedef struct { volatile int counter; } atomic_t;
 
 #define ATOMIC_INIT(i)	{ (i) }
@@ -63,6 +111,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 {
 	*addr &= ~mask;
 }
+#endif
 
 /* Atomic operations are already serializing on ARM */
 #define smp_mb__before_atomic_dec()	barrier()
-- 
2.27.0



From renaud.barbier at abaco.com  Fri Aug 13 01:16:47 2021
From: renaud.barbier at abaco.com (Renaud Barbier)
Date: Fri, 13 Aug 2021 09:16:47 +0100
Subject: [PATCH 2/3] nand: add NXP IFC nand driver
In-Reply-To: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
References: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
Message-ID: <1628842608-17031-3-git-send-email-renaud.barbier@abaco.com>

Add the NXP IFC nand driver support. This driver
can be used with the NXP QorIQ cores.

Originally, derived from U-boot commit cce573e (2015-10)

Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
---
 drivers/mtd/nand/Kconfig        |    7 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/fsl_ifc.h      |  116 ++++
 drivers/mtd/nand/nand_fsl_ifc.c | 1038 +++++++++++++++++++++++++++++++
 include/linux/fsl_ifc.h         |  305 +++++++++
 5 files changed, 1467 insertions(+)
 create mode 100644 drivers/mtd/nand/fsl_ifc.h
 create mode 100644 drivers/mtd/nand/nand_fsl_ifc.c
 create mode 100644 include/linux/fsl_ifc.h

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c69e5ce4e1..cf9f1fdc0c 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -42,6 +42,13 @@ config NAND_IMX
 	  and later, which use the GPMI NAND controller from the MXS series. 
 	  See the i.MX 'mxs' driver for those chips.
 
+config NAND_FSL_IFC
+	bool
+	prompt "FSL IFC NAND driver"
+	depends on ARCH_LAYERSCAPE
+	help
+	  Freescale IFC NAND driver for various chips.
+
 config NAND_MXS
 	bool
 	select STMP_DEVICE
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index f6e5b41e94..4fd14ddd63 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -22,3 +22,4 @@ pbl-$(CONFIG_NAND_S3C24XX)		+= nand_s3c24xx.o
 obj-$(CONFIG_NAND_MXS)			+= nand_mxs.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= nand_denali.o
 obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= nand_denali_dt.o
+obj-$(CONFIG_NAND_FSL_IFC)		+= nand_fsl_ifc.o
diff --git a/drivers/mtd/nand/fsl_ifc.h b/drivers/mtd/nand/fsl_ifc.h
new file mode 100644
index 0000000000..4c89f569f5
--- /dev/null
+++ b/drivers/mtd/nand/fsl_ifc.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ */
+
+/*
+ * The actual number of banks implemented depends on the IFC version
+ *    - IFC version 1.0 implements 4 banks.
+ *    - IFC version 1.1 onward implements 8 banks.
+ */
+#define FSL_IFC_BANK_COUNT 8
+
+#define FSL_IFC_REV		0x0000
+#define		FSL_IFC_V1_1_0	0x01010000
+#define		FSL_IFC_V2_0_0	0x02000000
+
+/*
+ * Version 1.1.0 adds offset 0x1000
+ * Version 2.0.0 adds offset 0x10000
+ */
+#define FSL_IFC_NCFGR		0x000
+
+#define		IFC_NAND_SRAM_INIT_EN           0x20000000
+
+/*
+ * NAND Flash Command Registers (NAND_FCR0/NAND_FCR1)
+ */
+#define FSL_IFC_FCR0		0x014
+/* General purpose FCM flash command bytes CMD0-CMD7 */
+#define		IFC_NAND_FCR0_CMD0_SHIFT	24
+#define		IFC_NAND_FCR0_CMD1_SHIFT	16
+#define		IFC_NAND_FCR0_CMD2_SHIFT	8
+#define		IFC_NAND_FCR0_CMD3_SHIFT	0
+#define FSL_IFC_ROW0		0x03c
+#define		IFC_NAND_COL_MS			0x80000000
+#define FSL_IFC_COL0		0x044
+#define FSL_IFC_ROW3		0x06c
+#define FSL_IFC_NAND_BC		0x108
+/*
+ * NAND Flash Instruction Registers (NAND_FIR0/NAND_FIR1/NAND_FIR2)
+ */
+#define FSL_IFC_FIR0		0x110
+/* NAND Machine specific opcodes OP0-OP14*/
+#define		IFC_NAND_FIR0_OP0_SHIFT		26
+#define		IFC_NAND_FIR0_OP1_SHIFT		20
+#define		IFC_NAND_FIR0_OP2_SHIFT		14
+#define		IFC_NAND_FIR0_OP3_SHIFT		8
+#define		IFC_NAND_FIR0_OP4_SHIFT		2
+#define FSL_IFC_FIR1		0x114
+#define		IFC_NAND_FIR1_OP5_SHIFT		26
+#define		IFC_NAND_FIR1_OP6_SHIFT		20
+#define		IFC_NAND_FIR1_OP7_SHIFT		14
+#define		IFC_NAND_FIR1_OP8_SHIFT		8
+#define FSL_IFC_NAND_CSEL	0x15c
+#define		IFC_NAND_CSEL_SHIFT		26
+#define FSL_IFC_NANDSEQ_STRT	0x164
+#define		IFC_NAND_SEQ_STRT_FIR_STRT	0x80000000
+/* NAND Event and Error Status Register */
+#define FSL_IFC_NAND_EVTER_STAT	0x16c
+#define		IFC_NAND_EVTER_STAT_OPC		0x80000000
+#define		IFC_NAND_EVTER_STAT_FTOER	0x08000000
+#define		IFC_NAND_EVTER_STAT_WPER	0x04000000
+/* NAND Flash Page Read Completion Event Status Register */
+#define FSL_IFC_PGRDCMPL_EVT_STAT 0x174
+/* NAND Event and Error Enable Register (NAND_EVTER_EN) */
+#define FSL_IFC_EVTER_EN	0x180
+#define		IFC_NAND_EVTER_EN_OPC_EN	0x80000000
+#define		IFC_NAND_EVTER_EN_PGRDCMPL_EN	0x20000000
+#define		IFC_NAND_EVTER_EN_FTOER_EN	0x08000000
+#define		IFC_NAND_EVTER_EN_WPER_EN	0x04000000
+
+#define FSL_IFC_NAND_FSR	0x1e0
+#define FSL_IFC_ECCSTAT(v)	(0x1e8 + (4 * v))
+#define		IFC_NAND_EVTER_STAT_ECCER	0x02000000
+
+/*
+ * Instruction opcodes to be programmed
+ * in FIR registers- 6bits
+ */
+enum ifc_nand_fir_opcodes {
+	IFC_FIR_OP_NOP,
+	IFC_FIR_OP_CA0,
+	IFC_FIR_OP_CA1,
+	IFC_FIR_OP_CA2,
+	IFC_FIR_OP_CA3,
+	IFC_FIR_OP_RA0,
+	IFC_FIR_OP_RA1,
+	IFC_FIR_OP_RA2,
+	IFC_FIR_OP_RA3,
+	IFC_FIR_OP_CMD0,
+	IFC_FIR_OP_CMD1,
+	IFC_FIR_OP_CMD2,
+	IFC_FIR_OP_CMD3,
+	IFC_FIR_OP_CMD4,
+	IFC_FIR_OP_CMD5,
+	IFC_FIR_OP_CMD6,
+	IFC_FIR_OP_CMD7,
+	IFC_FIR_OP_CW0,
+	IFC_FIR_OP_CW1,
+	IFC_FIR_OP_CW2,
+	IFC_FIR_OP_CW3,
+	IFC_FIR_OP_CW4,
+	IFC_FIR_OP_CW5,
+	IFC_FIR_OP_CW6,
+	IFC_FIR_OP_CW7,
+	IFC_FIR_OP_WBCD,
+	IFC_FIR_OP_RBCD,
+	IFC_FIR_OP_BTRD,
+	IFC_FIR_OP_RDSTAT,
+	IFC_FIR_OP_NWAIT,
+	IFC_FIR_OP_WFR,
+	IFC_FIR_OP_SBRD,
+	IFC_FIR_OP_UA,
+	IFC_FIR_OP_RB,
+};
diff --git a/drivers/mtd/nand/nand_fsl_ifc.c b/drivers/mtd/nand/nand_fsl_ifc.c
new file mode 100644
index 0000000000..64dc9c225f
--- /dev/null
+++ b/drivers/mtd/nand/nand_fsl_ifc.c
@@ -0,0 +1,1038 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Integrated Flash Controller NAND Machine Driver
+ *
+ * Copyright (c) 2012 Freescale Semiconductor, Inc
+ *
+ * Authors: Dipen Dudhat <Dipen.Dudhat at freescale.com>
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <nand.h>
+#include <errno.h>
+#include <clock.h>
+#include <io.h>
+#include <of_address.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/fsl_ifc.h>
+#include <asm-generic/io.h>
+#include "fsl_ifc.h"
+
+#define ERR_BYTE	0xFF
+#define IFC_TIMEOUT_MS	500
+/* overview of the fsl ifc controller */
+struct fsl_ifc_ctrl {
+	struct nand_controller controller;
+	/* device info */
+	void __iomem *rregs;  /* Run-time register		      */
+	void __iomem *gregs;  /* Global registers		      */
+	uint32_t version;
+	uint32_t page;       /* Last page written to / read from      */
+	uint32_t read_bytes; /* Number of bytes read during command   */
+	uint32_t column;     /* Saved column from SEQIN               */
+	uint32_t index;      /* Pointer to next byte to 'read'        */
+	uint32_t nand_stat;  /* status read from NEESR after last op  */
+	uint32_t oob;        /* Non zero if operating on OOB data     */
+	uint32_t eccread;    /* Non zero for a full-page ECC read     */
+	uint32_t max_bitflips; /* Saved during READ0 cmd              */
+	void __iomem *addr;  /* Address of assigned IFC buffer        */
+};
+
+/* mtd information per set */
+struct fsl_ifc_mtd {
+	struct device_d *dev;
+	struct nand_chip chip;
+	struct fsl_ifc_ctrl *ctrl;
+	uint32_t cs;		/* On which chipsel NAND is connected    */
+	uint32_t bufnum_mask;	/* bufnum = page & bufnum_mask */
+	void __iomem *vbase;    /* Chip select base virtual address     */
+	phys_addr_t pbase;	/* Chip select physical address		*/
+};
+
+static struct fsl_ifc_ctrl *ifc_ctrl;
+
+/* Generic flash bbt descriptors */
+static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
+};
+
+static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section,
+		struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->offset = 8;
+	oobregion->length = chip->ecc.total;
+
+	return 0;
+}
+
+static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section,
+		struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section > 1)
+		return -ERANGE;
+
+	if (mtd->writesize == 512 && !(chip->options & NAND_BUSWIDTH_16)) {
+		if (!section) {
+			oobregion->offset = 0;
+			oobregion->length = 5;
+		} else {
+			oobregion->offset = 6;
+			oobregion->length = 2;
+		}
+
+		return 0;
+	}
+
+	if (!section) {
+		oobregion->offset = 2;
+		oobregion->length = 6;
+	} else {
+		oobregion->offset = chip->ecc.total + 8;
+		oobregion->length = mtd->oobsize - oobregion->offset;
+	}
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops fsl_ifc_ooblayout_ops = {
+	.ecc = fsl_ifc_ooblayout_ecc,
+	.free = fsl_ifc_ooblayout_free,
+};
+
+/*
+ * Set up the IFC hardware block and page address fields, and the ifc nand
+ * structure addr field to point to the correct IFC buffer in memory
+ */
+static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	int buf_num;
+
+	if (page_addr != -1) {
+		ctrl->page = page_addr;
+		/* Program ROW0/COL0 */
+		ifc_out32(ctrl->rregs + FSL_IFC_ROW0, page_addr);
+		buf_num = page_addr & priv->bufnum_mask;
+		ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
+	}
+
+	ifc_out32(ctrl->rregs + FSL_IFC_COL0, (oob ? IFC_NAND_COL_MS : 0) |
+						column);
+	ctrl->index = column;
+
+	/* for OOB data point to the second half of the buffer */
+	if (oob)
+		ctrl->index += mtd->writesize;
+}
+
+/* returns nonzero if entire page is blank */
+static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
+			  uint32_t eccstat, uint32_t bufnum)
+{
+	return (eccstat >> ((3 - bufnum % 4) * 8)) & 15;
+}
+
+/* execute IFC NAND command and wait for it to complete */
+static void fsl_ifc_run_command(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint64_t time_start;
+	uint32_t eccstat;
+	int i;
+
+	/* set the chip select for NAND Transaction */
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_CSEL,
+			priv->cs << IFC_NAND_CSEL_SHIFT);
+
+	/* start read/write seq */
+	ifc_out32(ctrl->rregs + FSL_IFC_NANDSEQ_STRT,
+			IFC_NAND_SEQ_STRT_FIR_STRT);
+
+	ctrl->nand_stat = 0;
+
+	/* wait for NAND Machine complete flag or timeout */
+	time_start = get_time_ns();
+	while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
+		ctrl->nand_stat = ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
+
+		if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_OPC)
+			break;
+	}
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT, ctrl->nand_stat);
+
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_FTOER)
+		pr_err("%s: Flash Time Out Error\n", __func__);
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER)
+		pr_err("%s: Write Protect Error\n", __func__);
+
+	ctrl->max_bitflips = 0;
+
+	if (ctrl->eccread) {
+		int errors;
+		int bufnum = ctrl->page & priv->bufnum_mask;
+		int sector_start = bufnum * chip->ecc.steps;
+		int sector_end = sector_start + chip->ecc.steps - 1;
+
+		eccstat = ifc_in32(ctrl->rregs +
+				FSL_IFC_ECCSTAT(sector_start / 4));
+
+		for (i = sector_start; i <= sector_end; i++) {
+			if ((i != sector_start) && !(i % 4)) {
+				eccstat = ifc_in32(ctrl->rregs +
+						FSL_IFC_ECCSTAT(i / 4));
+			}
+			errors = check_read_ecc(mtd, ctrl, eccstat, i);
+
+			if (errors == 15) {
+				/*
+				 * Uncorrectable error.
+				 * We'll check for blank pages later.
+				 *
+				 * We disable ECCER reporting due to erratum
+				 * IFC-A002770 -- so report it now if we
+				 * see an uncorrectable error in ECCSTAT.
+				 */
+				ctrl->nand_stat |= IFC_NAND_EVTER_STAT_ECCER;
+				continue;
+			}
+
+			mtd->ecc_stats.corrected += errors;
+			ctrl->max_bitflips = max_t(unsigned int,
+					ctrl->max_bitflips, errors);
+		}
+
+		ctrl->eccread = 0;
+	}
+}
+
+static void
+fsl_ifc_do_read(struct nand_chip *chip, int oob, struct mtd_info *mtd)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	/* Program FIR/IFC_NAND_FCR0 for Small/Large page */
+	if (mtd->writesize > 512) {
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+			  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
+			  (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR1, 0x0);
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			  (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+	} else {
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
+			  (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR1, 0);
+
+		if (oob)
+			ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+				  NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
+		else
+			ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+				  NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+	}
+}
+
+/* cmdfunc send commands to the IFC NAND Machine */
+static void fsl_ifc_cmdfunc(struct nand_chip *chip, uint32_t command,
+			     int column, int page_addr)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	/* clear the read buffer */
+	ctrl->read_bytes = 0;
+	if (command != NAND_CMD_PAGEPROG)
+		ctrl->index = 0;
+
+	switch (command) {
+	/* READ0 read the entire buffer to use hardware ECC. */
+	case NAND_CMD_READ0: {
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+		set_addr(mtd, 0, page_addr, 0);
+
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		ctrl->index += column;
+
+		if (chip->ecc.mode == NAND_ECC_HW)
+			ctrl->eccread = 1;
+
+		fsl_ifc_do_read(chip, 0, mtd);
+		fsl_ifc_run_command(mtd);
+		return;
+	}
+
+	/* READOOB reads only the OOB because no ECC is performed. */
+	case NAND_CMD_READOOB:
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, mtd->oobsize - column);
+
+		set_addr(mtd, column, page_addr, 1);
+
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		fsl_ifc_do_read(chip, 1, mtd);
+		fsl_ifc_run_command(mtd);
+
+		return;
+
+	case NAND_CMD_RNDOUT:
+		if (chip->ecc.mode == NAND_ECC_HW)
+			break;
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+		set_addr(mtd, column, -1, 0);
+		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		/* For write size greater than 512 */
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			(IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			(IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR1, 0x0);
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			(NAND_CMD_RNDOUT << IFC_NAND_FCR0_CMD0_SHIFT) |
+			(NAND_CMD_RNDOUTSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+
+		fsl_ifc_run_command(mtd);
+		return;
+
+	case NAND_CMD_READID:
+	case NAND_CMD_PARAM: {
+		int timing = IFC_FIR_OP_RB;
+		int len = 8;
+
+		if (command == NAND_CMD_PARAM) {
+			timing = IFC_FIR_OP_RBCD;
+			len = 256 * 3;
+		}
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (timing << IFC_NAND_FIR0_OP2_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  command << IFC_NAND_FCR0_CMD0_SHIFT);
+		ifc_out32(ctrl->rregs + FSL_IFC_ROW3, column);
+
+		/*
+		 * although currently it's 8 bytes for READID, we always read
+		 * the maximum 256 bytes(for PARAM)
+		 */
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, len);
+		ctrl->read_bytes = len;
+
+		set_addr(mtd, 0, 0, 0);
+		fsl_ifc_run_command(mtd);
+		return;
+	}
+
+	/* ERASE1 stores the block and page address */
+	case NAND_CMD_ERASE1:
+		set_addr(mtd, 0, page_addr, 0);
+		return;
+
+	/* ERASE2 uses the block and page address from ERASE1 */
+	case NAND_CMD_ERASE2:
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
+
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			  (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
+
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+		ctrl->read_bytes = 0;
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* SEQIN sets up the addr buffer and all registers except the length */
+	case NAND_CMD_SEQIN: {
+		uint32_t nand_fcr0;
+
+		ctrl->column = column;
+		ctrl->oob = 0;
+
+		if (mtd->writesize > 512) {
+			nand_fcr0 =
+				(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
+				(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
+				(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
+
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+				  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+				  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				  (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
+				  (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR1,
+				  (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
+				  (IFC_FIR_OP_RDSTAT <<
+					IFC_NAND_FIR1_OP6_SHIFT) |
+				  (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
+		} else {
+			nand_fcr0 = ((NAND_CMD_PAGEPROG <<
+					IFC_NAND_FCR0_CMD1_SHIFT) |
+				    (NAND_CMD_SEQIN <<
+					IFC_NAND_FCR0_CMD2_SHIFT) |
+				    (NAND_CMD_STATUS <<
+					IFC_NAND_FCR0_CMD3_SHIFT));
+
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+				  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				  (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
+				  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
+				  (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
+			ifc_out32(ctrl->rregs + FSL_IFC_FIR1,
+				  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
+				  (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
+				  (IFC_FIR_OP_RDSTAT <<
+					IFC_NAND_FIR1_OP7_SHIFT) |
+				  (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
+
+			if (column >= mtd->writesize)
+				nand_fcr0 |=
+				NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
+			else
+				nand_fcr0 |=
+				NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
+		}
+
+		if (column >= mtd->writesize) {
+			/* OOB area --> READOOB */
+			column -= mtd->writesize;
+			ctrl->oob = 1;
+		}
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0, nand_fcr0);
+		set_addr(mtd, column, page_addr, ctrl->oob);
+		return;
+	}
+
+	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+	case NAND_CMD_PAGEPROG:
+		if (ctrl->oob)
+			ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC,
+				  ctrl->index - ctrl->column);
+		else
+			ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0);
+
+		fsl_ifc_run_command(mtd);
+		return;
+
+	case NAND_CMD_STATUS:
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			  (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
+		ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 1);
+		set_addr(mtd, 0, 0, 0);
+		ctrl->read_bytes = 1;
+
+		fsl_ifc_run_command(mtd);
+
+		/*
+		 * The chip always seems to report that it is
+		 * write-protected, even when it is not.
+		 */
+		if (chip->options & NAND_BUSWIDTH_16)
+			out_be16(ctrl->addr, in_be16(ctrl->addr) |
+					NAND_STATUS_WP);
+		else
+			out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
+		return;
+
+	case NAND_CMD_RESET:
+		ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+			  IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
+		ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+			  NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	default:
+		pr_err("%s: error, unsupported command 0x%x.\n",
+			__func__, command);
+	}
+}
+
+/* Write buf to the IFC NAND Controller Data Buffer */
+static void fsl_ifc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t bufsize = mtd->writesize + mtd->oobsize;
+
+	if (len <= 0) {
+		pr_info("%s of %d bytes", __func__, len);
+		ctrl->nand_stat = 0;
+		return;
+	}
+
+	if ((uint32_t)len > bufsize - ctrl->index) {
+		pr_err("%s beyond end of buffer (%d requested, %u available)\n",
+			__func__, len, bufsize - ctrl->index);
+		len = bufsize - ctrl->index;
+	}
+
+	memcpy_toio(ctrl->addr + ctrl->index, buf, len);
+	ctrl->index += len;
+}
+
+/*
+ * read a byte from either the IFC hardware buffer if it has any data left
+ * otherwise issue a command to read a single byte.
+ */
+static uint8_t fsl_ifc_read_byte(struct nand_chip *chip)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t offset;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ctrl->index < ctrl->read_bytes) {
+		offset = ctrl->index++;
+		return in_8(ctrl->addr + offset);
+	}
+
+	return ERR_BYTE;
+}
+
+/*
+ * Read two bytes from the IFC hardware buffer
+ * read function for 16-bit buswith
+ */
+static uint8_t fsl_ifc_read_byte16(struct nand_chip *chip)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint16_t data;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ctrl->index < ctrl->read_bytes) {
+		data = ifc_in16(ctrl->addr + ctrl->index);
+		ctrl->index += 2;
+		return (uint8_t)data;
+	}
+
+	return ERR_BYTE;
+}
+
+/* Read from the IFC Controller Data Buffer */
+static void fsl_ifc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	int avail;
+
+	if (len < 0)
+		return;
+
+	avail = min((uint32_t)len, ctrl->read_bytes - ctrl->index);
+	memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
+
+	ctrl->index += avail;
+
+	if (len > avail)
+		pr_err("%s beyond end of buffer (%d requested, %d available)\n",
+		       __func__, len, avail);
+}
+
+/* This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+static int fsl_ifc_wait(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t nand_fsr;
+	int status;
+
+	/* Use READ_STATUS command, but wait for the device to be ready */
+	ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+		  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+		  (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
+	ifc_out32(ctrl->rregs + FSL_IFC_FCR0, NAND_CMD_STATUS <<
+		  IFC_NAND_FCR0_CMD0_SHIFT);
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 1);
+	set_addr(mtd, 0, 0, 0);
+	ctrl->read_bytes = 1;
+
+	fsl_ifc_run_command(mtd);
+
+	nand_fsr = ifc_in32(ctrl->rregs + FSL_IFC_NAND_FSR);
+	status = nand_fsr >> 24;
+
+	/* Chip sometimes reporting write protect even when it's not */
+	return status | NAND_STATUS_WP;
+}
+
+/*
+ * The controller does not check for bitflips in erased pages,
+ * therefore software must check instead.
+ */
+static int
+check_erased_page(struct nand_chip *chip, u8 *buf, struct mtd_info *mtd)
+{
+	u8 *ecc = chip->oob_poi;
+	const int ecc_size = chip->ecc.bytes;
+	const int pkt_size = chip->ecc.size;
+	int i, res, bitflips = 0;
+	struct mtd_oob_region oobregion = { };
+
+
+	mtd_ooblayout_ecc(mtd, 0, &oobregion);
+	ecc += oobregion.offset;
+	for (i = 0; i < chip->ecc.steps; i++) {
+		res = nand_check_erased_ecc_chunk(buf, pkt_size, ecc, ecc_size,
+		NULL, 0, chip->ecc.strength);
+
+		if (res < 0) {
+			pr_err("fsl-ifc: NAND Flash ECC Uncorrectable Error\n");
+			mtd->ecc_stats.failed++;
+		} else if (res > 0) {
+			mtd->ecc_stats.corrected += res;
+		}
+		bitflips = max(res, bitflips);
+		buf += pkt_size;
+		ecc += ecc_size;
+	}
+
+	return bitflips;
+}
+
+static int fsl_ifc_read_page(struct nand_chip *chip, uint8_t *buf,
+		int oob_required, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
+	/*fsl_ifc_read_buf(chip, buf, mtd->writesize); */
+	if (oob_required)
+		fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize);
+
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) {
+		if (!oob_required)
+			fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize);
+
+		return check_erased_page(chip, buf, mtd);
+	}
+
+	if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+		mtd->ecc_stats.failed++;
+
+	return ctrl->max_bitflips;
+}
+
+/*
+ * ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static int fsl_ifc_write_page(struct nand_chip *chip, const uint8_t *buf,
+		int oob_required, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
+	fsl_ifc_write_buf(chip, chip->oob_poi, mtd->oobsize);
+
+	return nand_prog_page_end_op(chip);
+}
+
+static int match_bank(struct fsl_ifc_ctrl *ctrl, int bank, phys_addr_t addr)
+{
+	u32 cspr = get_ifc_cspr(ctrl->gregs, bank);
+
+	if (!(cspr & CSPR_V))
+		return 0;
+	if ((cspr & CSPR_MSEL) != CSPR_MSEL_NAND)
+		return 0;
+
+	return (cspr & CSPR_BA) == (addr & CSPR_BA);
+}
+
+static int fsl_ifc_ctrl_init(void)
+{
+	struct fsl_ifc_ctrl *ctrl;
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,ifc");
+	if (!np)
+		return -EINVAL;
+
+	ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
+	if (!ifc_ctrl)
+		return -ENOMEM;
+
+	ctrl = ifc_ctrl;
+	ctrl->read_bytes = 0;
+	ctrl->index = 0;
+	ctrl->addr = NULL;
+
+	ctrl->gregs = of_iomap(np, 0);
+
+	ctrl->version = ifc_in32(ctrl->gregs + FSL_IFC_REV);
+	if (ctrl->version >= FSL_IFC_V2_0_0)
+		ctrl->rregs = ctrl->gregs + 0x10000;
+	else
+		ctrl->rregs = ctrl->gregs + 0x1000;
+
+	/* clear event registers */
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT, ~0U);
+	ifc_out32(ctrl->rregs + FSL_IFC_PGRDCMPL_EVT_STAT, ~0U);
+
+	/* Enable error and event for any detected errors */
+	ifc_out32(ctrl->rregs + FSL_IFC_EVTER_EN,
+		  IFC_NAND_EVTER_EN_OPC_EN |
+		  IFC_NAND_EVTER_EN_PGRDCMPL_EN |
+		  IFC_NAND_EVTER_EN_FTOER_EN |
+		  IFC_NAND_EVTER_EN_WPER_EN);
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NCFGR, 0x0);
+
+	return 0;
+}
+
+static void fsl_ifc_select_chip(struct nand_chip *chip, int cs)
+{
+}
+
+static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv, uint32_t ver)
+{
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
+	uint32_t ncfgr = 0;
+	uint32_t time_start;
+
+	if (ctrl->version > FSL_IFC_V1_1_0) {
+		ncfgr = ifc_in32(ctrl->rregs + FSL_IFC_NCFGR);
+		ifc_out32(ctrl->rregs + FSL_IFC_NCFGR,
+				ncfgr | IFC_NAND_SRAM_INIT_EN);
+
+		/* wait for  SRAM_INIT bit to be clear or timeout */
+		time_start = get_time_ns();
+		while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
+			ifc_ctrl->nand_stat =
+				ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
+
+			if (!(ifc_ctrl->nand_stat & IFC_NAND_SRAM_INIT_EN))
+				return 0;
+		}
+		pr_err("fsl-ifc: Failed to Initialise SRAM\n");
+		return -EIO;
+	}
+
+	cs = priv->cs;
+	/* Save CSOR and CSOR_ext */
+	csor = get_ifc_csor(ctrl->gregs, cs);
+	csor_ext = get_ifc_csor_ext(ctrl->gregs, cs);
+
+	/* change PageSize 8K and SpareSize 1K*/
+	csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
+	set_ifc_csor(ctrl->gregs, cs, csor_8k);
+	set_ifc_csor_ext(ctrl->gregs, cs, 0x0000400);
+
+	/* READID */
+	ifc_out32(ctrl->rregs + FSL_IFC_FIR0,
+		  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+		  (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+		  (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+	ifc_out32(ctrl->rregs + FSL_IFC_FCR0,
+		  NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+	ifc_out32(ctrl->rregs + FSL_IFC_ROW3, 0x0);
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_BC, 0x0);
+
+	/* Program ROW0/COL0 */
+	ifc_out32(ctrl->rregs + FSL_IFC_ROW0, 0x0);
+	ifc_out32(ctrl->rregs + FSL_IFC_COL0, 0x0);
+
+	/* set the chip select for NAND Transaction */
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_CSEL,
+			priv->cs << IFC_NAND_CSEL_SHIFT);
+
+	/* start read seq */
+	ifc_out32(ctrl->rregs + FSL_IFC_NANDSEQ_STRT,
+			IFC_NAND_SEQ_STRT_FIR_STRT);
+
+	time_start = get_time_ns();
+	while (!is_timeout(time_start, IFC_TIMEOUT_MS * MSECOND)) {
+		ifc_ctrl->nand_stat =
+			ifc_in32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT);
+
+		if (ifc_ctrl->nand_stat & IFC_NAND_EVTER_STAT_OPC)
+			break;
+	}
+
+	if (ifc_ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) {
+		pr_err("fsl-ifc: Failed to Initialise SRAM\n");
+		return -EIO;
+	}
+
+	ifc_out32(ctrl->rregs + FSL_IFC_NAND_EVTER_STAT, ifc_ctrl->nand_stat);
+
+	/* Restore CSOR and CSOR_ext */
+	set_ifc_csor(ctrl->gregs, priv->cs, csor);
+	set_ifc_csor_ext(ctrl->gregs, priv->cs, csor_ext);
+
+	return 0;
+}
+
+static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
+{
+	struct fsl_ifc_ctrl *ctrl;
+	struct nand_chip *nand = &priv->chip;
+	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
+	uint32_t cspr = 0, csor = 0;
+	int ret = 0;
+
+	if (!ifc_ctrl) {
+		ret = fsl_ifc_ctrl_init();
+		if (ret)
+			return ret;
+	}
+	ctrl = priv->ctrl = ifc_ctrl;
+
+	if (priv->dev->device_node) {
+		int bank, banks;
+
+		 /* find which chip select it is connected to */
+		banks = (ctrl->version == FSL_IFC_V1_1_0) ? 4 : 8;
+		for (bank = 0; bank < banks; bank++) {
+			if (match_bank(ifc_ctrl, bank, priv->pbase))
+				break;
+		}
+		priv->cs = bank;
+		if (bank >= banks) {
+			pr_err("%s: address did not match any chip selects\n",
+				__func__);
+			return -ENODEV;
+		}
+	}
+
+	/*mtd->priv = nand; */
+	mtd->dev.parent = priv->dev;
+
+	/*
+	 * Fill in nand_chip structure
+	 * set up function call table
+	 */
+	nand->legacy.write_buf = fsl_ifc_write_buf;
+	nand->legacy.read_buf = fsl_ifc_read_buf;
+	nand->legacy.select_chip = fsl_ifc_select_chip;
+	nand->legacy.cmdfunc = fsl_ifc_cmdfunc;
+	nand->legacy.waitfunc = fsl_ifc_wait;
+
+	/* set up nand options */
+	nand->bbt_td = &bbt_main_descr;
+	nand->bbt_md = &bbt_mirror_descr;
+
+	/* set up nand options */
+	nand->options = NAND_NO_SUBPAGE_WRITE;
+	nand->bbt_options = NAND_BBT_USE_FLASH;
+
+	cspr = get_ifc_cspr(ctrl->gregs, priv->cs);
+	csor = get_ifc_csor(ctrl->gregs, priv->cs);
+
+	if (cspr & CSPR_PORT_SIZE_16) {
+		nand->legacy.read_byte = fsl_ifc_read_byte16;
+		nand->options |= NAND_BUSWIDTH_16;
+	} else {
+		nand->legacy.read_byte = fsl_ifc_read_byte;
+	}
+
+	nand->controller = &ifc_ctrl->controller;
+	nand->priv = priv;
+
+	nand->ecc.read_page = fsl_ifc_read_page;
+	nand->ecc.write_page = fsl_ifc_write_page;
+
+	/* Hardware generates ECC per 512 Bytes */
+	nand->ecc.size = 512;
+	nand->ecc.bytes = 8;
+
+	nand->legacy.chip_delay = 30;
+
+	switch (csor & CSOR_NAND_PGS_MASK) {
+	case CSOR_NAND_PGS_512:
+		if (!(nand->options & NAND_BUSWIDTH_16)) {
+			/* Avoid conflict with bad block marker */
+			bbt_main_descr.offs = 0;
+			bbt_mirror_descr.offs = 0;
+		}
+
+		nand->ecc.strength = 4;
+		priv->bufnum_mask = 15;
+		break;
+
+	case CSOR_NAND_PGS_2K:
+		nand->ecc.strength = 4;
+		priv->bufnum_mask = 3;
+		break;
+
+	case CSOR_NAND_PGS_4K:
+		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+		    CSOR_NAND_ECC_MODE_4) {
+			nand->ecc.strength = 4;
+		} else {
+			nand->ecc.strength = 8;
+			nand->ecc.bytes = 16;
+		}
+
+		priv->bufnum_mask = 1;
+		break;
+
+	case CSOR_NAND_PGS_8K:
+		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+		    CSOR_NAND_ECC_MODE_4) {
+			nand->ecc.strength = 4;
+		} else {
+			nand->ecc.strength = 8;
+			nand->ecc.bytes = 16;
+		}
+
+		priv->bufnum_mask = 0;
+		break;
+
+
+	default:
+		pr_err("ifc nand: bad csor %#x: bad page size\n", csor);
+		return -ENODEV;
+	}
+
+	/* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
+	if (csor & CSOR_NAND_ECC_DEC_EN) {
+		nand->ecc.mode = NAND_ECC_HW;
+		mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops);
+	} else {
+		nand->ecc.mode = NAND_ECC_SOFT;
+		nand->ecc.algo = NAND_ECC_HAMMING;
+	}
+
+	if (ctrl->version >= FSL_IFC_V1_1_0) {
+		ret = fsl_ifc_sram_init(priv, ctrl->version);
+		if (ret)
+			return ret;
+	}
+
+	if (ctrl->version >= FSL_IFC_V2_0_0)
+		priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
+
+	return 0;
+}
+
+static int fsl_ifc_nand_probe(struct device_d *dev)
+{
+	struct fsl_ifc_mtd *priv;
+	struct resource *iores;
+	struct mtd_info *mtd;
+	int ret = 0;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores)) {
+		ret = -ENOMEM;
+		goto bailout;
+	}
+	priv->pbase = iores->start;
+	priv->vbase = IOMEM(iores->start);
+
+	if (fsl_ifc_chip_init(priv)) {
+		ret = -ENOMEM;
+		goto bailout;
+	}
+
+	ret = nand_scan_ident(&priv->chip, 1, NULL);
+	if (ret)
+		goto bailout;
+
+	ret = nand_scan_tail(&priv->chip);
+	if (ret)
+		goto bailout;
+
+	mtd = nand_to_mtd(&priv->chip);
+	return add_mtd_nand_device(mtd, "nand");
+bailout:
+	kfree(priv);
+	return ret;
+}
+
+static __maybe_unused struct of_device_id fsl_nand_compatible[] = {
+	{
+		.compatible = "fsl,ifc-nand",
+	}, {
+	}
+};
+
+static struct driver_d fsl_ifc_driver = {
+	.name = "fsl_nand",
+	.probe = fsl_ifc_nand_probe,
+	.of_compatible = DRV_OF_COMPAT(fsl_nand_compatible),
+};
+device_platform_driver(fsl_ifc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FSL IFC NAND driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h
new file mode 100644
index 0000000000..2ff0626357
--- /dev/null
+++ b/include/linux/fsl_ifc.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later  */
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat at freescale.com>
+ *
+ */
+
+#ifndef __FSL_IFC_H
+#define __FSL_IFC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/log2.h>
+
+/* Big-Endian */
+#define ifc_in32(a)			ioread32be(a)
+#define ifc_out32(a, v)			iowrite32be(v, a)
+#define ifc_in16(a)			ioread16be(a)
+#define ifc_out16(a, v)			iowrite16be(v, a)
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+#define CSPR_BA				0xFFFF0000
+#define CSPR_BA_SHIFT			16
+#define CSPR_PORT_SIZE			0x00000180
+#define CSPR_PORT_SIZE_SHIFT		7
+#define CSPR_PORT_SIZE_8		0x00000080
+#define CSPR_PORT_SIZE_16		0x00000100
+#define CSPR_PORT_SIZE_32		0x00000180
+/* Write Protect */
+#define CSPR_WP				0x00000040
+#define CSPR_WP_SHIFT			6
+#define CSPR_MSEL			0x00000006
+#define CSPR_MSEL_SHIFT			1
+#define CSPR_MSEL_NOR			0x00000000
+#define CSPR_MSEL_NAND			0x00000002
+#define CSPR_MSEL_GPCM			0x00000004
+#define CSPR_V				0x00000001
+#define CSPR_V_SHIFT			0
+
+/* Convert an address into the right format for the CSPR Registers */
+#define CSPR_PHYS_ADDR(x)		(((uint64_t)x) & 0xffff0000)
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK			0xFFFF0000
+#define IFC_AMASK_SHIFT			16
+#define IFC_AMASK(n)			(IFC_AMASK_MASK << \
+					(ilog2(n) - IFC_AMASK_SHIFT))
+
+/*
+ * Chip Select Option Register IFC_NAND Machine
+ */
+#define CSOR_NAND_ECC_ENC_EN		0x80000000
+#define CSOR_NAND_ECC_MODE_MASK		0x30000000
+/* 4 bit correction per 520 Byte sector */
+#define CSOR_NAND_ECC_MODE_4		0x00000000
+/* 8 bit correction per 528 Byte sector */
+#define CSOR_NAND_ECC_MODE_8		0x10000000
+#define CSOR_NAND_ECC_DEC_EN		0x04000000
+/* Row Address Length */
+#define CSOR_NAND_RAL_MASK		0x01800000
+#define CSOR_NAND_RAL_SHIFT		20
+#define CSOR_NAND_RAL_1			0x00000000
+#define CSOR_NAND_RAL_2			0x00800000
+#define CSOR_NAND_RAL_3			0x01000000
+#define CSOR_NAND_RAL_4			0x01800000
+/* Page Size 512b, 2k, 4k */
+#define CSOR_NAND_PGS_MASK		0x00180000
+#define CSOR_NAND_PGS_SHIFT		16
+#define CSOR_NAND_PGS_512		0x00000000
+#define CSOR_NAND_PGS_2K		0x00080000
+#define CSOR_NAND_PGS_4K		0x00100000
+#define CSOR_NAND_PGS_8K		0x00180000
+/* Spare region Size */
+#define CSOR_NAND_SPRZ_MASK		0x0000E000
+#define CSOR_NAND_SPRZ_SHIFT		13
+#define CSOR_NAND_SPRZ_16		0x00000000
+#define CSOR_NAND_SPRZ_64		0x00002000
+#define CSOR_NAND_SPRZ_128		0x00004000
+#define CSOR_NAND_SPRZ_210		0x00006000
+#define CSOR_NAND_SPRZ_218		0x00008000
+#define CSOR_NAND_SPRZ_224		0x0000A000
+#define CSOR_NAND_SPRZ_CSOR_EXT	0x0000C000
+/* Pages Per Block */
+#define CSOR_NAND_PB_MASK		0x00000700
+#define CSOR_NAND_PB_SHIFT		8
+#define CSOR_NAND_PB(n)			((ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NAND_TRHZ_MASK		0x0000001C
+#define CSOR_NAND_TRHZ_SHIFT		2
+#define CSOR_NAND_TRHZ_20		0x00000000
+#define CSOR_NAND_TRHZ_40		0x00000004
+#define CSOR_NAND_TRHZ_60		0x00000008
+#define CSOR_NAND_TRHZ_80		0x0000000C
+#define CSOR_NAND_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_NAND_BCTLD			0x00000001
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+/* Enable Address shift Mode */
+#define CSOR_NOR_ADM_SHFT_MODE_EN	0x80000000
+/* Page Read Enable from NOR device */
+#define CSOR_NOR_PGRD_EN		0x10000000
+/* AVD Toggle Enable during Burst Program */
+#define CSOR_NOR_AVD_TGL_PGM_EN		0x01000000
+/* Address Data Multiplexing Shift */
+#define CSOR_NOR_ADM_MASK		0x0003E000
+#define CSOR_NOR_ADM_SHIFT_SHIFT	13
+#define CSOR_NOR_ADM_SHIFT(n)	((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
+/* Type of the NOR device hooked */
+#define CSOR_NOR_NOR_MODE_ASYNC_NOR	0x00000000
+#define CSOR_NOR_NOR_MODE_AVD_NOR	0x00000020
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NOR_TRHZ_MASK		0x0000001C
+#define CSOR_NOR_TRHZ_SHIFT		2
+#define CSOR_NOR_TRHZ_20		0x00000000
+#define CSOR_NOR_TRHZ_40		0x00000004
+#define CSOR_NOR_TRHZ_60		0x00000008
+#define CSOR_NOR_TRHZ_80		0x0000000C
+#define CSOR_NOR_TRHZ_100		0x00000010
+/* Buffer control disable */
+#define CSOR_NOR_BCTLD			0x00000001
+
+/*
+ * Flash Timing Registers (FTIM0 - FTIM2_CSn)
+ */
+/*
+ * FTIM0 - NAND Flash Mode
+ */
+#define FTIM0_NAND			0x7EFF3F3F
+#define FTIM0_NAND_TCCST_SHIFT		25
+#define FTIM0_NAND_TCCST(n)		((n) << FTIM0_NAND_TCCST_SHIFT)
+#define FTIM0_NAND_TWP_SHIFT	16
+#define FTIM0_NAND_TWP(n)	((n) << FTIM0_NAND_TWP_SHIFT)
+#define FTIM0_NAND_TWCHT_SHIFT	8
+#define FTIM0_NAND_TWCHT(n)	((n) << FTIM0_NAND_TWCHT_SHIFT)
+#define FTIM0_NAND_TWH_SHIFT	0
+#define FTIM0_NAND_TWH(n)	((n) << FTIM0_NAND_TWH_SHIFT)
+/*
+ * FTIM1 - NAND Flash Mode
+ */
+#define FTIM1_NAND			0xFFFF3FFF
+#define FTIM1_NAND_TADLE_SHIFT	24
+#define FTIM1_NAND_TADLE(n)	((n) << FTIM1_NAND_TADLE_SHIFT)
+#define FTIM1_NAND_TWBE_SHIFT	16
+#define FTIM1_NAND_TWBE(n)	((n) << FTIM1_NAND_TWBE_SHIFT)
+#define FTIM1_NAND_TRR_SHIFT	8
+#define FTIM1_NAND_TRR(n)	((n) << FTIM1_NAND_TRR_SHIFT)
+#define FTIM1_NAND_TRP_SHIFT	0
+#define FTIM1_NAND_TRP(n)	((n) << FTIM1_NAND_TRP_SHIFT)
+/*
+ * FTIM2 - NAND Flash Mode
+ */
+#define FTIM2_NAND			0x1FE1F8FF
+#define FTIM2_NAND_TRAD_SHIFT	21
+#define FTIM2_NAND_TRAD(n)	((n) << FTIM2_NAND_TRAD_SHIFT)
+#define FTIM2_NAND_TREH_SHIFT	11
+#define FTIM2_NAND_TREH(n)	((n) << FTIM2_NAND_TREH_SHIFT)
+#define FTIM2_NAND_TWHRE_SHIFT	0
+#define FTIM2_NAND_TWHRE(n)	((n) << FTIM2_NAND_TWHRE_SHIFT)
+/*
+ * FTIM0 - NOR Flash Mode
+ */
+#define FTIM0_NOR			0xF03F3F3F
+#define FTIM0_NOR_TACSE_SHIFT		28
+#define FTIM0_NOR_TACSE(n)		((n) << FTIM0_NOR_TACSE_SHIFT)
+#define FTIM0_NOR_TEADC_SHIFT		16
+#define FTIM0_NOR_TEADC(n)		((n) << FTIM0_NOR_TEADC_SHIFT)
+#define FTIM0_NOR_TAVDS_SHIFT		8
+#define FTIM0_NOR_TAVDS(n)		((n) << FTIM0_NOR_TAVDS_SHIFT)
+#define FTIM0_NOR_TEAHC_SHIFT		0
+#define FTIM0_NOR_TEAHC(n)		((n) << FTIM0_NOR_TEAHC_SHIFT)
+/*
+ * FTIM1 - NOR Flash Mode
+ */
+#define FTIM1_NOR			0xFF003F3F
+#define FTIM1_NOR_TACO_SHIFT		24
+#define FTIM1_NOR_TACO(n)		((n) << FTIM1_NOR_TACO_SHIFT)
+#define FTIM1_NOR_TRAD_NOR_SHIFT	8
+#define FTIM1_NOR_TRAD_NOR(n)		((n) << FTIM1_NOR_TRAD_NOR_SHIFT)
+#define FTIM1_NOR_TSEQRAD_NOR_SHIFT	0
+#define FTIM1_NOR_TSEQRAD_NOR(n)	((n) << FTIM1_NOR_TSEQRAD_NOR_SHIFT)
+/*
+ * FTIM2 - NOR Flash Mode
+ */
+#define FTIM2_NOR			0x0F3CFCFF
+#define FTIM2_NOR_TCS_SHIFT		24
+#define FTIM2_NOR_TCS(n)		((n) << FTIM2_NOR_TCS_SHIFT)
+#define FTIM2_NOR_TCH_SHIFT		18
+#define FTIM2_NOR_TCH(n)		((n) << FTIM2_NOR_TCH_SHIFT)
+#define FTIM2_NOR_TWPH_SHIFT		10
+#define FTIM2_NOR_TWPH(n)		((n) << FTIM2_NOR_TWPH_SHIFT)
+#define FTIM2_NOR_TWP_SHIFT		0
+#define FTIM2_NOR_TWP(n)		((n) << FTIM2_NOR_TWP_SHIFT)
+
+/*
+ * FTIM0 - Normal GPCM Mode
+ */
+#define FTIM0_GPCM			0xF03F3F3F
+#define FTIM0_GPCM_TACSE_SHIFT		28
+#define FTIM0_GPCM_TACSE(n)		((n) << FTIM0_GPCM_TACSE_SHIFT)
+#define FTIM0_GPCM_TEADC_SHIFT		16
+#define FTIM0_GPCM_TEADC(n)		((n) << FTIM0_GPCM_TEADC_SHIFT)
+#define FTIM0_GPCM_TAVDS_SHIFT		8
+#define FTIM0_GPCM_TAVDS(n)		((n) << FTIM0_GPCM_TAVDS_SHIFT)
+#define FTIM0_GPCM_TEAHC_SHIFT		0
+#define FTIM0_GPCM_TEAHC(n)		((n) << FTIM0_GPCM_TEAHC_SHIFT)
+/*
+ * FTIM1 - Normal GPCM Mode
+ */
+#define FTIM1_GPCM			0xFF003F00
+#define FTIM1_GPCM_TACO_SHIFT		24
+#define FTIM1_GPCM_TACO(n)		((n) << FTIM1_GPCM_TACO_SHIFT)
+#define FTIM1_GPCM_TRAD_SHIFT		8
+#define FTIM1_GPCM_TRAD(n)		((n) << FTIM1_GPCM_TRAD_SHIFT)
+/*
+ * FTIM2 - Normal GPCM Mode
+ */
+#define FTIM2_GPCM			0x0F3C00FF
+#define FTIM2_GPCM_TCS_SHIFT		24
+#define FTIM2_GPCM_TCS(n)		((n) << FTIM2_GPCM_TCS_SHIFT)
+#define FTIM2_GPCM_TCH_SHIFT		18
+#define FTIM2_GPCM_TCH(n)		((n) << FTIM2_GPCM_TCH_SHIFT)
+#define FTIM2_GPCM_TWP_SHIFT		0
+#define FTIM2_GPCM_TWP(n)		((n) << FTIM2_GPCM_TWP_SHIFT)
+
+/*
+ * General Control Register (GCR)
+ */
+#define IFC_GCR_MASK			0x8000F800
+/* reset all IFC hardware */
+#define IFC_GCR_SOFT_RST_ALL		0x80000000
+/* Turnaroud Time of external buffer */
+#define IFC_GCR_TBCTL_TRN_TIME		0x0000F800
+#define IFC_GCR_TBCTL_TRN_TIME_SHIFT	11
+
+/*
+ * Clock Control Register (CCR)
+ */
+#define IFC_CCR_MASK			0x0F0F8800
+/* Clock division ratio */
+#define IFC_CCR_CLK_DIV_MASK		0x0F000000
+#define IFC_CCR_CLK_DIV_SHIFT		24
+#define IFC_CCR_CLK_DIV(n)		((n-1) << IFC_CCR_CLK_DIV_SHIFT)
+/* IFC Clock Delay */
+#define IFC_CCR_CLK_DLY_MASK		0x000F0000
+#define IFC_CCR_CLK_DLY_SHIFT		16
+#define IFC_CCR_CLK_DLY(n)		((n) << IFC_CCR_CLK_DLY_SHIFT)
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+#define FSL_IFC_CSPRX(i)	(0x10 + ((i) * 0xc))
+#define FSL_IFC_CSORX(i)	(0x130 + ((i) * 0xc))
+#define FSL_IFC_CSORX_EXT(i)	(0x134 + ((i) * 0xc))
+#define FSL_IFC_AMASKX(i)	(0xa0 + ((i) * 0xc))
+#define FSL_IFC_CSX_FTIMY(i, j)	((0x1c0 + ((i) * 0x30)) + ((j) * 4))
+
+#define get_ifc_cspr(base, i) (ifc_in32(base + FSL_IFC_CSPRX(i)))
+#define get_ifc_csor(base, i) (ifc_in32(base + FSL_IFC_CSORX(i)))
+#define get_ifc_csor_ext(base, i) (ifc_in32(base + FSL_IFC_CSORX_EXT(i)))
+#define get_ifc_amask(base, i) (ifc_in32(base + FSL_IFC_AMASKX(i)))
+#define get_ifc_ftim(base, i, j) (ifc_in32(base + FSL_IFC_CSX_FTIMY(i, j)))
+
+#define set_ifc_cspr(base, i, v) (ifc_out32(base + FSL_IFC_CSPRX(i), v))
+#define set_ifc_csor(base, i, v) (ifc_out32(base + FSL_IFC_CSORX(i), v))
+#define set_ifc_csor_ext(base, i, v) (ifc_out32(base + FSL_IFC_CSORX_EXT(i),\
+				v))
+#define set_ifc_amask(base, i, v) (ifc_out32(base + FSL_IFC_AMASKX(i), v))
+#define set_ifc_ftim(base, i, j, v) \
+			(ifc_out32(base + FSL_IFC_CSX_FTIMY(i, j), v))
+
+#define FSL_IFC_GCR_OFFSET	0x40c
+#define FSL_IFC_CCR_OFFSET	0x44c
+
+enum ifc_chip_sel {
+	IFC_CS0,
+	IFC_CS1,
+	IFC_CS2,
+	IFC_CS3,
+	IFC_CS4,
+	IFC_CS5,
+	IFC_CS6,
+	IFC_CS7,
+};
+
+enum ifc_ftims {
+	IFC_FTIM0,
+	IFC_FTIM1,
+	IFC_FTIM2,
+	IFC_FTIM3,
+};
+
+#ifdef CONFIG_FSL_ERRATUM_IFC_A002769
+#undef CSPR_MSEL_NOR
+#define CSPR_MSEL_NOR	CSPR_MSEL_GPCM
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __FSL_IFC_H */
-- 
2.27.0



From m.felsch at pengutronix.de  Fri Aug 13 01:32:21 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Fri, 13 Aug 2021 10:32:21 +0200
Subject: [PATCH] fastboot net: add setter for global.fastboot.net.autostart
Message-ID: <20210813083221.31763-1-m.felsch@pengutronix.de>

Without this change the only possible way to start the
fastboot.net.autostart mechanism is by using the nv storage. Split
fastboot_on_boot() into two functions:
 - a globalvar setter fastboot_net_autostart_set() and
 - a the globalvar init function fastboot_net_init_globalvar().
This allows init scripts to start the autostart mechanism as well.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 net/fastboot.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/net/fastboot.c b/net/fastboot.c
index df388adc89..aa483f57a7 100644
--- a/net/fastboot.c
+++ b/net/fastboot.c
@@ -547,14 +547,12 @@ fail_generic_init:
 static struct fastboot_net *fastboot_net_obj;
 static int fastboot_net_autostart;
 
-static int fastboot_on_boot(void)
+static int fastboot_net_autostart_set(struct param_d *p, void * priv)
 {
 	struct fastboot_net *fbn;
+	static bool started;
 
-	globalvar_add_simple_bool("fastboot.net.autostart",
-				  &fastboot_net_autostart);
-
-	if (!fastboot_net_autostart)
+	if (!fastboot_net_autostart || started)
 		return 0;
 
 	ifup_all(0);
@@ -564,16 +562,25 @@ static int fastboot_on_boot(void)
 		return PTR_ERR(fbn);
 
 	fastboot_net_obj = fbn;
+	started = true;
+
 	return 0;
 }
 
+static int fastboot_net_init_globalvar(void)
+{
+	return globalvar_add_bool("fastboot.net.autostart",
+				  fastboot_net_autostart_set,
+				  &fastboot_net_autostart, NULL);
+}
+
 static void fastboot_net_exit(void)
 {
 	if (fastboot_net_obj)
 		fastboot_net_free(fastboot_net_obj);
 }
 
-postenvironment_initcall(fastboot_on_boot);
+postenvironment_initcall(fastboot_net_init_globalvar);
 predevshutdown_exitcall(fastboot_net_exit);
 
 BAREBOX_MAGICVAR(global.fastboot.net.autostart,
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Aug 13 01:38:28 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 13 Aug 2021 10:38:28 +0200
Subject: [PATCH] fastboot net: add setter for global.fastboot.net.autostart
In-Reply-To: <20210813083221.31763-1-m.felsch@pengutronix.de>
References: <20210813083221.31763-1-m.felsch@pengutronix.de>
Message-ID: <ab106998-cb7b-16cc-ad30-29fd29831075@pengutronix.de>

On 13.08.21 10:32, Marco Felsch wrote:
> Without this change the only possible way to start the
> fastboot.net.autostart mechanism is by using the nv storage. Split
> fastboot_on_boot() into two functions:
>  - a globalvar setter fastboot_net_autostart_set() and
>  - a the globalvar init function fastboot_net_init_globalvar().
> This allows init scripts to start the autostart mechanism as well.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> ---
>  net/fastboot.c | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)
> 
> diff --git a/net/fastboot.c b/net/fastboot.c
> index df388adc89..aa483f57a7 100644
> --- a/net/fastboot.c
> +++ b/net/fastboot.c
> @@ -547,14 +547,12 @@ fail_generic_init:
>  static struct fastboot_net *fastboot_net_obj;
>  static int fastboot_net_autostart;
>  
> -static int fastboot_on_boot(void)
> +static int fastboot_net_autostart_set(struct param_d *p, void * priv)
>  {
>  	struct fastboot_net *fbn;
> +	static bool started;
>  
> -	globalvar_add_simple_bool("fastboot.net.autostart",
> -				  &fastboot_net_autostart);
> -
> -	if (!fastboot_net_autostart)
> +	if (!fastboot_net_autostart || started)
>  		return 0;
>  
>  	ifup_all(0);
> @@ -564,16 +562,25 @@ static int fastboot_on_boot(void)
>  		return PTR_ERR(fbn);
>  
>  	fastboot_net_obj = fbn;
> +	started = true;
> +
>  	return 0;
>  }
>  
> +static int fastboot_net_init_globalvar(void)
> +{
> +	return globalvar_add_bool("fastboot.net.autostart",
> +				  fastboot_net_autostart_set,
> +				  &fastboot_net_autostart, NULL);
> +}
> +
>  static void fastboot_net_exit(void)
>  {
>  	if (fastboot_net_obj)
>  		fastboot_net_free(fastboot_net_obj);
>  }
>  
> -postenvironment_initcall(fastboot_on_boot);
> +postenvironment_initcall(fastboot_net_init_globalvar);
>  predevshutdown_exitcall(fastboot_net_exit);
>  
>  BAREBOX_MAGICVAR(global.fastboot.net.autostart,
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From u.kleine-koenig at pengutronix.de  Fri Aug 13 07:03:52 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Fri, 13 Aug 2021 16:03:52 +0200
Subject: [PATCH] mci: imx-esdhc-pbl: Fix two typos in a comment
Message-ID: <20210813140352.13233-1-u.kleine-koenig@pengutronix.de>

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/mci/imx-esdhc-pbl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index d7136f54922c..b253673dfe1d 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -143,8 +143,8 @@ esdhc_load_image(struct fsl_esdhc_host *host, ptrdiff_t address,
 		 *
 		 *     buf + ofs = entry
 		 *
-		 * solving the above for 'buf' gvies us the
-		 * adjustement that needs to be made:
+		 * solving the above for 'buf' gives us the
+		 * adjustment that needs to be made:
 		 *
 		 *     buf = entry - ofs
 		 *

base-commit: 72424fd057d135ec0e41139fe4cb5740471d33a5
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Fri Aug 13 08:22:42 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Fri, 13 Aug 2021 17:22:42 +0200
Subject: [PATCH v2 0/3] Support usb booting on i.MX8MP
Message-ID: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>

Hello,

compared to (implicit) v1, the following changed here:

 - be a bit more conservative in "imx-usb-loader: Add support for
   i.MX8MP" regarding last_transfer; feedback by Sascha Hauer

 - Add support in PBL to be actually booted using imx-usb-loader (only
   tested the vendor U-Boot for v1), also skip the barebox header (i.e.
   the first (usually) 0x8000 bytes) before the IVT header on uploadeing

There are two things that resulted in discussions between Lucas, Ahmad
and me during development of this series:

 - On i.MX8MM and i.MX8MQ after the PBL is uploaded it's followed up by
   the complete image. So the PBL is uploaded twice. The motivation for
   this behaviour was that when booting from MMC loading from offset 0
   is easier because depending on the mode the hardware is in the offset
   has to be specified in different ways. So to make the two modes more
   similar the PBL is loaded twice for both modes.

   Here however after the PBL only the piggy data is sent because it
   feels wrong for me to spend some extra effort in imx-usb-loader to do
   a kludge for USB just because there are some difficulties with MMC.

   Arguments for this choice (apart from that already being completed
   and tested :-) are:

   - No duplication of data that is overwritten anyhow
   - Better interoperability with U-Boot/mfg-tools
     While this is usually not our focus I consider it quite annoying
     that there are at least three implementations of imx-usb-loader and
     depending on which machine and bootloader you use you have to pick
     the right implementation. With the longterm goal to have
     imx-usb-loader and barebox available in Debian some
     interoperability would be nice.

   I quickly tried using the boot rom load image support when booting
   from SD, but it didn't work out of the box and I didn't debug that.
   However I imagine that in this mode it would also be more natural to
   not expect the PBL twice.

   Switching to the duplicated operation mode would make imx-usb-loader
   a bit more complicated (because in the MXS code path the duplication
   isn't available yet), in return we'd save an offset calculation in
   the PBL.

   I should be possible to look at the first post-PBL data chunk coming
   in via USB and judge which mode of operation is used and behave
   accordingly. If this is considered a good idea I can create a patch
   for that.

 - When booting via USB the boot source is identified as "serial". I
   would expect that the semantic of that is rs232 and not USB. The
   source of this confusion is probably that the Reference Manual calls
   the USB  boot mode "USB Serial Download boot". I stuck to
   BOOTSOURCE_SERIAL here for consistency. If it's not only me who would
   consider using BOOTSOURCE_USB instead a fix this should be changed
   consistently for all i.MX platforms.
   Ahmad pointed out that this might break barebox shell scripts.

Uwe Kleine-K?nig (3):
  imx8mp-evk: Add support for booting via USB
  imx-usb-loader: Drop nearly unused struct usb_id
  imx-usb-loader: Add support for i.MX8MP

 arch/arm/boards/nxp-imx8mp-evk/lowlevel.c |  27 +++++
 arch/arm/mach-imx/boot.c                  |   4 +-
 include/asm-generic/sections.h            |   1 +
 scripts/imx/imx-usb-loader.c              | 131 ++++++++++++----------
 4 files changed, 103 insertions(+), 60 deletions(-)


base-commit: 72424fd057d135ec0e41139fe4cb5740471d33a5
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Fri Aug 13 08:22:43 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Fri, 13 Aug 2021 17:22:43 +0200
Subject: [PATCH v2 1/3] imx8mp-evk: Add support for booting via USB
In-Reply-To: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210813152245.15841-2-u.kleine-koenig@pengutronix.de>

---
 arch/arm/boards/nxp-imx8mp-evk/lowlevel.c | 27 +++++++++++++++++++++++
 arch/arm/mach-imx/boot.c                  |  4 +++-
 include/asm-generic/sections.h            |  1 +
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
index 3298ded5866d..1fb7899198d6 100644
--- a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
+++ b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
@@ -99,6 +99,30 @@ static int power_init_board(void)
 	return 0;
 }
 
+/* read piggydata via a bootrom callback and place it behind our copy in SDRAM */
+static int imx8m_bootrom_load_image(void)
+{
+	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor) = *(void **)0x988;
+	size_t count = __piggydata_end - __piggydata_start;
+	char *p = (char *)MX8M_ATF_BL33_BASE_ADDR + (__piggydata_start - __image_start);
+
+	while (count) {
+		size_t chunksize = min(count, (size_t)1024);
+		int ret;
+
+		ret = download_image(p, 0, chunksize, (uintptr_t)p ^ chunksize);
+		if (ret != 0xf0) {
+			pr_err("Failed to load piggy data (ret = %x)\n", ret);
+			return -EIO;
+		}
+
+		p += chunksize;
+		count -= chunksize;
+	}
+
+	return 0;
+}
+
 extern struct dram_timing_info imx8mp_evk_dram_timing;
 
 static void start_atf(void)
@@ -125,6 +149,9 @@ static void start_atf(void)
 	case BOOTSOURCE_MMC:
 		imx8mp_esdhc_load_image(instance, false);
 		break;
+	case BOOTSOURCE_SERIAL:
+		imx8m_bootrom_load_image();
+		break;
 	default:
 		printf("Unhandled bootsource BOOTSOURCE_%d\n", src);
 		hang();
diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 2b66bbf71eb1..7c1d49291045 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -495,10 +495,12 @@ static void __imx7_get_boot_source(enum bootsource *src, int *instance,
 	case 5:
 		*src = BOOTSOURCE_NOR;
 		break;
-	case 15:
+	case 14: /* observed on i.MX8MP for USB "serial" booting */
+	case 15: /* observed on i.MX8MM for USB "serial" booting */
 		*src = BOOTSOURCE_SERIAL;
 		break;
 	default:
+		*src = BOOTSOURCE_UNKNOWN;
 		break;
 	}
 }
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 870bff21f668..597c4951ea5e 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -9,6 +9,7 @@ extern char _end[];
 extern char __image_start[];
 extern char __image_end[];
 extern char __piggydata_start[];
+extern char __piggydata_end[];
 extern void *_barebox_image_size;
 extern void *_barebox_bare_init_size;
 extern void *_barebox_pbl_size;
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Fri Aug 13 08:22:45 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Fri, 13 Aug 2021 17:22:45 +0200
Subject: [PATCH v2 3/3] imx-usb-loader: Add support for i.MX8MP
In-Reply-To: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210813152245.15841-4-u.kleine-koenig@pengutronix.de>

The i.MX8MP uses a protocol similar to the MXS. The relevant differences
are:

 - Maximal transfer size is 1020
 - HID reports must be sent to EP1 instead of using a control transfer
 - The FW_DOWNLOAD command must not be send.
 - The image to upload must start with the IVT header (usually at offset
   0x8000), so the barebox header isn't transferred.

Signed-off-by: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
---
 scripts/imx/imx-usb-loader.c | 80 +++++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 25 deletions(-)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 3e96c86f2f29..cf87e0f91d65 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -71,6 +71,7 @@ struct mach_id {
 #define DEV_IMX		0
 #define DEV_MXS		1
 	unsigned char dev_type;
+	unsigned char hid_endpoint;
 };
 
 struct usb_work {
@@ -177,6 +178,14 @@ static const struct mach_id imx_ids[] = {
 		.header_type = HDR_MX53,
 		.mode = MODE_HID,
 		.max_transfer = 1024,
+	}, {
+		.vid = 0x1fc9,
+		.pid = 0x0146,
+		.name = "i.MX8MP",
+		.header_type = HDR_MX53,
+		.max_transfer = 1020,
+		.dev_type = DEV_MXS,
+		.hid_endpoint = 1,
 	}, {
 		.vid = 0x1fc9,
 		.pid = 0x012b,
@@ -522,15 +531,22 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
 
 		if (report < 3) {
 			memcpy(&tmp[1], p, cnt);
-			err = libusb_control_transfer(usb_dev_handle,
-					CTRL_OUT,
-					HID_SET_REPORT,
-					(HID_REPORT_TYPE_OUTPUT << 8) | report,
-					0,
-					tmp, cnt + 1, 1000);
-			*last_trans = (err > 0) ? err - 1 : 0;
-			if (err > 0)
-				err = 0;
+			if (mach_id->hid_endpoint) {
+				int trans;
+				err = libusb_interrupt_transfer(usb_dev_handle,
+						mach_id->hid_endpoint, tmp, cnt + 1, &trans, 1000);
+				*last_trans = trans - 1;
+			} else {
+				err = libusb_control_transfer(usb_dev_handle,
+						CTRL_OUT,
+						HID_SET_REPORT,
+						(HID_REPORT_TYPE_OUTPUT << 8) | report,
+						0,
+						tmp, cnt + 1, 1000);
+				*last_trans = (err > 0) ? err - 1 : 0;
+				if (err > 0)
+					err = 0;
+			}
 		} else {
 			*last_trans = 0;
 			memset(&tmp[1], 0, cnt);
@@ -1500,32 +1516,46 @@ static int write_mem(const struct config_data *data, uint32_t addr,
 }
 
 /* MXS section */
-static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size)
+static int mxs_load_file(struct usb_work *curr, libusb_device_handle *dev, uint8_t *data, int size)
 {
 	static struct mxs_command dl_command;
 	int last_trans, err;
 	void *p;
 	int cnt;
 
-	dl_command.sign = htonl(0x424c5443); /* Signature: BLTC */
-	dl_command.tag = htonl(0x1);
-	dl_command.size = htonl(size);
-	dl_command.flags = 0;
-	dl_command.rsvd[0] = 0;
-	dl_command.rsvd[1] = 0;
-	dl_command.cmd = MXS_CMD_FW_DOWNLOAD;
-	dl_command.dw_size = htonl(size);
-
-	err = transfer(1, (unsigned char *) &dl_command, 20, &last_trans);
-	if (err) {
-		printf("transfer error at init step: err=%i, last_trans=%i\n",
-		       err, last_trans);
-		return err;
+	if (!mach_id->hid_endpoint) {
+		dl_command.sign = htonl(0x424c5443); /* Signature: BLTC */
+		dl_command.tag = htonl(0x1);
+		dl_command.size = htonl(size);
+		dl_command.flags = 0;
+		dl_command.rsvd[0] = 0;
+		dl_command.rsvd[1] = 0;
+		dl_command.cmd = MXS_CMD_FW_DOWNLOAD;
+		dl_command.dw_size = htonl(size);
+
+		err = transfer(1, (unsigned char *) &dl_command, 20, &last_trans);
+		if (err) {
+			printf("transfer error at init step: err=%i, last_trans=%i\n",
+					err, last_trans);
+			return err;
+		}
 	}
 
 	p = data;
 	cnt = size;
 
+	if (mach_id->header_type != HDR_NONE) {
+		unsigned int dummy;
+		err = process_header(curr, p, cnt, &dummy, &dummy, &dummy);
+		if (err < 0) {
+			printf("Failed to find IVT header\n");
+			return err;
+		}
+
+		p += err;
+		cnt -= err;
+	}
+
 	while (1) {
 		int now = get_min(cnt, mach_id->max_transfer);
 
@@ -1555,7 +1585,7 @@ static int mxs_work(struct usb_work *curr)
 	if (ret < 0)
 		return ret;
 
-	return mxs_load_file(usb_dev_handle, buf, fsize);
+	return mxs_load_file(curr, usb_dev_handle, buf, fsize);
 }
 /* end of mxs section */
 
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Fri Aug 13 08:22:44 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Fri, 13 Aug 2021 17:22:44 +0200
Subject: [PATCH v2 2/3] imx-usb-loader: Drop nearly unused struct usb_id
In-Reply-To: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210813152245.15841-3-u.kleine-koenig@pengutronix.de>

Only one of the two members of struct usb_id is actually used. So
replace struct usb_id by a struct mach_id.

Signed-off-by: Uwe Kleine-Koenig <u.kleine-koenig at pengutronix.de>
---
 scripts/imx/imx-usb-loader.c | 51 ++++++++++++------------------------
 1 file changed, 17 insertions(+), 34 deletions(-)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index cff77f27f264..3e96c86f2f29 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -52,7 +52,7 @@
 
 int verbose;
 static struct libusb_device_handle *usb_dev_handle;
-static struct usb_id *usb_id;
+static const struct mach_id *mach_id;
 
 struct mach_id {
 	struct mach_id * next;
@@ -79,11 +79,6 @@ struct usb_work {
 	unsigned char plug;
 };
 
-struct usb_id {
-	const struct mach_id *mach_id;
-	struct usb_work *work;
-};
-
 static const struct mach_id imx_ids[] = {
 	{
 		.vid = 0x066f,
@@ -507,8 +502,8 @@ static int read_file(const char *name, unsigned char **buffer, unsigned *size)
 static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
 {
 	int err;
-	if (cnt > usb_id->mach_id->max_transfer)
-		cnt = usb_id->mach_id->max_transfer;
+	if (cnt > mach_id->max_transfer)
+		cnt = mach_id->max_transfer;
 
 	if (verbose > 4) {
 		printf("report=%i\n", report);
@@ -516,7 +511,7 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
 			dump_bytes(p, cnt, 0);
 	}
 
-	if (usb_id->mach_id->mode == MODE_BULK) {
+	if (mach_id->mode == MODE_BULK) {
 		*last_trans = 0;
 		err = libusb_bulk_transfer(usb_dev_handle,
 					   (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
@@ -602,7 +597,7 @@ static int do_status(void)
 			break;
 	}
 
-	if (usb_id->mach_id->mode == MODE_HID) {
+	if (mach_id->mode == MODE_HID) {
 		err = transfer(4, tmp, sizeof(tmp), &last_trans);
 		if (err)
 			printf("4 in err=%i, last_trans=%i  %02x %02x %02x %02x\n",
@@ -810,7 +805,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
 
 	retry = 0;
 
-	if (usb_id->mach_id->mode == MODE_BULK) {
+	if (mach_id->mode == MODE_BULK) {
 		err = transfer(3, tmp, sizeof(tmp), &last_trans);
 		if (err)
 			printf("in err=%i, last_trans=%i  %02x %02x %02x %02x\n",
@@ -821,7 +816,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
 	cnt = len;
 
 	while (1) {
-		int now = get_min(cnt, usb_id->mach_id->max_transfer);
+		int now = get_min(cnt, mach_id->max_transfer);
 
 		if (!now)
 			break;
@@ -839,7 +834,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr,
 	if (mode_barebox)
 		return transfer_size;
 
-	if (usb_id->mach_id->mode == MODE_HID) {
+	if (mach_id->mode == MODE_HID) {
 		err = transfer(3, tmp, sizeof(tmp), &last_trans);
 		if (err)
 			printf("3 in err=%i, last_trans=%i  %02x %02x %02x %02x\n",
@@ -1233,7 +1228,7 @@ static int is_header(const unsigned char *p)
 	const struct imx_flash_header_v2 *hdr =
 		(const struct imx_flash_header_v2 *)p;
 
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 		if (ohdr->app_code_barker == 0xb1)
 			return 1;
@@ -1253,7 +1248,7 @@ static int perform_dcd(unsigned char *p, const unsigned char *file_start,
 	struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
 	int ret = 0;
 
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 		ret = write_dcd_table_old(ohdr, file_start, cnt);
 		ohdr->dcd_block_len = 0;
@@ -1274,7 +1269,7 @@ static int get_dl_start(const unsigned char *p, const unsigned char *file_start,
 		unsigned *header_addr)
 {
 	const unsigned char *file_end = file_start + cnt;
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 	{
 		struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
@@ -1315,7 +1310,7 @@ static int get_payload_start(const unsigned char *p, uint32_t *ofs)
 {
 	struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
 
-	switch (usb_id->mach_id->header_type) {
+	switch (mach_id->header_type) {
 	case HDR_MX51:
 		return -EINVAL;
 
@@ -1430,7 +1425,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
 
 		memcpy(verify_buffer, image, 64);
 
-		if ((type == FT_APP) && (usb_id->mach_id->mode != MODE_HID)) {
+		if ((type == FT_APP) && (mach_id->mode != MODE_HID)) {
 			type = FT_LOAD_ONLY;
 			verify = 2;
 		}
@@ -1469,7 +1464,7 @@ static int do_irom_download(struct usb_work *curr, int verify)
 		}
 	}
 
-	if (usb_id->mach_id->mode == MODE_HID && type == FT_APP) {
+	if (mach_id->mode == MODE_HID && type == FT_APP) {
 		printf("jumping to 0x%08x\n", header_addr);
 
 		ret = sdp_jump_address(header_addr);
@@ -1532,7 +1527,7 @@ static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size)
 	cnt = size;
 
 	while (1) {
-		int now = get_min(cnt, usb_id->mach_id->max_transfer);
+		int now = get_min(cnt, mach_id->max_transfer);
 
 		if (!now)
 			break;
@@ -1591,7 +1586,6 @@ static void usage(const char *prgname)
 
 int main(int argc, char *argv[])
 {
-	const struct mach_id *mach;
 	libusb_device **devs;
 	libusb_device *dev;
 	int r;
@@ -1663,7 +1657,7 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
-	dev = find_imx_dev(devs, &mach, devpath, devtype);
+	dev = find_imx_dev(devs, &mach_id, devpath, devtype);
 	if (!dev) {
 		fprintf(stderr, "no supported device found\n");
 		goto out;
@@ -1682,15 +1676,7 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
-	usb_id = malloc(sizeof(*usb_id));
-	if (!usb_id) {
-		perror("malloc");
-		exit(1);
-	}
-
-	usb_id->mach_id = mach;
-
-	if (mach->dev_type == DEV_MXS) {
+	if (mach_id->dev_type == DEV_MXS) {
 		ret = mxs_work(&w);
 		goto out;
 	}
@@ -1715,9 +1701,6 @@ int main(int argc, char *argv[])
 
 	ret = 0;
 out:
-	if (usb_id)
-		free(usb_id);
-
 	if (usb_dev_handle)
 		libusb_close(usb_dev_handle);
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Aug 13 12:26:45 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 13 Aug 2021 21:26:45 +0200
Subject: [PATCH v2 1/3] imx8mp-evk: Add support for booting via USB
In-Reply-To: <20210813152245.15841-2-u.kleine-koenig@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
 <20210813152245.15841-2-u.kleine-koenig@pengutronix.de>
Message-ID: <af0950b3-33fc-b36a-ad70-055e9af7acf2@pengutronix.de>

On 13.08.21 17:22, Uwe Kleine-K?nig wrote:

S-o-b missing.

> ---
>  arch/arm/boards/nxp-imx8mp-evk/lowlevel.c | 27 +++++++++++++++++++++++
>  arch/arm/mach-imx/boot.c                  |  4 +++-
>  include/asm-generic/sections.h            |  1 +
>  3 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
> index 3298ded5866d..1fb7899198d6 100644
> --- a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
> +++ b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
> @@ -99,6 +99,30 @@ static int power_init_board(void)
>  	return 0;
>  }
>  
> +/* read piggydata via a bootrom callback and place it behind our copy in SDRAM */
> +static int imx8m_bootrom_load_image(void)
> +{
> +	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor) = *(void **)0x988;

Would be nice to have this in a header, e.g.

extern struct imx8mp_bootrom_ops {
	/* ... */
	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor);
} *imx8mp_bootrom_ops = (void *)0x988;

> +	size_t count = __piggydata_end - __piggydata_start;
> +	char *p = (char *)MX8M_ATF_BL33_BASE_ADDR + (__piggydata_start - __image_start);
> +
> +	while (count) {
> +		size_t chunksize = min(count, (size_t)1024);
> +		int ret;
> +
> +		ret = download_image(p, 0, chunksize, (uintptr_t)p ^ chunksize);
> +		if (ret != 0xf0) {
> +			pr_err("Failed to load piggy data (ret = %x)\n", ret);
> +			return -EIO;
> +		}
> +
> +		p += chunksize;
> +		count -= chunksize;
> +	}
> +
> +	return 0;
> +}
> +
>  extern struct dram_timing_info imx8mp_evk_dram_timing;
>  
>  static void start_atf(void)
> @@ -125,6 +149,9 @@ static void start_atf(void)
>  	case BOOTSOURCE_MMC:
>  		imx8mp_esdhc_load_image(instance, false);
>  		break;
> +	case BOOTSOURCE_SERIAL:
> +		imx8m_bootrom_load_image();
> +		break;
>  	default:
>  		printf("Unhandled bootsource BOOTSOURCE_%d\n", src);
>  		hang();
> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> index 2b66bbf71eb1..7c1d49291045 100644
> --- a/arch/arm/mach-imx/boot.c
> +++ b/arch/arm/mach-imx/boot.c
> @@ -495,10 +495,12 @@ static void __imx7_get_boot_source(enum bootsource *src, int *instance,
>  	case 5:
>  		*src = BOOTSOURCE_NOR;
>  		break;
> -	case 15:
> +	case 14: /* observed on i.MX8MP for USB "serial" booting */
> +	case 15: /* observed on i.MX8MM for USB "serial" booting */
>  		*src = BOOTSOURCE_SERIAL;
>  		break;
>  	default:
> +		*src = BOOTSOURCE_UNKNOWN;
>  		break;
>  	}
>  }
> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> index 870bff21f668..597c4951ea5e 100644
> --- a/include/asm-generic/sections.h
> +++ b/include/asm-generic/sections.h
> @@ -9,6 +9,7 @@ extern char _end[];
>  extern char __image_start[];
>  extern char __image_end[];
>  extern char __piggydata_start[];
> +extern char __piggydata_end[];

Other code normally uses __image_end, but it seems __piggydata_end should be
equal to it. I'd prefer __image_end, because conceptually, you want to copy
off the rest of the image (which happens to be just the piggy data)

@Rouven, The sha sum is at the end of the image, right?
Would this be included this way?

>  extern void *_barebox_image_size;
>  extern void *_barebox_bare_init_size;
>  extern void *_barebox_pbl_size;
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From l.stach at pengutronix.de  Fri Aug 13 13:20:27 2021
From: l.stach at pengutronix.de (Lucas Stach)
Date: Fri, 13 Aug 2021 22:20:27 +0200
Subject: [PATCH v2 1/3] imx8mp-evk: Add support for booting via USB
In-Reply-To: <af0950b3-33fc-b36a-ad70-055e9af7acf2@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
 <20210813152245.15841-2-u.kleine-koenig@pengutronix.de>
 <af0950b3-33fc-b36a-ad70-055e9af7acf2@pengutronix.de>
Message-ID: <d4c6f3b9bf69d4a220e9f2dc7a266eb98226398d.camel@pengutronix.de>

Am Freitag, dem 13.08.2021 um 21:26 +0200 schrieb Ahmad Fatoum:
> On 13.08.21 17:22, Uwe Kleine-K?nig wrote:
> 
> S-o-b missing.
> 
> > ---
> >  arch/arm/boards/nxp-imx8mp-evk/lowlevel.c | 27 +++++++++++++++++++++++
> >  arch/arm/mach-imx/boot.c                  |  4 +++-
> >  include/asm-generic/sections.h            |  1 +
> >  3 files changed, 31 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
> > index 3298ded5866d..1fb7899198d6 100644
> > --- a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
> > +++ b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
> > @@ -99,6 +99,30 @@ static int power_init_board(void)
> >  	return 0;
> >  }
> >  
> > +/* read piggydata via a bootrom callback and place it behind our copy in SDRAM */
> > +static int imx8m_bootrom_load_image(void)
> > +{
> > +	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor) = *(void **)0x988;
> 
> Would be nice to have this in a header, e.g.
> 
> extern struct imx8mp_bootrom_ops {
> 	/* ... */
> 	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor);
> } *imx8mp_bootrom_ops = (void *)0x988;
> 
> > +	size_t count = __piggydata_end - __piggydata_start;
> > +	char *p = (char *)MX8M_ATF_BL33_BASE_ADDR + (__piggydata_start - __image_start);
> > +
> > +	while (count) {
> > +		size_t chunksize = min(count, (size_t)1024);
> > +		int ret;
> > +
> > +		ret = download_image(p, 0, chunksize, (uintptr_t)p ^ chunksize);
> > +		if (ret != 0xf0) {
> > +			pr_err("Failed to load piggy data (ret = %x)\n", ret);
> > +			return -EIO;
> > +		}
> > +
> > +		p += chunksize;
> > +		count -= chunksize;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
This shouldn't be in board code, but in some location where it is
reusable by other i.MX8MP boards.

> >  extern struct dram_timing_info imx8mp_evk_dram_timing;
> >  
> >  static void start_atf(void)
> > @@ -125,6 +149,9 @@ static void start_atf(void)
> >  	case BOOTSOURCE_MMC:
> >  		imx8mp_esdhc_load_image(instance, false);
> >  		break;
> > +	case BOOTSOURCE_SERIAL:
> > +		imx8m_bootrom_load_image();
> > +		break;
> >  	default:
> >  		printf("Unhandled bootsource BOOTSOURCE_%d\n", src);
> >  		hang();
> > diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
> > index 2b66bbf71eb1..7c1d49291045 100644
> > --- a/arch/arm/mach-imx/boot.c
> > +++ b/arch/arm/mach-imx/boot.c
> > @@ -495,10 +495,12 @@ static void __imx7_get_boot_source(enum bootsource *src, int *instance,
> >  	case 5:
> >  		*src = BOOTSOURCE_NOR;
> >  		break;
> > -	case 15:
> > +	case 14: /* observed on i.MX8MP for USB "serial" booting */
> > +	case 15: /* observed on i.MX8MM for USB "serial" booting */
> >  		*src = BOOTSOURCE_SERIAL;
> >  		break;
> >  	default:
> > +		*src = BOOTSOURCE_UNKNOWN;
> >  		break;
> >  	}
> >  }
> > diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> > index 870bff21f668..597c4951ea5e 100644
> > --- a/include/asm-generic/sections.h
> > +++ b/include/asm-generic/sections.h
> > @@ -9,6 +9,7 @@ extern char _end[];
> >  extern char __image_start[];
> >  extern char __image_end[];
> >  extern char __piggydata_start[];
> > +extern char __piggydata_end[];
> 
> Other code normally uses __image_end, but it seems __piggydata_end should be
> equal to it. I'd prefer __image_end, because conceptually, you want to copy
> off the rest of the image (which happens to be just the piggy data)
> 
> @Rouven, The sha sum is at the end of the image, right?
> Would this be included this way?

The checksum is built into the PBL, as it is used to authenticate the
piggydata, as the BootROM will only authenticate the initial loaded
part of the image, i.e. the PBL.

Regards,
Lucas



From l.stach at pengutronix.de  Fri Aug 13 13:32:44 2021
From: l.stach at pengutronix.de (Lucas Stach)
Date: Fri, 13 Aug 2021 22:32:44 +0200
Subject: [PATCH v2 0/3] Support usb booting on i.MX8MP
In-Reply-To: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
Message-ID: <18eb76a0689a44244b81d33d3606cb48f9f447ff.camel@pengutronix.de>

Hi Uwe,

Am Freitag, dem 13.08.2021 um 17:22 +0200 schrieb Uwe Kleine-K?nig:
> Hello,
> 
> compared to (implicit) v1, the following changed here:
> 
>  - be a bit more conservative in "imx-usb-loader: Add support for
>    i.MX8MP" regarding last_transfer; feedback by Sascha Hauer
> 
>  - Add support in PBL to be actually booted using imx-usb-loader (only
>    tested the vendor U-Boot for v1), also skip the barebox header (i.e.
>    the first (usually) 0x8000 bytes) before the IVT header on uploadeing
> 
> There are two things that resulted in discussions between Lucas, Ahmad
> and me during development of this series:
> 
>  - On i.MX8MM and i.MX8MQ after the PBL is uploaded it's followed up by
>    the complete image. So the PBL is uploaded twice. The motivation for
>    this behaviour was that when booting from MMC loading from offset 0
>    is easier because depending on the mode the hardware is in the offset
>    has to be specified in different ways. So to make the two modes more
>    similar the PBL is loaded twice for both modes.
> 
>    Here however after the PBL only the piggy data is sent because it
>    feels wrong for me to spend some extra effort in imx-usb-loader to do
>    a kludge for USB just because there are some difficulties with MMC.
> 
>    Arguments for this choice (apart from that already being completed
>    and tested :-) are:
> 
>    - No duplication of data that is overwritten anyhow
>    - Better interoperability with U-Boot/mfg-tools
>      While this is usually not our focus I consider it quite annoying
>      that there are at least three implementations of imx-usb-loader and
>      depending on which machine and bootloader you use you have to pick
>      the right implementation. With the longterm goal to have
>      imx-usb-loader and barebox available in Debian some
>      interoperability would be nice.
> 
>    I quickly tried using the boot rom load image support when booting
>    from SD, but it didn't work out of the box and I didn't debug that.
>    However I imagine that in this mode it would also be more natural to
>    not expect the PBL twice.
> 
>    Switching to the duplicated operation mode would make imx-usb-loader
>    a bit more complicated (because in the MXS code path the duplication
>    isn't available yet), in return we'd save an offset calculation in
>    the PBL.

I can follow those arguments, but for the sake of the sanity of
everyone involved I would vote for changing the i.MX8MM USB loading to
work in the same way, maybe even using the ROM API if it works there
too. i.MX8MM isn't too widely used yet, so I guess we can still change
it without inflicting too much incompatibility pain.

The i.MX8M* Barebox lowlevel flow is already quite delicate, so I would
rather avoid having to deal with subtle differences between the various
family members.

> 
>    I should be possible to look at the first post-PBL data chunk coming
>    in via USB and judge which mode of operation is used and behave
>    accordingly. If this is considered a good idea I can create a patch
>    for that.
> 
>  - When booting via USB the boot source is identified as "serial". I
>    would expect that the semantic of that is rs232 and not USB. The
>    source of this confusion is probably that the Reference Manual calls
>    the USB  boot mode "USB Serial Download boot". I stuck to
>    BOOTSOURCE_SERIAL here for consistency. If it's not only me who would
>    consider using BOOTSOURCE_USB instead a fix this should be changed
>    consistently for all i.MX platforms.
>    Ahmad pointed out that this might break barebox shell scripts.

This however sounds like breaking backwards compat for no real gain. As
even the reference manual calls this boot mode "serial" I always found
this quite clear. My vote is on keeping things as they are.

Regards,
Lucas

> 
> Uwe Kleine-K?nig (3):
>   imx8mp-evk: Add support for booting via USB
>   imx-usb-loader: Drop nearly unused struct usb_id
>   imx-usb-loader: Add support for i.MX8MP
> 
>  arch/arm/boards/nxp-imx8mp-evk/lowlevel.c |  27 +++++
>  arch/arm/mach-imx/boot.c                  |   4 +-
>  include/asm-generic/sections.h            |   1 +
>  scripts/imx/imx-usb-loader.c              | 131 ++++++++++++----------
>  4 files changed, 103 insertions(+), 60 deletions(-)
> 
> 
> base-commit: 72424fd057d135ec0e41139fe4cb5740471d33a5




From a.fatoum at pengutronix.de  Fri Aug 13 13:48:13 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 13 Aug 2021 22:48:13 +0200
Subject: [PATCH v2 1/3] imx8mp-evk: Add support for booting via USB
In-Reply-To: <d4c6f3b9bf69d4a220e9f2dc7a266eb98226398d.camel@pengutronix.de>
References: <20210813152245.15841-1-u.kleine-koenig@pengutronix.de>
 <20210813152245.15841-2-u.kleine-koenig@pengutronix.de>
 <af0950b3-33fc-b36a-ad70-055e9af7acf2@pengutronix.de>
 <d4c6f3b9bf69d4a220e9f2dc7a266eb98226398d.camel@pengutronix.de>
Message-ID: <52f51db6-252b-ff94-ec0e-3c79b7785158@pengutronix.de>

On 13.08.21 22:20, Lucas Stach wrote:
> Am Freitag, dem 13.08.2021 um 21:26 +0200 schrieb Ahmad Fatoum:
>> On 13.08.21 17:22, Uwe Kleine-K?nig wrote:
>>
>> S-o-b missing.
>>
>>> ---
>>>  arch/arm/boards/nxp-imx8mp-evk/lowlevel.c | 27 +++++++++++++++++++++++
>>>  arch/arm/mach-imx/boot.c                  |  4 +++-
>>>  include/asm-generic/sections.h            |  1 +
>>>  3 files changed, 31 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
>>> index 3298ded5866d..1fb7899198d6 100644
>>> --- a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
>>> +++ b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
>>> @@ -99,6 +99,30 @@ static int power_init_board(void)
>>>  	return 0;
>>>  }
>>>  
>>> +/* read piggydata via a bootrom callback and place it behind our copy in SDRAM */
>>> +static int imx8m_bootrom_load_image(void)
>>> +{
>>> +	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor) = *(void **)0x988;
>>
>> Would be nice to have this in a header, e.g.
>>
>> extern struct imx8mp_bootrom_ops {
>> 	/* ... */
>> 	int (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor);
>> } *imx8mp_bootrom_ops = (void *)0x988;
>>
>>> +	size_t count = __piggydata_end - __piggydata_start;
>>> +	char *p = (char *)MX8M_ATF_BL33_BASE_ADDR + (__piggydata_start - __image_start);
>>> +
>>> +	while (count) {
>>> +		size_t chunksize = min(count, (size_t)1024);
>>> +		int ret;
>>> +
>>> +		ret = download_image(p, 0, chunksize, (uintptr_t)p ^ chunksize);
>>> +		if (ret != 0xf0) {
>>> +			pr_err("Failed to load piggy data (ret = %x)\n", ret);
>>> +			return -EIO;
>>> +		}
>>> +
>>> +		p += chunksize;
>>> +		count -= chunksize;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
> This shouldn't be in board code, but in some location where it is
> reusable by other i.MX8MP boards.
> 
>>>  extern struct dram_timing_info imx8mp_evk_dram_timing;
>>>  
>>>  static void start_atf(void)
>>> @@ -125,6 +149,9 @@ static void start_atf(void)
>>>  	case BOOTSOURCE_MMC:
>>>  		imx8mp_esdhc_load_image(instance, false);
>>>  		break;
>>> +	case BOOTSOURCE_SERIAL:
>>> +		imx8m_bootrom_load_image();
>>> +		break;
>>>  	default:
>>>  		printf("Unhandled bootsource BOOTSOURCE_%d\n", src);
>>>  		hang();
>>> diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
>>> index 2b66bbf71eb1..7c1d49291045 100644
>>> --- a/arch/arm/mach-imx/boot.c
>>> +++ b/arch/arm/mach-imx/boot.c
>>> @@ -495,10 +495,12 @@ static void __imx7_get_boot_source(enum bootsource *src, int *instance,
>>>  	case 5:
>>>  		*src = BOOTSOURCE_NOR;
>>>  		break;
>>> -	case 15:
>>> +	case 14: /* observed on i.MX8MP for USB "serial" booting */
>>> +	case 15: /* observed on i.MX8MM for USB "serial" booting */
>>>  		*src = BOOTSOURCE_SERIAL;
>>>  		break;
>>>  	default:
>>> +		*src = BOOTSOURCE_UNKNOWN;
>>>  		break;
>>>  	}
>>>  }
>>> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
>>> index 870bff21f668..597c4951ea5e 100644
>>> --- a/include/asm-generic/sections.h
>>> +++ b/include/asm-generic/sections.h
>>> @@ -9,6 +9,7 @@ extern char _end[];
>>>  extern char __image_start[];
>>>  extern char __image_end[];
>>>  extern char __piggydata_start[];
>>> +extern char __piggydata_end[];
>>
>> Other code normally uses __image_end, but it seems __piggydata_end should be
>> equal to it. I'd prefer __image_end, because conceptually, you want to copy
>> off the rest of the image (which happens to be just the piggy data)
>>
>> @Rouven, The sha sum is at the end of the image, right?
>> Would this be included this way?
> 
> The checksum is built into the PBL, as it is used to authenticate the
> piggydata, as the BootROM will only authenticate the initial loaded
> part of the image, i.e. the PBL.

Of course. Excuse the brain fart.

> 
> Regards,
> Lucas
> 
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From antonynpavlov at gmail.com  Tue Aug 17 03:04:29 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:29 +0300
Subject: [PATCH 2/8] serial: add litex UART driver
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-3-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 drivers/serial/Makefile       |  1 +
 drivers/serial/serial_litex.c | 96 +++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)

diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5120b17376..45055371ea 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_DRIVER_SERIAL_DIGIC)		+= serial_digic.o
 obj-$(CONFIG_DRIVER_SERIAL_LPUART)		+= serial_lpuart.o
 obj-$(CONFIG_VIRTIO_CONSOLE)			+= virtio_console.o
 obj-$(CONFIG_SERIAL_SIFIVE)			+= serial_sifive.o
+obj-$(CONFIG_SOC_LITEX)				+= serial_litex.o
diff --git a/drivers/serial/serial_litex.c b/drivers/serial/serial_litex.c
new file mode 100644
index 0000000000..8562a45ecc
--- /dev/null
+++ b/drivers/serial/serial_litex.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+
+#define UART_RXTX	0x00
+#define UART_TXFULL	0x04
+#define UART_RXEMPTY	0x08
+#define UART_EV_PENDING	0x10
+#define  UART_EV_RX	(1 << 1)
+
+static inline uint32_t litex_serial_readb(struct console_device *cdev,
+						uint32_t offset)
+{
+	void __iomem *base = cdev->dev->priv;
+
+	return readb(base + offset);
+}
+
+static inline void litex_serial_writeb(struct console_device *cdev,
+					uint32_t value, uint32_t offset)
+{
+	void __iomem *base = cdev->dev->priv;
+
+	writeb(value, base + offset);
+}
+
+static void litex_serial_putc(struct console_device *cdev, char c)
+{
+	while (litex_serial_readb(cdev, UART_TXFULL))
+		;
+
+	litex_serial_writeb(cdev, c, UART_RXTX);
+}
+
+static int litex_serial_getc(struct console_device *cdev)
+{
+	int c;
+
+	while (litex_serial_readb(cdev, UART_RXEMPTY))
+		;
+
+	c = litex_serial_readb(cdev, UART_RXTX);
+
+	/* refresh UART_RXEMPTY by writing UART_EV_RX to UART_EV_PENDING */
+	litex_serial_writeb(cdev, UART_EV_RX, UART_EV_PENDING);
+
+	return c;
+}
+
+static int litex_serial_tstc(struct console_device *cdev)
+{
+	return !litex_serial_readb(cdev, UART_RXEMPTY);
+}
+
+static int litex_serial_probe(struct device_d *dev)
+{
+	struct resource *iores;
+	struct console_device *cdev;
+
+	cdev = xzalloc(sizeof(struct console_device));
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores))
+		return PTR_ERR(iores);
+
+	dev->priv = IOMEM(iores->start);
+	cdev->dev = dev;
+	cdev->tstc = &litex_serial_tstc;
+	cdev->putc = &litex_serial_putc;
+	cdev->getc = &litex_serial_getc;
+	cdev->setbrg = NULL;
+
+	console_register(cdev);
+
+	return 0;
+}
+
+static __maybe_unused struct of_device_id litex_serial_dt_ids[] = {
+	{
+		.compatible = "litex,uart",
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct driver_d litex_serial_driver = {
+	.name  = "litex-uart",
+	.probe = litex_serial_probe,
+	.of_compatible = DRV_OF_COMPAT(litex_serial_dt_ids),
+};
+console_platform_driver(litex_serial_driver);
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:28 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:28 +0300
Subject: [PATCH 1/8] clocksource: timer-riscv: select CSR from device tree
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-2-antonynpavlov@gmail.com>

barebox timer-riscv driver supports one of user counters:

  * 'cycle', counter for RDCYCLE instruction (CSR 0xc00);
  * 'time', timer for RDTIME instruction (CSR 0xc01).

At the moment in M-mode timer-riscv uses the 'cycle' counter,
and in S-mode timer-riscv uses the 'time' timer.

Alas picorv32 CPU core supports only the 'cycle' counter.
VexRiscV CPU core in M-mode supports only the 'time' timer.

This patch makes it possible to use the 'time' timer
for VexRiscV CPU in M-mode.

See also http://lists.infradead.org/pipermail/barebox/2021-May/036067.html

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/dts/erizo.dtsi         |  2 ++
 drivers/clocksource/timer-riscv.c | 24 ++++++++++++------------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/arch/riscv/dts/erizo.dtsi b/arch/riscv/dts/erizo.dtsi
index 228711bd69..4eb92ae6f1 100644
--- a/arch/riscv/dts/erizo.dtsi
+++ b/arch/riscv/dts/erizo.dtsi
@@ -22,6 +22,8 @@
 
 		timebase-frequency = <24000000>;
 
+		barebox,csr-cycle;
+
 		cpu at 0 {
 			device_type = "cpu";
 			compatible = "cliffordwolf,picorv32", "riscv";
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 5a517fe6b4..96637f988a 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -12,9 +12,8 @@
 #include <clock.h>
 #include <asm/timer.h>
 #include <asm/csr.h>
-#include <asm/system.h>
 
-static u64 notrace riscv_timer_get_count_sbi(void)
+static u64 notrace riscv_timer_get_count_time(void)
 {
 	__maybe_unused u32 hi, lo;
 
@@ -29,7 +28,7 @@ static u64 notrace riscv_timer_get_count_sbi(void)
 	return ((u64)hi << 32) | lo;
 }
 
-static u64 notrace riscv_timer_get_count_rdcycle(void)
+static u64 notrace riscv_timer_get_count_cycle(void)
 {
 	__maybe_unused u32 hi, lo;
 
@@ -44,24 +43,25 @@ static u64 notrace riscv_timer_get_count_rdcycle(void)
 	return ((u64)hi << 32) | lo;
 }
 
-static u64 notrace riscv_timer_get_count(void)
-{
-	if (riscv_mode() == RISCV_S_MODE)
-		return riscv_timer_get_count_sbi();
-	else
-		return riscv_timer_get_count_rdcycle();
-}
-
 static struct clocksource riscv_clocksource = {
-	.read		= riscv_timer_get_count,
 	.mask		= CLOCKSOURCE_MASK(64),
 	.priority	= 100,
 };
 
 static int riscv_timer_init(struct device_d* dev)
 {
+	struct device_node *cpu;
+
 	dev_dbg(dev, "running at %lu Hz\n", riscv_timebase);
 
+	cpu = of_find_node_by_path("/cpus");
+
+	if (of_property_read_bool(cpu, "barebox,csr-cycle")) {
+		riscv_clocksource.read = riscv_timer_get_count_cycle;
+	} else {
+		riscv_clocksource.read = riscv_timer_get_count_time;
+	}
+
 	riscv_clocksource.mult = clocksource_hz2mult(riscv_timebase, riscv_clocksource.shift);
 
 	return init_clock(&riscv_clocksource);
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:31 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:31 +0300
Subject: [PATCH 4/8] gpio: add driver for 74xx-ICs with MMIO access
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-5-antonynpavlov@gmail.com>

This patch adds driver to support GPIO functionality
for 74xx-compatible ICs with MMIO access.

Compatible models include:
     1 bit:   741G125 (Input), 741G74 (Output)
     2 bits:  742G125 (Input), 7474 (Output)
     4 bits:  74125 (Input), 74175 (Output)
     6 bits:  74365 (Input), 74174 (Output)
     8 bits:  74244 (Input), 74273 (Output)
     16 bits: 741624 (Input), 7416374 (Output)

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
Cc: Alexander Shiyan <shc_work at mail.ru>
---
 drivers/gpio/Kconfig          |  14 +++
 drivers/gpio/Makefile         |   1 +
 drivers/gpio/gpio-74xx-mmio.c | 165 ++++++++++++++++++++++++++++++++++
 3 files changed, 180 insertions(+)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 98a44fbbb5..f79c9ea67d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -21,6 +21,20 @@ config GPIO_74164
 	  shift registers. This driver can be used to provide access
 	  to more gpio outputs.
 
+config GPIO_74XX_MMIO
+	tristate "GPIO driver for 74xx-ICs with MMIO access"
+	depends on OFDEVICE
+	select GPIO_GENERIC
+	help
+	  Say yes here to support GPIO functionality for 74xx-compatible ICs
+	  with MMIO access. Compatible models include:
+	    1 bit:	741G125 (Input), 741G74 (Output)
+	    2 bits:	742G125 (Input), 7474 (Output)
+	    4 bits:	74125 (Input), 74175 (Output)
+	    6 bits:	74365 (Input), 74174 (Output)
+	    8 bits:	74244 (Input), 74273 (Output)
+	    16 bits:	741624 (Input), 7416374 (Output)
+
 config GPIO_CLPS711X
 	bool "GPIO support for CLPS711X"
 	depends on ARCH_CLPS711X || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 638cbb19a3..023973cb63 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o
 
 obj-$(CONFIG_GPIO_74164)	+= gpio-74164.o
+obj-$(CONFIG_GPIO_74XX_MMIO)	+= gpio-74xx-mmio.o
 obj-$(CONFIG_MACH_MIPS_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_DAVINCI)	+= gpio-davinci.o
 obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c
new file mode 100644
index 0000000000..5b688f4766
--- /dev/null
+++ b/drivers/gpio/gpio-74xx-mmio.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 74xx MMIO GPIO driver
+ *
+ *  Copyright (C) 2014 Alexander Shiyan <shc_work at mail.ru>
+ *
+ * Ported to barebox from linux-v5.4-rc6
+ *   Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <malloc.h>
+#include <of_device.h>
+
+#include <linux/err.h>
+#include <linux/basic_mmio_gpio.h>
+
+#define MMIO_74XX_DIR_IN	(0 << 8)
+#define MMIO_74XX_DIR_OUT	(1 << 8)
+#define MMIO_74XX_BIT_CNT(x)	((x) & 0xff)
+
+struct mmio_74xx_gpio_priv {
+	struct bgpio_chip	bgc;
+	unsigned int		flags;
+};
+
+static const struct of_device_id mmio_74xx_gpio_ids[] = {
+	{
+		.compatible	= "ti,741g125",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 1),
+	},
+	{
+		.compatible	= "ti,742g125",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 2),
+	},
+	{
+		.compatible	= "ti,74125",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 4),
+	},
+	{
+		.compatible	= "ti,74365",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 6),
+	},
+	{
+		.compatible	= "ti,74244",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 8),
+	},
+	{
+		.compatible	= "ti,741624",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 16),
+	},
+	{
+		.compatible	= "ti,741g74",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 1),
+	},
+	{
+		.compatible	= "ti,7474",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 2),
+	},
+	{
+		.compatible	= "ti,74175",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 4),
+	},
+	{
+		.compatible	= "ti,74174",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 6),
+	},
+	{
+		.compatible	= "ti,74273",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 8),
+	},
+	{
+		.compatible	= "ti,7416374",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 16),
+	},
+	{ }
+};
+
+static inline
+struct mmio_74xx_gpio_priv *to_mmio_74xx_gpio_priv(struct gpio_chip *gc)
+{
+	struct bgpio_chip *bgc =
+		container_of(gc, struct bgpio_chip, gc);
+
+	return container_of(bgc, struct mmio_74xx_gpio_priv, bgc);
+}
+
+static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc);
+
+	if (priv->flags & MMIO_74XX_DIR_OUT)
+		return GPIOF_DIR_OUT;
+
+	return GPIOF_DIR_IN;
+}
+
+static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc);
+
+	return (priv->flags & MMIO_74XX_DIR_OUT) ? -ENOTSUPP : 0;
+}
+
+static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc);
+
+	if (priv->flags & MMIO_74XX_DIR_OUT) {
+		gc->ops->set(gc, gpio, val);
+		return 0;
+	}
+
+	return -ENOTSUPP;
+}
+
+static int mmio_74xx_gpio_probe(struct device_d *dev)
+{
+	struct mmio_74xx_gpio_priv *priv;
+	void __iomem *dat;
+	int err;
+	struct gpio_chip *gc;
+
+	priv = xzalloc(sizeof(*priv));
+
+	priv->flags = (uintptr_t)of_device_get_match_data(dev);
+
+	dat = dev_request_mem_region(dev, 0);
+	if (IS_ERR(dat))
+		return PTR_ERR(dat);
+
+	err = bgpio_init(&priv->bgc, dev,
+			 DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
+			 dat, NULL, NULL, NULL, NULL, 0);
+	if (err)
+		return err;
+
+	gc = &priv->bgc.gc;
+	gc->ops->direction_input = mmio_74xx_dir_in;
+	gc->ops->direction_output = mmio_74xx_dir_out;
+	gc->ops->get_direction = mmio_74xx_get_direction;
+	gc->ngpio = MMIO_74XX_BIT_CNT(priv->flags);
+
+	dev->priv = priv;
+
+	return gpiochip_add(gc);
+}
+
+static struct driver_d mmio_74xx_gpio_driver = {
+	.name = "74xx-mmio-gpio",
+	.of_compatible	= DRV_OF_COMPAT(mmio_74xx_gpio_ids),
+	.probe = mmio_74xx_gpio_probe,
+};
+
+coredevice_platform_driver(mmio_74xx_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
+MODULE_DESCRIPTION("74xx MMIO GPIO driver");
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:27 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:27 +0300
Subject: [PATCH 0/8 v4] RISC-V: add LiteX SoC support
Message-ID: <20210817100435.114756-1-antonynpavlov@gmail.com>

Changes since v3:

  * rebased on top of next branch;
  * the "console: support set baudrate for fixed baudrate drivers" patch
    is introduced so the "litex serial: add setbrg callback" patch is dropped;
  * update mac0 IP-block base addresses in litex dts according to latest
    SoC configuration.

Changes since v2:

  * rebase on top of master branch (f873c7ff2497) +
    "RISC-V: extend multi-image to support both S- and M-Mode"
    (http://lists.infradead.org/pipermail/barebox/2021-May/036086.html).
  * "litex serial: add setbrg callback" patch by Marek Czerski is added
    for review;
  * fix "clocksource: timer-riscv: select CSR from device tree" patch;
  * change gpio IP-block base addresses in litex dts;
  * gpio-74xx-mmio uses device_get_match_data() now.

Changes since v1:

  * rebased on top of next branch;
  * new patches are introduced:
    * clocksource: timer-riscv: select CSR from device tree
    * RISC-V: make RISCV_SBI and RISCV_M_MODE explicitly mutually exclusive
    * RISC-V: make it possible to build RV32I multi-image with DEBUG_LL=n
  * almost all of Ahmad's notes are fixed (e.g. unused header files inclusions are dropped);
  * NOT FIXED: gpio-74xx-mmio still uses dev_get_drvdata(), not device_get_match_data()


Antony Pavlov (8):
  clocksource: timer-riscv: select CSR from device tree
  serial: add litex UART driver
  console: support set baudrate for fixed baudrate drivers
  gpio: add driver for 74xx-ICs with MMIO access
  spi: add litex spiflash driver
  net: add LiteEth driver
  RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
  RISC-V: add litex_linux_defconfig

 arch/riscv/Kconfig.socs                  |  14 +
 arch/riscv/boards/Makefile               |   1 +
 arch/riscv/boards/litex-linux/Makefile   |   3 +
 arch/riscv/boards/litex-linux/lowlevel.c |  22 ++
 arch/riscv/configs/litex_linux_defconfig |  75 +++++
 arch/riscv/dts/Makefile                  |   1 +
 arch/riscv/dts/erizo.dtsi                |   2 +
 arch/riscv/dts/litex-linux.dts           |  92 ++++++
 arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++
 arch/riscv/include/asm/debug_ll.h        |   3 +
 arch/riscv/include/asm/debug_ll_litex.h  | 123 ++++++++
 common/Kconfig                           |   4 +
 common/console.c                         |  10 +-
 drivers/clocksource/timer-riscv.c        |  24 +-
 drivers/gpio/Kconfig                     |  14 +
 drivers/gpio/Makefile                    |   1 +
 drivers/gpio/gpio-74xx-mmio.c            | 165 ++++++++++
 drivers/net/Kconfig                      |   8 +
 drivers/net/Makefile                     |   1 +
 drivers/net/liteeth.c                    | 376 +++++++++++++++++++++++
 drivers/serial/Makefile                  |   1 +
 drivers/serial/serial_litex.c            |  96 ++++++
 drivers/spi/Kconfig                      |   3 +
 drivers/spi/Makefile                     |   1 +
 drivers/spi/litex_spiflash.c             | 241 +++++++++++++++
 images/Makefile.riscv                    |   4 +
 26 files changed, 1318 insertions(+), 16 deletions(-)
 create mode 100644 arch/riscv/boards/litex-linux/Makefile
 create mode 100644 arch/riscv/boards/litex-linux/lowlevel.c
 create mode 100644 arch/riscv/configs/litex_linux_defconfig
 create mode 100644 arch/riscv/dts/litex-linux.dts
 create mode 100644 arch/riscv/dts/litex_soc_linux.dtsi
 create mode 100644 arch/riscv/include/asm/debug_ll_litex.h
 create mode 100644 drivers/gpio/gpio-74xx-mmio.c
 create mode 100644 drivers/net/liteeth.c
 create mode 100644 drivers/serial/serial_litex.c
 create mode 100644 drivers/spi/litex_spiflash.c

-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:30 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:30 +0300
Subject: [PATCH 3/8] console: support set baudrate for fixed baudrate drivers
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-4-antonynpavlov@gmail.com>

There are console drivers (linux, virtio, litex)
that don't support baud rate setting and has
no setbrg (set baudrate) callback, so
console_set_baudrate() returns -ENOSYS.

At the other hand console_set_baudrate() SUCCESS
return value is needed for the loadx/loady commands
correct work.

See discussion here:

  http://lists.infradead.org/pipermail/barebox/2021-May/036237.html

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 common/console.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/common/console.c b/common/console.c
index ad1a6aaab2..c902239e31 100644
--- a/common/console.c
+++ b/common/console.c
@@ -165,12 +165,12 @@ int console_set_baudrate(struct console_device *cdev, unsigned baudrate)
 	int ret;
 	unsigned char c;
 
-	if (!cdev->setbrg)
-		return -ENOSYS;
-
 	if (cdev->baudrate == baudrate)
 		return 0;
 
+	if (!cdev->setbrg)
+		return -ENOSYS;
+
 	/*
 	 * If the device is already active, change its baudrate.
 	 * The baudrate of an inactive device will be set at activation time.
@@ -336,11 +336,13 @@ int console_register(struct console_device *newcdev)
 		ret = newcdev->setbrg(newcdev, baudrate);
 		if (ret)
 			return ret;
-		newcdev->baudrate_param = newcdev->baudrate = baudrate;
+		newcdev->baudrate_param = baudrate;
 		dev_add_param_uint32(dev, "baudrate", console_baudrate_set,
 			NULL, &newcdev->baudrate_param, "%u", newcdev);
 	}
 
+	newcdev->baudrate = baudrate;
+
 	if (newcdev->putc && !newcdev->puts)
 		newcdev->puts = __console_puts;
 
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:33 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:33 +0300
Subject: [PATCH 6/8] net: add LiteEth driver
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-7-antonynpavlov@gmail.com>

LiteEth provides a small footprint and configurable Ethernet core.

LiteEth is part of LiteX libraries whose aims are to lower entry level of
complex FPGA cores by providing simple, elegant and efficient implementations
of components used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller...

Using Migen to describe the HDL allows the core to be highly and easily configurable.

LiteEth can be used as LiteX library or can be integrated with your standard
design flow by generating the verilog rtl that you will use as a standard core.

See https://github.com/enjoy-digital/liteeth for details.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
Signed-off-by: Marek Czerski <m.czerski at ap-tech.pl>
---
 drivers/net/Kconfig   |   8 +
 drivers/net/Makefile  |   1 +
 drivers/net/liteeth.c | 376 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 385 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 802169a86e..781c7e69db 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -285,6 +285,14 @@ config TSE_USE_DEDICATED_DESC_MEM
 	  reserved with a malloc but directly mapped to the memory
 	  address (defined in config.h)
 
+config DRIVER_NET_LITEETH
+	bool "LiteX ethernet driver"
+	select PHYLIB
+	select MDIO_BITBANG
+	help
+	  This option enables support for the LiteX LiteEth
+	  ethernet IP core.
+
 source "drivers/net/phy/Kconfig"
 source "drivers/net/usb/Kconfig"
 
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fb3e3bdee4..466c910b3e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_DRIVER_NET_TAP)		+= tap.o
 obj-$(CONFIG_DRIVER_NET_TSE)		+= altera_tse.o
 obj-$(CONFIG_DRIVER_NET_EFI_SNP)	+= efi-snp.o
 obj-$(CONFIG_DRIVER_NET_AG71XX)		+= ag71xx.o
+obj-$(CONFIG_DRIVER_NET_LITEETH)	+= liteeth.o
diff --git a/drivers/net/liteeth.c b/drivers/net/liteeth.c
new file mode 100644
index 0000000000..137cb854c5
--- /dev/null
+++ b/drivers/net/liteeth.c
@@ -0,0 +1,376 @@
+/*
+ * LiteX Liteeth Ethernet
+ *
+ * Copyright 2017 Joel Stanley <joel at jms.id.au>
+ *
+ * Ported to barebox from linux kernel
+ *   Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov at gmail.com>
+ *   Copyright (C) 2021 Marek Czerski <m.czerski at ap-tech.pl>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <linux/iopoll.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <of_net.h>
+#include <linux/phy.h>
+#include <linux/mdio-bitbang.h>
+
+#define DRV_NAME	"liteeth"
+
+#define LITEETH_WRITER_SLOT		0x00
+#define LITEETH_WRITER_LENGTH		0x04
+#define LITEETH_WRITER_ERRORS		0x08
+#define LITEETH_WRITER_EV_STATUS	0x0c
+#define LITEETH_WRITER_EV_PENDING	0x10
+#define LITEETH_WRITER_EV_ENABLE	0x14
+#define LITEETH_READER_START		0x18
+#define LITEETH_READER_READY		0x1c
+#define LITEETH_READER_LEVEL		0x20
+#define LITEETH_READER_SLOT		0x24
+#define LITEETH_READER_LENGTH		0x28
+#define LITEETH_READER_EV_STATUS	0x2c
+#define LITEETH_READER_EV_PENDING	0x30
+#define LITEETH_READER_EV_ENABLE	0x34
+#define LITEETH_PREAMBLE_CRC		0x38
+#define LITEETH_PREAMBLE_ERRORS		0x3c
+#define LITEETH_CRC_ERRORS		0x40
+
+#define LITEETH_PHY_CRG_RESET		0x00
+#define LITEETH_MDIO_W			0x04
+#define  MDIO_W_CLK			BIT(0)
+#define  MDIO_W_OE			BIT(1)
+#define  MDIO_W_DO			BIT(2)
+
+#define LITEETH_MDIO_R			0x08
+#define  MDIO_R_DI			BIT(0)
+
+#define LITEETH_BUFFER_SIZE		0x800
+#define MAX_PKT_SIZE			LITEETH_BUFFER_SIZE
+
+struct liteeth {
+	struct device_d *dev;
+	struct eth_device edev;
+	void __iomem *base;
+	void __iomem *mdio_base;
+	struct mii_bus *mii_bus;
+	struct mdiobb_ctrl mdiobb;
+
+	/* Link management */
+	int cur_duplex;
+	int cur_speed;
+
+	/* Tx */
+	int tx_slot;
+	int num_tx_slots;
+	void __iomem *tx_base;
+
+	/* Rx */
+	int rx_slot;
+	int num_rx_slots;
+	void __iomem *rx_base;
+};
+
+static inline void litex_write8(void __iomem *addr, u8 val)
+{
+	writeb(val, addr);
+}
+
+static inline void litex_write16(void __iomem *addr, u16 val)
+{
+	writew(val, addr);
+}
+
+static inline u8 litex_read8(void __iomem *addr)
+{
+	return readb(addr);
+}
+
+static inline u32 litex_read32(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static void liteeth_mdio_w_modify(struct liteeth *priv, u8 clear, u8 set)
+{
+	void __iomem *mdio_w = priv->mdio_base + LITEETH_MDIO_W;
+
+	litex_write8(mdio_w, (litex_read8(mdio_w) & ~clear) | set);
+}
+
+static void liteeth_mdio_ctrl(struct mdiobb_ctrl *ctrl, u8 mask, int set)
+{
+	struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb);
+
+	liteeth_mdio_w_modify(priv, mask, set ? mask : 0);
+}
+
+/* MDC pin control */
+static void liteeth_set_mdc(struct mdiobb_ctrl *ctrl, int level)
+{
+	liteeth_mdio_ctrl(ctrl, MDIO_W_CLK, level);
+}
+
+/* Data I/O pin control */
+static void liteeth_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output)
+{
+	liteeth_mdio_ctrl(ctrl, MDIO_W_OE, output);
+}
+
+/* Set data bit */
+static void liteeth_set_mdio_data(struct mdiobb_ctrl *ctrl, int value)
+{
+	liteeth_mdio_ctrl(ctrl, MDIO_W_DO, value);
+}
+
+/* Get data bit */
+static int liteeth_get_mdio_data(struct mdiobb_ctrl *ctrl)
+{
+	struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb);
+
+	return (litex_read8(priv->mdio_base + LITEETH_MDIO_R) & MDIO_R_DI) != 0;
+}
+
+/* MDIO bus control struct */
+static struct mdiobb_ops bb_ops = {
+	.set_mdc = liteeth_set_mdc,
+	.set_mdio_dir = liteeth_set_mdio_dir,
+	.set_mdio_data = liteeth_set_mdio_data,
+	.get_mdio_data = liteeth_get_mdio_data,
+};
+
+static int liteeth_init_dev(struct eth_device *edev)
+{
+	return 0;
+}
+
+static int liteeth_eth_open(struct eth_device *edev)
+{
+	struct liteeth *priv = edev->priv;
+	int ret;
+
+	/* Disable events */
+	litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0);
+	litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0);
+
+	/* Clear pending events? */
+	litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, 1);
+	litex_write8(priv->base + LITEETH_READER_EV_PENDING, 1);
+
+	ret = phy_device_connect(edev, priv->mii_bus, -1, NULL, 0, -1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int liteeth_eth_send(struct eth_device *edev, void *packet,
+				int packet_length)
+{
+	struct liteeth *priv = edev->priv;
+	void *txbuffer;
+	int ret;
+	u8 val;
+	u8 reg;
+
+	reg = litex_read8(priv->base + LITEETH_READER_EV_PENDING);
+	if (reg) {
+		litex_write8(priv->base + LITEETH_READER_EV_PENDING, reg);
+	}
+
+	/* Reject oversize packets */
+	if (unlikely(packet_length > MAX_PKT_SIZE)) {
+		dev_err(priv->dev, "tx packet too big\n");
+		goto drop;
+	}
+
+	txbuffer = priv->tx_base + priv->tx_slot * LITEETH_BUFFER_SIZE;
+	memcpy(txbuffer, packet, packet_length);
+	litex_write8(priv->base + LITEETH_READER_SLOT, priv->tx_slot);
+	litex_write16(priv->base + LITEETH_READER_LENGTH, packet_length);
+
+	ret = readb_poll_timeout(priv->base + LITEETH_READER_READY,
+			val, val, 1000);
+	if (ret == -ETIMEDOUT) {
+		dev_err(priv->dev, "LITEETH_READER_READY timed out\n");
+		goto drop;
+	}
+
+	litex_write8(priv->base + LITEETH_READER_START, 1);
+
+	priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots;
+
+drop:
+	return 0;
+}
+
+static int liteeth_eth_rx(struct eth_device *edev)
+{
+	struct liteeth *priv = edev->priv;
+	u8 rx_slot;
+	int len = 0;
+	u8 reg;
+
+	reg = litex_read8(priv->base + LITEETH_WRITER_EV_PENDING);
+	if (!reg) {
+		goto done;
+	}
+
+	len = litex_read32(priv->base + LITEETH_WRITER_LENGTH);
+	if (len == 0 || len > 2048) {
+		len = 0;
+		dev_err(priv->dev, "%s: invalid len %d\n", __func__, len);
+		litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg);
+		goto done;
+	}
+
+	rx_slot = litex_read8(priv->base + LITEETH_WRITER_SLOT);
+
+	memcpy(NetRxPackets[0], priv->rx_base + rx_slot * LITEETH_BUFFER_SIZE, len);
+
+	net_receive(edev, NetRxPackets[0], len);
+
+	litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg);
+
+done:
+	return len;
+}
+
+static void liteeth_eth_halt(struct eth_device *edev)
+{
+	struct liteeth *priv = edev->priv;
+
+	litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0);
+	litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0);
+}
+
+static void liteeth_reset_hw(struct liteeth *priv)
+{
+	/* Reset, twice */
+	litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0);
+	udelay(10);
+	litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 1);
+	udelay(10);
+	litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0);
+	udelay(10);
+}
+
+static int liteeth_get_ethaddr(struct eth_device *edev, unsigned char *m)
+{
+	return 0;
+}
+
+static int liteeth_set_ethaddr(struct eth_device *edev,
+					const unsigned char *mac_addr)
+{
+	return 0;
+}
+
+static int liteeth_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	struct eth_device *edev;
+	void __iomem *buf_base;
+	struct liteeth *priv;
+	int err;
+
+	priv = xzalloc(sizeof(struct liteeth));
+	edev = &priv->edev;
+	edev->priv = priv;
+	priv->dev = dev;
+
+	priv->base = dev_request_mem_region(dev, 0);
+	if (IS_ERR(priv->base)) {
+		err = PTR_ERR(priv->base);
+		goto err;
+	}
+
+	priv->mdio_base = dev_request_mem_region(dev, 1);
+	if (IS_ERR(priv->mdio_base)) {
+		err = PTR_ERR(priv->mdio_base);
+		goto err;
+	}
+
+	buf_base = dev_request_mem_region(dev, 2);
+	if (IS_ERR(buf_base)) {
+		err = PTR_ERR(buf_base);
+		goto err;
+	}
+
+	err = of_property_read_u32(np, "rx-fifo-depth",
+			&priv->num_rx_slots);
+	if (err) {
+		dev_err(dev, "unable to get rx-fifo-depth\n");
+		goto err;
+	}
+
+	err = of_property_read_u32(np, "tx-fifo-depth",
+			&priv->num_tx_slots);
+	if (err) {
+		dev_err(dev, "unable to get tx-fifo-depth\n");
+		goto err;
+	}
+
+	/* Rx slots */
+	priv->rx_base = buf_base;
+	priv->rx_slot = 0;
+
+	/* Tx slots come after Rx slots */
+	priv->tx_base = buf_base + priv->num_rx_slots * LITEETH_BUFFER_SIZE;
+	priv->tx_slot = 0;
+
+	edev->init = liteeth_init_dev;
+	edev->open = liteeth_eth_open;
+	edev->send = liteeth_eth_send;
+	edev->recv = liteeth_eth_rx;
+	edev->get_ethaddr = liteeth_get_ethaddr;
+	edev->set_ethaddr = liteeth_set_ethaddr;
+	edev->halt = liteeth_eth_halt;
+	edev->parent = dev;
+
+	priv->mdiobb.ops = &bb_ops;
+
+	priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
+	priv->mii_bus->parent = dev;
+
+	liteeth_reset_hw(priv);
+
+	err = eth_register(edev);
+	if (err) {
+		dev_err(dev, "failed to register edev\n");
+		goto err;
+	}
+
+	err = mdiobus_register(priv->mii_bus);
+	if (err) {
+		dev_err(dev, "failed to register mii_bus\n");
+		goto err;
+	}
+
+	dev_info(dev, DRV_NAME " driver registered\n");
+
+	return 0;
+
+err:
+	return err;
+}
+
+static const struct of_device_id liteeth_dt_ids[] = {
+	{
+		.compatible = "litex,liteeth"
+	}, {
+	}
+};
+
+static struct driver_d liteeth_driver = {
+	.name = DRV_NAME,
+	.probe = liteeth_probe,
+	.of_compatible = DRV_OF_COMPAT(liteeth_dt_ids),
+};
+device_platform_driver(liteeth_driver);
+
+MODULE_AUTHOR("Joel Stanley <joel at jms.id.au>");
+MODULE_LICENSE("GPL");
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:34 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:34 +0300
Subject: [PATCH 7/8] RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-8-antonynpavlov@gmail.com>

LiteX is a Migen-based System on Chip, supporting softcore
VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU.

See https://github.com/enjoy-digital/litex and
https://github.com/litex-hub/linux-on-litex-vexriscv
for details.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig.socs                  |  14 +++
 arch/riscv/boards/Makefile               |   1 +
 arch/riscv/boards/litex-linux/Makefile   |   3 +
 arch/riscv/boards/litex-linux/lowlevel.c |  22 ++++
 arch/riscv/dts/Makefile                  |   1 +
 arch/riscv/dts/litex-linux.dts           |  92 +++++++++++++++++
 arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++++++++
 arch/riscv/include/asm/debug_ll.h        |   3 +
 arch/riscv/include/asm/debug_ll_litex.h  | 123 +++++++++++++++++++++++
 common/Kconfig                           |   4 +
 images/Makefile.riscv                    |   4 +
 11 files changed, 316 insertions(+)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 221ea133d4..5c281918d5 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -95,4 +95,18 @@ config SIFIVE_L2
 	bool "SiFive L2 cache controller"
 	depends on CPU_SIFIVE
 
+config SOC_LITEX
+	bool "LiteX SoCs"
+	depends on ARCH_RV32I
+	select HAS_ASM_DEBUG_LL
+	select HAS_NMON
+	select USE_COMPRESSED_DTB
+	select RISCV_TIMER
+
+config BOARD_LITEX_LINUX
+	bool "litex linux board"
+	depends on SOC_LITEX
+	select RISCV_M_MODE
+	def_bool y
+
 endmenu
diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile
index cb28a25d8b..8d5d9d4fc6 100644
--- a/arch/riscv/boards/Makefile
+++ b/arch/riscv/boards/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_BOARD_ERIZO_GENERIC)	+= erizo/
 obj-$(CONFIG_BOARD_HIFIVE)		+= hifive/
 obj-$(CONFIG_BOARD_BEAGLEV)		+= beaglev/
+obj-$(CONFIG_BOARD_LITEX_LINUX)		+= litex-linux/
diff --git a/arch/riscv/boards/litex-linux/Makefile b/arch/riscv/boards/litex-linux/Makefile
new file mode 100644
index 0000000000..3d217ffe0b
--- /dev/null
+++ b/arch/riscv/boards/litex-linux/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+pbl-y += lowlevel.o
diff --git a/arch/riscv/boards/litex-linux/lowlevel.c b/arch/riscv/boards/litex-linux/lowlevel.c
new file mode 100644
index 0000000000..da23ef5633
--- /dev/null
+++ b/arch/riscv/boards/litex-linux/lowlevel.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <asm/barebox-riscv.h>
+#include <debug_ll.h>
+#include <asm/riscv_nmon.h>
+
+ENTRY_FUNCTION(start_litex_linux, a0, a1, a2)
+{
+	extern char __dtb_z_litex_linux_start[];
+	void *fdt;
+
+	barebox_nmon_entry();
+
+	putc_ll('>');
+
+	/* On POR, we are running from read-only memory here. */
+
+	fdt = __dtb_z_litex_linux_start + get_runtime_offset();
+
+	barebox_riscv_machine_entry(0x40000000, SZ_256M, fdt);
+}
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 4a15423b7f..17d7d249e4 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -8,5 +8,6 @@ pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o
 pbl-$(CONFIG_BOARD_HIFIVE) += hifive-unmatched-a00.dtb.o \
                               hifive-unleashed-a00.dtb.o
 pbl-$(CONFIG_BOARD_BEAGLEV) += jh7100-beaglev-starlight.dtb.o
+pbl-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux.dtb.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
diff --git a/arch/riscv/dts/litex-linux.dts b/arch/riscv/dts/litex-linux.dts
new file mode 100644
index 0000000000..d21fa57e30
--- /dev/null
+++ b/arch/riscv/dts/litex-linux.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include "litex_soc_linux.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "LiteX VexRiscV-SoC-Linux";
+	compatible = "litex,vexriscv-soc-linux";
+
+	aliases {
+		rom = &rom;
+		sram = &sram;
+	};
+
+	/* ARTY board */
+	rom: rom at 00000000 {
+		compatible = "mmio-sram";
+		reg = <0x00000000 0x00008000>;
+		read-only;
+	};
+
+	sram: sram at 20000000 {
+		compatible = "mmio-sram";
+		reg = <0x20000000 0x00004000>;
+	};
+
+	main_ram: memory at 40000000 {
+		device_type = "memory";
+		reg = <0x40000000 0x10000000>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&mac0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+
+	spiflash: w25q128 at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "winbond,w25q128", "jedec,spi-nor";
+		spi-max-frequency = <104000000>;
+		reg = <0>;
+	};
+};
+
+/ {
+	ledsgpio: gpio at f000a800 {
+		compatible = "ti,74175";
+		reg = <0xf000a800 0x4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		ld0 {
+			label = "arty:green:ld0";
+			gpios = <&ledsgpio 0 GPIO_ACTIVE_HIGH>;
+		};
+
+		ld1 {
+			label = "arty:green:ld1";
+			gpios = <&ledsgpio 1 GPIO_ACTIVE_HIGH>;
+		};
+
+		ld2 {
+			label = "arty:green:ld2";
+			gpios = <&ledsgpio 2 GPIO_ACTIVE_HIGH>;
+		};
+
+		ld3 {
+			label = "arty:green:ld3";
+			gpios = <&ledsgpio 3 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	swgpio: gpio at f0006000 {
+		compatible = "ti,74125";
+		reg = <0xf0006000 0x4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
diff --git a/arch/riscv/dts/litex_soc_linux.dtsi b/arch/riscv/dts/litex_soc_linux.dtsi
new file mode 100644
index 0000000000..94a0ba29da
--- /dev/null
+++ b/arch/riscv/dts/litex_soc_linux.dtsi
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+/ {
+	compatible = "litex,vexriscv-soc-linux";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		timebase-frequency = <100000000>; // 100 MHz
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "spinalhdl,vexriscv", "riscv";
+			reg = <0>;
+		};
+	};
+
+	uart0: serial at f0001000 {
+		compatible = "litex,uart";
+		reg = <0xf0001000 0x18>;
+		status = "disabled";
+	};
+
+	mac0: mac at f0006800 {
+		compatible = "litex,liteeth";
+		reg = <0xf0006800 0x7c /* base */
+			0xf0007000 0x0a /* mdio_base */
+			0xb0000000 0x2000>; /* buf_base */
+		tx-fifo-depth = <2>;
+		rx-fifo-depth = <2>;
+		status = "disabled";
+	};
+
+	spi0: spi at f000b800 {
+		compatible = "litex,spiflash";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg = <0xf000b800 0x100>;
+		status = "disabled";
+	};
+};
diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h
index b4caa0597a..a3b9c1c4bc 100644
--- a/arch/riscv/include/asm/debug_ll.h
+++ b/arch/riscv/include/asm/debug_ll.h
@@ -43,6 +43,9 @@ static inline void PUTC_LL(char ch)
 
 	writel(ch, uart0);
 }
+#elif defined CONFIG_DEBUG_LITEX
+
+#include <asm/debug_ll_litex.h>
 
 #endif
 
diff --git a/arch/riscv/include/asm/debug_ll_litex.h b/arch/riscv/include/asm/debug_ll_litex.h
new file mode 100644
index 0000000000..2fcdd9b0ec
--- /dev/null
+++ b/arch/riscv/include/asm/debug_ll_litex.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ * This file is part of barebox.
+ *
+ * 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_DEBUG_LL_LITEX__
+#define __ASM_DEBUG_LL_LITEX__
+
+/** @file
+ *  This File contains declaration for early output support
+ */
+
+#include <linux/kconfig.h>
+
+#define DEBUG_LL_UART_ADDR	0xf0001000
+#define UART_RXTX	0x00
+#define UART_TXFULL	0x04
+#define UART_RXEMPTY	0x08
+#define UART_EV_PENDING	0x10
+#define  UART_EV_RX	(1 << 1)
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * C macros
+ */
+
+#include <asm/io.h>
+
+static inline void PUTC_LL(char ch)
+{
+#ifdef CONFIG_DEBUG_LL
+	/* wait for space */
+	while (__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_TXFULL))
+		;
+
+	__raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_RXTX);
+#endif /* CONFIG_DEBUG_LL */
+}
+#else /* __ASSEMBLY__ */
+/*
+ * Macros for use in assembly language code
+ */
+
+/*
+ * output a character in a0
+ */
+.macro	debug_ll_outc_a0
+#ifdef CONFIG_DEBUG_LL
+
+	li	t0, DEBUG_LL_UART_ADDR
+
+201:
+	lbu	t1, UART_TXFULL(t0)	/* uart tx full ? */
+	andi	t1, t1, 0xff
+	bnez	t1, 201b		/* try again */
+
+	sb	a0, UART_RXTX(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
+
+/*
+ * 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 */
+	lbu	s0, UART_RXEMPTY(t0)
+	bnez    s0, 243f
+	li	s0, 1
+	j	244f
+243:	li	s0, 0
+244:	nop
+#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 */
+	lb	s0, UART_RXTX(t0)
+	li      t1, UART_EV_RX
+	sb	t1, UART_EV_PENDING(t0)
+
+#endif /* CONFIG_DEBUG_LL */
+.endm
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_DEBUG_LL_LITEX__ */
diff --git a/common/Kconfig b/common/Kconfig
index a9feae2ae8..cb8bd8b2bf 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1399,6 +1399,10 @@ config DEBUG_SIFIVE
 	bool "SiFive serial0 port"
 	depends on SOC_SIFIVE
 
+config DEBUG_LITEX
+	bool "LiteX serial port"
+	depends on SOC_LITEX
+
 endchoice
 
 config DEBUG_LL_NS16550
diff --git a/images/Makefile.riscv b/images/Makefile.riscv
index 4410765cf6..0645238c43 100644
--- a/images/Makefile.riscv
+++ b/images/Makefile.riscv
@@ -19,3 +19,7 @@ image-$(CONFIG_BOARD_HIFIVE) += barebox-hifive-unmatched.img barebox-hifive-unle
 pblb-$(CONFIG_BOARD_BEAGLEV) += start_beaglev_starlight
 FILE_barebox-beaglev-starlight.img = start_beaglev_starlight.pblb
 image-$(CONFIG_BOARD_BEAGLEV) += barebox-beaglev-starlight.img
+
+pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux
+FILE_barebox-litex-linux.img = start_litex_linux.pblb
+image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:35 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:35 +0300
Subject: [PATCH 8/8] RISC-V: add litex_linux_defconfig
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-9-antonynpavlov@gmail.com>

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

diff --git a/arch/riscv/configs/litex_linux_defconfig b/arch/riscv/configs/litex_linux_defconfig
new file mode 100644
index 0000000000..8e19964890
--- /dev/null
+++ b/arch/riscv/configs/litex_linux_defconfig
@@ -0,0 +1,75 @@
+CONFIG_SOC_LITEX=y
+CONFIG_STACK_SIZE=0x20000
+CONFIG_MALLOC_SIZE=0xf00000
+CONFIG_MALLOC_TLSF=y
+CONFIG_PANIC_HANG=y
+CONFIG_BAUDRATE=1000000
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_TIMESTAMP is not set
+CONFIG_BOOTM_SHOW_TYPE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_BOOTM_INITRD=y
+CONFIG_BOOTM_OFTREE=y
+CONFIG_BOOTM_OFTREE_UIMAGE=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=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_EXPORT=y
+CONFIG_CMD_CMP=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_OF_DUMP=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_NET=y
+CONFIG_NET_NFS=y
+CONFIG_NET_NETCONSOLE=y
+CONFIG_DRIVER_NET_LITEETH=y
+CONFIG_AR8327N_PHY=y
+CONFIG_AT803X_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_DRIVER_SPI_LITEX_SPIFLASH=y
+CONFIG_MTD=y
+# CONFIG_MTD_OOB_DEVICE is not set
+CONFIG_MTD_M25P80=y
+CONFIG_CLOCKSOURCE_DUMMY_RATE=20000
+CONFIG_SRAM=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
+CONFIG_GPIO_74XX_MMIO=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_PINCTRL is not set
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_DIGEST_CRC32_GENERIC=y
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:04:32 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:04:32 +0300
Subject: [PATCH 5/8] spi: add litex spiflash driver
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817100435.114756-6-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 drivers/spi/Kconfig          |   3 +
 drivers/spi/Makefile         |   1 +
 drivers/spi/litex_spiflash.c | 241 +++++++++++++++++++++++++++++++++++
 3 files changed, 245 insertions(+)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 91083ee709..e92cf675ab 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -74,6 +74,9 @@ config DRIVER_SPI_IMX_2_3
 	depends on ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6 || ARCH_IMX7 || ARCH_IMX8M
 	default y
 
+config DRIVER_SPI_LITEX_SPIFLASH
+	bool "Litex SPIFLASH bitbang master driver"
+
 config DRIVER_SPI_MXS
 	bool "i.MX (23,28) SPI Master driver"
 	depends on ARCH_IMX28
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 908d514a01..ac95ffc1db 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_DRIVER_SPI_ATH79) += ath79_spi.o
 obj-$(CONFIG_DRIVER_SPI_GPIO) += gpio_spi.o
 obj-$(CONFIG_DRIVER_SPI_FSL_QUADSPI) += spi-fsl-qspi.o
 obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
+obj-$(CONFIG_DRIVER_SPI_LITEX_SPIFLASH) += litex_spiflash.o
 obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o
 obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o
 obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o
diff --git a/drivers/spi/litex_spiflash.c b/drivers/spi/litex_spiflash.c
new file mode 100644
index 0000000000..26ef207699
--- /dev/null
+++ b/drivers/spi/litex_spiflash.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <spi/spi.h>
+#include <io.h>
+
+struct litex_spiflash_spi {
+	struct spi_master	master;
+	void __iomem		*regs;
+	u32			val;
+};
+
+#define SPIFLASH_BITBANG 0x0
+#define  SPIFLASH_BB_MOSI BIT(0)
+#define  SPIFLASH_BB_CLK BIT(1)
+#define  SPIFLASH_BB_CSN BIT(2)
+#define  SPIFLASH_BB_DIR BIT(3)
+
+#define SPIFLASH_MISO 0x4
+#define SPIFLASH_BITBANG_EN 0x8
+
+static inline u32 litex_spiflash_spi_rr(struct litex_spiflash_spi *sp, int reg)
+{
+	return readl(sp->regs + reg);
+}
+
+static inline void litex_spiflash_spi_wr(struct litex_spiflash_spi *sp, u32 val, int reg)
+{
+	writel(val, sp->regs + reg);
+}
+
+static inline void setbits(struct litex_spiflash_spi *sp, int bits, int on)
+{
+	/*
+	 * We are the only user of SCSPTR so no locking is required.
+	 * Reading bit 2 and 0 in SCSPTR gives pin state as input.
+	 * Writing the same bits sets the output value.
+	 * This makes regular read-modify-write difficult so we
+	 * use sp->val to keep track of the latest register value.
+	 */
+
+	if (on)
+		sp->val |= bits;
+	else
+		sp->val &= ~bits;
+
+	litex_spiflash_spi_wr(sp, sp->val, SPIFLASH_BITBANG);
+}
+
+static inline struct litex_spiflash_spi *litex_spiflash_spidev_to_sp(struct spi_device *spi)
+{
+	return container_of(spi->master, struct litex_spiflash_spi, master);
+}
+
+static inline void setsck(struct spi_device *spi, int on)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+
+	setbits(sc, SPIFLASH_BB_CLK, on);
+}
+
+static inline void setmosi(struct spi_device *spi, int on)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+
+	sc->val &= ~SPIFLASH_BB_DIR;
+	setbits(sc, SPIFLASH_BB_MOSI, on);
+}
+
+static inline u32 getmiso(struct spi_device *spi)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+
+	setbits(sc, SPIFLASH_BB_DIR, 1);
+	return !!((litex_spiflash_spi_rr(sc, SPIFLASH_MISO) & 1));
+}
+
+#define spidelay(nsecs) udelay(nsecs/1000)
+
+#include "spi-bitbang-txrx.h"
+
+static inline void litex_spiflash_spi_chipselect(struct litex_spiflash_spi *sc, int on)
+{
+	setbits(sc, SPIFLASH_BB_CSN, on);
+}
+
+static int litex_spiflash_spi_setup(struct spi_device *spi)
+{
+	struct spi_master *master = spi->master;
+	struct device_d spi_dev = spi->dev;
+
+	if (spi->bits_per_word != 8) {
+		dev_err(master->dev, "master doesn't support %d bits per word requested by %s\n",
+			spi->bits_per_word, spi_dev.name);
+		return -EINVAL;
+	}
+
+	if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != SPI_MODE_0) {
+		dev_err(master->dev, "master doesn't support SPI_MODE%d requested by %s\n",
+			spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int litex_spiflash_spi_read(struct spi_device *spi, void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	u8 *rxf_buf = buf;
+
+	while (cnt < nbyte) {
+		*rxf_buf = bitbang_txrx_be_cpha1(spi, 1000, 1, 0, 8);
+		rxf_buf++;
+		cnt++;
+	}
+
+	return cnt;
+}
+
+static int litex_spiflash_spi_write(struct spi_device *spi,
+				const void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	const u8 *txf_buf = buf;
+
+	while (cnt < nbyte) {
+		bitbang_txrx_be_cpha1(spi, 1000, 1, (u32)*txf_buf, 8);
+		txf_buf++;
+		cnt++;
+	}
+
+	return 0;
+}
+
+static int litex_spiflash_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+	struct spi_transfer *t;
+
+	mesg->actual_length = 0;
+
+	/* activate chip select signal */
+	litex_spiflash_spi_chipselect(sc, 0);
+
+	list_for_each_entry(t, &mesg->transfers, transfer_list) {
+
+		if (t->tx_buf)
+			litex_spiflash_spi_write(spi, t->tx_buf, t->len);
+
+		if (t->rx_buf)
+			litex_spiflash_spi_read(spi, t->rx_buf, t->len);
+
+		mesg->actual_length += t->len;
+	}
+
+	/* inactivate chip select signal */
+	litex_spiflash_spi_chipselect(sc, 1);
+
+	return 0;
+}
+
+static void litex_spiflash_spi_enable(struct litex_spiflash_spi *sp)
+{
+	u32 val;
+
+	/* set SPIFLASH_BB_DIR = 0 */
+	val = SPIFLASH_BB_CSN | SPIFLASH_BB_CLK | SPIFLASH_BB_MOSI;
+	litex_spiflash_spi_wr(sp, val, SPIFLASH_BITBANG);
+
+	/* enable GPIO mode */
+	litex_spiflash_spi_wr(sp, 1, SPIFLASH_BITBANG_EN);
+}
+
+static void litex_spiflash_spi_disable(struct litex_spiflash_spi *sp)
+{
+	/* disable GPIO mode */
+	litex_spiflash_spi_wr(sp, 0, SPIFLASH_BITBANG_EN);
+}
+
+static int litex_spiflash_spi_probe(struct device_d *dev)
+{
+	struct resource *iores;
+	struct spi_master *master;
+	struct litex_spiflash_spi *litex_spiflash_spi;
+
+	litex_spiflash_spi = xzalloc(sizeof(*litex_spiflash_spi));
+	dev->priv = litex_spiflash_spi;
+
+	master = &litex_spiflash_spi->master;
+	master->dev = dev;
+
+	master->bus_num = dev->id;
+	master->setup = litex_spiflash_spi_setup;
+	master->transfer = litex_spiflash_spi_transfer;
+	master->num_chipselect = 1;
+
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores))
+		return PTR_ERR(iores);
+	litex_spiflash_spi->regs = IOMEM(iores->start);
+
+	litex_spiflash_spi_enable(litex_spiflash_spi);
+
+	/* inactivate chip select signal */
+	litex_spiflash_spi_chipselect(litex_spiflash_spi, 1);
+
+	spi_register_master(master);
+
+	return 0;
+}
+
+static void litex_spiflash_spi_remove(struct device_d *dev)
+{
+	struct litex_spiflash_spi *sp = dev->priv;
+
+	litex_spiflash_spi_disable(sp);
+}
+
+static __maybe_unused struct of_device_id litex_spiflash_spi_dt_ids[] = {
+	{
+		.compatible = "litex,spiflash",
+	},
+	{
+		/* sentinel */
+	}
+};
+
+static struct driver_d litex_spiflash_spi_driver = {
+	.name  = "litex-spiflash",
+	.probe = litex_spiflash_spi_probe,
+	.remove = litex_spiflash_spi_remove,
+	.of_compatible = DRV_OF_COMPAT(litex_spiflash_spi_dt_ids),
+};
+device_platform_driver(litex_spiflash_spi_driver);
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:10:21 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:10:21 +0300
Subject: [PATCH 0/8 v4] RISC-V: add LiteX SoC support
In-Reply-To: <20210817100435.114756-1-antonynpavlov@gmail.com>
References: <20210817100435.114756-1-antonynpavlov@gmail.com>
Message-ID: <20210817131021.674041b1630520e20dbe6995@gmail.com>

On Tue, 17 Aug 2021 13:04:27 +0300
Antony Pavlov <antonynpavlov at gmail.com> wrote:

I have used git format-patch in a inproper way. Sorry!

I'll resend the patchseries.


> Changes since v3:
> 
>   * rebased on top of next branch;
>   * the "console: support set baudrate for fixed baudrate drivers" patch
>     is introduced so the "litex serial: add setbrg callback" patch is dropped;
>   * update mac0 IP-block base addresses in litex dts according to latest
>     SoC configuration.
> 
> Changes since v2:
> 
>   * rebase on top of master branch (f873c7ff2497) +
>     "RISC-V: extend multi-image to support both S- and M-Mode"
>     (http://lists.infradead.org/pipermail/barebox/2021-May/036086.html).
>   * "litex serial: add setbrg callback" patch by Marek Czerski is added
>     for review;
>   * fix "clocksource: timer-riscv: select CSR from device tree" patch;
>   * change gpio IP-block base addresses in litex dts;
>   * gpio-74xx-mmio uses device_get_match_data() now.
> 
> Changes since v1:
> 
>   * rebased on top of next branch;
>   * new patches are introduced:
>     * clocksource: timer-riscv: select CSR from device tree
>     * RISC-V: make RISCV_SBI and RISCV_M_MODE explicitly mutually exclusive
>     * RISC-V: make it possible to build RV32I multi-image with DEBUG_LL=n
>   * almost all of Ahmad's notes are fixed (e.g. unused header files inclusions are dropped);
>   * NOT FIXED: gpio-74xx-mmio still uses dev_get_drvdata(), not device_get_match_data()
> 
> 
> Antony Pavlov (8):
>   clocksource: timer-riscv: select CSR from device tree
>   serial: add litex UART driver
>   console: support set baudrate for fixed baudrate drivers
>   gpio: add driver for 74xx-ICs with MMIO access
>   spi: add litex spiflash driver
>   net: add LiteEth driver
>   RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
>   RISC-V: add litex_linux_defconfig
> 
>  arch/riscv/Kconfig.socs                  |  14 +
>  arch/riscv/boards/Makefile               |   1 +
>  arch/riscv/boards/litex-linux/Makefile   |   3 +
>  arch/riscv/boards/litex-linux/lowlevel.c |  22 ++
>  arch/riscv/configs/litex_linux_defconfig |  75 +++++
>  arch/riscv/dts/Makefile                  |   1 +
>  arch/riscv/dts/erizo.dtsi                |   2 +
>  arch/riscv/dts/litex-linux.dts           |  92 ++++++
>  arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++
>  arch/riscv/include/asm/debug_ll.h        |   3 +
>  arch/riscv/include/asm/debug_ll_litex.h  | 123 ++++++++
>  common/Kconfig                           |   4 +
>  common/console.c                         |  10 +-
>  drivers/clocksource/timer-riscv.c        |  24 +-
>  drivers/gpio/Kconfig                     |  14 +
>  drivers/gpio/Makefile                    |   1 +
>  drivers/gpio/gpio-74xx-mmio.c            | 165 ++++++++++
>  drivers/net/Kconfig                      |   8 +
>  drivers/net/Makefile                     |   1 +
>  drivers/net/liteeth.c                    | 376 +++++++++++++++++++++++
>  drivers/serial/Makefile                  |   1 +
>  drivers/serial/serial_litex.c            |  96 ++++++
>  drivers/spi/Kconfig                      |   3 +
>  drivers/spi/Makefile                     |   1 +
>  drivers/spi/litex_spiflash.c             | 241 +++++++++++++++
>  images/Makefile.riscv                    |   4 +
>  26 files changed, 1318 insertions(+), 16 deletions(-)
>  create mode 100644 arch/riscv/boards/litex-linux/Makefile
>  create mode 100644 arch/riscv/boards/litex-linux/lowlevel.c
>  create mode 100644 arch/riscv/configs/litex_linux_defconfig
>  create mode 100644 arch/riscv/dts/litex-linux.dts
>  create mode 100644 arch/riscv/dts/litex_soc_linux.dtsi
>  create mode 100644 arch/riscv/include/asm/debug_ll_litex.h
>  create mode 100644 drivers/gpio/gpio-74xx-mmio.c
>  create mode 100644 drivers/net/liteeth.c
>  create mode 100644 drivers/serial/serial_litex.c
>  create mode 100644 drivers/spi/litex_spiflash.c
> 
> -- 
> 2.32.0
> 


-- 
Best regards,
? Antony Pavlov


From antonynpavlov at gmail.com  Tue Aug 17 03:10:56 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:10:56 +0300
Subject: [PATCH RESEND v4 0/8] RISC-V: add LiteX SoC support
Message-ID: <20210817101104.114945-1-antonynpavlov@gmail.com>

Changes since v3:

  * rebased on top of next branch;
  * the "console: support set baudrate for fixed baudrate drivers" patch
    is introduced so the "litex serial: add setbrg callback" patch is dropped;
  * update mac0 IP-block base addresses in litex dts according to latest
    SoC configuration.

Changes since v2:

  * rebase on top of master branch (f873c7ff2497) +
    "RISC-V: extend multi-image to support both S- and M-Mode"
    (http://lists.infradead.org/pipermail/barebox/2021-May/036086.html).
  * "litex serial: add setbrg callback" patch by Marek Czerski is added
    for review;
  * fix "clocksource: timer-riscv: select CSR from device tree" patch;
  * change gpio IP-block base addresses in litex dts;
  * gpio-74xx-mmio uses device_get_match_data() now.

Changes since v1:

  * rebased on top of next branch;
  * new patches are introduced:
    * clocksource: timer-riscv: select CSR from device tree
    * RISC-V: make RISCV_SBI and RISCV_M_MODE explicitly mutually exclusive
    * RISC-V: make it possible to build RV32I multi-image with DEBUG_LL=n
  * almost all of Ahmad's notes are fixed (e.g. unused header files inclusions are dropped);
  * NOT FIXED: gpio-74xx-mmio still uses dev_get_drvdata(), not device_get_match_data()


Antony Pavlov (8):
  clocksource: timer-riscv: select CSR from device tree
  serial: add litex UART driver
  console: support set baudrate for fixed baudrate drivers
  gpio: add driver for 74xx-ICs with MMIO access
  spi: add litex spiflash driver
  net: add LiteEth driver
  RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
  RISC-V: add litex_linux_defconfig

 arch/riscv/Kconfig.socs                  |  14 +
 arch/riscv/boards/Makefile               |   1 +
 arch/riscv/boards/litex-linux/Makefile   |   3 +
 arch/riscv/boards/litex-linux/lowlevel.c |  22 ++
 arch/riscv/configs/litex_linux_defconfig |  75 +++++
 arch/riscv/dts/Makefile                  |   1 +
 arch/riscv/dts/erizo.dtsi                |   2 +
 arch/riscv/dts/litex-linux.dts           |  92 ++++++
 arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++
 arch/riscv/include/asm/debug_ll.h        |   3 +
 arch/riscv/include/asm/debug_ll_litex.h  | 123 ++++++++
 common/Kconfig                           |   4 +
 common/console.c                         |  10 +-
 drivers/clocksource/timer-riscv.c        |  24 +-
 drivers/gpio/Kconfig                     |  14 +
 drivers/gpio/Makefile                    |   1 +
 drivers/gpio/gpio-74xx-mmio.c            | 165 ++++++++++
 drivers/net/Kconfig                      |   8 +
 drivers/net/Makefile                     |   1 +
 drivers/net/liteeth.c                    | 376 +++++++++++++++++++++++
 drivers/serial/Makefile                  |   1 +
 drivers/serial/serial_litex.c            |  96 ++++++
 drivers/spi/Kconfig                      |   3 +
 drivers/spi/Makefile                     |   1 +
 drivers/spi/litex_spiflash.c             | 241 +++++++++++++++
 images/Makefile.riscv                    |   4 +
 26 files changed, 1318 insertions(+), 16 deletions(-)
 create mode 100644 arch/riscv/boards/litex-linux/Makefile
 create mode 100644 arch/riscv/boards/litex-linux/lowlevel.c
 create mode 100644 arch/riscv/configs/litex_linux_defconfig
 create mode 100644 arch/riscv/dts/litex-linux.dts
 create mode 100644 arch/riscv/dts/litex_soc_linux.dtsi
 create mode 100644 arch/riscv/include/asm/debug_ll_litex.h
 create mode 100644 drivers/gpio/gpio-74xx-mmio.c
 create mode 100644 drivers/net/liteeth.c
 create mode 100644 drivers/serial/serial_litex.c
 create mode 100644 drivers/spi/litex_spiflash.c

-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:10:57 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:10:57 +0300
Subject: [PATCH RESEND v4 1/8] clocksource: timer-riscv: select CSR from
 device tree
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-2-antonynpavlov@gmail.com>

barebox timer-riscv driver supports one of user counters:

  * 'cycle', counter for RDCYCLE instruction (CSR 0xc00);
  * 'time', timer for RDTIME instruction (CSR 0xc01).

At the moment in M-mode timer-riscv uses the 'cycle' counter,
and in S-mode timer-riscv uses the 'time' timer.

Alas picorv32 CPU core supports only the 'cycle' counter.
VexRiscV CPU core in M-mode supports only the 'time' timer.

This patch makes it possible to use the 'time' timer
for VexRiscV CPU in M-mode.

See also http://lists.infradead.org/pipermail/barebox/2021-May/036067.html

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/dts/erizo.dtsi         |  2 ++
 drivers/clocksource/timer-riscv.c | 24 ++++++++++++------------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/arch/riscv/dts/erizo.dtsi b/arch/riscv/dts/erizo.dtsi
index 228711bd69..4eb92ae6f1 100644
--- a/arch/riscv/dts/erizo.dtsi
+++ b/arch/riscv/dts/erizo.dtsi
@@ -22,6 +22,8 @@
 
 		timebase-frequency = <24000000>;
 
+		barebox,csr-cycle;
+
 		cpu at 0 {
 			device_type = "cpu";
 			compatible = "cliffordwolf,picorv32", "riscv";
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 5a517fe6b4..96637f988a 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -12,9 +12,8 @@
 #include <clock.h>
 #include <asm/timer.h>
 #include <asm/csr.h>
-#include <asm/system.h>
 
-static u64 notrace riscv_timer_get_count_sbi(void)
+static u64 notrace riscv_timer_get_count_time(void)
 {
 	__maybe_unused u32 hi, lo;
 
@@ -29,7 +28,7 @@ static u64 notrace riscv_timer_get_count_sbi(void)
 	return ((u64)hi << 32) | lo;
 }
 
-static u64 notrace riscv_timer_get_count_rdcycle(void)
+static u64 notrace riscv_timer_get_count_cycle(void)
 {
 	__maybe_unused u32 hi, lo;
 
@@ -44,24 +43,25 @@ static u64 notrace riscv_timer_get_count_rdcycle(void)
 	return ((u64)hi << 32) | lo;
 }
 
-static u64 notrace riscv_timer_get_count(void)
-{
-	if (riscv_mode() == RISCV_S_MODE)
-		return riscv_timer_get_count_sbi();
-	else
-		return riscv_timer_get_count_rdcycle();
-}
-
 static struct clocksource riscv_clocksource = {
-	.read		= riscv_timer_get_count,
 	.mask		= CLOCKSOURCE_MASK(64),
 	.priority	= 100,
 };
 
 static int riscv_timer_init(struct device_d* dev)
 {
+	struct device_node *cpu;
+
 	dev_dbg(dev, "running at %lu Hz\n", riscv_timebase);
 
+	cpu = of_find_node_by_path("/cpus");
+
+	if (of_property_read_bool(cpu, "barebox,csr-cycle")) {
+		riscv_clocksource.read = riscv_timer_get_count_cycle;
+	} else {
+		riscv_clocksource.read = riscv_timer_get_count_time;
+	}
+
 	riscv_clocksource.mult = clocksource_hz2mult(riscv_timebase, riscv_clocksource.shift);
 
 	return init_clock(&riscv_clocksource);
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:10:58 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:10:58 +0300
Subject: [PATCH RESEND v4 2/8] serial: add litex UART driver
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-3-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 drivers/serial/Makefile       |  1 +
 drivers/serial/serial_litex.c | 96 +++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)

diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5120b17376..45055371ea 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_DRIVER_SERIAL_DIGIC)		+= serial_digic.o
 obj-$(CONFIG_DRIVER_SERIAL_LPUART)		+= serial_lpuart.o
 obj-$(CONFIG_VIRTIO_CONSOLE)			+= virtio_console.o
 obj-$(CONFIG_SERIAL_SIFIVE)			+= serial_sifive.o
+obj-$(CONFIG_SOC_LITEX)				+= serial_litex.o
diff --git a/drivers/serial/serial_litex.c b/drivers/serial/serial_litex.c
new file mode 100644
index 0000000000..8562a45ecc
--- /dev/null
+++ b/drivers/serial/serial_litex.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+
+#define UART_RXTX	0x00
+#define UART_TXFULL	0x04
+#define UART_RXEMPTY	0x08
+#define UART_EV_PENDING	0x10
+#define  UART_EV_RX	(1 << 1)
+
+static inline uint32_t litex_serial_readb(struct console_device *cdev,
+						uint32_t offset)
+{
+	void __iomem *base = cdev->dev->priv;
+
+	return readb(base + offset);
+}
+
+static inline void litex_serial_writeb(struct console_device *cdev,
+					uint32_t value, uint32_t offset)
+{
+	void __iomem *base = cdev->dev->priv;
+
+	writeb(value, base + offset);
+}
+
+static void litex_serial_putc(struct console_device *cdev, char c)
+{
+	while (litex_serial_readb(cdev, UART_TXFULL))
+		;
+
+	litex_serial_writeb(cdev, c, UART_RXTX);
+}
+
+static int litex_serial_getc(struct console_device *cdev)
+{
+	int c;
+
+	while (litex_serial_readb(cdev, UART_RXEMPTY))
+		;
+
+	c = litex_serial_readb(cdev, UART_RXTX);
+
+	/* refresh UART_RXEMPTY by writing UART_EV_RX to UART_EV_PENDING */
+	litex_serial_writeb(cdev, UART_EV_RX, UART_EV_PENDING);
+
+	return c;
+}
+
+static int litex_serial_tstc(struct console_device *cdev)
+{
+	return !litex_serial_readb(cdev, UART_RXEMPTY);
+}
+
+static int litex_serial_probe(struct device_d *dev)
+{
+	struct resource *iores;
+	struct console_device *cdev;
+
+	cdev = xzalloc(sizeof(struct console_device));
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores))
+		return PTR_ERR(iores);
+
+	dev->priv = IOMEM(iores->start);
+	cdev->dev = dev;
+	cdev->tstc = &litex_serial_tstc;
+	cdev->putc = &litex_serial_putc;
+	cdev->getc = &litex_serial_getc;
+	cdev->setbrg = NULL;
+
+	console_register(cdev);
+
+	return 0;
+}
+
+static __maybe_unused struct of_device_id litex_serial_dt_ids[] = {
+	{
+		.compatible = "litex,uart",
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct driver_d litex_serial_driver = {
+	.name  = "litex-uart",
+	.probe = litex_serial_probe,
+	.of_compatible = DRV_OF_COMPAT(litex_serial_dt_ids),
+};
+console_platform_driver(litex_serial_driver);
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:11:00 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:11:00 +0300
Subject: [PATCH RESEND v4 4/8] gpio: add driver for 74xx-ICs with MMIO access
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-5-antonynpavlov@gmail.com>

This patch adds driver to support GPIO functionality
for 74xx-compatible ICs with MMIO access.

Compatible models include:
     1 bit:   741G125 (Input), 741G74 (Output)
     2 bits:  742G125 (Input), 7474 (Output)
     4 bits:  74125 (Input), 74175 (Output)
     6 bits:  74365 (Input), 74174 (Output)
     8 bits:  74244 (Input), 74273 (Output)
     16 bits: 741624 (Input), 7416374 (Output)

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
Cc: Alexander Shiyan <shc_work at mail.ru>
---
 drivers/gpio/Kconfig          |  14 +++
 drivers/gpio/Makefile         |   1 +
 drivers/gpio/gpio-74xx-mmio.c | 165 ++++++++++++++++++++++++++++++++++
 3 files changed, 180 insertions(+)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 98a44fbbb5..f79c9ea67d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -21,6 +21,20 @@ config GPIO_74164
 	  shift registers. This driver can be used to provide access
 	  to more gpio outputs.
 
+config GPIO_74XX_MMIO
+	tristate "GPIO driver for 74xx-ICs with MMIO access"
+	depends on OFDEVICE
+	select GPIO_GENERIC
+	help
+	  Say yes here to support GPIO functionality for 74xx-compatible ICs
+	  with MMIO access. Compatible models include:
+	    1 bit:	741G125 (Input), 741G74 (Output)
+	    2 bits:	742G125 (Input), 7474 (Output)
+	    4 bits:	74125 (Input), 74175 (Output)
+	    6 bits:	74365 (Input), 74174 (Output)
+	    8 bits:	74244 (Input), 74273 (Output)
+	    16 bits:	741624 (Input), 7416374 (Output)
+
 config GPIO_CLPS711X
 	bool "GPIO support for CLPS711X"
 	depends on ARCH_CLPS711X || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 638cbb19a3..023973cb63 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o
 
 obj-$(CONFIG_GPIO_74164)	+= gpio-74164.o
+obj-$(CONFIG_GPIO_74XX_MMIO)	+= gpio-74xx-mmio.o
 obj-$(CONFIG_MACH_MIPS_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_DAVINCI)	+= gpio-davinci.o
 obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c
new file mode 100644
index 0000000000..5b688f4766
--- /dev/null
+++ b/drivers/gpio/gpio-74xx-mmio.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 74xx MMIO GPIO driver
+ *
+ *  Copyright (C) 2014 Alexander Shiyan <shc_work at mail.ru>
+ *
+ * Ported to barebox from linux-v5.4-rc6
+ *   Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <malloc.h>
+#include <of_device.h>
+
+#include <linux/err.h>
+#include <linux/basic_mmio_gpio.h>
+
+#define MMIO_74XX_DIR_IN	(0 << 8)
+#define MMIO_74XX_DIR_OUT	(1 << 8)
+#define MMIO_74XX_BIT_CNT(x)	((x) & 0xff)
+
+struct mmio_74xx_gpio_priv {
+	struct bgpio_chip	bgc;
+	unsigned int		flags;
+};
+
+static const struct of_device_id mmio_74xx_gpio_ids[] = {
+	{
+		.compatible	= "ti,741g125",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 1),
+	},
+	{
+		.compatible	= "ti,742g125",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 2),
+	},
+	{
+		.compatible	= "ti,74125",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 4),
+	},
+	{
+		.compatible	= "ti,74365",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 6),
+	},
+	{
+		.compatible	= "ti,74244",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 8),
+	},
+	{
+		.compatible	= "ti,741624",
+		.data		= (const void *)(MMIO_74XX_DIR_IN | 16),
+	},
+	{
+		.compatible	= "ti,741g74",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 1),
+	},
+	{
+		.compatible	= "ti,7474",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 2),
+	},
+	{
+		.compatible	= "ti,74175",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 4),
+	},
+	{
+		.compatible	= "ti,74174",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 6),
+	},
+	{
+		.compatible	= "ti,74273",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 8),
+	},
+	{
+		.compatible	= "ti,7416374",
+		.data		= (const void *)(MMIO_74XX_DIR_OUT | 16),
+	},
+	{ }
+};
+
+static inline
+struct mmio_74xx_gpio_priv *to_mmio_74xx_gpio_priv(struct gpio_chip *gc)
+{
+	struct bgpio_chip *bgc =
+		container_of(gc, struct bgpio_chip, gc);
+
+	return container_of(bgc, struct mmio_74xx_gpio_priv, bgc);
+}
+
+static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc);
+
+	if (priv->flags & MMIO_74XX_DIR_OUT)
+		return GPIOF_DIR_OUT;
+
+	return GPIOF_DIR_IN;
+}
+
+static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc);
+
+	return (priv->flags & MMIO_74XX_DIR_OUT) ? -ENOTSUPP : 0;
+}
+
+static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc);
+
+	if (priv->flags & MMIO_74XX_DIR_OUT) {
+		gc->ops->set(gc, gpio, val);
+		return 0;
+	}
+
+	return -ENOTSUPP;
+}
+
+static int mmio_74xx_gpio_probe(struct device_d *dev)
+{
+	struct mmio_74xx_gpio_priv *priv;
+	void __iomem *dat;
+	int err;
+	struct gpio_chip *gc;
+
+	priv = xzalloc(sizeof(*priv));
+
+	priv->flags = (uintptr_t)of_device_get_match_data(dev);
+
+	dat = dev_request_mem_region(dev, 0);
+	if (IS_ERR(dat))
+		return PTR_ERR(dat);
+
+	err = bgpio_init(&priv->bgc, dev,
+			 DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
+			 dat, NULL, NULL, NULL, NULL, 0);
+	if (err)
+		return err;
+
+	gc = &priv->bgc.gc;
+	gc->ops->direction_input = mmio_74xx_dir_in;
+	gc->ops->direction_output = mmio_74xx_dir_out;
+	gc->ops->get_direction = mmio_74xx_get_direction;
+	gc->ngpio = MMIO_74XX_BIT_CNT(priv->flags);
+
+	dev->priv = priv;
+
+	return gpiochip_add(gc);
+}
+
+static struct driver_d mmio_74xx_gpio_driver = {
+	.name = "74xx-mmio-gpio",
+	.of_compatible	= DRV_OF_COMPAT(mmio_74xx_gpio_ids),
+	.probe = mmio_74xx_gpio_probe,
+};
+
+coredevice_platform_driver(mmio_74xx_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
+MODULE_DESCRIPTION("74xx MMIO GPIO driver");
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:11:02 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:11:02 +0300
Subject: [PATCH RESEND v4 6/8] net: add LiteEth driver
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-7-antonynpavlov@gmail.com>

LiteEth provides a small footprint and configurable Ethernet core.

LiteEth is part of LiteX libraries whose aims are to lower entry level of
complex FPGA cores by providing simple, elegant and efficient implementations
of components used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller...

Using Migen to describe the HDL allows the core to be highly and easily configurable.

LiteEth can be used as LiteX library or can be integrated with your standard
design flow by generating the verilog rtl that you will use as a standard core.

See https://github.com/enjoy-digital/liteeth for details.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
Signed-off-by: Marek Czerski <m.czerski at ap-tech.pl>
---
 drivers/net/Kconfig   |   8 +
 drivers/net/Makefile  |   1 +
 drivers/net/liteeth.c | 376 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 385 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 802169a86e..781c7e69db 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -285,6 +285,14 @@ config TSE_USE_DEDICATED_DESC_MEM
 	  reserved with a malloc but directly mapped to the memory
 	  address (defined in config.h)
 
+config DRIVER_NET_LITEETH
+	bool "LiteX ethernet driver"
+	select PHYLIB
+	select MDIO_BITBANG
+	help
+	  This option enables support for the LiteX LiteEth
+	  ethernet IP core.
+
 source "drivers/net/phy/Kconfig"
 source "drivers/net/usb/Kconfig"
 
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fb3e3bdee4..466c910b3e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_DRIVER_NET_TAP)		+= tap.o
 obj-$(CONFIG_DRIVER_NET_TSE)		+= altera_tse.o
 obj-$(CONFIG_DRIVER_NET_EFI_SNP)	+= efi-snp.o
 obj-$(CONFIG_DRIVER_NET_AG71XX)		+= ag71xx.o
+obj-$(CONFIG_DRIVER_NET_LITEETH)	+= liteeth.o
diff --git a/drivers/net/liteeth.c b/drivers/net/liteeth.c
new file mode 100644
index 0000000000..137cb854c5
--- /dev/null
+++ b/drivers/net/liteeth.c
@@ -0,0 +1,376 @@
+/*
+ * LiteX Liteeth Ethernet
+ *
+ * Copyright 2017 Joel Stanley <joel at jms.id.au>
+ *
+ * Ported to barebox from linux kernel
+ *   Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov at gmail.com>
+ *   Copyright (C) 2021 Marek Czerski <m.czerski at ap-tech.pl>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <linux/iopoll.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <of_net.h>
+#include <linux/phy.h>
+#include <linux/mdio-bitbang.h>
+
+#define DRV_NAME	"liteeth"
+
+#define LITEETH_WRITER_SLOT		0x00
+#define LITEETH_WRITER_LENGTH		0x04
+#define LITEETH_WRITER_ERRORS		0x08
+#define LITEETH_WRITER_EV_STATUS	0x0c
+#define LITEETH_WRITER_EV_PENDING	0x10
+#define LITEETH_WRITER_EV_ENABLE	0x14
+#define LITEETH_READER_START		0x18
+#define LITEETH_READER_READY		0x1c
+#define LITEETH_READER_LEVEL		0x20
+#define LITEETH_READER_SLOT		0x24
+#define LITEETH_READER_LENGTH		0x28
+#define LITEETH_READER_EV_STATUS	0x2c
+#define LITEETH_READER_EV_PENDING	0x30
+#define LITEETH_READER_EV_ENABLE	0x34
+#define LITEETH_PREAMBLE_CRC		0x38
+#define LITEETH_PREAMBLE_ERRORS		0x3c
+#define LITEETH_CRC_ERRORS		0x40
+
+#define LITEETH_PHY_CRG_RESET		0x00
+#define LITEETH_MDIO_W			0x04
+#define  MDIO_W_CLK			BIT(0)
+#define  MDIO_W_OE			BIT(1)
+#define  MDIO_W_DO			BIT(2)
+
+#define LITEETH_MDIO_R			0x08
+#define  MDIO_R_DI			BIT(0)
+
+#define LITEETH_BUFFER_SIZE		0x800
+#define MAX_PKT_SIZE			LITEETH_BUFFER_SIZE
+
+struct liteeth {
+	struct device_d *dev;
+	struct eth_device edev;
+	void __iomem *base;
+	void __iomem *mdio_base;
+	struct mii_bus *mii_bus;
+	struct mdiobb_ctrl mdiobb;
+
+	/* Link management */
+	int cur_duplex;
+	int cur_speed;
+
+	/* Tx */
+	int tx_slot;
+	int num_tx_slots;
+	void __iomem *tx_base;
+
+	/* Rx */
+	int rx_slot;
+	int num_rx_slots;
+	void __iomem *rx_base;
+};
+
+static inline void litex_write8(void __iomem *addr, u8 val)
+{
+	writeb(val, addr);
+}
+
+static inline void litex_write16(void __iomem *addr, u16 val)
+{
+	writew(val, addr);
+}
+
+static inline u8 litex_read8(void __iomem *addr)
+{
+	return readb(addr);
+}
+
+static inline u32 litex_read32(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static void liteeth_mdio_w_modify(struct liteeth *priv, u8 clear, u8 set)
+{
+	void __iomem *mdio_w = priv->mdio_base + LITEETH_MDIO_W;
+
+	litex_write8(mdio_w, (litex_read8(mdio_w) & ~clear) | set);
+}
+
+static void liteeth_mdio_ctrl(struct mdiobb_ctrl *ctrl, u8 mask, int set)
+{
+	struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb);
+
+	liteeth_mdio_w_modify(priv, mask, set ? mask : 0);
+}
+
+/* MDC pin control */
+static void liteeth_set_mdc(struct mdiobb_ctrl *ctrl, int level)
+{
+	liteeth_mdio_ctrl(ctrl, MDIO_W_CLK, level);
+}
+
+/* Data I/O pin control */
+static void liteeth_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output)
+{
+	liteeth_mdio_ctrl(ctrl, MDIO_W_OE, output);
+}
+
+/* Set data bit */
+static void liteeth_set_mdio_data(struct mdiobb_ctrl *ctrl, int value)
+{
+	liteeth_mdio_ctrl(ctrl, MDIO_W_DO, value);
+}
+
+/* Get data bit */
+static int liteeth_get_mdio_data(struct mdiobb_ctrl *ctrl)
+{
+	struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb);
+
+	return (litex_read8(priv->mdio_base + LITEETH_MDIO_R) & MDIO_R_DI) != 0;
+}
+
+/* MDIO bus control struct */
+static struct mdiobb_ops bb_ops = {
+	.set_mdc = liteeth_set_mdc,
+	.set_mdio_dir = liteeth_set_mdio_dir,
+	.set_mdio_data = liteeth_set_mdio_data,
+	.get_mdio_data = liteeth_get_mdio_data,
+};
+
+static int liteeth_init_dev(struct eth_device *edev)
+{
+	return 0;
+}
+
+static int liteeth_eth_open(struct eth_device *edev)
+{
+	struct liteeth *priv = edev->priv;
+	int ret;
+
+	/* Disable events */
+	litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0);
+	litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0);
+
+	/* Clear pending events? */
+	litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, 1);
+	litex_write8(priv->base + LITEETH_READER_EV_PENDING, 1);
+
+	ret = phy_device_connect(edev, priv->mii_bus, -1, NULL, 0, -1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int liteeth_eth_send(struct eth_device *edev, void *packet,
+				int packet_length)
+{
+	struct liteeth *priv = edev->priv;
+	void *txbuffer;
+	int ret;
+	u8 val;
+	u8 reg;
+
+	reg = litex_read8(priv->base + LITEETH_READER_EV_PENDING);
+	if (reg) {
+		litex_write8(priv->base + LITEETH_READER_EV_PENDING, reg);
+	}
+
+	/* Reject oversize packets */
+	if (unlikely(packet_length > MAX_PKT_SIZE)) {
+		dev_err(priv->dev, "tx packet too big\n");
+		goto drop;
+	}
+
+	txbuffer = priv->tx_base + priv->tx_slot * LITEETH_BUFFER_SIZE;
+	memcpy(txbuffer, packet, packet_length);
+	litex_write8(priv->base + LITEETH_READER_SLOT, priv->tx_slot);
+	litex_write16(priv->base + LITEETH_READER_LENGTH, packet_length);
+
+	ret = readb_poll_timeout(priv->base + LITEETH_READER_READY,
+			val, val, 1000);
+	if (ret == -ETIMEDOUT) {
+		dev_err(priv->dev, "LITEETH_READER_READY timed out\n");
+		goto drop;
+	}
+
+	litex_write8(priv->base + LITEETH_READER_START, 1);
+
+	priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots;
+
+drop:
+	return 0;
+}
+
+static int liteeth_eth_rx(struct eth_device *edev)
+{
+	struct liteeth *priv = edev->priv;
+	u8 rx_slot;
+	int len = 0;
+	u8 reg;
+
+	reg = litex_read8(priv->base + LITEETH_WRITER_EV_PENDING);
+	if (!reg) {
+		goto done;
+	}
+
+	len = litex_read32(priv->base + LITEETH_WRITER_LENGTH);
+	if (len == 0 || len > 2048) {
+		len = 0;
+		dev_err(priv->dev, "%s: invalid len %d\n", __func__, len);
+		litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg);
+		goto done;
+	}
+
+	rx_slot = litex_read8(priv->base + LITEETH_WRITER_SLOT);
+
+	memcpy(NetRxPackets[0], priv->rx_base + rx_slot * LITEETH_BUFFER_SIZE, len);
+
+	net_receive(edev, NetRxPackets[0], len);
+
+	litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg);
+
+done:
+	return len;
+}
+
+static void liteeth_eth_halt(struct eth_device *edev)
+{
+	struct liteeth *priv = edev->priv;
+
+	litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0);
+	litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0);
+}
+
+static void liteeth_reset_hw(struct liteeth *priv)
+{
+	/* Reset, twice */
+	litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0);
+	udelay(10);
+	litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 1);
+	udelay(10);
+	litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0);
+	udelay(10);
+}
+
+static int liteeth_get_ethaddr(struct eth_device *edev, unsigned char *m)
+{
+	return 0;
+}
+
+static int liteeth_set_ethaddr(struct eth_device *edev,
+					const unsigned char *mac_addr)
+{
+	return 0;
+}
+
+static int liteeth_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	struct eth_device *edev;
+	void __iomem *buf_base;
+	struct liteeth *priv;
+	int err;
+
+	priv = xzalloc(sizeof(struct liteeth));
+	edev = &priv->edev;
+	edev->priv = priv;
+	priv->dev = dev;
+
+	priv->base = dev_request_mem_region(dev, 0);
+	if (IS_ERR(priv->base)) {
+		err = PTR_ERR(priv->base);
+		goto err;
+	}
+
+	priv->mdio_base = dev_request_mem_region(dev, 1);
+	if (IS_ERR(priv->mdio_base)) {
+		err = PTR_ERR(priv->mdio_base);
+		goto err;
+	}
+
+	buf_base = dev_request_mem_region(dev, 2);
+	if (IS_ERR(buf_base)) {
+		err = PTR_ERR(buf_base);
+		goto err;
+	}
+
+	err = of_property_read_u32(np, "rx-fifo-depth",
+			&priv->num_rx_slots);
+	if (err) {
+		dev_err(dev, "unable to get rx-fifo-depth\n");
+		goto err;
+	}
+
+	err = of_property_read_u32(np, "tx-fifo-depth",
+			&priv->num_tx_slots);
+	if (err) {
+		dev_err(dev, "unable to get tx-fifo-depth\n");
+		goto err;
+	}
+
+	/* Rx slots */
+	priv->rx_base = buf_base;
+	priv->rx_slot = 0;
+
+	/* Tx slots come after Rx slots */
+	priv->tx_base = buf_base + priv->num_rx_slots * LITEETH_BUFFER_SIZE;
+	priv->tx_slot = 0;
+
+	edev->init = liteeth_init_dev;
+	edev->open = liteeth_eth_open;
+	edev->send = liteeth_eth_send;
+	edev->recv = liteeth_eth_rx;
+	edev->get_ethaddr = liteeth_get_ethaddr;
+	edev->set_ethaddr = liteeth_set_ethaddr;
+	edev->halt = liteeth_eth_halt;
+	edev->parent = dev;
+
+	priv->mdiobb.ops = &bb_ops;
+
+	priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
+	priv->mii_bus->parent = dev;
+
+	liteeth_reset_hw(priv);
+
+	err = eth_register(edev);
+	if (err) {
+		dev_err(dev, "failed to register edev\n");
+		goto err;
+	}
+
+	err = mdiobus_register(priv->mii_bus);
+	if (err) {
+		dev_err(dev, "failed to register mii_bus\n");
+		goto err;
+	}
+
+	dev_info(dev, DRV_NAME " driver registered\n");
+
+	return 0;
+
+err:
+	return err;
+}
+
+static const struct of_device_id liteeth_dt_ids[] = {
+	{
+		.compatible = "litex,liteeth"
+	}, {
+	}
+};
+
+static struct driver_d liteeth_driver = {
+	.name = DRV_NAME,
+	.probe = liteeth_probe,
+	.of_compatible = DRV_OF_COMPAT(liteeth_dt_ids),
+};
+device_platform_driver(liteeth_driver);
+
+MODULE_AUTHOR("Joel Stanley <joel at jms.id.au>");
+MODULE_LICENSE("GPL");
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:11:04 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:11:04 +0300
Subject: [PATCH RESEND v4 8/8] RISC-V: add litex_linux_defconfig
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-9-antonynpavlov@gmail.com>

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

diff --git a/arch/riscv/configs/litex_linux_defconfig b/arch/riscv/configs/litex_linux_defconfig
new file mode 100644
index 0000000000..8e19964890
--- /dev/null
+++ b/arch/riscv/configs/litex_linux_defconfig
@@ -0,0 +1,75 @@
+CONFIG_SOC_LITEX=y
+CONFIG_STACK_SIZE=0x20000
+CONFIG_MALLOC_SIZE=0xf00000
+CONFIG_MALLOC_TLSF=y
+CONFIG_PANIC_HANG=y
+CONFIG_BAUDRATE=1000000
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_TIMESTAMP is not set
+CONFIG_BOOTM_SHOW_TYPE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_BOOTM_INITRD=y
+CONFIG_BOOTM_OFTREE=y
+CONFIG_BOOTM_OFTREE_UIMAGE=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=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_EXPORT=y
+CONFIG_CMD_CMP=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_OF_DUMP=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_NET=y
+CONFIG_NET_NFS=y
+CONFIG_NET_NETCONSOLE=y
+CONFIG_DRIVER_NET_LITEETH=y
+CONFIG_AR8327N_PHY=y
+CONFIG_AT803X_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_DRIVER_SPI_LITEX_SPIFLASH=y
+CONFIG_MTD=y
+# CONFIG_MTD_OOB_DEVICE is not set
+CONFIG_MTD_M25P80=y
+CONFIG_CLOCKSOURCE_DUMMY_RATE=20000
+CONFIG_SRAM=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
+CONFIG_GPIO_74XX_MMIO=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_PINCTRL is not set
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_DIGEST_CRC32_GENERIC=y
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:10:59 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:10:59 +0300
Subject: [PATCH RESEND v4 3/8] console: support set baudrate for fixed
 baudrate drivers
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-4-antonynpavlov@gmail.com>

There are console drivers (linux, virtio, litex)
that don't support baud rate setting and has
no setbrg (set baudrate) callback, so
console_set_baudrate() returns -ENOSYS.

At the other hand console_set_baudrate() SUCCESS
return value is needed for the loadx/loady commands
correct work.

See discussion here:

  http://lists.infradead.org/pipermail/barebox/2021-May/036237.html

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 common/console.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/common/console.c b/common/console.c
index ad1a6aaab2..c902239e31 100644
--- a/common/console.c
+++ b/common/console.c
@@ -165,12 +165,12 @@ int console_set_baudrate(struct console_device *cdev, unsigned baudrate)
 	int ret;
 	unsigned char c;
 
-	if (!cdev->setbrg)
-		return -ENOSYS;
-
 	if (cdev->baudrate == baudrate)
 		return 0;
 
+	if (!cdev->setbrg)
+		return -ENOSYS;
+
 	/*
 	 * If the device is already active, change its baudrate.
 	 * The baudrate of an inactive device will be set at activation time.
@@ -336,11 +336,13 @@ int console_register(struct console_device *newcdev)
 		ret = newcdev->setbrg(newcdev, baudrate);
 		if (ret)
 			return ret;
-		newcdev->baudrate_param = newcdev->baudrate = baudrate;
+		newcdev->baudrate_param = baudrate;
 		dev_add_param_uint32(dev, "baudrate", console_baudrate_set,
 			NULL, &newcdev->baudrate_param, "%u", newcdev);
 	}
 
+	newcdev->baudrate = baudrate;
+
 	if (newcdev->putc && !newcdev->puts)
 		newcdev->puts = __console_puts;
 
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:11:01 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:11:01 +0300
Subject: [PATCH RESEND v4 5/8] spi: add litex spiflash driver
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-6-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 drivers/spi/Kconfig          |   3 +
 drivers/spi/Makefile         |   1 +
 drivers/spi/litex_spiflash.c | 241 +++++++++++++++++++++++++++++++++++
 3 files changed, 245 insertions(+)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 91083ee709..e92cf675ab 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -74,6 +74,9 @@ config DRIVER_SPI_IMX_2_3
 	depends on ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6 || ARCH_IMX7 || ARCH_IMX8M
 	default y
 
+config DRIVER_SPI_LITEX_SPIFLASH
+	bool "Litex SPIFLASH bitbang master driver"
+
 config DRIVER_SPI_MXS
 	bool "i.MX (23,28) SPI Master driver"
 	depends on ARCH_IMX28
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 908d514a01..ac95ffc1db 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_DRIVER_SPI_ATH79) += ath79_spi.o
 obj-$(CONFIG_DRIVER_SPI_GPIO) += gpio_spi.o
 obj-$(CONFIG_DRIVER_SPI_FSL_QUADSPI) += spi-fsl-qspi.o
 obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
+obj-$(CONFIG_DRIVER_SPI_LITEX_SPIFLASH) += litex_spiflash.o
 obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o
 obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o
 obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o
diff --git a/drivers/spi/litex_spiflash.c b/drivers/spi/litex_spiflash.c
new file mode 100644
index 0000000000..26ef207699
--- /dev/null
+++ b/drivers/spi/litex_spiflash.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <spi/spi.h>
+#include <io.h>
+
+struct litex_spiflash_spi {
+	struct spi_master	master;
+	void __iomem		*regs;
+	u32			val;
+};
+
+#define SPIFLASH_BITBANG 0x0
+#define  SPIFLASH_BB_MOSI BIT(0)
+#define  SPIFLASH_BB_CLK BIT(1)
+#define  SPIFLASH_BB_CSN BIT(2)
+#define  SPIFLASH_BB_DIR BIT(3)
+
+#define SPIFLASH_MISO 0x4
+#define SPIFLASH_BITBANG_EN 0x8
+
+static inline u32 litex_spiflash_spi_rr(struct litex_spiflash_spi *sp, int reg)
+{
+	return readl(sp->regs + reg);
+}
+
+static inline void litex_spiflash_spi_wr(struct litex_spiflash_spi *sp, u32 val, int reg)
+{
+	writel(val, sp->regs + reg);
+}
+
+static inline void setbits(struct litex_spiflash_spi *sp, int bits, int on)
+{
+	/*
+	 * We are the only user of SCSPTR so no locking is required.
+	 * Reading bit 2 and 0 in SCSPTR gives pin state as input.
+	 * Writing the same bits sets the output value.
+	 * This makes regular read-modify-write difficult so we
+	 * use sp->val to keep track of the latest register value.
+	 */
+
+	if (on)
+		sp->val |= bits;
+	else
+		sp->val &= ~bits;
+
+	litex_spiflash_spi_wr(sp, sp->val, SPIFLASH_BITBANG);
+}
+
+static inline struct litex_spiflash_spi *litex_spiflash_spidev_to_sp(struct spi_device *spi)
+{
+	return container_of(spi->master, struct litex_spiflash_spi, master);
+}
+
+static inline void setsck(struct spi_device *spi, int on)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+
+	setbits(sc, SPIFLASH_BB_CLK, on);
+}
+
+static inline void setmosi(struct spi_device *spi, int on)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+
+	sc->val &= ~SPIFLASH_BB_DIR;
+	setbits(sc, SPIFLASH_BB_MOSI, on);
+}
+
+static inline u32 getmiso(struct spi_device *spi)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+
+	setbits(sc, SPIFLASH_BB_DIR, 1);
+	return !!((litex_spiflash_spi_rr(sc, SPIFLASH_MISO) & 1));
+}
+
+#define spidelay(nsecs) udelay(nsecs/1000)
+
+#include "spi-bitbang-txrx.h"
+
+static inline void litex_spiflash_spi_chipselect(struct litex_spiflash_spi *sc, int on)
+{
+	setbits(sc, SPIFLASH_BB_CSN, on);
+}
+
+static int litex_spiflash_spi_setup(struct spi_device *spi)
+{
+	struct spi_master *master = spi->master;
+	struct device_d spi_dev = spi->dev;
+
+	if (spi->bits_per_word != 8) {
+		dev_err(master->dev, "master doesn't support %d bits per word requested by %s\n",
+			spi->bits_per_word, spi_dev.name);
+		return -EINVAL;
+	}
+
+	if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != SPI_MODE_0) {
+		dev_err(master->dev, "master doesn't support SPI_MODE%d requested by %s\n",
+			spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int litex_spiflash_spi_read(struct spi_device *spi, void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	u8 *rxf_buf = buf;
+
+	while (cnt < nbyte) {
+		*rxf_buf = bitbang_txrx_be_cpha1(spi, 1000, 1, 0, 8);
+		rxf_buf++;
+		cnt++;
+	}
+
+	return cnt;
+}
+
+static int litex_spiflash_spi_write(struct spi_device *spi,
+				const void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	const u8 *txf_buf = buf;
+
+	while (cnt < nbyte) {
+		bitbang_txrx_be_cpha1(spi, 1000, 1, (u32)*txf_buf, 8);
+		txf_buf++;
+		cnt++;
+	}
+
+	return 0;
+}
+
+static int litex_spiflash_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
+	struct spi_transfer *t;
+
+	mesg->actual_length = 0;
+
+	/* activate chip select signal */
+	litex_spiflash_spi_chipselect(sc, 0);
+
+	list_for_each_entry(t, &mesg->transfers, transfer_list) {
+
+		if (t->tx_buf)
+			litex_spiflash_spi_write(spi, t->tx_buf, t->len);
+
+		if (t->rx_buf)
+			litex_spiflash_spi_read(spi, t->rx_buf, t->len);
+
+		mesg->actual_length += t->len;
+	}
+
+	/* inactivate chip select signal */
+	litex_spiflash_spi_chipselect(sc, 1);
+
+	return 0;
+}
+
+static void litex_spiflash_spi_enable(struct litex_spiflash_spi *sp)
+{
+	u32 val;
+
+	/* set SPIFLASH_BB_DIR = 0 */
+	val = SPIFLASH_BB_CSN | SPIFLASH_BB_CLK | SPIFLASH_BB_MOSI;
+	litex_spiflash_spi_wr(sp, val, SPIFLASH_BITBANG);
+
+	/* enable GPIO mode */
+	litex_spiflash_spi_wr(sp, 1, SPIFLASH_BITBANG_EN);
+}
+
+static void litex_spiflash_spi_disable(struct litex_spiflash_spi *sp)
+{
+	/* disable GPIO mode */
+	litex_spiflash_spi_wr(sp, 0, SPIFLASH_BITBANG_EN);
+}
+
+static int litex_spiflash_spi_probe(struct device_d *dev)
+{
+	struct resource *iores;
+	struct spi_master *master;
+	struct litex_spiflash_spi *litex_spiflash_spi;
+
+	litex_spiflash_spi = xzalloc(sizeof(*litex_spiflash_spi));
+	dev->priv = litex_spiflash_spi;
+
+	master = &litex_spiflash_spi->master;
+	master->dev = dev;
+
+	master->bus_num = dev->id;
+	master->setup = litex_spiflash_spi_setup;
+	master->transfer = litex_spiflash_spi_transfer;
+	master->num_chipselect = 1;
+
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores))
+		return PTR_ERR(iores);
+	litex_spiflash_spi->regs = IOMEM(iores->start);
+
+	litex_spiflash_spi_enable(litex_spiflash_spi);
+
+	/* inactivate chip select signal */
+	litex_spiflash_spi_chipselect(litex_spiflash_spi, 1);
+
+	spi_register_master(master);
+
+	return 0;
+}
+
+static void litex_spiflash_spi_remove(struct device_d *dev)
+{
+	struct litex_spiflash_spi *sp = dev->priv;
+
+	litex_spiflash_spi_disable(sp);
+}
+
+static __maybe_unused struct of_device_id litex_spiflash_spi_dt_ids[] = {
+	{
+		.compatible = "litex,spiflash",
+	},
+	{
+		/* sentinel */
+	}
+};
+
+static struct driver_d litex_spiflash_spi_driver = {
+	.name  = "litex-spiflash",
+	.probe = litex_spiflash_spi_probe,
+	.remove = litex_spiflash_spi_remove,
+	.of_compatible = DRV_OF_COMPAT(litex_spiflash_spi_dt_ids),
+};
+device_platform_driver(litex_spiflash_spi_driver);
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:11:03 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:11:03 +0300
Subject: [PATCH RESEND v4 7/8] RISC-V: add LiteX SoC and
 linux-on-litex-vexriscv support
In-Reply-To: <20210817101104.114945-1-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
Message-ID: <20210817101104.114945-8-antonynpavlov@gmail.com>

LiteX is a Migen-based System on Chip, supporting softcore
VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU.

See https://github.com/enjoy-digital/litex and
https://github.com/litex-hub/linux-on-litex-vexriscv
for details.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 arch/riscv/Kconfig.socs                  |  14 +++
 arch/riscv/boards/Makefile               |   1 +
 arch/riscv/boards/litex-linux/Makefile   |   3 +
 arch/riscv/boards/litex-linux/lowlevel.c |  22 ++++
 arch/riscv/dts/Makefile                  |   1 +
 arch/riscv/dts/litex-linux.dts           |  92 +++++++++++++++++
 arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++++++++
 arch/riscv/include/asm/debug_ll.h        |   3 +
 arch/riscv/include/asm/debug_ll_litex.h  | 123 +++++++++++++++++++++++
 common/Kconfig                           |   4 +
 images/Makefile.riscv                    |   4 +
 11 files changed, 316 insertions(+)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 221ea133d4..5c281918d5 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -95,4 +95,18 @@ config SIFIVE_L2
 	bool "SiFive L2 cache controller"
 	depends on CPU_SIFIVE
 
+config SOC_LITEX
+	bool "LiteX SoCs"
+	depends on ARCH_RV32I
+	select HAS_ASM_DEBUG_LL
+	select HAS_NMON
+	select USE_COMPRESSED_DTB
+	select RISCV_TIMER
+
+config BOARD_LITEX_LINUX
+	bool "litex linux board"
+	depends on SOC_LITEX
+	select RISCV_M_MODE
+	def_bool y
+
 endmenu
diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile
index cb28a25d8b..8d5d9d4fc6 100644
--- a/arch/riscv/boards/Makefile
+++ b/arch/riscv/boards/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_BOARD_ERIZO_GENERIC)	+= erizo/
 obj-$(CONFIG_BOARD_HIFIVE)		+= hifive/
 obj-$(CONFIG_BOARD_BEAGLEV)		+= beaglev/
+obj-$(CONFIG_BOARD_LITEX_LINUX)		+= litex-linux/
diff --git a/arch/riscv/boards/litex-linux/Makefile b/arch/riscv/boards/litex-linux/Makefile
new file mode 100644
index 0000000000..3d217ffe0b
--- /dev/null
+++ b/arch/riscv/boards/litex-linux/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+pbl-y += lowlevel.o
diff --git a/arch/riscv/boards/litex-linux/lowlevel.c b/arch/riscv/boards/litex-linux/lowlevel.c
new file mode 100644
index 0000000000..da23ef5633
--- /dev/null
+++ b/arch/riscv/boards/litex-linux/lowlevel.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <asm/barebox-riscv.h>
+#include <debug_ll.h>
+#include <asm/riscv_nmon.h>
+
+ENTRY_FUNCTION(start_litex_linux, a0, a1, a2)
+{
+	extern char __dtb_z_litex_linux_start[];
+	void *fdt;
+
+	barebox_nmon_entry();
+
+	putc_ll('>');
+
+	/* On POR, we are running from read-only memory here. */
+
+	fdt = __dtb_z_litex_linux_start + get_runtime_offset();
+
+	barebox_riscv_machine_entry(0x40000000, SZ_256M, fdt);
+}
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 4a15423b7f..17d7d249e4 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -8,5 +8,6 @@ pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o
 pbl-$(CONFIG_BOARD_HIFIVE) += hifive-unmatched-a00.dtb.o \
                               hifive-unleashed-a00.dtb.o
 pbl-$(CONFIG_BOARD_BEAGLEV) += jh7100-beaglev-starlight.dtb.o
+pbl-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux.dtb.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
diff --git a/arch/riscv/dts/litex-linux.dts b/arch/riscv/dts/litex-linux.dts
new file mode 100644
index 0000000000..d21fa57e30
--- /dev/null
+++ b/arch/riscv/dts/litex-linux.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include "litex_soc_linux.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "LiteX VexRiscV-SoC-Linux";
+	compatible = "litex,vexriscv-soc-linux";
+
+	aliases {
+		rom = &rom;
+		sram = &sram;
+	};
+
+	/* ARTY board */
+	rom: rom at 00000000 {
+		compatible = "mmio-sram";
+		reg = <0x00000000 0x00008000>;
+		read-only;
+	};
+
+	sram: sram at 20000000 {
+		compatible = "mmio-sram";
+		reg = <0x20000000 0x00004000>;
+	};
+
+	main_ram: memory at 40000000 {
+		device_type = "memory";
+		reg = <0x40000000 0x10000000>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&mac0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+
+	spiflash: w25q128 at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "winbond,w25q128", "jedec,spi-nor";
+		spi-max-frequency = <104000000>;
+		reg = <0>;
+	};
+};
+
+/ {
+	ledsgpio: gpio at f000a800 {
+		compatible = "ti,74175";
+		reg = <0xf000a800 0x4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		ld0 {
+			label = "arty:green:ld0";
+			gpios = <&ledsgpio 0 GPIO_ACTIVE_HIGH>;
+		};
+
+		ld1 {
+			label = "arty:green:ld1";
+			gpios = <&ledsgpio 1 GPIO_ACTIVE_HIGH>;
+		};
+
+		ld2 {
+			label = "arty:green:ld2";
+			gpios = <&ledsgpio 2 GPIO_ACTIVE_HIGH>;
+		};
+
+		ld3 {
+			label = "arty:green:ld3";
+			gpios = <&ledsgpio 3 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	swgpio: gpio at f0006000 {
+		compatible = "ti,74125";
+		reg = <0xf0006000 0x4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
diff --git a/arch/riscv/dts/litex_soc_linux.dtsi b/arch/riscv/dts/litex_soc_linux.dtsi
new file mode 100644
index 0000000000..94a0ba29da
--- /dev/null
+++ b/arch/riscv/dts/litex_soc_linux.dtsi
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+/ {
+	compatible = "litex,vexriscv-soc-linux";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		timebase-frequency = <100000000>; // 100 MHz
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "spinalhdl,vexriscv", "riscv";
+			reg = <0>;
+		};
+	};
+
+	uart0: serial at f0001000 {
+		compatible = "litex,uart";
+		reg = <0xf0001000 0x18>;
+		status = "disabled";
+	};
+
+	mac0: mac at f0006800 {
+		compatible = "litex,liteeth";
+		reg = <0xf0006800 0x7c /* base */
+			0xf0007000 0x0a /* mdio_base */
+			0xb0000000 0x2000>; /* buf_base */
+		tx-fifo-depth = <2>;
+		rx-fifo-depth = <2>;
+		status = "disabled";
+	};
+
+	spi0: spi at f000b800 {
+		compatible = "litex,spiflash";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg = <0xf000b800 0x100>;
+		status = "disabled";
+	};
+};
diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h
index b4caa0597a..a3b9c1c4bc 100644
--- a/arch/riscv/include/asm/debug_ll.h
+++ b/arch/riscv/include/asm/debug_ll.h
@@ -43,6 +43,9 @@ static inline void PUTC_LL(char ch)
 
 	writel(ch, uart0);
 }
+#elif defined CONFIG_DEBUG_LITEX
+
+#include <asm/debug_ll_litex.h>
 
 #endif
 
diff --git a/arch/riscv/include/asm/debug_ll_litex.h b/arch/riscv/include/asm/debug_ll_litex.h
new file mode 100644
index 0000000000..2fcdd9b0ec
--- /dev/null
+++ b/arch/riscv/include/asm/debug_ll_litex.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
+ *
+ * This file is part of barebox.
+ *
+ * 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_DEBUG_LL_LITEX__
+#define __ASM_DEBUG_LL_LITEX__
+
+/** @file
+ *  This File contains declaration for early output support
+ */
+
+#include <linux/kconfig.h>
+
+#define DEBUG_LL_UART_ADDR	0xf0001000
+#define UART_RXTX	0x00
+#define UART_TXFULL	0x04
+#define UART_RXEMPTY	0x08
+#define UART_EV_PENDING	0x10
+#define  UART_EV_RX	(1 << 1)
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * C macros
+ */
+
+#include <asm/io.h>
+
+static inline void PUTC_LL(char ch)
+{
+#ifdef CONFIG_DEBUG_LL
+	/* wait for space */
+	while (__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_TXFULL))
+		;
+
+	__raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_RXTX);
+#endif /* CONFIG_DEBUG_LL */
+}
+#else /* __ASSEMBLY__ */
+/*
+ * Macros for use in assembly language code
+ */
+
+/*
+ * output a character in a0
+ */
+.macro	debug_ll_outc_a0
+#ifdef CONFIG_DEBUG_LL
+
+	li	t0, DEBUG_LL_UART_ADDR
+
+201:
+	lbu	t1, UART_TXFULL(t0)	/* uart tx full ? */
+	andi	t1, t1, 0xff
+	bnez	t1, 201b		/* try again */
+
+	sb	a0, UART_RXTX(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
+
+/*
+ * 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 */
+	lbu	s0, UART_RXEMPTY(t0)
+	bnez    s0, 243f
+	li	s0, 1
+	j	244f
+243:	li	s0, 0
+244:	nop
+#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 */
+	lb	s0, UART_RXTX(t0)
+	li      t1, UART_EV_RX
+	sb	t1, UART_EV_PENDING(t0)
+
+#endif /* CONFIG_DEBUG_LL */
+.endm
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_DEBUG_LL_LITEX__ */
diff --git a/common/Kconfig b/common/Kconfig
index a9feae2ae8..cb8bd8b2bf 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1399,6 +1399,10 @@ config DEBUG_SIFIVE
 	bool "SiFive serial0 port"
 	depends on SOC_SIFIVE
 
+config DEBUG_LITEX
+	bool "LiteX serial port"
+	depends on SOC_LITEX
+
 endchoice
 
 config DEBUG_LL_NS16550
diff --git a/images/Makefile.riscv b/images/Makefile.riscv
index 4410765cf6..0645238c43 100644
--- a/images/Makefile.riscv
+++ b/images/Makefile.riscv
@@ -19,3 +19,7 @@ image-$(CONFIG_BOARD_HIFIVE) += barebox-hifive-unmatched.img barebox-hifive-unle
 pblb-$(CONFIG_BOARD_BEAGLEV) += start_beaglev_starlight
 FILE_barebox-beaglev-starlight.img = start_beaglev_starlight.pblb
 image-$(CONFIG_BOARD_BEAGLEV) += barebox-beaglev-starlight.img
+
+pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux
+FILE_barebox-litex-linux.img = start_litex_linux.pblb
+image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img
-- 
2.32.0



From antonynpavlov at gmail.com  Tue Aug 17 03:16:28 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 17 Aug 2021 13:16:28 +0300
Subject: [PATCH v3 00/10] RISC-V: add LiteX SoC support; resurrect nmon
In-Reply-To: <32db3d61-f04c-5940-600c-fb2435808beb@pengutronix.de>
References: <20210525071952.18045-1-antonynpavlov@gmail.com>
 <32db3d61-f04c-5940-600c-fb2435808beb@pengutronix.de>
Message-ID: <20210817131628.3a7483f1ec121fb8822bdc99@gmail.com>

On Wed, 11 Aug 2021 10:52:53 +0200
Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:

Hi Ahmad!

> Hello Antony,
> 
> On 25.05.21 09:19, Antony Pavlov wrote:
> > Changes since v2:
> > 
> >   * rebase on top of master branch (f873c7ff2497) +
> >     "RISC-V: extend multi-image to support both S- and M-Mode"
> >     (http://lists.infradead.org/pipermail/barebox/2021-May/036086.html).
> >   * "litex serial: add setbrg callback" patch by Marek Czerski is added
> >     for review;
> >   * fix "clocksource: timer-riscv: select CSR from device tree" patch;
> >   * change gpio IP-block base addresses in litex dts;
> >   * gpio-74xx-mmio uses device_get_match_data() now.
> > 
> > Changes since v1:
> > 
> >   * rebased on top of next branch;
> >   * new patches are introduced:
> >     * clocksource: timer-riscv: select CSR from device tree
> >     * RISC-V: make RISCV_SBI and RISCV_M_MODE explicitly mutually exclusive
> >     * RISC-V: make it possible to build RV32I multi-image with DEBUG_LL=n
> >   * almost all of Ahmad's notes are fixed (e.g. unused header files inclusions are dropped);
> >   * NOT FIXED: gpio-74xx-mmio still uses dev_get_drvdata(), not device_get_match_data()
> > 
> > Antony Pavlov (9):
> >   clocksource: timer-riscv: select CSR from device tree
> >   RISC-V: make it possible to run nmon from PBL C code
> >   RISC-V: boards: erizo: make it possible to use nmon
> >   serial: add litex UART driver
> >   gpio: add driver for 74xx-ICs with MMIO access
> >   spi: add litex spiflash driver
> >   net: add LiteEth driver
> >   RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
> >   RISC-V: add litex_linux_defconfig
> > 
> > Marek Czerski (1):
> >   litex serial: add setbrg callback
> 
> I'd like to give this a try eventually while following:
> https://github.com/enjoy-digital/litex/wiki/Use-LiteX-on-the-Acorn-CLE-215
> 
> Do you intend to submit a new revision soon? Is it ok for you if I respin
> this series?

Sorry for delay with reply, I was on vacation.

I have just resend litex patchseries v4.
I have tested it with linux binaries from this repo:

   https://github.com/frantony/arty-linux-on-litex-vexriscv-prebuilt

What do you want to respin in the litex patchseries?

-- 
Best regards,
? Antony Pavlov
 
> Cheers,
> Ahmad
> 
> >  arch/riscv/Kconfig.socs                  |  14 +
> >  arch/riscv/boards/Makefile               |   1 +
> >  arch/riscv/boards/erizo/lowlevel.c       |   4 +
> >  arch/riscv/boards/litex-linux/Makefile   |   3 +
> >  arch/riscv/boards/litex-linux/lowlevel.c |  22 ++
> >  arch/riscv/boot/Makefile                 |   1 +
> >  arch/riscv/boot/nmon_entry.S             |  13 +
> >  arch/riscv/configs/litex_linux_defconfig |  76 +++++
> >  arch/riscv/dts/Makefile                  |   1 +
> >  arch/riscv/dts/erizo.dtsi                |   2 +
> >  arch/riscv/dts/litex-linux.dts           |  92 ++++++
> >  arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++
> >  arch/riscv/include/asm/debug_ll.h        |   3 +
> >  arch/riscv/include/asm/debug_ll_litex.h  | 123 ++++++++
> >  arch/riscv/include/asm/riscv_nmon.h      |  49 ++-
> >  common/Kconfig                           |   4 +
> >  drivers/clocksource/timer-riscv.c        |  24 +-
> >  drivers/gpio/Kconfig                     |  14 +
> >  drivers/gpio/Makefile                    |   1 +
> >  drivers/gpio/gpio-74xx-mmio.c            | 165 ++++++++++
> >  drivers/net/Kconfig                      |   8 +
> >  drivers/net/Makefile                     |   1 +
> >  drivers/net/liteeth.c                    | 376 +++++++++++++++++++++++
> >  drivers/serial/Makefile                  |   1 +
> >  drivers/serial/serial_litex.c            | 103 +++++++
> >  drivers/spi/Kconfig                      |   3 +
> >  drivers/spi/Makefile                     |   1 +
> >  drivers/spi/litex_spiflash.c             | 241 +++++++++++++++
> >  images/Makefile.riscv                    |   4 +
> >  29 files changed, 1370 insertions(+), 29 deletions(-)
> >  create mode 100644 arch/riscv/boards/litex-linux/Makefile
> >  create mode 100644 arch/riscv/boards/litex-linux/lowlevel.c
> >  create mode 100644 arch/riscv/boot/nmon_entry.S
> >  create mode 100644 arch/riscv/configs/litex_linux_defconfig
> >  create mode 100644 arch/riscv/dts/litex-linux.dts
> >  create mode 100644 arch/riscv/dts/litex_soc_linux.dtsi
> >  create mode 100644 arch/riscv/include/asm/debug_ll_litex.h
> >  create mode 100644 drivers/gpio/gpio-74xx-mmio.c
> >  create mode 100644 drivers/net/liteeth.c
> >  create mode 100644 drivers/serial/serial_litex.c
> >  create mode 100644 drivers/spi/litex_spiflash.c
> > 
> 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



From a.fatoum at pengutronix.de  Tue Aug 17 03:20:49 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 17 Aug 2021 12:20:49 +0200
Subject: [PATCH v3 00/10] RISC-V: add LiteX SoC support; resurrect nmon
In-Reply-To: <20210817131628.3a7483f1ec121fb8822bdc99@gmail.com>
References: <20210525071952.18045-1-antonynpavlov@gmail.com>
 <32db3d61-f04c-5940-600c-fb2435808beb@pengutronix.de>
 <20210817131628.3a7483f1ec121fb8822bdc99@gmail.com>
Message-ID: <be85f6fc-126b-828b-de1f-a9c407211075@pengutronix.de>

On 17.08.21 12:16, Antony Pavlov wrote:
> On Wed, 11 Aug 2021 10:52:53 +0200
> Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:
> 
> Hi Ahmad!
> 
>> Hello Antony,
>>
>> On 25.05.21 09:19, Antony Pavlov wrote:
>>> Changes since v2:
>>>
>>>   * rebase on top of master branch (f873c7ff2497) +
>>>     "RISC-V: extend multi-image to support both S- and M-Mode"
>>>     (http://lists.infradead.org/pipermail/barebox/2021-May/036086.html).
>>>   * "litex serial: add setbrg callback" patch by Marek Czerski is added
>>>     for review;
>>>   * fix "clocksource: timer-riscv: select CSR from device tree" patch;
>>>   * change gpio IP-block base addresses in litex dts;
>>>   * gpio-74xx-mmio uses device_get_match_data() now.
>>>
>>> Changes since v1:
>>>
>>>   * rebased on top of next branch;
>>>   * new patches are introduced:
>>>     * clocksource: timer-riscv: select CSR from device tree
>>>     * RISC-V: make RISCV_SBI and RISCV_M_MODE explicitly mutually exclusive
>>>     * RISC-V: make it possible to build RV32I multi-image with DEBUG_LL=n
>>>   * almost all of Ahmad's notes are fixed (e.g. unused header files inclusions are dropped);
>>>   * NOT FIXED: gpio-74xx-mmio still uses dev_get_drvdata(), not device_get_match_data()
>>>
>>> Antony Pavlov (9):
>>>   clocksource: timer-riscv: select CSR from device tree
>>>   RISC-V: make it possible to run nmon from PBL C code
>>>   RISC-V: boards: erizo: make it possible to use nmon
>>>   serial: add litex UART driver
>>>   gpio: add driver for 74xx-ICs with MMIO access
>>>   spi: add litex spiflash driver
>>>   net: add LiteEth driver
>>>   RISC-V: add LiteX SoC and linux-on-litex-vexriscv support
>>>   RISC-V: add litex_linux_defconfig
>>>
>>> Marek Czerski (1):
>>>   litex serial: add setbrg callback
>>
>> I'd like to give this a try eventually while following:
>> https://github.com/enjoy-digital/litex/wiki/Use-LiteX-on-the-Acorn-CLE-215
>>
>> Do you intend to submit a new revision soon? Is it ok for you if I respin
>> this series?
> 
> Sorry for delay with reply, I was on vacation.

No worries. :)

> 
> I have just resend litex patchseries v4.
> I have tested it with linux binaries from this repo:
> 
>    https://github.com/frantony/arty-linux-on-litex-vexriscv-prebuilt
> 
> What do you want to respin in the litex patchseries?

Just rebase, address feedback and give it a try.

Thanks for the respin. Building and loading linux-on-litex-vexriscv onto
my FPGA worked, so I'll give your series a try as well later.

(What doesn't yet work is use as PCIe endpoint[1]. Still monkey debugging that)

[1]: https://github.com/enjoy-digital/litepcie/issues/54

Cheers,
Ahmad

> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Aug 17 21:46:03 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 18 Aug 2021 06:46:03 +0200
Subject: [PATCH 1/5] net: drop Calxeda Highbank xgmac driver support
In-Reply-To: <20210812121944.4419-1-a.fatoum@pengutronix.de>
References: <20210812121944.4419-1-a.fatoum@pengutronix.de>
Message-ID: <20210818044603.GC24834@pengutronix.de>

On Thu, Aug 12, 2021 at 02:19:40PM +0200, Ahmad Fatoum wrote:
> Support for MACH_HIGHBANK was removed in f0f96c3322d5
> ("ARM: remove Calxeda Highbank support"). There are no device trees
> either barebox or upstream using this network controller, so remove
> the driver as well.
> 
> Fixes: f0f96c3322d5 ("ARM: remove Calxeda Highbank support")
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/net/Kconfig  |   4 -
>  drivers/net/Makefile |   1 -
>  drivers/net/xgmac.c  | 734 -------------------------------------------
>  3 files changed, 739 deletions(-)
>  delete mode 100644 drivers/net/xgmac.c

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Aug 17 21:48:12 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 18 Aug 2021 06:48:12 +0200
Subject: [PATCH] fastboot net: add setter for global.fastboot.net.autostart
In-Reply-To: <20210813083221.31763-1-m.felsch@pengutronix.de>
References: <20210813083221.31763-1-m.felsch@pengutronix.de>
Message-ID: <20210818044812.GD24834@pengutronix.de>

On Fri, Aug 13, 2021 at 10:32:21AM +0200, Marco Felsch wrote:
> Without this change the only possible way to start the
> fastboot.net.autostart mechanism is by using the nv storage. Split
> fastboot_on_boot() into two functions:
>  - a globalvar setter fastboot_net_autostart_set() and
>  - a the globalvar init function fastboot_net_init_globalvar().
> This allows init scripts to start the autostart mechanism as well.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  net/fastboot.c | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Aug 17 21:48:58 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 18 Aug 2021 06:48:58 +0200
Subject: [PATCH] mci: imx-esdhc-pbl: Fix two typos in a comment
In-Reply-To: <20210813140352.13233-1-u.kleine-koenig@pengutronix.de>
References: <20210813140352.13233-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210818044858.GE24834@pengutronix.de>

On Fri, Aug 13, 2021 at 04:03:52PM +0200, Uwe Kleine-K?nig wrote:
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---
>  drivers/mci/imx-esdhc-pbl.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Aug 17 21:51:31 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 18 Aug 2021 06:51:31 +0200
Subject: [PATCH v2] ARM: i.MX6: boot: detect USB serial downloader more
 reliable
In-Reply-To: <20210812083651.3576-1-m.felsch@pengutronix.de>
References: <20210812083651.3576-1-m.felsch@pengutronix.de>
Message-ID: <20210818045131.GF24834@pengutronix.de>

On Thu, Aug 12, 2021 at 10:36:51AM +0200, Marco Felsch wrote:
> The problem with the BootROM is that the SRC registers are not set
> accordingly in case of a failed primary boot. E.g. if the device is
> configured to boot from an eMMC and the eMMC is empty or image is
> corrupt, the BootROM goes into 'recovery boot mode' (reference manual
> Figure 8-1) and the last possible recovery option is the serial
> downloader. In such case the SRC registers still indicate that the
> device was booted from an eMMC instead of serial-download.
> 
> This commit ports the U-Boot commit [1] with slightly adaptions suggested
> by Ahmad to Barebox. Also we need to reorder the imx6_init() else we
> reset the otg-controller to early.
> 
> [1] https://source.denx.de/u-boot/u-boot/-/commit/e203dcf23e9eabc2e4f3d0b079457cd1516f2081
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  arch/arm/mach-imx/boot.c  | 27 +++++++++++++++++++++++++++
>  arch/arm/mach-imx/imx6.c  |  9 +++++++--
>  include/soc/fsl/fsl_udc.h | 11 +++++++++++
>  3 files changed, 45 insertions(+), 2 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From o.rempel at pengutronix.de  Wed Aug 18 05:19:39 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:39 +0200
Subject: [PATCH v1 0/6] protonic: fix and maintaining 
Message-ID: <20210818121945.26089-1-o.rempel@pengutronix.de>

This patch series contains fixes and updates for currently mainlined
protonic boards.

Robin van der Gracht (6):
  ARM: boards: protonic-imx6: Run usb boot entry instead of bare device
  ARM: boards: protonic-imx6: Don't fixup MAC address for disabled
    device
  ARM: dts: imx6dl-prtvt7: Add brand state variable
  ARM: boards: protonic-imx6: Don't register SD with bbu
  ARM: boards: protonic-imx6: Add emmc_usdhc machine data variable
  ARM: boards: protonic-imx6: Enable bootchooser on prti6g board

 arch/arm/boards/protonic-imx6/board.c | 41 ++++++++++++++++++++++-----
 arch/arm/dts/imx6dl-prtvt7.dts        | 11 +++++++
 2 files changed, 45 insertions(+), 7 deletions(-)

-- 
2.30.2


From o.rempel at pengutronix.de  Wed Aug 18 05:19:43 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:43 +0200
Subject: [PATCH v1 4/6] ARM: boards: protonic-imx6: Don't register SD with bbu
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210818121945.26089-5-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

SD boot is only used during development. Since the usdhc interface index
differs from board to board removing it is easier than adding another
board variable/flag.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 7368f3458f..38630dc2af 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -427,10 +427,6 @@ static int prt_imx6_bbu(struct prt_imx6_priv *priv)
 	if (ret)
 		goto exit_bbu;
 
-	ret = imx6_bbu_internal_mmc_register_handler("SD", "/dev/mmc0", 0);
-	if (ret)
-		goto exit_bbu;
-
 	return 0;
 exit_bbu:
 	dev_err(priv->dev, "Failed to register bbu: %i\n", ret);
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 18 05:19:42 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:42 +0200
Subject: [PATCH v1 3/6] ARM: dts: imx6dl-prtvt7: Add brand state variable
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210818121945.26089-4-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

prtvt7 may have different brands. So, add prtvt7 specific brand state
variable.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/dts/imx6dl-prtvt7.dts | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/dts/imx6dl-prtvt7.dts b/arch/arm/dts/imx6dl-prtvt7.dts
index b1fd13bdd7..19794add17 100644
--- a/arch/arm/dts/imx6dl-prtvt7.dts
+++ b/arch/arm/dts/imx6dl-prtvt7.dts
@@ -3,3 +3,14 @@
 
 #include <arm/imx6dl-prtvt7.dts>
 #include "imx6qdl-prti6q-emmc.dtsi"
+
+&state_emmc {
+	magic = <0x72766467>;
+
+	brand {
+		reg = <0x1b0 0x4>;
+		type = "enum32";
+		names = "unbranded", "agco", "vermeer";
+		default = <0>;
+	};
+};
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 18 05:19:40 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:40 +0200
Subject: [PATCH v1 1/6] ARM: boards: protonic-imx6: Run usb boot entry instead
 of bare device
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210818121945.26089-2-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

There is a usb boot script in the enviromnent. Bare device boots work well
with bootspec but we decided to not use that anymore.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 6eb31a4bc4..e7938ac0fd 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -340,7 +340,7 @@ static void prt_imx6_check_usb_boot(void *data)
 
 	second_word++;
 	if (strncmp(second_word, "usb", 3) == 0) {
-		bootsrc = usbdisk;
+		bootsrc = "usb";
 	} else if (strncmp(second_word, "recovery", 8) == 0) {
 		bootsrc = "recovery";
 	} else {
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 18 05:19:44 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:44 +0200
Subject: [PATCH v1 5/6] ARM: boards: protonic-imx6: Add emmc_usdhc machine
 data variable
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210818121945.26089-6-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

The i.MX6 ultralite only has 2 usdhc ports which will be indexed as '0'
and '1'. The bbu setup code assumes it is attached as '/dev/mmc2'.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 30 ++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 38630dc2af..0cfafdcc26 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -70,6 +70,7 @@ struct prt_machine_data {
 	unsigned int hw_rev;
 	unsigned int i2c_addr;
 	unsigned int i2c_adapter;
+	unsigned int emmc_usdhc;
 	unsigned int flags;
 	int (*init)(struct prt_imx6_priv *priv);
 };
@@ -411,6 +412,7 @@ static int prt_imx6_bbu(struct prt_imx6_priv *priv)
 {
 	const struct prt_machine_data *dcfg = priv->dcfg;
 	u32 emmc_flags = 0;
+	char *devicefile;
 	int ret;
 
 	if (dcfg->flags & PRT_IMX6_BOOTSRC_SPI_NOR) {
@@ -422,7 +424,12 @@ static int prt_imx6_bbu(struct prt_imx6_priv *priv)
 		emmc_flags = BBU_HANDLER_FLAG_DEFAULT;
 	}
 
-	ret = imx6_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc2",
+	devicefile = basprintf("mmc%d", dcfg->emmc_usdhc);
+	if (!devicefile) {
+		ret = -ENOMEM;
+		goto exit_bbu;
+	}
+	ret = imx6_bbu_internal_mmcboot_register_handler("eMMC", devicefile,
 						   emmc_flags);
 	if (ret)
 		goto exit_bbu;
@@ -807,6 +814,7 @@ static const struct prt_machine_data prt_imx6_cfg_alti6p[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_EMMC,
 	}, {
 		.hw_id = UINT_MAX
@@ -819,6 +827,7 @@ static const struct prt_machine_data prt_imx6_cfg_victgo[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_victgo,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -832,12 +841,14 @@ static const struct prt_machine_data prt_imx6_cfg_vicut1[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x50,
 		.i2c_adapter = 1,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
 		.hw_id = HW_TYPE_VICUT1,
 		.hw_rev = 1,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_kvg_yaco,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -845,6 +856,7 @@ static const struct prt_machine_data prt_imx6_cfg_vicut1[] = {
 		.hw_rev = 1,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_kvg_new,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -858,12 +870,14 @@ static const struct prt_machine_data prt_imx6_cfg_vicut1q[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x50,
 		.i2c_adapter = 1,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
 		.hw_id = HW_TYPE_VICUT1,
 		.hw_rev = 1,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_kvg_yaco,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -871,6 +885,7 @@ static const struct prt_machine_data prt_imx6_cfg_vicut1q[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_kvg_yaco,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -878,6 +893,7 @@ static const struct prt_machine_data prt_imx6_cfg_vicut1q[] = {
 		.hw_rev = 1,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_kvg_new,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -891,6 +907,7 @@ static const struct prt_machine_data prt_imx6_cfg_vicutp[] = {
 		.hw_rev = 1,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.init = prt_imx6_init_kvg_new,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
@@ -904,6 +921,7 @@ static const struct prt_machine_data prt_imx6_cfg_lanmcu[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER,
 	}, {
 		.hw_id = UINT_MAX
@@ -916,6 +934,7 @@ static const struct prt_machine_data prt_imx6_cfg_plybas[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR | PRT_IMX6_USB_LONG_DELAY,
 	}, {
 		.hw_id = UINT_MAX
@@ -928,6 +947,7 @@ static const struct prt_machine_data prt_imx6_cfg_plym2m[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR | PRT_IMX6_USB_LONG_DELAY,
 	}, {
 		.hw_id = UINT_MAX
@@ -940,6 +960,7 @@ static const struct prt_machine_data prt_imx6_cfg_prti6g[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 1,
 		.init = prt_imx6_init_prti6g,
 		.flags = PRT_IMX6_BOOTSRC_EMMC,
 	}, {
@@ -953,12 +974,14 @@ static const struct prt_machine_data prt_imx6_cfg_prti6q[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 2,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
 		.hw_id = HW_TYPE_PRTI6Q,
 		.hw_rev = 1,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
 		.hw_id = UINT_MAX
@@ -971,6 +994,7 @@ static const struct prt_machine_data prt_imx6_cfg_prtmvt[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
 		.hw_id = UINT_MAX
@@ -983,6 +1007,7 @@ static const struct prt_machine_data prt_imx6_cfg_prtrvt[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_SPI_NOR,
 	}, {
 		.hw_id = UINT_MAX
@@ -995,6 +1020,7 @@ static const struct prt_machine_data prt_imx6_cfg_prtvt7[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER,
 	}, {
 		.hw_id = UINT_MAX
@@ -1007,6 +1033,7 @@ static const struct prt_machine_data prt_imx6_cfg_prtwd2[] = {
 		.hw_rev = 0,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_EMMC,
 	}, {
 		.hw_id = UINT_MAX
@@ -1019,6 +1046,7 @@ static const struct prt_machine_data prt_imx6_cfg_prtwd3[] = {
 		.hw_rev = 2,
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
+		.emmc_usdhc = 2,
 		.flags = PRT_IMX6_BOOTSRC_EMMC,
 	}, {
 		.hw_id = UINT_MAX
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 18 05:19:41 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:41 +0200
Subject: [PATCH v1 2/6] ARM: boards: protonic-imx6: Don't fixup MAC address
 for disabled device
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210818121945.26089-3-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

The prtvt7 board variant has no enabled ethernet interface. For these
boards the MAC address in the RFID flash is unset or invalid and should
not be copied to the device-tree.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index e7938ac0fd..7368f3458f 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -171,6 +171,9 @@ static int prt_imx6_set_mac(struct prt_imx6_priv *priv,
 		return -ENODEV;
 	}
 
+	if (!of_device_is_available(node))
+		return 0;
+
 	if (!is_valid_ether_addr(&rfid->mac[0])) {
 		unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")];
 
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 18 05:19:45 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 18 Aug 2021 14:19:45 +0200
Subject: [PATCH v1 6/6] ARM: boards: protonic-imx6: Enable bootchooser on
 prti6g board
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210818121945.26089-7-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

Bootchooser is now ported to the prti6g board. So, let barebox know
about it.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 0cfafdcc26..9ded94b3b0 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -962,7 +962,7 @@ static const struct prt_machine_data prt_imx6_cfg_prti6g[] = {
 		.i2c_adapter = 0,
 		.emmc_usdhc = 1,
 		.init = prt_imx6_init_prti6g,
-		.flags = PRT_IMX6_BOOTSRC_EMMC,
+		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER,
 	}, {
 		.hw_id = UINT_MAX
 	},
-- 
2.30.2



From m.tretter at pengutronix.de  Wed Aug 18 05:58:48 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 18 Aug 2021 14:58:48 +0200
Subject: [PATCH] ARM: zynqmp: use std_file_update as update handler
Message-ID: <20210818125848.560293-1-m.tretter@pengutronix.de>

The update handler for zynqmp copies the boot.bin file into an existing
fat partition. There is already a better implementation by
bbu_register_std_file_update(). Drop the custom implementation.

Keep the previous functions with its signature to have an obvious common
update handler for all ZynqMP boards.

Suggested-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 arch/arm/mach-zynqmp/zynqmp-bbu.c | 40 +++----------------------------
 1 file changed, 3 insertions(+), 37 deletions(-)

diff --git a/arch/arm/mach-zynqmp/zynqmp-bbu.c b/arch/arm/mach-zynqmp/zynqmp-bbu.c
index d1197c01dc41..7ac8c2b8a994 100644
--- a/arch/arm/mach-zynqmp/zynqmp-bbu.c
+++ b/arch/arm/mach-zynqmp/zynqmp-bbu.c
@@ -4,45 +4,11 @@
  */
 
 #include <common.h>
-#include <libfile.h>
 #include <mach/zynqmp-bbu.h>
 
-static int zynqmp_bbu_handler(struct bbu_handler *handler,
-		struct bbu_data *data)
-{
-	int ret = 0;
-
-	ret = bbu_confirm(data);
-	if (ret)
-		return ret;
-
-	ret = copy_file(data->imagefile, data->devicefile, 1);
-	if (ret < 0) {
-		pr_err("update failed: %s", strerror(-ret));
-		return ret;
-	}
-
-	return ret;
-}
-
 int zynqmp_bbu_register_handler(const char *name, char *devicefile,
-		unsigned long flags)
+				unsigned long flags)
 {
-	struct bbu_handler *handler;
-	int ret = 0;
-
-	if (!name || !devicefile)
-		return -EINVAL;
-
-	handler = xzalloc(sizeof(*handler));
-	handler->name = name;
-	handler->devicefile = devicefile;
-	handler->flags = flags;
-	handler->handler = zynqmp_bbu_handler;
-
-	ret = bbu_register_handler(handler);
-	if (ret)
-		free(handler);
-
-	return ret;
+	return bbu_register_std_file_update(name, flags, devicefile,
+					    filetype_zynq_image);
 }
-- 
2.30.2



From m.tretter at pengutronix.de  Wed Aug 18 06:35:03 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 18 Aug 2021 15:35:03 +0200
Subject: [PATCH 1/3] firmware: zynqmp-fpga: initialize flags at function start
In-Reply-To: <20210818133505.582698-1-m.tretter@pengutronix.de>
References: <20210818133505.582698-1-m.tretter@pengutronix.de>
Message-ID: <20210818133505.582698-2-m.tretter@pengutronix.de>

The ZYNQMP_FPGA_BIT_ONLY_BIN flag is always set when programming the
FPGA. Simplify the code by initializing the flags with
ZYNQMP_FPGA_BIT_ONLY_BIN already set.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 drivers/firmware/zynqmp-fpga.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 0fc229bfd3dd..736d1950fa5e 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -205,7 +205,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	enum xilinx_byte_order byte_order;
 	u64 addr;
 	int status = 0;
-	u8 flags = 0;
+	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
 
 	if (!mgr->buf) {
 		status = -ENOBUFS;
@@ -259,9 +259,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 
 	addr = (u64)buf_aligned;
 
-	/* we do not provide a header */
-	flags |= ZYNQMP_FPGA_BIT_ONLY_BIN;
-
 	if (!(mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) && buf_size) {
 		status = mgr->eemi_ops->fpga_load(addr,
 				(u32)(uintptr_t)buf_size,
-- 
2.30.2



From m.tretter at pengutronix.de  Wed Aug 18 06:35:02 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 18 Aug 2021 15:35:02 +0200
Subject: [PATCH 0/3] firmware: zynqmp-fpga: fix fpga loading with optimized
 string functions
Message-ID: <20210818133505.582698-1-m.tretter@pengutronix.de>

If CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS is enabled, loading the FPGA fails
with an abort, because the optimized memcpy can only be used on cached memory.
As the bitstream can be several MBs large, we want to use the optimized
functions. Fix the abort by using a cached mapping with streaming DMA.

Michael Tretter (3):
  firmware: zynqmp-fpga: initialize flags at function start
  firmware: zynqmp-fpga: avoid additional buffer for size argument
  firmware: zynqmp-fpga: do not use DMA coherent memory for bitstream

 drivers/firmware/zynqmp-fpga.c | 54 ++++++++++++++++------------------
 1 file changed, 26 insertions(+), 28 deletions(-)

-- 
2.30.2



From m.tretter at pengutronix.de  Wed Aug 18 06:35:05 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 18 Aug 2021 15:35:05 +0200
Subject: [PATCH 3/3] firmware: zynqmp-fpga: do not use DMA coherent memory for
 bitstream
In-Reply-To: <20210818133505.582698-1-m.tretter@pengutronix.de>
References: <20210818133505.582698-1-m.tretter@pengutronix.de>
Message-ID: <20210818133505.582698-4-m.tretter@pengutronix.de>

Trying to do unaligned access of coherent memory on AArch64 will lead to
an abort. This can happen when the FPGA loader copies the bitstream to
the temporary buffer for the transfer to the FPGA.

Convert the driver to use regular memory for the temporary buffer to
prevent the issue.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 drivers/firmware/zynqmp-fpga.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 667910479aa7..0a0e7e880849 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -203,7 +203,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	size_t body_length;
 	int header_length = 0;
 	enum xilinx_byte_order byte_order;
-	u64 addr;
+	dma_addr_t addr;
 	int status = 0;
 	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
 
@@ -240,13 +240,19 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	 * memory. Allocate some extra space at the end of the buffer for the
 	 * bitstream size.
 	 */
-	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
-					 DMA_ADDRESS_BROKEN);
+	buf_aligned = dma_alloc(body_length + sizeof(u32));
 	if (!buf_aligned) {
 		status = -ENOBUFS;
 		goto err_free;
 	}
 
+	addr = dma_map_single(&mgr->dev, buf_aligned,
+			      body_length + sizeof(u32), DMA_TO_DEVICE);
+	if (dma_mapping_error(&mgr->dev, addr)) {
+		status = -EFAULT;
+		goto err_free;
+	}
+
 	if (!(mgr->features & ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL) &&
 	    byte_order == XILINX_BYTE_ORDER_BIN)
 		copy_words_swapped((u32 *)buf_aligned, body,
@@ -254,8 +260,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	else
 		memcpy((u32 *)buf_aligned, body, body_length);
 
-	addr = (u64)buf_aligned;
-
 	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
 		buf_size = body_length;
 	} else {
@@ -263,11 +267,13 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		buf_size = addr + body_length;
 	}
 
-	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
+	dma_sync_single_for_device(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
+	status = mgr->eemi_ops->fpga_load((u64)addr, buf_size, flags);
+	dma_sync_single_for_cpu(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
 	if (status < 0)
 		dev_err(&mgr->dev, "unable to load fpga\n");
 
-	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
+	dma_free(buf_aligned);
 
  err_free:
 	free(mgr->buf);
-- 
2.30.2



From m.tretter at pengutronix.de  Wed Aug 18 06:35:04 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 18 Aug 2021 15:35:04 +0200
Subject: [PATCH 2/3] firmware: zynqmp-fpga: avoid additional buffer for size
 argument
In-Reply-To: <20210818133505.582698-1-m.tretter@pengutronix.de>
References: <20210818133505.582698-1-m.tretter@pengutronix.de>
Message-ID: <20210818133505.582698-3-m.tretter@pengutronix.de>

There are two different APIs for loading an FPGA via the pmu-fw as
indicated by the ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED feature flag.
The pmu-fw expects as second argument either the size of the bitstream or a
pointer to the size of the bitstream.

The driver allocates a separate buffer for the size, which results in
the allocation of a 4k page for storing a 32 bit value.

Allocate some more memory for the bitstream and append the size of the
bitstream at the end of the bitstream to avoid the additional memory
allocation.

Add a comment to explain the surprising size of the allocation.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 drivers/firmware/zynqmp-fpga.c | 37 +++++++++++++++-------------------
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 736d1950fa5e..667910479aa7 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -197,8 +197,8 @@ static void zynqmp_fpga_show_header(const struct device_d *dev,
 static int fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
-	char *buf_aligned;
-	u32 *buf_size = NULL;
+	u32 *buf_aligned;
+	u32 buf_size;
 	u32 *body;
 	size_t body_length;
 	int header_length = 0;
@@ -234,17 +234,14 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		goto err_free;
 	}
 
-	if (!(mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED)) {
-		buf_size = dma_alloc_coherent(sizeof(*buf_size),
-		DMA_ADDRESS_BROKEN);
-		if (!buf_size) {
-			status = -ENOBUFS;
-			goto err_free;
-		}
-		*buf_size = body_length;
-	}
-
-	buf_aligned = dma_alloc_coherent(body_length, DMA_ADDRESS_BROKEN);
+	/*
+	 * The PMU FW variants without the ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED
+	 * feature expect a pointer to the bitstream size, which is stored in
+	 * memory. Allocate some extra space at the end of the buffer for the
+	 * bitstream size.
+	 */
+	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
+					 DMA_ADDRESS_BROKEN);
 	if (!buf_aligned) {
 		status = -ENOBUFS;
 		goto err_free;
@@ -259,20 +256,18 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 
 	addr = (u64)buf_aligned;
 
-	if (!(mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) && buf_size) {
-		status = mgr->eemi_ops->fpga_load(addr,
-				(u32)(uintptr_t)buf_size,
-				flags);
-		dma_free_coherent(buf_size, 0, sizeof(*buf_size));
+	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
+		buf_size = body_length;
 	} else {
-		status = mgr->eemi_ops->fpga_load(addr, (u32)(body_length),
-						  flags);
+		buf_aligned[body_length / sizeof(*buf_aligned)] = body_length;
+		buf_size = addr + body_length;
 	}
 
+	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
 	if (status < 0)
 		dev_err(&mgr->dev, "unable to load fpga\n");
 
-	dma_free_coherent(buf_aligned, 0, body_length);
+	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
 
  err_free:
 	free(mgr->buf);
-- 
2.30.2



From l.stach at pengutronix.de  Wed Aug 18 06:47:02 2021
From: l.stach at pengutronix.de (Lucas Stach)
Date: Wed, 18 Aug 2021 15:47:02 +0200
Subject: [PATCH 3/3] firmware: zynqmp-fpga: do not use DMA coherent
 memory for bitstream
In-Reply-To: <20210818133505.582698-4-m.tretter@pengutronix.de>
References: <20210818133505.582698-1-m.tretter@pengutronix.de>
 <20210818133505.582698-4-m.tretter@pengutronix.de>
Message-ID: <8719b93227095011ebf0a83b5aed202acc8f8d23.camel@pengutronix.de>

Am Mittwoch, dem 18.08.2021 um 15:35 +0200 schrieb Michael Tretter:
> Trying to do unaligned access of coherent memory on AArch64 will lead to
> an abort. This can happen when the FPGA loader copies the bitstream to
> the temporary buffer for the transfer to the FPGA.
> 
> Convert the driver to use regular memory for the temporary buffer to
> prevent the issue.
> 
> Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
> ---
>  drivers/firmware/zynqmp-fpga.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
> index 667910479aa7..0a0e7e880849 100644
> --- a/drivers/firmware/zynqmp-fpga.c
> +++ b/drivers/firmware/zynqmp-fpga.c
> @@ -203,7 +203,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
>  	size_t body_length;
>  	int header_length = 0;
>  	enum xilinx_byte_order byte_order;
> -	u64 addr;
> +	dma_addr_t addr;
>  	int status = 0;
>  	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
>  
> @@ -240,13 +240,19 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
>  	 * memory. Allocate some extra space at the end of the buffer for the
>  	 * bitstream size.
>  	 */
> -	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
> -					 DMA_ADDRESS_BROKEN);
> +	buf_aligned = dma_alloc(body_length + sizeof(u32));
>  	if (!buf_aligned) {
>  		status = -ENOBUFS;
>  		goto err_free;
>  	}
>  
> +	addr = dma_map_single(&mgr->dev, buf_aligned,
> +			      body_length + sizeof(u32), DMA_TO_DEVICE);
> +	if (dma_mapping_error(&mgr->dev, addr)) {
> +		status = -EFAULT;
> +		goto err_free;
> +	}
> +
Usage of both dma_map_single and explicit dma_sync_single_for_* for a
single transfer looks odd. dma_map_single already does the cache sync,
which you then do a second time in the sync calls.

Instead you should move this dma_map_single call to the place where you
added the dma_sync_single_for_device and replace the
dma_sync_single_for_cpu with a dma_unmap_single.

Regards,
Lucas

>  	if (!(mgr->features & ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL) &&
>  	    byte_order == XILINX_BYTE_ORDER_BIN)
>  		copy_words_swapped((u32 *)buf_aligned, body,
> @@ -254,8 +260,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
>  	else
>  		memcpy((u32 *)buf_aligned, body, body_length);
>  
> -	addr = (u64)buf_aligned;
> -
>  	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
>  		buf_size = body_length;
>  	} else {
> @@ -263,11 +267,13 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
>  		buf_size = addr + body_length;
>  	}
>  
> -	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
> +	dma_sync_single_for_device(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
> +	status = mgr->eemi_ops->fpga_load((u64)addr, buf_size, flags);
> +	dma_sync_single_for_cpu(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
>  	if (status < 0)
>  		dev_err(&mgr->dev, "unable to load fpga\n");
>  
> -	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
> +	dma_free(buf_aligned);
>  
>   err_free:
>  	free(mgr->buf);




From m.tretter at pengutronix.de  Thu Aug 19 01:12:48 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Thu, 19 Aug 2021 10:12:48 +0200
Subject: [PATCH v2 0/3] firmware: zynqmp-fpga: fix fpga loading with optimized
 string functions
Message-ID: <20210819081251.726840-1-m.tretter@pengutronix.de>

If CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS is enabled, loading the FPGA fails
with an abort, because the optimized memcpy can only be used on cached memory.
As the bitstream can be several MBs large, we want to use the optimized
functions. Fix the abort by using a cached mapping with streaming DMA.

v2 drops the explicit dma_sync_single_for_device and instead uses
dma_map_single to flush the temporary buffer. I also fixed the error handling
in case the mapping fails and made the size of the extra space at the end of
the temporary buffer more explicit.

Michael

Changelog:

Michael Tretter (3):
  firmware: zynqmp-fpga: initialize flags at function start
  firmware: zynqmp-fpga: avoid additional buffer for size argument
  firmware: zynqmp-fpga: do not use DMA coherent memory for bitstream

 drivers/firmware/zynqmp-fpga.c | 55 +++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 28 deletions(-)

-- 
2.30.2



From m.tretter at pengutronix.de  Thu Aug 19 01:12:51 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Thu, 19 Aug 2021 10:12:51 +0200
Subject: [PATCH v2 3/3] firmware: zynqmp-fpga: do not use DMA coherent memory
 for bitstream
In-Reply-To: <20210819081251.726840-1-m.tretter@pengutronix.de>
References: <20210819081251.726840-1-m.tretter@pengutronix.de>
Message-ID: <20210819081251.726840-4-m.tretter@pengutronix.de>

Trying to do unaligned access of coherent memory on AArch64 will lead to
an abort. This can happen when the FPGA loader copies the bitstream to
the temporary buffer for the transfer to the FPGA.

Convert the driver to use regular memory for the temporary buffer to
prevent the issue.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
Changelog:

v2:
- drop dma_sync_single_for_device and use dma_map_single to flush
- fix missing free of DMA memory in case of mapping error
- use size_of(buf_size) to clarify extra space in buffer
---
 drivers/firmware/zynqmp-fpga.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 667910479aa7..b76607f7eec1 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -203,7 +203,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	size_t body_length;
 	int header_length = 0;
 	enum xilinx_byte_order byte_order;
-	u64 addr;
+	dma_addr_t addr;
 	int status = 0;
 	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
 
@@ -237,11 +237,10 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	/*
 	 * The PMU FW variants without the ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED
 	 * feature expect a pointer to the bitstream size, which is stored in
-	 * memory. Allocate some extra space at the end of the buffer for the
+	 * memory. Allocate extra space at the end of the buffer for the
 	 * bitstream size.
 	 */
-	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
-					 DMA_ADDRESS_BROKEN);
+	buf_aligned = dma_alloc(body_length + sizeof(buf_size));
 	if (!buf_aligned) {
 		status = -ENOBUFS;
 		goto err_free;
@@ -254,8 +253,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	else
 		memcpy((u32 *)buf_aligned, body, body_length);
 
-	addr = (u64)buf_aligned;
-
 	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
 		buf_size = body_length;
 	} else {
@@ -263,11 +260,21 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		buf_size = addr + body_length;
 	}
 
-	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
+	addr = dma_map_single(&mgr->dev, buf_aligned,
+			      body_length + sizeof(buf_size), DMA_TO_DEVICE);
+	if (dma_mapping_error(&mgr->dev, addr)) {
+		status = -EFAULT;
+		goto err_free_dma;
+	}
+
+	status = mgr->eemi_ops->fpga_load((u64)addr, buf_size, flags);
+	dma_unmap_single(&mgr->dev, addr, body_length + sizeof(buf_size),
+			 DMA_TO_DEVICE);
 	if (status < 0)
 		dev_err(&mgr->dev, "unable to load fpga\n");
 
-	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
+err_free_dma:
+	dma_free(buf_aligned);
 
  err_free:
 	free(mgr->buf);
-- 
2.30.2



From m.tretter at pengutronix.de  Thu Aug 19 01:12:49 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Thu, 19 Aug 2021 10:12:49 +0200
Subject: [PATCH v2 1/3] firmware: zynqmp-fpga: initialize flags at function
 start
In-Reply-To: <20210819081251.726840-1-m.tretter@pengutronix.de>
References: <20210819081251.726840-1-m.tretter@pengutronix.de>
Message-ID: <20210819081251.726840-2-m.tretter@pengutronix.de>

The ZYNQMP_FPGA_BIT_ONLY_BIN flag is always set when programming the
FPGA. Simplify the code by initializing the flags with
ZYNQMP_FPGA_BIT_ONLY_BIN already set.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 drivers/firmware/zynqmp-fpga.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 0fc229bfd3dd..736d1950fa5e 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -205,7 +205,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	enum xilinx_byte_order byte_order;
 	u64 addr;
 	int status = 0;
-	u8 flags = 0;
+	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
 
 	if (!mgr->buf) {
 		status = -ENOBUFS;
@@ -259,9 +259,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 
 	addr = (u64)buf_aligned;
 
-	/* we do not provide a header */
-	flags |= ZYNQMP_FPGA_BIT_ONLY_BIN;
-
 	if (!(mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) && buf_size) {
 		status = mgr->eemi_ops->fpga_load(addr,
 				(u32)(uintptr_t)buf_size,
-- 
2.30.2



From m.tretter at pengutronix.de  Thu Aug 19 01:12:50 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Thu, 19 Aug 2021 10:12:50 +0200
Subject: [PATCH v2 2/3] firmware: zynqmp-fpga: avoid additional buffer for
 size argument
In-Reply-To: <20210819081251.726840-1-m.tretter@pengutronix.de>
References: <20210819081251.726840-1-m.tretter@pengutronix.de>
Message-ID: <20210819081251.726840-3-m.tretter@pengutronix.de>

There are two different APIs for loading an FPGA via the pmu-fw as
indicated by the ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED feature flag.
The pmu-fw expects as second argument either the size of the bitstream or a
pointer to the size of the bitstream.

The driver allocates a separate buffer for the size, which results in
the allocation of a 4k page for storing a 32 bit value.

Allocate some more memory for the bitstream and append the size of the
bitstream at the end of the bitstream to avoid the additional memory
allocation.

Add a comment to explain the surprising size of the allocation.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 drivers/firmware/zynqmp-fpga.c | 37 +++++++++++++++-------------------
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 736d1950fa5e..667910479aa7 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -197,8 +197,8 @@ static void zynqmp_fpga_show_header(const struct device_d *dev,
 static int fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
-	char *buf_aligned;
-	u32 *buf_size = NULL;
+	u32 *buf_aligned;
+	u32 buf_size;
 	u32 *body;
 	size_t body_length;
 	int header_length = 0;
@@ -234,17 +234,14 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		goto err_free;
 	}
 
-	if (!(mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED)) {
-		buf_size = dma_alloc_coherent(sizeof(*buf_size),
-		DMA_ADDRESS_BROKEN);
-		if (!buf_size) {
-			status = -ENOBUFS;
-			goto err_free;
-		}
-		*buf_size = body_length;
-	}
-
-	buf_aligned = dma_alloc_coherent(body_length, DMA_ADDRESS_BROKEN);
+	/*
+	 * The PMU FW variants without the ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED
+	 * feature expect a pointer to the bitstream size, which is stored in
+	 * memory. Allocate some extra space at the end of the buffer for the
+	 * bitstream size.
+	 */
+	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
+					 DMA_ADDRESS_BROKEN);
 	if (!buf_aligned) {
 		status = -ENOBUFS;
 		goto err_free;
@@ -259,20 +256,18 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 
 	addr = (u64)buf_aligned;
 
-	if (!(mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) && buf_size) {
-		status = mgr->eemi_ops->fpga_load(addr,
-				(u32)(uintptr_t)buf_size,
-				flags);
-		dma_free_coherent(buf_size, 0, sizeof(*buf_size));
+	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
+		buf_size = body_length;
 	} else {
-		status = mgr->eemi_ops->fpga_load(addr, (u32)(body_length),
-						  flags);
+		buf_aligned[body_length / sizeof(*buf_aligned)] = body_length;
+		buf_size = addr + body_length;
 	}
 
+	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
 	if (status < 0)
 		dev_err(&mgr->dev, "unable to load fpga\n");
 
-	dma_free_coherent(buf_aligned, 0, body_length);
+	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
 
  err_free:
 	free(mgr->buf);
-- 
2.30.2



From m.tretter at pengutronix.de  Thu Aug 19 01:14:35 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Thu, 19 Aug 2021 10:14:35 +0200
Subject: [PATCH 3/3] firmware: zynqmp-fpga: do not use DMA coherent
 memory for bitstream
In-Reply-To: <8719b93227095011ebf0a83b5aed202acc8f8d23.camel@pengutronix.de>
References: <20210818133505.582698-1-m.tretter@pengutronix.de>
 <20210818133505.582698-4-m.tretter@pengutronix.de>
 <8719b93227095011ebf0a83b5aed202acc8f8d23.camel@pengutronix.de>
Message-ID: <20210819081435.GE12231@pengutronix.de>

On Wed, 18 Aug 2021 15:47:02 +0200, Lucas Stach wrote:
> Am Mittwoch, dem 18.08.2021 um 15:35 +0200 schrieb Michael Tretter:
> > Trying to do unaligned access of coherent memory on AArch64 will lead to
> > an abort. This can happen when the FPGA loader copies the bitstream to
> > the temporary buffer for the transfer to the FPGA.
> > 
> > Convert the driver to use regular memory for the temporary buffer to
> > prevent the issue.
> > 
> > Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
> > ---
> >  drivers/firmware/zynqmp-fpga.c | 20 +++++++++++++-------
> >  1 file changed, 13 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
> > index 667910479aa7..0a0e7e880849 100644
> > --- a/drivers/firmware/zynqmp-fpga.c
> > +++ b/drivers/firmware/zynqmp-fpga.c
> > @@ -203,7 +203,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
> >  	size_t body_length;
> >  	int header_length = 0;
> >  	enum xilinx_byte_order byte_order;
> > -	u64 addr;
> > +	dma_addr_t addr;
> >  	int status = 0;
> >  	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
> >  
> > @@ -240,13 +240,19 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
> >  	 * memory. Allocate some extra space at the end of the buffer for the
> >  	 * bitstream size.
> >  	 */
> > -	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
> > -					 DMA_ADDRESS_BROKEN);
> > +	buf_aligned = dma_alloc(body_length + sizeof(u32));
> >  	if (!buf_aligned) {
> >  		status = -ENOBUFS;
> >  		goto err_free;
> >  	}
> >  
> > +	addr = dma_map_single(&mgr->dev, buf_aligned,
> > +			      body_length + sizeof(u32), DMA_TO_DEVICE);
> > +	if (dma_mapping_error(&mgr->dev, addr)) {
> > +		status = -EFAULT;
> > +		goto err_free;
> > +	}
> > +
> Usage of both dma_map_single and explicit dma_sync_single_for_* for a
> single transfer looks odd. dma_map_single already does the cache sync,
> which you then do a second time in the sync calls.
> 
> Instead you should move this dma_map_single call to the place where you
> added the dma_sync_single_for_device and replace the
> dma_sync_single_for_cpu with a dma_unmap_single.

Thanks, I just sent a v2.

Michael

> 
> Regards,
> Lucas
> 
> >  	if (!(mgr->features & ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL) &&
> >  	    byte_order == XILINX_BYTE_ORDER_BIN)
> >  		copy_words_swapped((u32 *)buf_aligned, body,
> > @@ -254,8 +260,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
> >  	else
> >  		memcpy((u32 *)buf_aligned, body, body_length);
> >  
> > -	addr = (u64)buf_aligned;
> > -
> >  	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
> >  		buf_size = body_length;
> >  	} else {
> > @@ -263,11 +267,13 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
> >  		buf_size = addr + body_length;
> >  	}
> >  
> > -	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
> > +	dma_sync_single_for_device(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
> > +	status = mgr->eemi_ops->fpga_load((u64)addr, buf_size, flags);
> > +	dma_sync_single_for_cpu(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
> >  	if (status < 0)
> >  		dev_err(&mgr->dev, "unable to load fpga\n");
> >  
> > -	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
> > +	dma_free(buf_aligned);
> >  
> >   err_free:
> >  	free(mgr->buf);
> 
> 
> 


From ahmad at a3f.at  Mon Aug 23 04:57:13 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Mon, 23 Aug 2021 13:57:13 +0200
Subject: [PATCH] fixup! asm-generic: include bitio.h from io.h
Message-ID: <20210823115713.139527-1-ahmad@a3f.at>

bitio.h checks for a setbits macro and would define its own if none was
defined. This means setbits can't be used as symbol name later. Fix
this.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/spi/ath79_spi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
index e47896be624e..2a4e32a4cc50 100644
--- a/drivers/spi/ath79_spi.c
+++ b/drivers/spi/ath79_spi.c
@@ -55,7 +55,7 @@ static inline void ath79_spi_wr(struct ath79_spi *sp, u32 val, int reg)
 	__raw_writel(val, sp->regs + reg);
 }
 
-static inline void setbits(struct ath79_spi *sp, int bits, int on)
+static inline void ath79_spi_setbits(struct ath79_spi *sp, int bits, int on)
 {
 	/*
 	 * We are the only user of SCSPTR so no locking is required.
@@ -82,14 +82,14 @@ static inline void setsck(struct spi_device *spi, int on)
 {
 	struct ath79_spi *sc = ath79_spidev_to_sp(spi);
 
-	setbits(sc, AR71XX_SPI_IOC_CLK, on);
+	ath79_spi_setbits(sc, AR71XX_SPI_IOC_CLK, on);
 }
 
 static inline void setmosi(struct spi_device *spi, int on)
 {
 	struct ath79_spi *sc = ath79_spidev_to_sp(spi);
 
-	setbits(sc, AR71XX_SPI_IOC_DO, on);
+	ath79_spi_setbits(sc, AR71XX_SPI_IOC_DO, on);
 }
 
 static inline u32 getmiso(struct spi_device *spi)
-- 
2.33.0



From ahmad at a3f.at  Mon Aug 23 04:57:51 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Mon, 23 Aug 2021 13:57:51 +0200
Subject: [PATCH] fixup! spi: add litex spiflash driver
In-Reply-To: <20210817101104.114945-6-antonynpavlov@gmail.com>
References: <20210817101104.114945-6-antonynpavlov@gmail.com>
Message-ID: <20210823115751.140020-1-ahmad@a3f.at>

bitio.h checks for a setbits macro and would define its own if none was
defined. This means setbits can't be used as symbol name later. Fix
this.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/spi/litex_spiflash.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/litex_spiflash.c b/drivers/spi/litex_spiflash.c
index 26ef207699eb..6701e9866a13 100644
--- a/drivers/spi/litex_spiflash.c
+++ b/drivers/spi/litex_spiflash.c
@@ -35,7 +35,7 @@ static inline void litex_spiflash_spi_wr(struct litex_spiflash_spi *sp, u32 val,
 	writel(val, sp->regs + reg);
 }
 
-static inline void setbits(struct litex_spiflash_spi *sp, int bits, int on)
+static inline void litex_spiflash_setbits(struct litex_spiflash_spi *sp, int bits, int on)
 {
 	/*
 	 * We are the only user of SCSPTR so no locking is required.
@@ -62,7 +62,7 @@ static inline void setsck(struct spi_device *spi, int on)
 {
 	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
 
-	setbits(sc, SPIFLASH_BB_CLK, on);
+	litex_spiflash_setbits(sc, SPIFLASH_BB_CLK, on);
 }
 
 static inline void setmosi(struct spi_device *spi, int on)
@@ -70,14 +70,14 @@ static inline void setmosi(struct spi_device *spi, int on)
 	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
 
 	sc->val &= ~SPIFLASH_BB_DIR;
-	setbits(sc, SPIFLASH_BB_MOSI, on);
+	litex_spiflash_setbits(sc, SPIFLASH_BB_MOSI, on);
 }
 
 static inline u32 getmiso(struct spi_device *spi)
 {
 	struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi);
 
-	setbits(sc, SPIFLASH_BB_DIR, 1);
+	litex_spiflash_setbits(sc, SPIFLASH_BB_DIR, 1);
 	return !!((litex_spiflash_spi_rr(sc, SPIFLASH_MISO) & 1));
 }
 
@@ -87,7 +87,7 @@ static inline u32 getmiso(struct spi_device *spi)
 
 static inline void litex_spiflash_spi_chipselect(struct litex_spiflash_spi *sc, int on)
 {
-	setbits(sc, SPIFLASH_BB_CSN, on);
+	litex_spiflash_setbits(sc, SPIFLASH_BB_CSN, on);
 }
 
 static int litex_spiflash_spi_setup(struct spi_device *spi)
-- 
2.33.0



From a.fatoum at pengutronix.de  Mon Aug 23 04:58:58 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 23 Aug 2021 13:58:58 +0200
Subject: [PATCH RESEND v4 2/8] serial: add litex UART driver
In-Reply-To: <20210817101104.114945-3-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
 <20210817101104.114945-3-antonynpavlov@gmail.com>
Message-ID: <96981f4e-1345-94c7-a081-3aef68b5d97e@pengutronix.de>

On 17.08.21 12:10, Antony Pavlov wrote:
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Tested-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> ---
>  drivers/serial/Makefile       |  1 +
>  drivers/serial/serial_litex.c | 96 +++++++++++++++++++++++++++++++++++
>  2 files changed, 97 insertions(+)
> 
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index 5120b17376..45055371ea 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -24,3 +24,4 @@ obj-$(CONFIG_DRIVER_SERIAL_DIGIC)		+= serial_digic.o
>  obj-$(CONFIG_DRIVER_SERIAL_LPUART)		+= serial_lpuart.o
>  obj-$(CONFIG_VIRTIO_CONSOLE)			+= virtio_console.o
>  obj-$(CONFIG_SERIAL_SIFIVE)			+= serial_sifive.o
> +obj-$(CONFIG_SOC_LITEX)				+= serial_litex.o
> diff --git a/drivers/serial/serial_litex.c b/drivers/serial/serial_litex.c
> new file mode 100644
> index 0000000000..8562a45ecc
> --- /dev/null
> +++ b/drivers/serial/serial_litex.c
> @@ -0,0 +1,96 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <io.h>
> +
> +#define UART_RXTX	0x00
> +#define UART_TXFULL	0x04
> +#define UART_RXEMPTY	0x08
> +#define UART_EV_PENDING	0x10
> +#define  UART_EV_RX	(1 << 1)
> +
> +static inline uint32_t litex_serial_readb(struct console_device *cdev,
> +						uint32_t offset)
> +{
> +	void __iomem *base = cdev->dev->priv;
> +
> +	return readb(base + offset);
> +}
> +
> +static inline void litex_serial_writeb(struct console_device *cdev,
> +					uint32_t value, uint32_t offset)
> +{
> +	void __iomem *base = cdev->dev->priv;
> +
> +	writeb(value, base + offset);
> +}
> +
> +static void litex_serial_putc(struct console_device *cdev, char c)
> +{
> +	while (litex_serial_readb(cdev, UART_TXFULL))
> +		;
> +
> +	litex_serial_writeb(cdev, c, UART_RXTX);
> +}
> +
> +static int litex_serial_getc(struct console_device *cdev)
> +{
> +	int c;
> +
> +	while (litex_serial_readb(cdev, UART_RXEMPTY))
> +		;
> +
> +	c = litex_serial_readb(cdev, UART_RXTX);
> +
> +	/* refresh UART_RXEMPTY by writing UART_EV_RX to UART_EV_PENDING */
> +	litex_serial_writeb(cdev, UART_EV_RX, UART_EV_PENDING);
> +
> +	return c;
> +}
> +
> +static int litex_serial_tstc(struct console_device *cdev)
> +{
> +	return !litex_serial_readb(cdev, UART_RXEMPTY);
> +}
> +
> +static int litex_serial_probe(struct device_d *dev)
> +{
> +	struct resource *iores;
> +	struct console_device *cdev;
> +
> +	cdev = xzalloc(sizeof(struct console_device));
> +	iores = dev_request_mem_resource(dev, 0);
> +	if (IS_ERR(iores))
> +		return PTR_ERR(iores);
> +
> +	dev->priv = IOMEM(iores->start);
> +	cdev->dev = dev;
> +	cdev->tstc = &litex_serial_tstc;
> +	cdev->putc = &litex_serial_putc;
> +	cdev->getc = &litex_serial_getc;
> +	cdev->setbrg = NULL;
> +
> +	console_register(cdev);
> +
> +	return 0;
> +}
> +
> +static __maybe_unused struct of_device_id litex_serial_dt_ids[] = {
> +	{
> +		.compatible = "litex,uart",
> +	}, {
> +		/* sentinel */
> +	}
> +};
> +
> +static struct driver_d litex_serial_driver = {
> +	.name  = "litex-uart",
> +	.probe = litex_serial_probe,
> +	.of_compatible = DRV_OF_COMPAT(litex_serial_dt_ids),
> +};
> +console_platform_driver(litex_serial_driver);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Aug 23 05:01:52 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 23 Aug 2021 14:01:52 +0200
Subject: [PATCH RESEND v4 3/8] console: support set baudrate for fixed
 baudrate drivers
In-Reply-To: <20210817101104.114945-4-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
 <20210817101104.114945-4-antonynpavlov@gmail.com>
Message-ID: <b8bd0c12-c757-dfd1-188a-e9c261eb0f55@pengutronix.de>

On 17.08.21 12:10, Antony Pavlov wrote:
> There are console drivers (linux, virtio, litex)
> that don't support baud rate setting and has
> no setbrg (set baudrate) callback, so
> console_set_baudrate() returns -ENOSYS.
> 
> At the other hand console_set_baudrate() SUCCESS
> return value is needed for the loadx/loady commands
> correct work.
> 
> See discussion here:
> 
>   http://lists.infradead.org/pipermail/barebox/2021-May/036237.html
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Tested-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

> ---
>  common/console.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/common/console.c b/common/console.c
> index ad1a6aaab2..c902239e31 100644
> --- a/common/console.c
> +++ b/common/console.c
> @@ -165,12 +165,12 @@ int console_set_baudrate(struct console_device *cdev, unsigned baudrate)
>  	int ret;
>  	unsigned char c;
>  
> -	if (!cdev->setbrg)
> -		return -ENOSYS;
> -
>  	if (cdev->baudrate == baudrate)
>  		return 0;
>  
> +	if (!cdev->setbrg)
> +		return -ENOSYS;
> +
>  	/*
>  	 * If the device is already active, change its baudrate.
>  	 * The baudrate of an inactive device will be set at activation time.
> @@ -336,11 +336,13 @@ int console_register(struct console_device *newcdev)
>  		ret = newcdev->setbrg(newcdev, baudrate);
>  		if (ret)
>  			return ret;
> -		newcdev->baudrate_param = newcdev->baudrate = baudrate;
> +		newcdev->baudrate_param = baudrate;
>  		dev_add_param_uint32(dev, "baudrate", console_baudrate_set,
>  			NULL, &newcdev->baudrate_param, "%u", newcdev);
>  	}
>  
> +	newcdev->baudrate = baudrate;
> +
>  	if (newcdev->putc && !newcdev->puts)
>  		newcdev->puts = __console_puts;
>  
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Aug 23 05:06:09 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 23 Aug 2021 14:06:09 +0200
Subject: [PATCH RESEND v4 7/8] RISC-V: add LiteX SoC and
 linux-on-litex-vexriscv support
In-Reply-To: <20210817101104.114945-8-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
 <20210817101104.114945-8-antonynpavlov@gmail.com>
Message-ID: <f234164a-64b9-63ae-8ecc-97336d5c695c@pengutronix.de>

On 17.08.21 12:11, Antony Pavlov wrote:
> LiteX is a Migen-based System on Chip, supporting softcore
> VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU.
> 
> See https://github.com/enjoy-digital/litex and
> https://github.com/litex-hub/linux-on-litex-vexriscv
> for details.
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  arch/riscv/Kconfig.socs                  |  14 +++
>  arch/riscv/boards/Makefile               |   1 +
>  arch/riscv/boards/litex-linux/Makefile   |   3 +
>  arch/riscv/boards/litex-linux/lowlevel.c |  22 ++++
>  arch/riscv/dts/Makefile                  |   1 +
>  arch/riscv/dts/litex-linux.dts           |  92 +++++++++++++++++
>  arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++++++++
>  arch/riscv/include/asm/debug_ll.h        |   3 +
>  arch/riscv/include/asm/debug_ll_litex.h  | 123 +++++++++++++++++++++++
>  common/Kconfig                           |   4 +
>  images/Makefile.riscv                    |   4 +
>  11 files changed, 316 insertions(+)
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 221ea133d4..5c281918d5 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -95,4 +95,18 @@ config SIFIVE_L2
>  	bool "SiFive L2 cache controller"
>  	depends on CPU_SIFIVE
>  
> +config SOC_LITEX
> +	bool "LiteX SoCs"
> +	depends on ARCH_RV32I
> +	select HAS_ASM_DEBUG_LL
> +	select HAS_NMON
> +	select USE_COMPRESSED_DTB
> +	select RISCV_TIMER
> +
> +config BOARD_LITEX_LINUX
> +	bool "litex linux board"
> +	depends on SOC_LITEX
> +	select RISCV_M_MODE
> +	def_bool y
> +
>  endmenu
> diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile
> index cb28a25d8b..8d5d9d4fc6 100644
> --- a/arch/riscv/boards/Makefile
> +++ b/arch/riscv/boards/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_BOARD_ERIZO_GENERIC)	+= erizo/
>  obj-$(CONFIG_BOARD_HIFIVE)		+= hifive/
>  obj-$(CONFIG_BOARD_BEAGLEV)		+= beaglev/
> +obj-$(CONFIG_BOARD_LITEX_LINUX)		+= litex-linux/
> diff --git a/arch/riscv/boards/litex-linux/Makefile b/arch/riscv/boards/litex-linux/Makefile
> new file mode 100644
> index 0000000000..3d217ffe0b
> --- /dev/null
> +++ b/arch/riscv/boards/litex-linux/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +pbl-y += lowlevel.o
> diff --git a/arch/riscv/boards/litex-linux/lowlevel.c b/arch/riscv/boards/litex-linux/lowlevel.c
> new file mode 100644
> index 0000000000..da23ef5633
> --- /dev/null
> +++ b/arch/riscv/boards/litex-linux/lowlevel.c
> @@ -0,0 +1,22 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <common.h>
> +#include <asm/barebox-riscv.h>
> +#include <debug_ll.h>
> +#include <asm/riscv_nmon.h>
> +
> +ENTRY_FUNCTION(start_litex_linux, a0, a1, a2)
> +{
> +	extern char __dtb_z_litex_linux_start[];
> +	void *fdt;
> +
> +	barebox_nmon_entry();
> +
> +	putc_ll('>');
> +
> +	/* On POR, we are running from read-only memory here. */

Do we? I thought BIOS loads barebox to RAM first?

> +
> +	fdt = __dtb_z_litex_linux_start + get_runtime_offset();
> +
> +	barebox_riscv_machine_entry(0x40000000, SZ_256M, fdt);
> +}
> diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
> index 4a15423b7f..17d7d249e4 100644
> --- a/arch/riscv/dts/Makefile
> +++ b/arch/riscv/dts/Makefile
> @@ -8,5 +8,6 @@ pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o
>  pbl-$(CONFIG_BOARD_HIFIVE) += hifive-unmatched-a00.dtb.o \
>                                hifive-unleashed-a00.dtb.o
>  pbl-$(CONFIG_BOARD_BEAGLEV) += jh7100-beaglev-starlight.dtb.o
> +pbl-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux.dtb.o
>  
>  clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
> diff --git a/arch/riscv/dts/litex-linux.dts b/arch/riscv/dts/litex-linux.dts
> new file mode 100644
> index 0000000000..d21fa57e30
> --- /dev/null
> +++ b/arch/riscv/dts/litex-linux.dts
> @@ -0,0 +1,92 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include "litex_soc_linux.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/ {
> +	model = "LiteX VexRiscV-SoC-Linux";
> +	compatible = "litex,vexriscv-soc-linux";
> +
> +	aliases {
> +		rom = &rom;
> +		sram = &sram;
> +	};
> +
> +	/* ARTY board */
> +	rom: rom at 00000000 {

I can see why RAM is specific to ARTY, but why ROM?

> +		compatible = "mmio-sram";
> +		reg = <0x00000000 0x00008000>;
> +		read-only;
> +	};
> +
> +	sram: sram at 20000000 {
> +		compatible = "mmio-sram";
> +		reg = <0x20000000 0x00004000>;
> +	};
> +
> +	main_ram: memory at 40000000 {
> +		device_type = "memory";
> +		reg = <0x40000000 0x10000000>;
> +	};
> +};
> +
> +&uart0 {
> +	status = "okay";
> +};
> +
> +&mac0 {
> +	status = "okay";
> +};
> +
> +&spi0 {
> +	status = "okay";
> +
> +	spiflash: w25q128 at 0 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		compatible = "winbond,w25q128", "jedec,spi-nor";
> +		spi-max-frequency = <104000000>;
> +		reg = <0>;
> +	};
> +};
> +
> +/ {
> +	ledsgpio: gpio at f000a800 {
> +		compatible = "ti,74175";
> +		reg = <0xf000a800 0x4>;
> +		gpio-controller;
> +		#gpio-cells = <2>;
> +	};
> +
> +	leds {
> +		compatible = "gpio-leds";
> +
> +		ld0 {
> +			label = "arty:green:ld0";
> +			gpios = <&ledsgpio 0 GPIO_ACTIVE_HIGH>;
> +		};
> +
> +		ld1 {
> +			label = "arty:green:ld1";
> +			gpios = <&ledsgpio 1 GPIO_ACTIVE_HIGH>;
> +		};
> +
> +		ld2 {
> +			label = "arty:green:ld2";
> +			gpios = <&ledsgpio 2 GPIO_ACTIVE_HIGH>;
> +		};
> +
> +		ld3 {
> +			label = "arty:green:ld3";
> +			gpios = <&ledsgpio 3 GPIO_ACTIVE_HIGH>;
> +		};
> +	};
> +
> +	swgpio: gpio at f0006000 {
> +		compatible = "ti,74125";
> +		reg = <0xf0006000 0x4>;
> +		gpio-controller;
> +		#gpio-cells = <2>;
> +	};
> +};
> diff --git a/arch/riscv/dts/litex_soc_linux.dtsi b/arch/riscv/dts/litex_soc_linux.dtsi
> new file mode 100644
> index 0000000000..94a0ba29da
> --- /dev/null
> +++ b/arch/riscv/dts/litex_soc_linux.dtsi
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +/dts-v1/;
> +
> +/ {
> +	compatible = "litex,vexriscv-soc-linux";
> +
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		timebase-frequency = <100000000>; // 100 MHz
> +
> +		cpu at 0 {
> +			device_type = "cpu";
> +			compatible = "spinalhdl,vexriscv", "riscv";
> +			reg = <0>;
> +		};
> +	};
> +
> +	uart0: serial at f0001000 {
> +		compatible = "litex,uart";
> +		reg = <0xf0001000 0x18>;
> +		status = "disabled";
> +	};
> +
> +	mac0: mac at f0006800 {
> +		compatible = "litex,liteeth";
> +		reg = <0xf0006800 0x7c /* base */
> +			0xf0007000 0x0a /* mdio_base */
> +			0xb0000000 0x2000>; /* buf_base */
> +		tx-fifo-depth = <2>;
> +		rx-fifo-depth = <2>;
> +		status = "disabled";
> +	};
> +
> +	spi0: spi at f000b800 {
> +		compatible = "litex,spiflash";
> +
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		reg = <0xf000b800 0x100>;
> +		status = "disabled";
> +	};
> +};
> diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h
> index b4caa0597a..a3b9c1c4bc 100644
> --- a/arch/riscv/include/asm/debug_ll.h
> +++ b/arch/riscv/include/asm/debug_ll.h
> @@ -43,6 +43,9 @@ static inline void PUTC_LL(char ch)
>  
>  	writel(ch, uart0);
>  }
> +#elif defined CONFIG_DEBUG_LITEX
> +
> +#include <asm/debug_ll_litex.h>
>  
>  #endif
>  
> diff --git a/arch/riscv/include/asm/debug_ll_litex.h b/arch/riscv/include/asm/debug_ll_litex.h
> new file mode 100644
> index 0000000000..2fcdd9b0ec
> --- /dev/null
> +++ b/arch/riscv/include/asm/debug_ll_litex.h
> @@ -0,0 +1,123 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
> + *
> + * This file is part of barebox.
> + *
> + * 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.

Nitpick: That part could be dropped as the SPDX-License-Identifier
above says as much.

> + *
> + */
> +
> +#ifndef __ASM_DEBUG_LL_LITEX__
> +#define __ASM_DEBUG_LL_LITEX__
> +
> +/** @file
> + *  This File contains declaration for early output support
> + */
> +
> +#include <linux/kconfig.h>
> +
> +#define DEBUG_LL_UART_ADDR	0xf0001000
> +#define UART_RXTX	0x00
> +#define UART_TXFULL	0x04
> +#define UART_RXEMPTY	0x08
> +#define UART_EV_PENDING	0x10
> +#define  UART_EV_RX	(1 << 1)
> +
> +
> +#ifndef __ASSEMBLY__
> +
> +/*
> + * C macros
> + */
> +
> +#include <asm/io.h>
> +
> +static inline void PUTC_LL(char ch)
> +{
> +#ifdef CONFIG_DEBUG_LL
> +	/* wait for space */
> +	while (__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_TXFULL))
> +		;
> +
> +	__raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_RXTX);
> +#endif /* CONFIG_DEBUG_LL */
> +}
> +#else /* __ASSEMBLY__ */
> +/*
> + * Macros for use in assembly language code
> + */
> +
> +/*
> + * output a character in a0
> + */
> +.macro	debug_ll_outc_a0
> +#ifdef CONFIG_DEBUG_LL
> +
> +	li	t0, DEBUG_LL_UART_ADDR
> +
> +201:
> +	lbu	t1, UART_TXFULL(t0)	/* uart tx full ? */
> +	andi	t1, t1, 0xff
> +	bnez	t1, 201b		/* try again */
> +
> +	sb	a0, UART_RXTX(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
> +
> +/*
> + * 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 */
> +	lbu	s0, UART_RXEMPTY(t0)
> +	bnez    s0, 243f
> +	li	s0, 1
> +	j	244f
> +243:	li	s0, 0
> +244:	nop
> +#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 */
> +	lb	s0, UART_RXTX(t0)
> +	li      t1, UART_EV_RX
> +	sb	t1, UART_EV_PENDING(t0)
> +
> +#endif /* CONFIG_DEBUG_LL */
> +.endm
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* __ASM_DEBUG_LL_LITEX__ */
> diff --git a/common/Kconfig b/common/Kconfig
> index a9feae2ae8..cb8bd8b2bf 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -1399,6 +1399,10 @@ config DEBUG_SIFIVE
>  	bool "SiFive serial0 port"
>  	depends on SOC_SIFIVE
>  
> +config DEBUG_LITEX
> +	bool "LiteX serial port"
> +	depends on SOC_LITEX
> +
>  endchoice
>  
>  config DEBUG_LL_NS16550
> diff --git a/images/Makefile.riscv b/images/Makefile.riscv
> index 4410765cf6..0645238c43 100644
> --- a/images/Makefile.riscv
> +++ b/images/Makefile.riscv
> @@ -19,3 +19,7 @@ image-$(CONFIG_BOARD_HIFIVE) += barebox-hifive-unmatched.img barebox-hifive-unle
>  pblb-$(CONFIG_BOARD_BEAGLEV) += start_beaglev_starlight
>  FILE_barebox-beaglev-starlight.img = start_beaglev_starlight.pblb
>  image-$(CONFIG_BOARD_BEAGLEV) += barebox-beaglev-starlight.img
> +
> +pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux
> +FILE_barebox-litex-linux.img = start_litex_linux.pblb
> +image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Aug 23 05:08:52 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 23 Aug 2021 14:08:52 +0200
Subject: [PATCH RESEND v4 1/8] clocksource: timer-riscv: select CSR from
 device tree
In-Reply-To: <20210817101104.114945-2-antonynpavlov@gmail.com>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
 <20210817101104.114945-2-antonynpavlov@gmail.com>
Message-ID: <ce1667b1-e42f-3836-9747-393a5fd8afc7@pengutronix.de>

On 17.08.21 12:10, Antony Pavlov wrote:
> barebox timer-riscv driver supports one of user counters:
> 
>   * 'cycle', counter for RDCYCLE instruction (CSR 0xc00);
>   * 'time', timer for RDTIME instruction (CSR 0xc01).
> 
> At the moment in M-mode timer-riscv uses the 'cycle' counter,
> and in S-mode timer-riscv uses the 'time' timer.
> 
> Alas picorv32 CPU core supports only the 'cycle' counter.
> VexRiscV CPU core in M-mode supports only the 'time' timer.
> 
> This patch makes it possible to use the 'time' timer
> for VexRiscV CPU in M-mode.
> 
> See also http://lists.infradead.org/pipermail/barebox/2021-May/036067.html

Comment from earlier series:

"It also changes the default for M-Mode from cycle to time.

I can't comment on whether this is ok, I just copied the logic

from Linux."

Can you say why this is ok?

> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  arch/riscv/dts/erizo.dtsi         |  2 ++
>  drivers/clocksource/timer-riscv.c | 24 ++++++++++++------------
>  2 files changed, 14 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/riscv/dts/erizo.dtsi b/arch/riscv/dts/erizo.dtsi
> index 228711bd69..4eb92ae6f1 100644
> --- a/arch/riscv/dts/erizo.dtsi
> +++ b/arch/riscv/dts/erizo.dtsi
> @@ -22,6 +22,8 @@
>  
>  		timebase-frequency = <24000000>;
>  
> +		barebox,csr-cycle;
> +
>  		cpu at 0 {
>  			device_type = "cpu";
>  			compatible = "cliffordwolf,picorv32", "riscv";
> diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
> index 5a517fe6b4..96637f988a 100644
> --- a/drivers/clocksource/timer-riscv.c
> +++ b/drivers/clocksource/timer-riscv.c
> @@ -12,9 +12,8 @@
>  #include <clock.h>
>  #include <asm/timer.h>
>  #include <asm/csr.h>
> -#include <asm/system.h>
>  
> -static u64 notrace riscv_timer_get_count_sbi(void)
> +static u64 notrace riscv_timer_get_count_time(void)
>  {
>  	__maybe_unused u32 hi, lo;
>  
> @@ -29,7 +28,7 @@ static u64 notrace riscv_timer_get_count_sbi(void)
>  	return ((u64)hi << 32) | lo;
>  }
>  
> -static u64 notrace riscv_timer_get_count_rdcycle(void)
> +static u64 notrace riscv_timer_get_count_cycle(void)
>  {
>  	__maybe_unused u32 hi, lo;
>  
> @@ -44,24 +43,25 @@ static u64 notrace riscv_timer_get_count_rdcycle(void)
>  	return ((u64)hi << 32) | lo;
>  }
>  
> -static u64 notrace riscv_timer_get_count(void)
> -{
> -	if (riscv_mode() == RISCV_S_MODE)
> -		return riscv_timer_get_count_sbi();
> -	else
> -		return riscv_timer_get_count_rdcycle();
> -}
> -
>  static struct clocksource riscv_clocksource = {
> -	.read		= riscv_timer_get_count,
>  	.mask		= CLOCKSOURCE_MASK(64),
>  	.priority	= 100,
>  };
>  
>  static int riscv_timer_init(struct device_d* dev)
>  {
> +	struct device_node *cpu;
> +
>  	dev_dbg(dev, "running at %lu Hz\n", riscv_timebase);
>  
> +	cpu = of_find_node_by_path("/cpus");
> +
> +	if (of_property_read_bool(cpu, "barebox,csr-cycle")) {
> +		riscv_clocksource.read = riscv_timer_get_count_cycle;
> +	} else {
> +		riscv_clocksource.read = riscv_timer_get_count_time;
> +	}
> +
>  	riscv_clocksource.mult = clocksource_hz2mult(riscv_timebase, riscv_clocksource.shift);
>  
>  	return init_clock(&riscv_clocksource);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 06:36:49 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 15:36:49 +0200
Subject: [PATCH] hush: fix conditional statements exit code
In-Reply-To: <20210810054712.1547433-1-andrej.picej@norik.com>
References: <20210810054712.1547433-1-andrej.picej@norik.com>
Message-ID: <20210823133649.GG24834@pengutronix.de>

On Tue, Aug 10, 2021 at 07:47:12AM +0200, Andrej Picej wrote:
> Fix conditional statements ("if" , "elif", "while" and "until") exit
> code when used in scripts. Before the change, when conditional statement
> evaluated false just before the end of the script, script's exit code
> would have been 1 (instead of 0), which implies error condition. This is
> not expected nor desired behavior, so correct it by handling such cases
> and passing exit code 0 (SUCCESS) instead in such situations.
> 
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> ---
> This problem/bug was previously discussed on barebox mailing list.
> Although a simple workaround was found (explicit exit 0 at the end of
> scripts), a decision for fixing Hush was encouraged.
> ---
>  common/hush.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)

Tested and applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 06:39:19 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 15:39:19 +0200
Subject: [PATCH] fixup! asm-generic: include bitio.h from io.h
In-Reply-To: <20210823115713.139527-1-ahmad@a3f.at>
References: <20210823115713.139527-1-ahmad@a3f.at>
Message-ID: <20210823133919.GI24834@pengutronix.de>

On Mon, Aug 23, 2021 at 01:57:13PM +0200, Ahmad Fatoum wrote:
> bitio.h checks for a setbits macro and would define its own if none was
> defined. This means setbits can't be used as symbol name later. Fix
> this.
> 
> Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
> ---
>  drivers/spi/ath79_spi.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 06:45:35 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 15:45:35 +0200
Subject: [PATCH v1 0/6] protonic: fix and maintaining
In-Reply-To: <20210818121945.26089-1-o.rempel@pengutronix.de>
References: <20210818121945.26089-1-o.rempel@pengutronix.de>
Message-ID: <20210823134535.GJ24834@pengutronix.de>

On Wed, Aug 18, 2021 at 02:19:39PM +0200, Oleksij Rempel wrote:
> This patch series contains fixes and updates for currently mainlined
> protonic boards.
> 
> Robin van der Gracht (6):
>   ARM: boards: protonic-imx6: Run usb boot entry instead of bare device
>   ARM: boards: protonic-imx6: Don't fixup MAC address for disabled
>     device
>   ARM: dts: imx6dl-prtvt7: Add brand state variable
>   ARM: boards: protonic-imx6: Don't register SD with bbu
>   ARM: boards: protonic-imx6: Add emmc_usdhc machine data variable
>   ARM: boards: protonic-imx6: Enable bootchooser on prti6g board

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 06:48:20 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 15:48:20 +0200
Subject: [PATCH v2 1/2] file_list: add file_list_parse_null()
In-Reply-To: <20210810052928.101783-1-r.czerwinski@pengutronix.de>
References: <20210810052928.101783-1-r.czerwinski@pengutronix.de>
Message-ID: <20210823134820.GK24834@pengutronix.de>

On Tue, Aug 10, 2021 at 07:29:27AM +0200, Rouven Czerwinski wrote:
> Move the usbgadget parse() function to file_list and rename it to
> file_list_parse_null() which will return a NULL pointer instead of an
> error. Also adjust the callers in the usbgadget code.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> 
> ---
> v2: rebase on master to fix USB mass storage conflict
> ---
>  common/file-list.c  | 16 ++++++++++++++++
>  common/usbgadget.c  | 24 ++++--------------------
>  include/file-list.h |  1 +
>  3 files changed, 21 insertions(+), 20 deletions(-)

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 06:51:52 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 15:51:52 +0200
Subject: [PATCH v2 0/3] firmware: zynqmp-fpga: fix fpga loading with
 optimized string functions
In-Reply-To: <20210819081251.726840-1-m.tretter@pengutronix.de>
References: <20210819081251.726840-1-m.tretter@pengutronix.de>
Message-ID: <20210823135152.GL24834@pengutronix.de>

On Thu, Aug 19, 2021 at 10:12:48AM +0200, Michael Tretter wrote:
> If CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS is enabled, loading the FPGA fails
> with an abort, because the optimized memcpy can only be used on cached memory.
> As the bitstream can be several MBs large, we want to use the optimized
> functions. Fix the abort by using a cached mapping with streaming DMA.
> 
> v2 drops the explicit dma_sync_single_for_device and instead uses
> dma_map_single to flush the temporary buffer. I also fixed the error handling
> in case the mapping fails and made the size of the extra space at the end of
> the temporary buffer more explicit.
> 
> Michael
> 
> Changelog:
> 
> Michael Tretter (3):
>   firmware: zynqmp-fpga: initialize flags at function start
>   firmware: zynqmp-fpga: avoid additional buffer for size argument
>   firmware: zynqmp-fpga: do not use DMA coherent memory for bitstream
> 
>  drivers/firmware/zynqmp-fpga.c | 55 +++++++++++++++++-----------------
>  1 file changed, 27 insertions(+), 28 deletions(-)

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 06:53:00 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 15:53:00 +0200
Subject: [PATCH] ARM: zynqmp: use std_file_update as update handler
In-Reply-To: <20210818125848.560293-1-m.tretter@pengutronix.de>
References: <20210818125848.560293-1-m.tretter@pengutronix.de>
Message-ID: <20210823135300.GM24834@pengutronix.de>

On Wed, Aug 18, 2021 at 02:58:48PM +0200, Michael Tretter wrote:
> The update handler for zynqmp copies the boot.bin file into an existing
> fat partition. There is already a better implementation by
> bbu_register_std_file_update(). Drop the custom implementation.
> 
> Keep the previous functions with its signature to have an obvious common
> update handler for all ZynqMP boards.
> 
> Suggested-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
> ---
>  arch/arm/mach-zynqmp/zynqmp-bbu.c | 40 +++----------------------------
>  1 file changed, 3 insertions(+), 37 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 07:03:51 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 16:03:51 +0200
Subject: [PATCH 3/3] ls1046ardb: enable IFC NAND.
In-Reply-To: <1628842608-17031-4-git-send-email-renaud.barbier@abaco.com>
References: <1628842608-17031-1-git-send-email-renaud.barbier@abaco.com>
 <1628842608-17031-4-git-send-email-renaud.barbier@abaco.com>
Message-ID: <20210823140351.GN24834@pengutronix.de>

On Fri, Aug 13, 2021 at 09:16:48AM +0100, Renaud Barbier wrote:
> Set the NAND timings and enable the IFC NAND driver.
> 
> Signed-off-by: Renaud Barbier <renaud.barbier at abaco.com>
> ---
>  arch/arm/configs/layerscape_defconfig | 11 +++++++
>  arch/arm/mach-layerscape/Makefile     |  1 +
>  arch/arm/mach-layerscape/nand.c       | 44 +++++++++++++++++++++++++++
>  3 files changed, 56 insertions(+)
>  create mode 100644 arch/arm/mach-layerscape/nand.c
> 
> diff --git a/arch/arm/configs/layerscape_defconfig b/arch/arm/configs/layerscape_defconfig
> index 394cd95c98..fb8e885353 100644
> --- a/arch/arm/configs/layerscape_defconfig
> +++ b/arch/arm/configs/layerscape_defconfig
> @@ -34,6 +34,10 @@ CONFIG_CMD_GO=y
>  CONFIG_CMD_RESET=y
>  CONFIG_CMD_UIMAGE=y
>  CONFIG_CMD_PARTITION=y
> +CONFIG_CMD_MOUNT=y
> +CONFIG_CMD_UBI=y
> +CONFIG_CMD_UBIFORMAT=y
> +CONFIG_CMD_UMOUNT=y
>  CONFIG_CMD_EXPORT=y
>  CONFIG_CMD_LOADENV=y
>  CONFIG_CMD_PRINTENV=y
> @@ -69,6 +73,7 @@ CONFIG_CMD_GPIO=y
>  CONFIG_CMD_I2C=y
>  CONFIG_CMD_LED=y
>  CONFIG_CMD_SPI=y
> +CONFIG_CMD_NAND=y
>  CONFIG_CMD_LED_TRIGGER=y
>  CONFIG_CMD_WD=y
>  CONFIG_CMD_BAREBOX_UPDATE=y
> @@ -85,6 +90,10 @@ CONFIG_DP83867_PHY=y
>  CONFIG_REALTEK_PHY=y
>  CONFIG_NET_DSA_MV88E6XXX=y
>  CONFIG_DRIVER_SPI_FSL_QUADSPI=y
> +CONFIG_NAND=y
> +CONFIG_NAND_FSL_IFC=y
> +CONFIG_MTD_UBI=y
> +CONFIG_MTD_UBI_BEB_LIMIT=20
>  CONFIG_I2C=y
>  CONFIG_I2C_IMX=y
>  CONFIG_I2C_MUX=y
> @@ -112,5 +121,7 @@ CONFIG_FS_NFS=y
>  CONFIG_FS_FAT=y
>  CONFIG_FS_FAT_WRITE=y
>  CONFIG_FS_FAT_LFN=y
> +CONFIG_FS_UBIFS=y
> +CONFIG_FS_UBIFS_COMPRESSION_LZO=y
>  CONFIG_ZLIB=y
>  CONFIG_LZO_DECOMPRESS=y
> diff --git a/arch/arm/mach-layerscape/Makefile b/arch/arm/mach-layerscape/Makefile
> index 854a327c91..99da7b2af0 100644
> --- a/arch/arm/mach-layerscape/Makefile
> +++ b/arch/arm/mach-layerscape/Makefile
> @@ -6,3 +6,4 @@ obj-pbl-y += boot.o
>  pbl-y += xload-qspi.o xload.o
>  obj-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa.o ppa-entry.o
>  obj-$(CONFIG_BOOTM) += pblimage.o
> +obj-$(CONFIG_NAND_FSL_IFC) += nand.o
> diff --git a/arch/arm/mach-layerscape/nand.c b/arch/arm/mach-layerscape/nand.c
> new file mode 100644
> index 0000000000..b36c6b3c46
> --- /dev/null
> +++ b/arch/arm/mach-layerscape/nand.c
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <common.h>
> +#include <init.h>
> +#include <of_address.h>
> +#include <linux/fsl_ifc.h>
> +
> +static int rdb_nand_init(void)
> +{
> +	struct device_node *np;
> +	void __iomem *ifc;
> +
> +	if (!of_machine_is_compatible("fsl,ls1046a-rdb"))
> +		return 0;

The code as such is board specific and thus should be in
arch/arm/boards/ls1046ardb/. We could make a architecture specific
helper function from it which is then called by the board code, but the
values written to the registers below are probably very board specific
anyway, so with a generic helper function we wouldn't win that much.

I moved rdb_nand_init() to the board code while applying.

Thanks
 Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 07:11:00 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 16:11:00 +0200
Subject: [PATCH v2] arm: rockchip-rk3568-evb: add hardware id detection
In-Reply-To: <20210705160457.7346-1-michael.riesch@wolfvision.net>
References: <20210705160457.7346-1-michael.riesch@wolfvision.net>
Message-ID: <20210823141100.GB31210@pengutronix.de>

On Mon, Jul 05, 2021 at 06:04:57PM +0200, Michael Riesch wrote:
> The RK3568 EVB uses a voltage divider to determine the hardware ID of
> the board. At the moment, the voltage levels for seven EVB variants are
> defined. This commit adds a late_initcall to the board code that reads
> out the voltage and populates the hardware ID as environment variable.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
> v2:
> - add compatible check
> - return early in case the voltage cannot be read
> - populate hardware ID as environment variable
> 
>  arch/arm/boards/rockchip-rk3568-evb/board.c | 56 +++++++++++++++++++++
>  1 file changed, 56 insertions(+)
> 
> diff --git a/arch/arm/boards/rockchip-rk3568-evb/board.c b/arch/arm/boards/rockchip-rk3568-evb/board.c
> index 57c24ed3c..f8b257e57 100644
> --- a/arch/arm/boards/rockchip-rk3568-evb/board.c
> +++ b/arch/arm/boards/rockchip-rk3568-evb/board.c
> @@ -2,7 +2,13 @@
>  #include <common.h>
>  #include <init.h>
>  #include <mach/bbu.h>
> +#include <aiodev.h>
>  #include <bootsource.h>
> +#include <environment.h>
> +#include <globalvar.h>
> +#include <magicvar.h>
> +
> +static bool machine_is_rk3568_evb = false;
>  
>  static int rk3568_evb_probe(struct device_d *dev)
>  {
> @@ -11,6 +17,7 @@ static int rk3568_evb_probe(struct device_d *dev)
>  
>  	barebox_set_model("Rockchip RK3568 EVB");
>  	barebox_set_hostname("rk3568-evb");
> +	machine_is_rk3568_evb = true;
>  
>  	if (bootsource == BOOTSOURCE_MMC && instance == 1)
>  		of_device_enable_path("/chosen/environment-sd");
> @@ -34,3 +41,52 @@ static struct driver_d rk3568_evb_board_driver = {
>  	.of_compatible = rk3568_evb_of_match,
>  };
>  coredevice_platform_driver(rk3568_evb_board_driver);
> +
> +static int rk3568_evb_detect_hwid(void)
> +{
> +	int ret;
> +	int evb_hwid_voltage;
> +	struct aiochannel *evb_hwid_chan;
> +	char *evb_hwid;
> +
> +	if (!machine_is_rk3568_evb)
> +		return 0;
> +
> +	evb_hwid_chan = aiochannel_by_name("aiodev0.in_value1_mV");

This fails to link when CONFIG_AIODEV is disabled. I added an early
return at the top of this function to fix that.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Aug 23 07:27:17 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 23 Aug 2021 16:27:17 +0200
Subject: v2021.08.0
Message-ID: <20210823142717.GO24834@pengutronix.de>


Hi All,

I am happy to announce barebox-2021.08.0.

There are some interesting changes this time. Finally deep probe support
has landed. Deep probe is a new way of handling dependencies between
devices. With device tree support dependencies are now very well
expressed in the device tree, so this information is used to probe a
device another device depends on just when it's needed. This makes
-EPROBE_DEFER unnecessary, which was (and still is) present in barebox,
but never worked very well. Deep probe is enabled per board, so you are
encouraged to enable it for your favourite board and see if it still
works.

Other than that the Rockchip rk3568 support is now pretty much
completed. Board support for the rk3568-EVB is added, so it's ready to
be used.

For a full list of changes see below.

Have Fun!
  Sascha

----------------------------------------------------------------
Ahmad Fatoum (73):
      nvmem: bsec: remove unused, left-over, struct member
      nvmem: treat devices without nvmem_bus::write as read only
      nvmem: add support for new read-only memory (rmem) binding
      nvmem: add support for nvmem-cells binding
      sandbox: use nvmem on top of stickypage for reset reason
      power: reset: port Linux generic NVMEM reboot mode driver
      sandbox: use nvmem-reboot-mode instead of syscon-reboot-mode
      sandbox: dts: fix unit-address for state partition
      nvmem: add command to list nvmem devices
      sandbox: hostfile: move initcall to earlier postcore level
      commands: md: don't leak heap memory with unaligned accesses
      clocksource: RISC-V: demote probe success messages to debug level
      RISC-V: virt: select only one timer
      RISC-V: extend multi-image to support both S- and M-Mode
      RISC-V: cpuinfo: return some output for non-SBI systems as well
      of: of_net: sync of_get_mac_address with Linux for NVMEM support
      net: consult device tree for ethernet address in NVMEM as fall-back
      RISC-V: S-Mode: propagate Hart ID
      RISC-V: erizo: make it easier to reuse ns16550 debug_ll
      RISC-V: socs: add Kconfig entry for StarFive JH7100
      nvmem: add StarFive OTP support
      RISC-V: dma: support multiple dma_alloc_coherent backends
      RISC-V: add exception support
      RISC-V: support incoherent I-Cache
      drivers: soc: sifive: add basic L2 cache controller driver
      soc: starfive: add support for JH7100 incoherent interconnect
      soc: sifive: l2_cache: enable maximum available cache ways
      net: designware: fix non-1:1 mapped 64-bit systems
      net: designware: add support for IP integrated into StarFive SoC
      mci: allocate DMA-able memory
      mci: allocate sector_buf on demand
      dma: allocate 32-byte aligned buffers by default
      mci: dw_mmc: add optional reset line
      mci: dw_mmc: match against StarFive MMC compatibles
      clk: add initial StarFive clock support
      reset: add StarFive reset controller driver
      watchdog: add StarFive watchdog driver
      hw_random: add driver for RNG on StarFive SoC
      reset: add device_reset_all helper
      gpio: add support for StarFive GPIO controller
      misc: add power sequencing driver for initializing StarFive peripherals
      RISC-V: StarFive: add board support for BeagleV Starlight
      reset: stm32: remove implicit sizeof(long) == 4 expectation
      input: virtio: poll from poller, not bthread
      bthread: add debug print for scheduler context switches
      common: move workqueue handling from poller_call() to sched()
      common: bthread: schedule only in command context
      bthread: implement basic Linux-like completion API
      Documentation: devel: background-execution: update bthread docs
      usbgadget: refactor usbgadget_register to accept array
      usbgadget: add support for USB mass storage gadget
      spi: imx: enable use for i.MX8MM and i.MX8MP
      bthread: remove thread exit codes
      bthread: replace blocking bthread_stop with nonblocking bthread_cancel
      bthread: add options to create and delete dummy bthreads
      string: implement strchrnul
      console: respect baudrate specified in device-tree stdout-path
      test: self: add tests for progress notifier
      nvmem: fix dev_dbg(unregistered_device, ...)
      driver: add CONFIG_DEBUG_PROBES
      pinctrl: stm32: support deep probe
      ARM: imx6: marsboard: simplify ar8035 PHY fixups
      ARM: imx6: marsboard: enable deep-probe
      OF: gpio: drop duplicate of_device_ensure_probed
      sandbox: ship sample environment
      sandbox: power: set $global.system.reset=POR on poweroff
      sandbox: fix probe order dependency between watchdog and power
      of: partition: implement of_partition_ensure_probed
      state: support deep probe
      nvmem: support deep probe
      sandbox: turn into deep probe platform
      Revert "sandbox: hostfile: move initcall to earlier postcore level"
      ARM: at91: fix building samad2 images without sama5d3

Antony Pavlov (3):
      RISC-V: make it possible to run nmon from PBL C code
      RISC-V: boards: erizo: make it possible to use nmon
      RISC-V: boards: beaglev: make it possible to use nmon

Geert Uytterhoeven (1):
      clk: starfive-jh7100: Fix duplicate numbers

Lucas Stach (1):
      of: base: move memory init from DT to initcall

Marco Felsch (9):
      imx53: remove unused imx53_add_nand
      of: platform: remove check of already added devices
      of: platform: Keep track of populated platform devices
      of: base: move clock init from of_probe() to barebox_register_of()
      initcall: add of_populate_initcall
      common: add initial barebox deep-probe support
      ARM: i.MX: esdctl: add deep-probe support
      ARM: stm32mp: ddrctrl: add deep-probe support
      ARM: boards: mx6-sabrelite: add deep-probe support

Michael Riesch (2):
      aiodev: add driver for Rockchip SARADC
      arm: rk3568-evb1: add support for Rockchip SARADC

Michael Tretter (7):
      ARM: zynqmp: set reset source
      clk: zynqmp: do not enable already enabled clocks
      dts: zcu104: add Barebox environment
      ARM: zynqmp: add update handler
      ARM: zynqmp: zcu104: register update handler
      ARM: zynqmp: defconfig: enable more features
      Documentation: zynqmp: add some documentation

Rouven Czerwinski (5):
      usb: usb251xb: remove >=0 check for u32 port
      common: bbu: only add available handlers
      common: bbu: add pr_fmt
      image-sparse: remove unused define
      mci: imx-esdhc-pbl: initialize fsl_esdhc_host

Sascha Hauer (79):
      regulator: fixed: Use gpiod
      usb: storage: Improve message
      usb: ehci: Fix unitialized variable
      clk: fix of clk set defaults when dev is a clk provider
      ARM: mmu: inherit pte flags from pmd
      clk: Add clk_name_* functions
      clk: rockchip rk3568: Initialize clocks
      filetype: Add Rockchip boot image type
      ARM: Rockchip: Add rkimage tool
      ARM: Add relocate_to_adr_full()
      ARM: Rockchip: Add rk3568 dtsi files
      filetype: Add function to check if a filetype is a compressed file
      arm64: bootm: Add dryrun check
      riscv: bootm: Add dryrun check
      libfile: Add copy_fd()
      ARM: Add atf common support
      of: of_copy_node(): Copy phandles as well
      of: Add function to duplicate a device tree
      fdt: Check blob size during unflattening
      firmware: make device_node argument non const
      libbb: Add find_path function
      firmware: consolidate ifdefs
      firmware: Add search path
      firmware: Fix device_node matching
      firmware: recognize by reproducible name
      blspec: Set firmware searchpath
      overlay: Add of_overlay_apply_file()
      firmware: Load from global search path
      of: Set of_chosen and of_model earlier
      of: implement of_get_stdoutpath()
      pinctrl: Find controller node first
      common: Explicitly probe consoles earlier with deep probe
      pinctrl: Add deep probe support
      phy: Add deep probe support
      ARM: i.MX Phytec physom: convert to board driver
      ARM: i.MX Phytec physom: Add deep-probe support
      of: Add dummy driver
      of: refuse to delete root node of live tree
      of: Fix deep-probe triggering when removing nodes
      ARM: Rockchip: Add rk3568 support
      ARM: rockchip: Add bootm handler for RKNS images
      ARM: Rockchip: Add rk3568 evb board support
      Add rockchip_v8_defconfig
      clk: rockchip rk3568: Register softrst handler
      usb: ehci: Handle clocks and phys
      phy: Rockchip: Add driver for usb2phy
      phy: rockchip: Add naneng-combphy support
      ARM: Rockchip: rk3568: Add USB nodes
      ARM: Rockchip: rk3568 EVB: Add USB support
      ARM64: Implement mem*_*io()
      usb: dwc3: Use _io functions on dma coherent memory
      ARM: Rockchip: rk3568 EVB: Add eMMC pinmux
      pinctrl: rockchip: Register gpios as device
      ARM: rockchip_v8_defconfig Disable ARC_EMAC driver
      blspec: Rework firmware load
      overlay: Add filters to choose which overlays to apply
      blspec: Apply overlays from rootfs
      doc: devicetree: Refer to internal device tree also as live tree
      Documentation: Add documentation for device tree overlays
      of_firmware: Fix handling of firmware-name property
      dts: update to v5.13-rc6
      dts: update to v5.13-rc7
      Merge branch 'for-next/arm'
      Merge branch 'for-next/clk'
      Merge branch 'for-next/deep-probe'
      Merge branch 'for-next/dts'
      Merge branch 'for-next/firmware'
      Merge branch 'for-next/misc'
      Merge branch 'for-next/nvmem'
      Merge branch 'for-next/riscv'
      Merge branch 'for-next/rockchip'
      Merge branch 'for-next/usb'
      Merge branch 'for-next/usb-gadget'
      Merge branch 'for-next/zynqmp'
      crypto: add crypto_memneq()
      crypto: digest: use crypto_memneq()
      password: Use crypto_memneq() to compare hashes
      fit: Use digest_verify() to verify hashes
      Release v2021.08.0

Steffen Trumtrar (9):
      reset: add of_reset_control_get to header
      drivers: add fpga bridge framework
      drivers: fpga: add socfpga bridges
      firmware: socfpga: change function prefixes
      firmware: import fpga-mgr.h from linux
      of: kconfig: of_overlay uses firmwaremgr_load_file
      drivers: firmware: socfpga: remove bridges shutdown
      firmware: add support for compressed images
      firmware: socfpga: set APPLYCFG after loading bitstream

Uwe Kleine-K?nig (1):
      w1: Replace license and copyright boilerplate by SPDX identifiers

Yunus Bas (1):
      commands: of_property: Extend command usage on external dtb

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From r.czerwinski at pengutronix.de  Mon Aug 23 23:47:07 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Tue, 24 Aug 2021 08:47:07 +0200
Subject: [PATCH v2 8/8] PBL: enable LIBFDT for OP-TEE early loading
In-Reply-To: <edee4bbe-ba6e-7356-5ce7-984a4009134d@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-9-r.czerwinski@pengutronix.de>
 <edee4bbe-ba6e-7356-5ce7-984a4009134d@pengutronix.de>
Message-ID: <a10ab29f12e4146cbd9db271e7cb506084f45b7b.camel@pengutronix.de>

On Thu, 2021-08-05 at 15:53 +0200, Ahmad Fatoum wrote:
> On 03.08.21 11:44, Rouven Czerwinski wrote:
> > This allows the OP-TEE early loaded board to add the reserved memory
> > entries for the correct MMU setup. This is done by including pbl/fdt.h
> > and using fdt_fill_reserve_mem().
> > 
> > Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> 
> Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> 
> Would be nice if we had a board upstream that made use of this.

The Webasto CCBV2 can make use of this, however due to incompatibility
with THUMB it is not enabled in the default config. I will include the
necessary changes for ccbv2 in this series.

Regards,
Rouven



From a.fatoum at pengutronix.de  Tue Aug 24 00:09:37 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 24 Aug 2021 09:09:37 +0200
Subject: [PATCH v2 3/8] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <20210809183042.GF11515@pengutronix.de>
References: <20210803094418.475609-1-r.czerwinski@pengutronix.de>
 <20210803094418.475609-4-r.czerwinski@pengutronix.de>
 <270994d8-2970-5095-2f82-f8cf29054629@pengutronix.de>
 <20210809183042.GF11515@pengutronix.de>
Message-ID: <501906d6-58ff-7399-9ba4-012dc0a27537@pengutronix.de>

On 09.08.21 20:30, Sascha Hauer wrote:
> On Thu, Aug 05, 2021 at 04:06:42PM +0200, Ahmad Fatoum wrote:
>> On 03.08.21 11:44, Rouven Czerwinski wrote:
>>> Use the information from the reserved memory entries to modify the
>>> mapping of memory regions to mark them as uncachable and not-executable.
>>> This also prevents the processor from speculating into these regions,
>>> preventing hard to debug scenarios where boots fail for unknown reasons.
>>>
>>> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
>>> ---
>>>  arch/arm/cpu/mmu.c | 34 ++++++++++++++++++++++++++++++++--
>>>  1 file changed, 32 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
>>> index 6388e1bf14..73f4cf5b36 100644
>>> --- a/arch/arm/cpu/mmu.c
>>> +++ b/arch/arm/cpu/mmu.c
>>> @@ -17,6 +17,7 @@
>>>  #include <memory.h>
>>>  #include <asm/system_info.h>
>>>  #include <asm/sections.h>
>>> +#include <of.h>
>>>  
>>>  #include "mmu.h"
>>>  
>>> @@ -407,6 +408,36 @@ static void vectors_init(void)
>>>  	create_vector_table(ARM_LOW_VECTORS);
>>>  }
>>>  
>>> +static void create_sections_with_intersect(struct memory_bank *bank)
>>> +{
>>> +	struct of_reserve_map *res_map;
>>> +	unsigned long j_end;
>>> +	unsigned long end;
>>> +	unsigned long j;
>>> +	u32 pmd_flags;
>>> +	int i;
>>> +
>>> +	res_map = of_get_reserve_map();
>>> +	if (!res_map)
>>> +		return;
>>
>> If there is no reserve map, you should still map the banks cached.
>> So this early exit is wrong.
>>
>>> +
>>> +	end = bank->start + bank->size - 1;
>>> +
>>> +	for (j = bank->start; j < end; j += PGDIR_SIZE) {
>>> +		pmd_flags = PMD_SECT_DEF_CACHED;
>>> +		j_end = j + PGDIR_SIZE - 1;
>>> +
>>> +		for (i = 0; i < res_map->num_entries; i++) {
>>> +			if ((BIT(i) & res_map->xn) &&
>>> +			    j_end >= res_map->start[i] &&
>>> +			    j_end <= res_map->end[i])
>>> +				pmd_flags = PMD_SECT_DEF_UNCACHED | PMD_SECT_XN;
>>> +		}
>>> +
>>> +		create_sections(ttb, j, j_end, pmd_flags);
>>> +	}
>>
>> Do we need the nested loop? Can't we create sections cached first
>> and then iterate once over the reserved map, deduce the sections containing
>> start and end and map those uncached?
> 
> Wouldn't that open a window to speculate into the areas we want to avoid
> speculating into in the first place?

Right. Forgot that MMU is enabled here.

> 
> Sascha
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Tue Aug 24 02:51:18 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 24 Aug 2021 11:51:18 +0200
Subject: [PATCH 1/2] video: simplefb-client: populate video mode field
Message-ID: <20210824095119.15907-1-a.fatoum@pengutronix.de>

Video drivers should initialize fb_info->mode, so device parameters for
mode and enable/disable can function as expected. This wasn't done in
the simplefb driver so far, fix this.

This also lets us drop some initialization of the fb_info, because it
can be calculated from the mode. The very verbose mode info print
can be dropped as well, because it's now available in devinfo.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/video/simplefb-client.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/video/simplefb-client.c b/drivers/video/simplefb-client.c
index 1f26ac506741..e1f241d4d874 100644
--- a/drivers/video/simplefb-client.c
+++ b/drivers/video/simplefb-client.c
@@ -30,6 +30,11 @@ struct simplefb_params {
 	struct simplefb_format *format;
 };
 
+struct simplefb {
+	struct fb_info info;
+	struct fb_videomode mode;
+};
+
 static int simplefb_parse_dt(struct device_d *dev,
 			   struct simplefb_params *params)
 {
@@ -80,6 +85,7 @@ static int simplefb_probe(struct device_d *dev)
 {
 	int ret;
 	struct simplefb_params params;
+	struct simplefb *simplefb;
 	struct fb_info *info;
 	struct resource *mem;
 
@@ -96,17 +102,19 @@ static int simplefb_probe(struct device_d *dev)
 		return PTR_ERR(mem);
 	}
 
-	info = xzalloc(sizeof(*info));
-	dev->priv = info;
+	simplefb = xzalloc(sizeof(*simplefb));
+
+	simplefb->mode.name = params.format->name;
+	simplefb->mode.xres = params.width;
+	simplefb->mode.yres = params.height;
 
-	info->xres = params.width;
-	info->yres = params.height;
+	info = &simplefb->info;
+	info->mode = &simplefb->mode;
 	info->bits_per_pixel = params.format->bits_per_pixel;
 	info->red = params.format->red;
 	info->green = params.format->green;
 	info->blue = params.format->blue;
 	info->transp = params.format->transp;
-	info->line_length = params.stride;
 
 	info->screen_base = (void *)mem->start;
 	info->screen_size = resource_size(mem);
@@ -116,10 +124,6 @@ static int simplefb_probe(struct device_d *dev)
 
 	dev_info(dev, "framebuffer at 0x%p, 0x%lx bytes\n",
 		 info->screen_base, info->screen_size);
-	dev_info(dev, "format=%s, mode=%dx%dx%d, linelength=%d\n",
-		 params.format->name,
-		 info->xres, info->yres,
-		 info->bits_per_pixel, info->line_length);
 
 	info->dev.parent = dev;
 	ret = register_framebuffer(info);
-- 
2.30.2



From a.fatoum at pengutronix.de  Tue Aug 24 02:51:19 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 24 Aug 2021 11:51:19 +0200
Subject: [PATCH 2/2] video: simplefb-client: make probe less verbose
In-Reply-To: <20210824095119.15907-1-a.fatoum@pengutronix.de>
References: <20210824095119.15907-1-a.fatoum@pengutronix.de>
Message-ID: <20210824095119.15907-2-a.fatoum@pengutronix.de>

Printing the framebuffer base is unnecessary because it's already
contained in the dev_printf prefix. Make the message shorter
and only print it on success.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/video/simplefb-client.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/video/simplefb-client.c b/drivers/video/simplefb-client.c
index e1f241d4d874..2367713ba4ae 100644
--- a/drivers/video/simplefb-client.c
+++ b/drivers/video/simplefb-client.c
@@ -122,9 +122,6 @@ static int simplefb_probe(struct device_d *dev)
 
 	info->fbops = &simplefb_ops;
 
-	dev_info(dev, "framebuffer at 0x%p, 0x%lx bytes\n",
-		 info->screen_base, info->screen_size);
-
 	info->dev.parent = dev;
 	ret = register_framebuffer(info);
 	if (ret < 0) {
@@ -132,7 +129,7 @@ static int simplefb_probe(struct device_d *dev)
 		return ret;
 	}
 
-	dev_info(dev, "simplefb registered!\n");
+	dev_info(dev, "size %s registered\n", size_human_readable(info->screen_size));
 
 	return 0;
 }
-- 
2.30.2



From m.felsch at pengutronix.de  Tue Aug 24 03:46:48 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 24 Aug 2021 12:46:48 +0200
Subject: [PATCH] usb: imx-us-phy: add vbus_valid ro parameter
Message-ID: <20210824104648.15938-1-m.felsch@pengutronix.de>

The parameter can be used by init scripts to detect a plugged usb cable.
Upon a plugged usb cable the barebox behaviour can be changed which can
be useful e.g. during production to apply a special production
environment.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 drivers/usb/imx/imx-usb-phy.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
index 32098ef248..9420c8c109 100644
--- a/drivers/usb/imx/imx-usb-phy.c
+++ b/drivers/usb/imx/imx-usb-phy.c
@@ -37,9 +37,12 @@
 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
 
 #define ANADIG_USB1_CHRG_DETECT_SET		0x1b4
-#define ANADIG_USB2_CHRG_DETECT_SET		0x214
 #define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20)
 #define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19)
+#define ANADIG_USB1_VBUS_DETECT_STAT		0x1c0
+#define ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID	BIT(3)
+#define ANADIG_USB2_CHRG_DETECT_SET		0x214
+#define ANADIG_USB2_VBUS_DETECT_STAT		0x220
 
 struct imx_usbphy {
 	struct usb_phy usb_phy;
@@ -132,6 +135,27 @@ static const struct phy_ops imx_phy_ops = {
 	.to_usbphy = imx_usbphy_to_usbphy,
 };
 
+/* Albeit the access can only happen serial use two variables */
+unsigned int vbus_valid_usb1;
+unsigned int vbus_valid_usb2;
+
+static int imx_usbphy_get_vbus_state(struct param_d *p, void *priv)
+{
+	struct imx_usbphy *imxphy = priv;
+	unsigned int *vbus_valid;
+	unsigned int reg, val;
+
+	reg = imxphy->port_id ?
+		ANADIG_USB1_VBUS_DETECT_STAT :
+		ANADIG_USB2_VBUS_DETECT_STAT;
+	val = readl(imxphy->anatop + reg);
+
+	vbus_valid = imxphy->port_id ? &vbus_valid_usb1 : &vbus_valid_usb2;
+	*vbus_valid = !!(val & ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID);
+
+	return 0;
+}
+
 static int imx_usbphy_probe(struct device_d *dev)
 {
 	struct resource *iores;
@@ -149,11 +173,19 @@ static int imx_usbphy_probe(struct device_d *dev)
 	imxphy->port_id = ret;
 
 	if (of_get_property(np, "fsl,anatop", NULL)) {
+		unsigned int *vbus_valid = imxphy->port_id ?
+			&vbus_valid_usb1 :
+			&vbus_valid_usb2;
+
 		imxphy->anatop =
 			syscon_base_lookup_by_phandle(np, "fsl,anatop");
 		ret = PTR_ERR_OR_ZERO(imxphy->anatop);
 		if (ret)
 			goto err_free;
+
+		dev_add_param_bool(dev, "vbus_valid", param_set_readonly,
+				   imx_usbphy_get_vbus_state, vbus_valid,
+				   imxphy);
 	}
 
 	iores = dev_request_mem_resource(dev, 0);
-- 
2.30.2



From a.fatoum at pengutronix.de  Tue Aug 24 04:01:08 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 24 Aug 2021 13:01:08 +0200
Subject: [PATCH] usb: imx-us-phy: add vbus_valid ro parameter
In-Reply-To: <20210824104648.15938-1-m.felsch@pengutronix.de>
References: <20210824104648.15938-1-m.felsch@pengutronix.de>
Message-ID: <36ae0849-3c29-ae3e-eb52-7271cf345232@pengutronix.de>

Hello Marco,

On 24.08.21 12:46, Marco Felsch wrote:
> The parameter can be used by init scripts to detect a plugged usb cable.
> Upon a plugged usb cable the barebox behaviour can be changed which can
> be useful e.g. during production to apply a special production
> environment.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  drivers/usb/imx/imx-usb-phy.c | 34 +++++++++++++++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
> index 32098ef248..9420c8c109 100644
> --- a/drivers/usb/imx/imx-usb-phy.c
> +++ b/drivers/usb/imx/imx-usb-phy.c
> @@ -37,9 +37,12 @@
>  #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
>  
>  #define ANADIG_USB1_CHRG_DETECT_SET		0x1b4
> -#define ANADIG_USB2_CHRG_DETECT_SET		0x214
>  #define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20)
>  #define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19)
> +#define ANADIG_USB1_VBUS_DETECT_STAT		0x1c0
> +#define ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID	BIT(3)
> +#define ANADIG_USB2_CHRG_DETECT_SET		0x214
> +#define ANADIG_USB2_VBUS_DETECT_STAT		0x220
>  
>  struct imx_usbphy {
>  	struct usb_phy usb_phy;
> @@ -132,6 +135,27 @@ static const struct phy_ops imx_phy_ops = {
>  	.to_usbphy = imx_usbphy_to_usbphy,
>  };
>  
> +/* Albeit the access can only happen serial use two variables */
> +unsigned int vbus_valid_usb1;
> +unsigned int vbus_valid_usb2;
> +
> +static int imx_usbphy_get_vbus_state(struct param_d *p, void *priv)
> +{
> +	struct imx_usbphy *imxphy = priv;
> +	unsigned int *vbus_valid;
> +	unsigned int reg, val;
> +
> +	reg = imxphy->port_id ?
> +		ANADIG_USB1_VBUS_DETECT_STAT :
> +		ANADIG_USB2_VBUS_DETECT_STAT;
> +	val = readl(imxphy->anatop + reg);
> +
> +	vbus_valid = imxphy->port_id ? &vbus_valid_usb1 : &vbus_valid_usb2;
> +	*vbus_valid = !!(val & ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID);
> +
> +	return 0;
> +}
> +
>  static int imx_usbphy_probe(struct device_d *dev)
>  {
>  	struct resource *iores;
> @@ -149,11 +173,19 @@ static int imx_usbphy_probe(struct device_d *dev)
>  	imxphy->port_id = ret;
>  
>  	if (of_get_property(np, "fsl,anatop", NULL)) {
> +		unsigned int *vbus_valid = imxphy->port_id ?
> +			&vbus_valid_usb1 :
> +			&vbus_valid_usb2;

Can you allocate this in imxphy? That way you avoid globals
and don't hardcode the existance of only two phys into the driver.

> +
>  		imxphy->anatop =
>  			syscon_base_lookup_by_phandle(np, "fsl,anatop");
>  		ret = PTR_ERR_OR_ZERO(imxphy->anatop);
>  		if (ret)
>  			goto err_free;
> +
> +		dev_add_param_bool(dev, "vbus_valid", param_set_readonly,
> +				   imx_usbphy_get_vbus_state, vbus_valid,
> +				   imxphy);

I assume valid == usb port is in gadget mode and host is supplying vbus?
What happens when port is in host mode? A comment explaining this would
be nice.

>  	}
>  
>  	iores = dev_request_mem_resource(dev, 0);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Tue Aug 24 04:13:46 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 24 Aug 2021 13:13:46 +0200
Subject: [PATCH] usb: imx-us-phy: add vbus_valid ro parameter
In-Reply-To: <36ae0849-3c29-ae3e-eb52-7271cf345232@pengutronix.de>
References: <20210824104648.15938-1-m.felsch@pengutronix.de>
 <36ae0849-3c29-ae3e-eb52-7271cf345232@pengutronix.de>
Message-ID: <YSTUamOOiYth87rF@pengutronix.de>

Hi Ahmad,

On 21-08-24 13:01, Ahmad Fatoum wrote:
> Hello Marco,
> 
> On 24.08.21 12:46, Marco Felsch wrote:
> > The parameter can be used by init scripts to detect a plugged usb cable.
> > Upon a plugged usb cable the barebox behaviour can be changed which can
> > be useful e.g. during production to apply a special production
> > environment.
> > 
> > Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> > ---
> >  drivers/usb/imx/imx-usb-phy.c | 34 +++++++++++++++++++++++++++++++++-
> >  1 file changed, 33 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
> > index 32098ef248..9420c8c109 100644
> > --- a/drivers/usb/imx/imx-usb-phy.c
> > +++ b/drivers/usb/imx/imx-usb-phy.c
> > @@ -37,9 +37,12 @@
> >  #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
> >  
> >  #define ANADIG_USB1_CHRG_DETECT_SET		0x1b4
> > -#define ANADIG_USB2_CHRG_DETECT_SET		0x214
> >  #define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20)
> >  #define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19)
> > +#define ANADIG_USB1_VBUS_DETECT_STAT		0x1c0
> > +#define ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID	BIT(3)
> > +#define ANADIG_USB2_CHRG_DETECT_SET		0x214
> > +#define ANADIG_USB2_VBUS_DETECT_STAT		0x220
> >  
> >  struct imx_usbphy {
> >  	struct usb_phy usb_phy;
> > @@ -132,6 +135,27 @@ static const struct phy_ops imx_phy_ops = {
> >  	.to_usbphy = imx_usbphy_to_usbphy,
> >  };
> >  
> > +/* Albeit the access can only happen serial use two variables */
> > +unsigned int vbus_valid_usb1;
> > +unsigned int vbus_valid_usb2;
> > +
> > +static int imx_usbphy_get_vbus_state(struct param_d *p, void *priv)
> > +{
> > +	struct imx_usbphy *imxphy = priv;
> > +	unsigned int *vbus_valid;
> > +	unsigned int reg, val;
> > +
> > +	reg = imxphy->port_id ?
> > +		ANADIG_USB1_VBUS_DETECT_STAT :
> > +		ANADIG_USB2_VBUS_DETECT_STAT;
> > +	val = readl(imxphy->anatop + reg);
> > +
> > +	vbus_valid = imxphy->port_id ? &vbus_valid_usb1 : &vbus_valid_usb2;
> > +	*vbus_valid = !!(val & ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID);
> > +
> > +	return 0;
> > +}
> > +
> >  static int imx_usbphy_probe(struct device_d *dev)
> >  {
> >  	struct resource *iores;
> > @@ -149,11 +173,19 @@ static int imx_usbphy_probe(struct device_d *dev)
> >  	imxphy->port_id = ret;
> >  
> >  	if (of_get_property(np, "fsl,anatop", NULL)) {
> > +		unsigned int *vbus_valid = imxphy->port_id ?
> > +			&vbus_valid_usb1 :
> > +			&vbus_valid_usb2;
> 
> Can you allocate this in imxphy? That way you avoid globals
> and don't hardcode the existance of only two phys into the driver.

You're right, good point.

> > +
> >  		imxphy->anatop =
> >  			syscon_base_lookup_by_phandle(np, "fsl,anatop");
> >  		ret = PTR_ERR_OR_ZERO(imxphy->anatop);
> >  		if (ret)
> >  			goto err_free;
> > +
> > +		dev_add_param_bool(dev, "vbus_valid", param_set_readonly,
> > +				   imx_usbphy_get_vbus_state, vbus_valid,
> > +				   imxphy);
> 
> I assume valid == usb port is in gadget mode and host is supplying vbus?

Your're right.

> What happens when port is in host mode? A comment explaining this would
> be nice.

That's a good question didn't checked this and the datasheet don't
distinguish between those modes. I will test it and add a comment.

Regards,
  Marco

> 
> >  	}
> >  
> >  	iores = dev_request_mem_resource(dev, 0);
> > 
> 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Tue Aug 24 04:21:15 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 24 Aug 2021 13:21:15 +0200
Subject: [PATCH] usb: imx-us-phy: add vbus_valid ro parameter
In-Reply-To: <YSTUamOOiYth87rF@pengutronix.de>
References: <20210824104648.15938-1-m.felsch@pengutronix.de>
 <36ae0849-3c29-ae3e-eb52-7271cf345232@pengutronix.de>
 <YSTUamOOiYth87rF@pengutronix.de>
Message-ID: <94931ec0-c614-abe0-5396-85dbde991690@pengutronix.de>

On 24.08.21 13:13, Marco Felsch wrote:
> Hi Ahmad,
> 
> On 21-08-24 13:01, Ahmad Fatoum wrote:
>> Hello Marco,
>>
>> On 24.08.21 12:46, Marco Felsch wrote:
>>> The parameter can be used by init scripts to detect a plugged usb cable.
>>> Upon a plugged usb cable the barebox behaviour can be changed which can
>>> be useful e.g. during production to apply a special production
>>> environment.
>>>
>>> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
>>> ---
>>>  drivers/usb/imx/imx-usb-phy.c | 34 +++++++++++++++++++++++++++++++++-
>>>  1 file changed, 33 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
>>> index 32098ef248..9420c8c109 100644
>>> --- a/drivers/usb/imx/imx-usb-phy.c
>>> +++ b/drivers/usb/imx/imx-usb-phy.c
>>> @@ -37,9 +37,12 @@
>>>  #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
>>>  
>>>  #define ANADIG_USB1_CHRG_DETECT_SET		0x1b4
>>> -#define ANADIG_USB2_CHRG_DETECT_SET		0x214
>>>  #define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20)
>>>  #define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19)
>>> +#define ANADIG_USB1_VBUS_DETECT_STAT		0x1c0
>>> +#define ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID	BIT(3)
>>> +#define ANADIG_USB2_CHRG_DETECT_SET		0x214
>>> +#define ANADIG_USB2_VBUS_DETECT_STAT		0x220
>>>  
>>>  struct imx_usbphy {
>>>  	struct usb_phy usb_phy;
>>> @@ -132,6 +135,27 @@ static const struct phy_ops imx_phy_ops = {
>>>  	.to_usbphy = imx_usbphy_to_usbphy,
>>>  };
>>>  
>>> +/* Albeit the access can only happen serial use two variables */
>>> +unsigned int vbus_valid_usb1;
>>> +unsigned int vbus_valid_usb2;
>>> +
>>> +static int imx_usbphy_get_vbus_state(struct param_d *p, void *priv)
>>> +{
>>> +	struct imx_usbphy *imxphy = priv;
>>> +	unsigned int *vbus_valid;
>>> +	unsigned int reg, val;
>>> +
>>> +	reg = imxphy->port_id ?
>>> +		ANADIG_USB1_VBUS_DETECT_STAT :
>>> +		ANADIG_USB2_VBUS_DETECT_STAT;
>>> +	val = readl(imxphy->anatop + reg);
>>> +
>>> +	vbus_valid = imxphy->port_id ? &vbus_valid_usb1 : &vbus_valid_usb2;
>>> +	*vbus_valid = !!(val & ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static int imx_usbphy_probe(struct device_d *dev)
>>>  {
>>>  	struct resource *iores;
>>> @@ -149,11 +173,19 @@ static int imx_usbphy_probe(struct device_d *dev)
>>>  	imxphy->port_id = ret;
>>>  
>>>  	if (of_get_property(np, "fsl,anatop", NULL)) {
>>> +		unsigned int *vbus_valid = imxphy->port_id ?
>>> +			&vbus_valid_usb1 :
>>> +			&vbus_valid_usb2;
>>
>> Can you allocate this in imxphy? That way you avoid globals
>> and don't hardcode the existance of only two phys into the driver.
> 
> You're right, good point.
> 
>>> +
>>>  		imxphy->anatop =
>>>  			syscon_base_lookup_by_phandle(np, "fsl,anatop");
>>>  		ret = PTR_ERR_OR_ZERO(imxphy->anatop);
>>>  		if (ret)
>>>  			goto err_free;
>>> +
>>> +		dev_add_param_bool(dev, "vbus_valid", param_set_readonly,
>>> +				   imx_usbphy_get_vbus_state, vbus_valid,
>>> +				   imxphy);
>>
>> I assume valid == usb port is in gadget mode and host is supplying vbus?
> 
> Your're right.
> 
>> What happens when port is in host mode? A comment explaining this would
>> be nice.
> 
> That's a good question didn't checked this and the datasheet don't
> distinguish between those modes. I will test it and add a comment.

prt_imx6_check_usb_boot may also be interesting to you. The protonic boards
use this to detect whether a USB drive is connected or not.

Combining those could give you a usb.connected_to={gadget,host,none}

(or some other better name)

Cheers,
Ahmad

> 
> Regards,
>   Marco
> 
>>
>>>  	}
>>>  
>>>  	iores = dev_request_mem_resource(dev, 0);
>>>
>>
>>
>> -- 
>> Pengutronix e.K.                           |                             |
>> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
>> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
>> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>>
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Tue Aug 24 05:12:08 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 24 Aug 2021 14:12:08 +0200
Subject: [PATCH v2] usb: imx-us-phy: add vbus_valid ro parameter
Message-ID: <20210824121208.31988-1-m.felsch@pengutronix.de>

The parameter can be used by init scripts to detect a plugged usb cable.
Upon a plugged usb cable the barebox behaviour can be changed which can
be useful e.g. during production to apply a special production
environment.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
v2:
- move vbus_valid into 'struct imx_usbphy' to avoid global vars
- add comment

 drivers/usb/imx/imx-usb-phy.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
index 32098ef248..6a58e71ba2 100644
--- a/drivers/usb/imx/imx-usb-phy.c
+++ b/drivers/usb/imx/imx-usb-phy.c
@@ -37,9 +37,12 @@
 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
 
 #define ANADIG_USB1_CHRG_DETECT_SET		0x1b4
-#define ANADIG_USB2_CHRG_DETECT_SET		0x214
 #define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20)
 #define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19)
+#define ANADIG_USB1_VBUS_DETECT_STAT		0x1c0
+#define ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID	BIT(3)
+#define ANADIG_USB2_CHRG_DETECT_SET		0x214
+#define ANADIG_USB2_VBUS_DETECT_STAT		0x220
 
 struct imx_usbphy {
 	struct usb_phy usb_phy;
@@ -49,6 +52,8 @@ struct imx_usbphy {
 	struct clk *clk;
 	struct phy_provider *provider;
 	int port_id;
+
+	unsigned int vbus_valid;
 };
 
 static int imx_usbphy_phy_init(struct phy *phy)
@@ -132,6 +137,21 @@ static const struct phy_ops imx_phy_ops = {
 	.to_usbphy = imx_usbphy_to_usbphy,
 };
 
+static int imx_usbphy_get_vbus_state(struct param_d *p, void *priv)
+{
+	struct imx_usbphy *imxphy = priv;
+	unsigned int reg, val;
+
+	reg = imxphy->port_id ?
+		ANADIG_USB1_VBUS_DETECT_STAT :
+		ANADIG_USB2_VBUS_DETECT_STAT;
+	val = readl(imxphy->anatop + reg);
+
+	imxphy->vbus_valid  = !!(val & ANADIG_USB1_VBUS_DETECT_STAT_VBUS_VALID);
+
+	return 0;
+}
+
 static int imx_usbphy_probe(struct device_d *dev)
 {
 	struct resource *iores;
@@ -154,6 +174,15 @@ static int imx_usbphy_probe(struct device_d *dev)
 		ret = PTR_ERR_OR_ZERO(imxphy->anatop);
 		if (ret)
 			goto err_free;
+
+		/*
+		 * This is useful in case of usb-otg = device. In host case
+		 * it isn't that useful since we are the supplier of the vbus
+		 * signal.
+		 */
+		dev_add_param_bool(dev, "vbus_valid", param_set_readonly,
+				   imx_usbphy_get_vbus_state,
+				   &imxphy->vbus_valid, imxphy);
 	}
 
 	iores = dev_request_mem_resource(dev, 0);
-- 
2.30.2



From r.czerwinski at pengutronix.de  Tue Aug 24 23:55:54 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Wed, 25 Aug 2021 08:55:54 +0200
Subject: [PATCH] net: eqos: let phy_resume handle fixed link phys
Message-ID: <20210825065554.23283-1-r.czerwinski@pengutronix.de>

Currently barebox will try to talk to the phy over mdio, even if the
parent is a fixed-link. This will result in the following stacktrace:

  barebox at Linux Automation Test Automation Controller (TAC):/ dhcp
  unable to handle NULL pointer dereference at address 0x00000130
  pc : [<dfc01800>]    lr : [<dfc0f963>]
  sp : dffefd40  ip : 004c4b40  fp : d00286e0
  r10: cf25cc4e  r9 : 00000000  r8 : 05f5e100
  r7 : 00000130  r6 : 00000000  r5 : 00000000  r4 : 00000130
  r3 : 00000109  r2 : 00000000  r1 : 00000000  r0 : 00000130
  Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
  WARNING: [<dfc01800>] (slice_acquire+0xc/0x28) from [<dfc0f963>] (mdiobus_read+0x13/0x28)
  WARNING: [<dfc0f963>] (mdiobus_read+0x13/0x28) from [<dfc10685>] (eqos_start+0x85/0x32c)
  WARNING: [<dfc10685>] (eqos_start+0x85/0x32c) from [<dfc3cdf1>] (eth_open+0xd/0x24)
  WARNING: [<dfc3cdf1>] (eth_open+0xd/0x24) from [<dfc3e391>] (dhcp+0xb/0x3a)
  WARNING: [<dfc3e391>] (dhcp+0xb/0x3a) from [<dfc30fab>] (do_dhcp+0xfb/0x114)
  WARNING: [<dfc30fab>] (do_dhcp+0xfb/0x114) from [<dfc0490f>] (execute_command+0x23/0x4c)
  WARNING: [<dfc0490f>] (execute_command+0x23/0x4c) from [<dfc0a127>] (run_list_real+0x5bf/0x638)
  WARNING: [<dfc0a127>] (run_list_real+0x5bf/0x638) from [<dfc09a2b>] (parse_stream_outer+0xc7/0x154)
  WARNING: [<dfc09a2b>] (parse_stream_outer+0xc7/0x154) from [<dfc0a383>] (run_shell+0x3f/0x6c)
  WARNING: [<dfc0a383>] (run_shell+0x3f/0x6c) from [<dfc010b9>] (run_init+0x191/0x200)
  WARNING: [<dfc010b9>] (run_init+0x191/0x200) from [<dfc01153>] (start_barebox+0x2b/0x6c)
  WARNING: [<dfc01153>] (start_barebox+0x2b/0x6c) from [<dfc4be6d>] (barebox_non_pbl_start+0x121/0x164)
  WARNING: [<dfc4be6d>] (barebox_non_pbl_start+0x121/0x164) from [<dfc00005>] (__bare_init_start+0x1/0xc)

  WARNING: [<dfc4da7d>] (unwind_backtrace+0x1/0x78) from [<dfc01461>] (panic+0x1d/0x34)
  WARNING: [<dfc01461>] (panic+0x1d/0x34) from [<dfc4b6a3>] (do_exception+0xf/0x14)
  WARNING: [<dfc4b6a3>] (do_exception+0xf/0x14) from [<dfc4b711>] (do_data_abort+0x21/0x34)
  WARNING: [<dfc4b711>] (do_data_abort+0x21/0x34) from [<dfc4b454>] (do_abort_6+0x48/0x54)

Simply return with 0 if bus is zero which indicates that the phy is
connected to a fixed link.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 drivers/net/designware_eqos.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
index f83ec12714..f83e5d6d9b 100644
--- a/drivers/net/designware_eqos.c
+++ b/drivers/net/designware_eqos.c
@@ -362,6 +362,10 @@ static int phy_resume(struct phy_device *phydev)
 {
 	int bmcr;
 
+	// Bus will be NULL if a fixed-link is used.
+	if (!phydev->bus)
+		return 0;
+
 	bmcr = phy_read(phydev, MII_BMCR);
 	if (bmcr < 0)
 		return bmcr;
-- 
2.32.0



From r.czerwinski at pengutronix.de  Wed Aug 25 00:05:42 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Wed, 25 Aug 2021 09:05:42 +0200
Subject: [PATCH] net: eqos: let phy_resume handle fixed link phys
In-Reply-To: <20210825065554.23283-1-r.czerwinski@pengutronix.de>
References: <20210825065554.23283-1-r.czerwinski@pengutronix.de>
Message-ID: <6a4ba5a28c9049e1b73cf8ee01929504a7dd95a6.camel@pengutronix.de>

Hello,

self review time.

On Wed, 2021-08-25 at 08:55 +0200, Rouven Czerwinski wrote:
> Currently barebox will try to talk to the phy over mdio, even if the
> parent is a fixed-link. This will result in the following stacktrace:
> 
>   barebox at Linux Automation Test Automation Controller (TAC):/ dhcp
>   unable to handle NULL pointer dereference at address 0x00000130
>   pc : [<dfc01800>]    lr : [<dfc0f963>]
>   sp : dffefd40  ip : 004c4b40  fp : d00286e0
>   r10: cf25cc4e  r9 : 00000000  r8 : 05f5e100
>   r7 : 00000130  r6 : 00000000  r5 : 00000000  r4 : 00000130
>   r3 : 00000109  r2 : 00000000  r1 : 00000000  r0 : 00000130
>   Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
>   WARNING: [<dfc01800>] (slice_acquire+0xc/0x28) from [<dfc0f963>] (mdiobus_read+0x13/0x28)
>   WARNING: [<dfc0f963>] (mdiobus_read+0x13/0x28) from [<dfc10685>] (eqos_start+0x85/0x32c)
>   WARNING: [<dfc10685>] (eqos_start+0x85/0x32c) from [<dfc3cdf1>] (eth_open+0xd/0x24)
>   WARNING: [<dfc3cdf1>] (eth_open+0xd/0x24) from [<dfc3e391>] (dhcp+0xb/0x3a)
>   WARNING: [<dfc3e391>] (dhcp+0xb/0x3a) from [<dfc30fab>] (do_dhcp+0xfb/0x114)
>   WARNING: [<dfc30fab>] (do_dhcp+0xfb/0x114) from [<dfc0490f>] (execute_command+0x23/0x4c)
>   WARNING: [<dfc0490f>] (execute_command+0x23/0x4c) from [<dfc0a127>] (run_list_real+0x5bf/0x638)
>   WARNING: [<dfc0a127>] (run_list_real+0x5bf/0x638) from [<dfc09a2b>] (parse_stream_outer+0xc7/0x154)
>   WARNING: [<dfc09a2b>] (parse_stream_outer+0xc7/0x154) from [<dfc0a383>] (run_shell+0x3f/0x6c)
>   WARNING: [<dfc0a383>] (run_shell+0x3f/0x6c) from [<dfc010b9>] (run_init+0x191/0x200)
>   WARNING: [<dfc010b9>] (run_init+0x191/0x200) from [<dfc01153>] (start_barebox+0x2b/0x6c)
>   WARNING: [<dfc01153>] (start_barebox+0x2b/0x6c) from [<dfc4be6d>] (barebox_non_pbl_start+0x121/0x164)
>   WARNING: [<dfc4be6d>] (barebox_non_pbl_start+0x121/0x164) from [<dfc00005>] (__bare_init_start+0x1/0xc)
> 
>   WARNING: [<dfc4da7d>] (unwind_backtrace+0x1/0x78) from [<dfc01461>] (panic+0x1d/0x34)
>   WARNING: [<dfc01461>] (panic+0x1d/0x34) from [<dfc4b6a3>] (do_exception+0xf/0x14)
>   WARNING: [<dfc4b6a3>] (do_exception+0xf/0x14) from [<dfc4b711>] (do_data_abort+0x21/0x34)
>   WARNING: [<dfc4b711>] (do_data_abort+0x21/0x34) from [<dfc4b454>] (do_abort_6+0x48/0x54)
> 
> Simply return with 0 if bus is zero which indicates that the phy is
                                 ^NULL not zero?
> connected to a fixed link.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  drivers/net/designware_eqos.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
> index f83ec12714..f83e5d6d9b 100644
> --- a/drivers/net/designware_eqos.c
> +++ b/drivers/net/designware_eqos.c
> @@ -362,6 +362,10 @@ static int phy_resume(struct phy_device *phydev)
>  {
>  	int bmcr;
>  
> +	// Bus will be NULL if a fixed-link is used.
> +	if (!phydev->bus)
> +		return 0;
> +
>  	bmcr = phy_read(phydev, MII_BMCR);
>  	if (bmcr < 0)
>  		return bmcr;

Regards,
Rouven



From a.fatoum at pengutronix.de  Wed Aug 25 02:27:01 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 25 Aug 2021 11:27:01 +0200
Subject: [PATCH] Documentation: framebuffer: remove note about lack of
 backlight support
Message-ID: <20210825092701.30436-1-a.fatoum@pengutronix.de>

barebox supports PWM backlight. Remove the notice about lack of support.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 Documentation/user/framebuffer.rst | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/Documentation/user/framebuffer.rst b/Documentation/user/framebuffer.rst
index 8b95ad6b8700..d17df822f299 100644
--- a/Documentation/user/framebuffer.rst
+++ b/Documentation/user/framebuffer.rst
@@ -4,9 +4,7 @@ Framebuffer support
 Framebuffer splash 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
+barebox supports BMP and PNG graphics using the :ref:`command_splash` command. Since barebox
 has nothing useful to show on the framebuffer it doesn't enable it during startup.
 A framebuffer can be enabled with the ``enable`` parameter of the framebuffer device:
 
@@ -39,7 +37,7 @@ A typical script to enable the framebuffer could look like this:
   # wait for signals to become stable
   msleep 100
 
-  # finally enable backlight
+  # finally enable backlight manually if no driver exists
   gpio_direction_output 42 1
 
 Framebuffer console
-- 
2.30.2



From m.felsch at pengutronix.de  Wed Aug 25 04:35:25 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 25 Aug 2021 13:35:25 +0200
Subject: [PATCH] mtd: spi-nor: remove use-large-blocks left over
Message-ID: <20210825113525.5434-1-m.felsch@pengutronix.de>

Commit 8e3318b5bc ("mtd: spi-nor: introduce SPI 1-2-2 and SPI 1-4-4
protocols") added the spi_nor_select_erase() function. This function
don't take the use_large_blocks parameter into account anymore and
instead relies only on the Kconfig config.

This commit removes the left over 'use_large_blocks' and
'use-large-blocks' references to cleanup the code base and to avoid
confusion. No functional changes are made.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 Documentation/devicetree/bindings/mtd/m25p80.rst | 10 ----------
 drivers/mtd/devices/m25p80.c                     |  6 +-----
 drivers/mtd/spi-nor/spi-nor.c                    |  3 +--
 include/linux/mtd/spi-nor.h                      |  4 +---
 4 files changed, 3 insertions(+), 20 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/m25p80.rst

diff --git a/Documentation/devicetree/bindings/mtd/m25p80.rst b/Documentation/devicetree/bindings/mtd/m25p80.rst
deleted file mode 100644
index 09e8b8eff6..0000000000
--- a/Documentation/devicetree/bindings/mtd/m25p80.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-MTD SPI driver for ST M25Pxx (and similar) serial flash chips
-=============================================================
-
-Additionally to the Linux bindings in ``dts/Bindings/mtd/jedec,spi-nor.txt``
-the barebox driver has the following optional properties:
-
-- use-large-blocks : Use large blocks rather than the 4K blocks some devices
-                     support. 4K erase blocks do not work with UBIFS which needs
-		     a minimum erase block size of 15360 bytes. Also bigger sectors
-		     are faster to erase.
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 8845ec3a3e..0685a61491 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -219,7 +219,6 @@ static int m25p_probe(struct device_d *dev)
 	};
 	const char			*flash_name = NULL;
 	int				device_id;
-	bool				use_large_blocks;
 	int ret;
 
 	data = dev->platform_data;
@@ -261,10 +260,7 @@ static int m25p_probe(struct device_d *dev)
 	else
 		flash_name = NULL; /* auto-detect */
 
-	use_large_blocks = of_property_read_bool(dev->device_node,
-			"use-large-blocks");
-
-	ret = spi_nor_scan(nor, flash_name, &hwcaps, use_large_blocks);
+	ret = spi_nor_scan(nor, flash_name, &hwcaps);
 	if (ret)
 		return ret;
 
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bd748ff5b4..10f026d7c2 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1363,8 +1363,7 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
 }
 
 int spi_nor_scan(struct spi_nor *nor, const char *name,
-		 const struct spi_nor_hwcaps *hwcaps,
-		 bool use_large_blocks)
+		 const struct spi_nor_hwcaps *hwcaps)
 {
 	struct spi_nor_flash_parameter params;
 	const struct spi_device_id	*id = NULL;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 1c6f442866..08c54baf02 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -302,7 +302,6 @@ struct spi_nor_hwcaps {
  * @nor:	the spi_nor structure
  * @name:	the chip type name
  * @hwcaps:	the hardware capabilities supported by the controller driver
- * @use_large_blocks: prefer large blocks even if 4k blocks are supported
  *
  * The drivers can use this fuction to scan the SPI NOR.
  * In the scanning, it will try to get all the necessary information to
@@ -313,7 +312,6 @@ struct spi_nor_hwcaps {
  * Return: 0 for success, others for failure.
  */
 int spi_nor_scan(struct spi_nor *nor, const char *name,
-		 const struct spi_nor_hwcaps *hwcaps,
-		 bool use_large_blocks);
+		 const struct spi_nor_hwcaps *hwcaps);
 
 #endif
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 25 05:54:28 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 25 Aug 2021 14:54:28 +0200
Subject: [PATCH v1 2/4] ARM: boards: protonic-imx6: use decode error values
 instead error numbers.
In-Reply-To: <20210825125430.26901-1-o.rempel@pengutronix.de>
References: <20210825125430.26901-1-o.rempel@pengutronix.de>
Message-ID: <20210825125430.26901-3-o.rempel@pengutronix.de>

Current barebox version provides "%pe" support with error to string
conversion. So, let's use it.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 81e09a8d8b..9a95495327 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -138,7 +138,7 @@ static int prt_imx6_read_rfid(struct prt_imx6_priv *priv, void *buf,
 	/* 0x6000 user storage in the RFID tag */
 	ret = i2c_read_reg(&cl, 0x6000 | I2C_ADDR_16_BIT, buf, size);
 	if (ret < 0) {
-		dev_err(dev, "Failed to read the RFID: %i\n", ret);
+		dev_err(dev, "Failed to read the RFID: %pe\n", ERR_PTR(ret));
 		return ret;
 	}
 
@@ -404,7 +404,7 @@ static int prt_imx6_env_init(struct prt_imx6_priv *priv)
 	return 0;
 
 exit_env_init:
-	dev_err(dev, "Failed to set env: %i\n", ret);
+	dev_err(dev, "Failed to set env: %pe\n", ERR_PTR(ret));
 
 	return ret;
 }
@@ -437,7 +437,7 @@ static int prt_imx6_bbu(struct prt_imx6_priv *priv)
 
 	return 0;
 exit_bbu:
-	dev_err(priv->dev, "Failed to register bbu: %i\n", ret);
+	dev_err(priv->dev, "Failed to register bbu: %pe\n", ERR_PTR(ret));
 	return ret;
 }
 
@@ -510,7 +510,7 @@ static int prt_imx6_yaco_set_kvg_power_mode(struct prt_imx6_priv *priv,
 	return 0;
 
 exit_yaco_set_kvg_power_mode:
-	dev_err(dev, "Failed to set YaCO pw mode: %i", ret);
+	dev_err(dev, "Failed to set YaCO pw mode: %pe", ERR_PTR(ret));
 
 	return ret;
 }
@@ -679,7 +679,7 @@ free_eeprom:
 free_alias:
 	kfree(alias);
 exit_error:
-	dev_err(priv->dev, "Failed to apply fixup: %i\n", ret);
+	dev_err(priv->dev, "Failed to apply fixup: %pe\n", ERR_PTR(ret));
 	return ret;
 }
 
@@ -700,7 +700,7 @@ static int prt_imx6_of_fixup(struct device_node *root, void *data)
 
 	return 0;
 exit_of_fixups:
-	dev_err(priv->dev, "Failed to apply OF fixups: %i\n", ret);
+	dev_err(priv->dev, "Failed to apply OF fixups: %pe\n", ERR_PTR(ret));
 	return ret;
 }
 
@@ -729,7 +729,7 @@ static int prt_imx6_get_id(struct prt_imx6_priv *priv)
 
 	return 0;
 exit_get_id:
-	dev_err(priv->dev, "Failed to read gpio ID: %i\n", ret);
+	dev_err(priv->dev, "Failed to read gpio ID: %pe\n", ERR_PTR(ret));
 	return ret;
 }
 
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 25 05:54:26 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 25 Aug 2021 14:54:26 +0200
Subject: [PATCH v1 0/6] protonic: maintaining and new board
Message-ID: <20210825125430.26901-1-o.rempel@pengutronix.de>

This patch series contains fixes and updates for currently mainlined
protonic boards and one new board.

Please close one eye on the arch/arm/dts/imx6ull-jozacp.dtsi, it will be
reviewed and reworked on the kernel side.

Oleksij Rempel (2):
  ARM: boards: protonic-imx6: enable deep-probe support
  ARM: boards: protonic-imx6: use decode error values instead error
    numbers.

Robin van der Gracht (2):
  ARM: boards: protonic-imx6: Skip usb check on prtvt7 by default
  ARM: boards: protonic-imx6: Add support for jozacp board

 arch/arm/boards/protonic-imx6/board.c         | 109 +++-
 .../protonic-imx6/flash-header-jozacp.imxcfg  |  81 +++
 arch/arm/boards/protonic-imx6/lowlevel.c      |  20 +
 arch/arm/dts/Makefile                         |   3 +-
 arch/arm/dts/imx6ull-jozacp.dts               |  47 ++
 arch/arm/dts/imx6ull-jozacp.dtsi              | 525 ++++++++++++++++++
 images/Makefile.imx                           |   2 +
 7 files changed, 761 insertions(+), 26 deletions(-)
 create mode 100644 arch/arm/boards/protonic-imx6/flash-header-jozacp.imxcfg
 create mode 100644 arch/arm/dts/imx6ull-jozacp.dts
 create mode 100644 arch/arm/dts/imx6ull-jozacp.dtsi

-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 25 05:54:27 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 25 Aug 2021 14:54:27 +0200
Subject: [PATCH v1 1/4] ARM: boards: protonic-imx6: enable deep-probe support
In-Reply-To: <20210825125430.26901-1-o.rempel@pengutronix.de>
References: <20210825125430.26901-1-o.rempel@pengutronix.de>
Message-ID: <20210825125430.26901-2-o.rempel@pengutronix.de>

Enable deep-probe support and fix gpio dependency for the early probe.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 9ded94b3b0..81e09a8d8b 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -5,6 +5,7 @@
 
 #include <bbu.h>
 #include <common.h>
+#include <deep-probe.h>
 #include <environment.h>
 #include <fcntl.h>
 #include <gpio.h>
@@ -707,8 +708,17 @@ static int prt_imx6_get_id(struct prt_imx6_priv *priv)
 {
 	struct gpio gpios_type[] = GPIO_HW_TYPE_ID;
 	struct gpio gpios_rev[] = GPIO_HW_REV_ID;
+	struct device_node *gpio_np = NULL;
 	int ret;
 
+	gpio_np = of_find_node_by_name(NULL, "gpio at 20a0000");
+	if (!gpio_np)
+		return -ENODEV;
+
+	ret = of_device_ensure_probed(gpio_np);
+	if (ret)
+		return ret;
+
 	ret = gpio_array_to_id(gpios_type, ARRAY_SIZE(gpios_type), &priv->hw_id);
 	if (ret)
 		goto exit_get_id;
@@ -1071,6 +1081,7 @@ static const struct of_device_id prt_imx6_of_match[] = {
 	{ .compatible = "prt,prtwd3", .data = &prt_imx6_cfg_prtwd3 },
 	{ /* sentinel */ },
 };
+BAREBOX_DEEP_PROBE_ENABLE(prt_imx6_of_match);
 
 static struct driver_d prt_imx6_board_driver = {
 	.name = "board-protonic-imx6",
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 25 05:54:29 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 25 Aug 2021 14:54:29 +0200
Subject: [PATCH v1 3/4] ARM: boards: protonic-imx6: Skip usb check on prtvt7
 by default
In-Reply-To: <20210825125430.26901-1-o.rempel@pengutronix.de>
References: <20210825125430.26901-1-o.rempel@pengutronix.de>
Message-ID: <20210825125430.26901-4-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

This product has physical buttons. When a certain combination is pressed,
the usb check should be performed otherwise it can be skipped to allow
faster booting.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 61 +++++++++++++++++++--------
 1 file changed, 43 insertions(+), 18 deletions(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 9a95495327..cacbdafa31 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -84,6 +84,7 @@ struct prt_imx6_priv {
 	const char *name;
 	struct poller_async poller;
 	unsigned int usb_delay;
+	unsigned int no_usb_check;
 };
 
 struct prti6q_rfid_contents {
@@ -380,16 +381,20 @@ static int prt_imx6_env_init(struct prt_imx6_priv *priv)
 	if (ret)
 		goto exit_env_init;
 
-	if (dcfg->flags & PRT_IMX6_USB_LONG_DELAY)
-		priv->usb_delay = 4;
-	else
-		priv->usb_delay = 1;
-
-	/* the usb_delay value is used for poller_call_async() */
-	delay = basprintf("%d", priv->usb_delay);
-	ret = setenv("global.autoboot_timeout", delay);
-	if (ret)
-		goto exit_env_init;
+	if (priv->no_usb_check) {
+		set_autoboot_state(AUTOBOOT_BOOT);
+	} else {
+		if (dcfg->flags & PRT_IMX6_USB_LONG_DELAY)
+			priv->usb_delay = 4;
+		else
+			priv->usb_delay = 1;
+
+		/* the usb_delay value is used for poller_call_async() */
+		delay = basprintf("%d", priv->usb_delay);
+		ret = setenv("global.autoboot_timeout", delay);
+		if (ret)
+			goto exit_env_init;
+	}
 
 	if (dcfg->flags & PRT_IMX6_BOOTCHOOSER)
 		bootsrc = "bootchooser";
@@ -458,14 +463,16 @@ static int prt_imx6_devices_init(void)
 
 	prt_imx6_env_init(priv);
 
-	ret = poller_async_register(&priv->poller, "usb-boot");
-	if (ret) {
-		dev_err(priv->dev, "can't setup poller\n");
-		return ret;
-	}
+	if (!priv->no_usb_check) {
+		ret = poller_async_register(&priv->poller, "usb-boot");
+		if (ret) {
+			dev_err(priv->dev, "can't setup poller\n");
+			return ret;
+		}
 
-	poller_call_async(&priv->poller, priv->usb_delay * SECOND,
-			  &prt_imx6_check_usb_boot, priv);
+		poller_call_async(&priv->poller, priv->usb_delay * SECOND,
+				  &prt_imx6_check_usb_boot, priv);
+	}
 
 	return 0;
 }
@@ -618,6 +625,22 @@ static int prt_imx6_init_kvg_yaco(struct prt_imx6_priv *priv)
 	return prt_imx6_init_kvg_power(priv, PW_MODE_KVG_WITH_YACO);
 }
 
+#define GPIO_KEY_F6     (0xe0 + 5)
+#define GPIO_KEY_CYCLE  (0xe0 + 2)
+
+static int prt_imx6_init_prtvt7(struct prt_imx6_priv *priv)
+{
+	/* This function relies heavely on the gpio-pca9539 driver */
+
+	gpio_direction_input(GPIO_KEY_F6);
+	gpio_direction_input(GPIO_KEY_CYCLE);
+
+	if (gpio_get_value(GPIO_KEY_CYCLE) && gpio_get_value(GPIO_KEY_F6))
+		priv->no_usb_check = 1;
+
+	return 0;
+}
+
 static int prt_imx6_rfid_fixup(struct prt_imx6_priv *priv,
 			       struct device_node *root)
 {
@@ -1031,7 +1054,9 @@ static const struct prt_machine_data prt_imx6_cfg_prtvt7[] = {
 		.i2c_addr = 0x51,
 		.i2c_adapter = 0,
 		.emmc_usdhc = 2,
-		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER,
+		.init = prt_imx6_init_prtvt7,
+		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER |
+			PRT_IMX6_USB_LONG_DELAY,
 	}, {
 		.hw_id = UINT_MAX
 	},
-- 
2.30.2



From o.rempel at pengutronix.de  Wed Aug 25 05:54:30 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Wed, 25 Aug 2021 14:54:30 +0200
Subject: [PATCH v1 4/4] ARM: boards: protonic-imx6: Add support for jozacp
 board
In-Reply-To: <20210825125430.26901-1-o.rempel@pengutronix.de>
References: <20210825125430.26901-1-o.rempel@pengutronix.de>
Message-ID: <20210825125430.26901-5-o.rempel@pengutronix.de>

From: Robin van der Gracht <robin at protonic.nl>

The jozacp is an industrial imx6ull based board with ethernet,
wifi and zigbee.

Note: this patch includes WIP version of the devicetree:
 arch/arm/dts/imx6ull-jozacp.dtsi. This devicetree will be reworked,
 mainlined to the kernel and at the end replaced with the kernel
 mainline version.

Signed-off-by: Robin van der Gracht <robin at protonic.nl>
Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c         |  23 +
 .../protonic-imx6/flash-header-jozacp.imxcfg  |  81 +++
 arch/arm/boards/protonic-imx6/lowlevel.c      |  20 +
 arch/arm/dts/Makefile                         |   3 +-
 arch/arm/dts/imx6ull-jozacp.dts               |  47 ++
 arch/arm/dts/imx6ull-jozacp.dtsi              | 525 ++++++++++++++++++
 images/Makefile.imx                           |   2 +
 7 files changed, 700 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boards/protonic-imx6/flash-header-jozacp.imxcfg
 create mode 100644 arch/arm/dts/imx6ull-jozacp.dts
 create mode 100644 arch/arm/dts/imx6ull-jozacp.dtsi

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index cacbdafa31..9b2a00c6c3 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -51,6 +51,8 @@ enum {
 	HW_TYPE_LANMCU = 23,
 	HW_TYPE_PLYBAS = 24,
 	HW_TYPE_VICTGO = 28,
+	HW_TYPE_JOZACP = 30,
+	HW_TYPE_JOZACPP = 31,
 };
 
 enum prt_imx6_kvg_pw_mode {
@@ -1088,6 +1090,26 @@ static const struct prt_machine_data prt_imx6_cfg_prtwd3[] = {
 	},
 };
 
+static const struct prt_machine_data prt_imx6_cfg_jozacp[] = {
+	{
+		.hw_id = HW_TYPE_JOZACP,
+		.hw_rev = 1,
+		.i2c_addr = 0x51,
+		.i2c_adapter = 0,
+		.emmc_usdhc = 0,
+		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER,
+	}, {
+		.hw_id = HW_TYPE_JOZACPP,
+		.hw_rev = 1,
+		.i2c_addr = 0x51,
+		.i2c_adapter = 0,
+		.emmc_usdhc = 0,
+		.flags = PRT_IMX6_BOOTSRC_EMMC | PRT_IMX6_BOOTCHOOSER,
+	}, {
+		.hw_id = UINT_MAX
+	},
+};
+
 static const struct of_device_id prt_imx6_of_match[] = {
 	{ .compatible = "alt,alti6p", .data = &prt_imx6_cfg_alti6p },
 	{ .compatible = "kvg,victgo", .data = &prt_imx6_cfg_victgo },
@@ -1104,6 +1126,7 @@ static const struct of_device_id prt_imx6_of_match[] = {
 	{ .compatible = "prt,prtvt7", .data = &prt_imx6_cfg_prtvt7 },
 	{ .compatible = "prt,prtwd2", .data = &prt_imx6_cfg_prtwd2 },
 	{ .compatible = "prt,prtwd3", .data = &prt_imx6_cfg_prtwd3 },
+	{ .compatible = "joz,jozacp", .data = &prt_imx6_cfg_jozacp },
 	{ /* sentinel */ },
 };
 BAREBOX_DEEP_PROBE_ENABLE(prt_imx6_of_match);
diff --git a/arch/arm/boards/protonic-imx6/flash-header-jozacp.imxcfg b/arch/arm/boards/protonic-imx6/flash-header-jozacp.imxcfg
new file mode 100644
index 0000000000..ec9fb84108
--- /dev/null
+++ b/arch/arm/boards/protonic-imx6/flash-header-jozacp.imxcfg
@@ -0,0 +1,81 @@
+soc imx6
+loadaddr 0x80000000
+ivtofs 0x400
+
+#include "ddr3-defines.imxcfg"
+#include "padsetup-ul.imxcfg"
+
+/* Set Read data delay 3 delay units for all bits */
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+
+/* MDMISC No addr mirror, 1 WALAT, 5 RALAT, DDR3 mode */
+wm 32 0x021b0018 0x00011740
+
+/* CSCR: Configuration mode */
+wm 32 0x021b001c 0x00008000
+
+wm 32 0x021b000c MDCFG0_2G_400MHZ
+wm 32 0x021b0010 MDCFG1_400MHZ
+wm 32 0x021b0014 MDCFG2_400MHZ
+
+/* MDRWD */
+wm 32 0x021b002c 0x000026d2
+
+wm 32 0x021b0030 MDOR_2G_400MHZ
+wm 32 0x021b0008 MDOTC_400MHZ
+wm 32 0x021b0004 MDPDC_400MHZ
+wm 32 0x021b0040 0x00000047	/* MDASP_512MIB */
+wm 32 0x021b0000 MDCTL_2G_16BIT
+
+/* DDR3 MR config */
+wm 32 0x021b001c DDR3_MR2_400MHZ_RTT_120
+
+/*
+ * DDR3 chip MR3, n = 3, vvvv = 0 (no configurable function of interest).
+ */
+wm 32 0x021b001c 0x00008033
+
+wm 32 0x021b001c DDR3_MR1_RTT_120_ODS_40
+wm 32 0x021b001c DDR3_MR0_400MHZ
+
+/*
+ * ZQ calibration, n = 0x10 (Precharge all):
+ * Bit 10 = 1:  Start ZQ calibration
+ * REGISTER: 0x04008040
+ */
+wm 32 0x021b001c 0x04008040
+
+/* MPZQHWCTRL */
+wm 32 0x021b0800 0xa1390003 /* ZQ mode = 3  force calibration */
+
+wm 32 0x021b0020 MDREF_64KHZ
+
+wm 32 0x021b0818 0x00000117	/* MPODTCTRL_ODT_120 */
+
+wm 32 0x021b083c MPDGCTRL0_CH0_400MHZ
+
+/* MPRDDLCTL, MPWRDLCTL */
+wm 32 0x021b0848 0x40404040 /* TODO. Read delay line conf. */
+wm 32 0x021b0850 0x40404040 /* For now set all to 50%. */
+
+/* MPWLDECTRL0 */
+wm 32 0x021b080c 0x001f001f /* TODO. Write level delay control */
+
+/* MPMUR0 */
+wm 32 0x021b08b8 0x00000800 /* Force measurement on delay lines */
+
+/* MDSCR */
+wm 32 0x021b001c 0x00000000 /* Disable configuration req */
+
+/* MAPSR */
+wm 32 0x021b0404 0x00011007 /* 0x0001...? FIXME: Disable powersaving for now  */
+
+/* Enable all clocks */
+wm 32 0x020c4068 0xffffffff
+wm 32 0x020c406c 0xffffffff
+wm 32 0x020c4070 0xffffffff
+wm 32 0x020c4074 0xffffffff
+wm 32 0x020c4078 0xffffffff
+wm 32 0x020c407c 0xffffffff
+wm 32 0x020c4080 0xffffffff
diff --git a/arch/arm/boards/protonic-imx6/lowlevel.c b/arch/arm/boards/protonic-imx6/lowlevel.c
index f5784cc6b1..ef8e7016d1 100644
--- a/arch/arm/boards/protonic-imx6/lowlevel.c
+++ b/arch/arm/boards/protonic-imx6/lowlevel.c
@@ -24,6 +24,7 @@ extern char __dtb_z_imx6dl_vicut1_start[];
 extern char __dtb_z_imx6qp_prtwd3_start[];
 extern char __dtb_z_imx6qp_vicutp_start[];
 extern char __dtb_z_imx6ul_prti6g_start[];
+extern char __dtb_z_imx6ull_jozacp_start[];
 
 ENTRY_FUNCTION(start_imx6q_prti6q, r0, r1, r2)
 {
@@ -189,3 +190,22 @@ ENTRY_FUNCTION(start_imx6ul_prti6g, r0, r1, r2)
 
 	imx6ul_barebox_entry(fdt);
 }
+
+ENTRY_FUNCTION(start_imx6ull_jozacp, r0, r1, r2)
+{
+	void *fdt;
+
+	imx6ul_cpu_lowlevel_init();
+
+	/* Disconnect USDHC2 from SD card */
+	writel(0x5, 0x020e0178);
+	writel(0x5, 0x020e017c);
+	writel(0x5, 0x020e0180);
+	writel(0x5, 0x020e0184);
+	writel(0x5, 0x020e0188);
+	writel(0x5, 0x020e018c);
+
+	fdt = __dtb_z_imx6ull_jozacp_start + get_runtime_offset();
+
+	imx6ul_barebox_entry(fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index ffa9fe88c1..2acdb08483 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -91,7 +91,8 @@ lwl-$(CONFIG_MACH_PROTONIC_IMX6) += \
 	imx6dl-vicut1.dtb.o \
 	imx6qp-prtwd3.dtb.o \
 	imx6qp-vicutp.dtb.o \
-	imx6ul-prti6g.dtb.o
+	imx6ul-prti6g.dtb.o \
+	imx6ull-jozacp.dtb.o
 lwl-$(CONFIG_MACH_PROTONIC_IMX8M) += imx8mm-prt8mm.dtb.o
 lwl-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
 lwl-$(CONFIG_MACH_PHYTEC_SOM_RK3288) += rk3288-phycore-som.dtb.o
diff --git a/arch/arm/dts/imx6ull-jozacp.dts b/arch/arm/dts/imx6ull-jozacp.dts
new file mode 100644
index 0000000000..f41028455a
--- /dev/null
+++ b/arch/arm/dts/imx6ull-jozacp.dts
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/dts-v1/;
+
+#include "imx6ull-jozacp.dtsi"
+
+/ {
+	chosen {
+		stdout-path = &uart1;
+
+		environment at 0 {
+			compatible = "barebox,environment";
+			device-path = &usdhc1, "partname:barebox-environment";
+		};
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* Address will be determined by the bootloader */
+		ramoops {
+			compatible = "ramoops";
+		};
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* Address will be determined by the bootloader */
+		ramoops {
+			compatible = "ramoops";
+		};
+	};
+};
+
+&usdhc1 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	partition at 40000 {
+		label = "barebox-environment";
+		reg = <0x40000 0x80000>;
+	};
+};
diff --git a/arch/arm/dts/imx6ull-jozacp.dtsi b/arch/arm/dts/imx6ull-jozacp.dtsi
new file mode 100644
index 0000000000..f7d35684f8
--- /dev/null
+++ b/arch/arm/dts/imx6ull-jozacp.dtsi
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2020 Protonic Holland
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+#include <arm/imx6ull.dtsi>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "JOZ Access Point";
+	compatible = "joz,jozacp", "fsl,imx6ull";
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_5v: 5v-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "regulator-5V";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: 3p3-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "regulator-3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			vin-supply = <&reg_5v>;
+			regulator-always-on;
+		};
+
+		reg_1p4v: 1p4-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "regulator-1P4V";
+			regulator-min-microvolt = <1400000>;
+			regulator-max-microvolt = <1400000>;
+			vin-supply = <&reg_5v>;
+			regulator-always-on;
+		};
+
+		reg_vbus: vbus-regulator {
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_vbus>;
+			compatible = "regulator-fixed";
+			regulator-name = "regulator-vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			vin-supply = <&reg_5v>;
+			gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	usdhc2_pwrseq: usdhc2-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_wlan0_reg_on>;
+		reset-gpios = <&gpio4 25 GPIO_ACTIVE_LOW>;
+	};
+
+	pwm_leds {
+		compatible = "pwm-leds";
+
+		rgb1_red {
+			label = "pwm:red:rgb1";
+			pwms = <&pwm1 0 10000000 0>;
+			max-brightness = <255>;
+		};
+
+		rgb1_green {
+			label = "pwm:green:rgb1";
+			pwms = <&pwm3 0 10000000 0>;
+			max-brightness = <255>;
+		};
+
+		rgb1_blue {
+			label = "pwm:blue:rgb1";
+			pwms = <&pwm5 0 10000000 0>;
+			max-brightness = <255>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		rgb2_red {
+			label = "pwm:red:rgb2";
+			pwms = <&pwm2 0 10000000 0>;
+			max-brightness = <255>;
+		};
+
+		rgb2_green {
+			label = "pwm:green:rgb2";
+			pwms = <&pwm4 0 10000000 0>;
+			max-brightness = <255>;
+			linux,default-trigger = "netdev";
+		};
+
+		rgb2_blue {
+			label = "pwm:blue:rgb2";
+			pwms = <&pwm6 0 10000000 0>;
+			max-brightness = <255>;
+		};
+	};
+};
+
+&cpu0 {
+	clock-frequency = <792000000>;
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			/* HW Revision */
+			MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09	0x1b0b0
+			MX6UL_PAD_ENET2_RX_EN__GPIO2_IO10	0x1b0b0
+
+			/* HW ID */
+			MX6UL_PAD_ENET2_TX_DATA0__GPIO2_IO11	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA1__GPIO2_IO12	0x1b0b0
+			MX6UL_PAD_ENET2_TX_EN__GPIO2_IO13	0x1b0b0
+			MX6UL_PAD_ENET2_TX_CLK__GPIO2_IO14	0x1b0b0
+			MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15	0x1b0b0
+
+			/* Digital inputs */
+			MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0x11000
+			MX6UL_PAD_GPIO1_IO04__GPIO1_IO04	0x11000
+			MX6UL_PAD_GPIO1_IO05__GPIO1_IO05	0x11000
+			MX6UL_PAD_GPIO1_IO08__GPIO1_IO08	0x11000
+			MX6UL_PAD_GPIO1_IO09__GPIO1_IO09	0x11000
+
+			/* Isolated outputs */
+			MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20	0x01020
+			MX6UL_PAD_UART2_RX_DATA__GPIO1_IO21	0x01020
+			MX6UL_PAD_UART2_RTS_B__GPIO1_IO23	0x01020
+			MX6UL_PAD_UART3_TX_DATA__GPIO1_IO24	0x01020
+			MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25	0x01020
+		>;
+	};
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO07__ENET1_MDC	 0x1b0b0
+			MX6UL_PAD_GPIO1_IO06__ENET1_MDIO	0x1b0b0
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
+		>;
+	};
+
+	pinctrl_can1: can1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b0b0
+			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_MCLK__I2C1_SDA		0x4001f8b1
+			MX6UL_PAD_CSI_PIXCLK__I2C1_SCL		0x4001f8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART5_RX_DATA__I2C2_SDA	0x4001f8b1
+			MX6UL_PAD_UART5_TX_DATA__I2C2_SCL	0x4001f8b1
+		>;
+	};
+
+	pinctrl_pwm1: pwm1-grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA00__PWM1_OUT		0x01010
+		>;
+	};
+
+	pinctrl_pwm2: pwm2-grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA01__PWM2_OUT		0x01010
+		>;
+	};
+
+	pinctrl_pwm3: pwm3-grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA02__PWM3_OUT		0x01010
+		>;
+	};
+
+	pinctrl_pwm4: pwm4-grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA03__PWM4_OUT		0x01010
+		>;
+	};
+
+	pinctrl_pwm5: pwm5-grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA18__PWM5_OUT		0x01010
+		>;
+	};
+
+	pinctrl_pwm6: pwm6-grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA19__PWM6_OUT		0x01010
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_DATA04__UART2_DCE_TX	0x1b0b0
+			MX6UL_PAD_NAND_DATA05__UART2_DCE_RX	0x1b0b0
+			MX6UL_PAD_NAND_DATA06__GPIO4_IO08	0x1b0b0
+			MX6UL_PAD_NAND_DATA07__GPIO4_IO09	0x1b0b0
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_CLK__UART4_DCE_TX		0x1b0b0
+			MX6UL_PAD_LCD_ENABLE__UART4_DCE_RX	0x1b0b0
+			MX6UL_PAD_LCD_HSYNC__UART4_DCE_CTS	0x1b0b0
+			MX6UL_PAD_LCD_VSYNC__UART4_DCE_RTS	0x1b0b0
+			MX6UL_PAD_LCD_RESET__GPIO3_IO04		0x1b0b0
+		>;
+	};
+
+	pinctrl_vbus: vbus0grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0x030b0
+		>;
+	};
+
+	pinctrl_usbotg1: usbotg1grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO01__USB_OTG1_OC	0x1b0b0
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_WP_B__USDHC1_RESET_B	0x17099
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x1f099
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x10099
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x17099
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x17099
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x17099
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x17099
+			MX6UL_PAD_NAND_READY_B__USDHC1_DATA4	0x17099
+			MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5	0x17099
+			MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6	0x17099
+			MX6UL_PAD_NAND_CLE__USDHC1_DATA7	0x17099
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_VSYNC__USDHC2_CLK		0x100b9
+			MX6UL_PAD_CSI_HSYNC__USDHC2_CMD		0x170b9
+			MX6UL_PAD_CSI_DATA00__USDHC2_DATA0	0x170b9
+			MX6UL_PAD_CSI_DATA01__USDHC2_DATA1	0x170b9
+			MX6UL_PAD_CSI_DATA02__USDHC2_DATA2	0x170b9
+			MX6UL_PAD_CSI_DATA03__USDHC2_DATA3	0x170b9
+		>;
+	};
+
+	pinctrl_wlan0_reg_on: wlan0-regon-grp0 {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA04__GPIO4_IO25	0x03020
+		>;
+	};
+
+	pinctrl_wlan0_host_wake: wlan0-host_wake-grp0 {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA05__GPIO4_IO26	0x1b0b0
+		>;
+	};
+
+	pinctrl_bt0_reg_on: bt0-regon-grp0 {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA07__GPIO4_IO28	0x03020
+		>;
+	};
+
+	pinctrl_bt0_host_wake: bt0-host_wake-grp0 {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA06__GPIO4_IO27	0x1b0b0
+		>;
+	};
+
+	pinctrl_etnphy0_rst: etnphy-rstgrp-grp0 {
+		fsl,pins = <
+			MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28	0x038b0
+		>;
+	};
+
+	pinctrl_etnphy0_int: etnphy-intgrp-grp0 {
+		fsl,pins = <
+			MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29	0x170b0
+		>;
+	};
+};
+
+&iomuxc_snvs {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_snvs_hog>;
+
+	pinctrl_snvs_hog: snvs-hog-grp {
+		fsl,pins = <
+			/* Digital outputs */
+			MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02	0x00020
+			MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03	0x00020
+			MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x00020
+			MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05	0x00020
+			MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06	0x00020
+
+			/* Digital outputs fault feedback */
+			MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00	0x17000
+			MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01	0x17000
+			MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07	0x17000
+			MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x17000
+			MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09	0x17000
+		>;
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1 &pinctrl_etnphy0_rst>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy0>;
+	phy-reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
+	phy-reset-duration = <11>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 0 {
+			reg = <0>;
+			clocks = <&clks IMX6UL_CLK_ENET_REF>;
+			clock-names = "rmii-ref";
+			interrupt-parent = <&gpio1>;
+			interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	clock-frequency = <100000>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	rtc: pcf8563 at 51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&snvs_rtc {
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	cts-gpios = <&gpio4 8 GPIO_ACTIVE_LOW>;
+	rts-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
+	status = "disabled";
+
+	bluetooth {
+		compatible = "brcm,bcm43438-bt";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_bt0_reg_on &pinctrl_bt0_host_wake>;
+		host-wakeup-gpios = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+		vbat-supply = <&reg_3p3v>;
+		vddio-supply = <&reg_3p3v>;
+		max-speed = <921600>;
+	};
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	dtr-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg1>;
+	vbus-supply = <&reg_vbus>;
+	dr_mode = "host";
+	over-current-active-low;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	vmmc-supply = <&reg_3p3v>;
+	bus-width = <8>;
+	no-1-8-v;
+	non-removable;
+	cap-mmc-hw-reset;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	mmc-pwrseq = <&usdhc2_pwrseq>;
+	bus-width = <4>;
+	no-1-8-v;
+	non-removable;
+	pm-ignore-notify;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	brcmf: bcrmf at 1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_wlan0_host_wake>;
+		//interrupt-parent = <&gpio4>;
+		//interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+		//interrupt-names = "host-wake";
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&pwm5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm5>;
+	status = "okay";
+};
+
+&pwm6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm6>;
+	status = "okay";
+};
diff --git a/images/Makefile.imx b/images/Makefile.imx
index dd927aba55..2baca6b4ea 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -329,6 +329,8 @@ $(call build_imx_habv4img, CONFIG_MACH_PROTONIC_IMX6, start_imx6qp_prtwd3, proto
 
 $(call build_imx_habv4img, CONFIG_MACH_PROTONIC_IMX6, start_imx6qp_vicutp, protonic-imx6/flash-header-vicutp, protonic-vicutp)
 
+$(call build_imx_habv4img, CONFIG_MACH_PROTONIC_IMX6, start_imx6ull_jozacp, protonic-imx6/flash-header-jozacp, protonic-jozacp)
+
 $(call build_imx_habv4img, CONFIG_MACH_KONTRON_SAMX6I, start_imx6q_samx6i, kontron-samx6i/flash-header-samx6i-quad, imx6q-samx6i)
 
 $(call build_imx_habv4img, CONFIG_MACH_KONTRON_SAMX6I, start_imx6dl_samx6i, kontron-samx6i/flash-header-samx6i-duallite, imx6dl-samx6i)
-- 
2.30.2



From m.felsch at pengutronix.de  Wed Aug 25 07:49:04 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 25 Aug 2021 16:49:04 +0200
Subject: [PATCH] state: backend_raw: fix ignoring unpack failures
Message-ID: <20210825144904.4929-1-m.felsch@pengutronix.de>

This is required to inform the state framework that the state variable
set have changed and we need to write the new variable set. Without this
fix the new variable set is never written since the state never sets
dirty=1 and so state_save() will return early without saving the new
variable set.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
I keeped the continue instead of break out early so the user gets
informed which variables do not fit.

Regards,
  Marco

 common/state/backend_format_raw.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/common/state/backend_format_raw.c b/common/state/backend_format_raw.c
index 5a71149d34..ea962606cc 100644
--- a/common/state/backend_format_raw.c
+++ b/common/state/backend_format_raw.c
@@ -183,6 +183,7 @@ static int backend_format_raw_unpack(struct state_backend_format *format,
 	const struct backend_raw_header *header;
 	const void *data;
 	struct state_backend_format_raw *backend_raw = get_format_raw(format);
+	int ret = 0;
 
 	header = (const struct backend_raw_header *)buf;
 	data = buf + sizeof(*header);
@@ -191,12 +192,13 @@ static int backend_format_raw_unpack(struct state_backend_format *format,
 		if (sv->start + sv->size > header->data_len) {
 			dev_err(backend_raw->dev, "State variable ends behind valid data, %s\n",
 				sv->name);
+			ret = -ENOSPC;
 			continue;
 		}
 		memcpy(sv->raw, data + sv->start, sv->size);
 	}
 
-	return 0;
+	return ret;
 }
 
 static int backend_format_raw_pack(struct state_backend_format *format,
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Aug 26 09:57:18 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 26 Aug 2021 18:57:18 +0200
Subject: [PATCH] ARM: i.MX8MP: bbu: use correct offset for eMMC boot partition
Message-ID: <20210826165718.1905-1-a.fatoum@pengutronix.de>

According to the i.MX8MP RM rev3, the bootrom expects the bootloader to
sit directly at the start of the eMMC boot partition.

The 32K offset is only valid for eMMC user partitions and SD. Reflect
this in the code. This should allow changing the update handler for
the i.MX8MP-EVK from using the eMMC user area to using the eMMC boot
partition. This isn't done here, because the change wasn't tested
on actual hardware.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
Change is untested. Would be great if someone can confirm on actual HW.
(And adjust the EVK boot handler)
---
 arch/arm/mach-imx/imx-bbu-internal.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c
index 880f8b249642..32c6f44fb4ac 100644
--- a/arch/arm/mach-imx/imx-bbu-internal.c
+++ b/arch/arm/mach-imx/imx-bbu-internal.c
@@ -393,6 +393,15 @@ static unsigned long imx_bbu_flash_header_offset_mmc(void)
 	return SZ_1K;
 }
 
+static unsigned long imx_bbu_flash_header_offset_mmcboot(void)
+{
+	if (cpu_is_mx8mp())
+		return 0;
+
+	/* Older i.MX use for boot partition the same offset as eMMC user/SD */
+	return imx_bbu_flash_header_offset_mmc();
+}
+
 static int imx_bbu_update(struct bbu_handler *handler, struct bbu_data *data)
 {
 	struct imx_internal_bbu_handler *imx_handler =
@@ -608,7 +617,7 @@ static int imx_bbu_internal_mmcboot_register_handler(const char *name,
 	struct imx_internal_bbu_handler *imx_handler;
 
 	imx_handler = __init_handler(name, devicefile, flags);
-	imx_handler->flash_header_offset = imx_bbu_flash_header_offset_mmc();
+	imx_handler->flash_header_offset = imx_bbu_flash_header_offset_mmcboot();
 
 	imx_handler->handler.handler = imx_bbu_internal_mmcboot_update;
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Aug 30 04:51:56 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 30 Aug 2021 13:51:56 +0200
Subject: [PATCH v2 3/3] ARM: i.MX8MP: EVK: change bbu handler from eMMC user
 to boot partition
In-Reply-To: <20210830115156.21907-1-a.fatoum@pengutronix.de>
References: <20210830115156.21907-1-a.fatoum@pengutronix.de>
Message-ID: <20210830115156.21907-3-a.fatoum@pengutronix.de>

With recent changes, it's now possible to update and start barebox from
an eMMC boot partition on the i.MX8MP. Reflect this in the board code, so
future barebox updates on eMMC will automatically leverage this.

Tested on an i.MX8MN, which has the same flash header offsets as the 8MP.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - new patch. Tested on i.MX8MN.
---
 arch/arm/boards/nxp-imx8mp-evk/board.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boards/nxp-imx8mp-evk/board.c b/arch/arm/boards/nxp-imx8mp-evk/board.c
index a3ff59810888..8f1c2471091e 100644
--- a/arch/arm/boards/nxp-imx8mp-evk/board.c
+++ b/arch/arm/boards/nxp-imx8mp-evk/board.c
@@ -37,7 +37,7 @@ static int nxp_imx8mp_evk_init(void)
 	}
 
 	imx8m_bbu_internal_mmc_register_handler("SD", "/dev/mmc1.barebox", sd_bbu_flag);
-	imx8m_bbu_internal_mmc_register_handler("eMMC", "/dev/mmc2", emmc_bbu_flag);
+	imx8m_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc2", emmc_bbu_flag);
 
 	val = readl(MX8MP_IOMUXC_GPR_BASE_ADDR + MX8MP_IOMUXC_GPR1);
 	val |= MX8MP_IOMUXC_GPR1_ENET1_RGMII_EN;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Aug 30 04:51:54 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 30 Aug 2021 13:51:54 +0200
Subject: [PATCH v2 1/3] ARM: i.MX8MP: bbu: fix wrong flash header offset for
 eMMC boot partition
Message-ID: <20210830115156.21907-1-a.fatoum@pengutronix.de>

According to the reference manual of the i.MX8MP, the bootrom expects
the bootloader to sit directly at the start of the eMMC boot partition.

The 32K offset is only valid for eMMC user partitions and SD.
Tell barebox_update about this, so it can strip away the first 32K
when writing to an eMMC boot partition.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - fix wrong use of flash header offset: This refers to offset in file,
    but we want to change offset on disk. There is a knob for that
    (IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER), so use that instead

Tested on i.MX8MN.
---
 arch/arm/mach-imx/imx-bbu-internal.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c
index 880f8b249642..91e1785d18e0 100644
--- a/arch/arm/mach-imx/imx-bbu-internal.c
+++ b/arch/arm/mach-imx/imx-bbu-internal.c
@@ -393,6 +393,18 @@ static unsigned long imx_bbu_flash_header_offset_mmc(void)
 	return SZ_1K;
 }
 
+static unsigned long imx_bbu_flash_header_offset_mmcboot(unsigned long *flags)
+{
+	/*
+	 * i.MX8MP places IVT directly at start of eMMC boot partition. IVT
+	 * in eMMC user partition and SD is at 32K offset.
+	 */
+	if (cpu_is_mx8mp())
+		*flags |= IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER;
+
+	return imx_bbu_flash_header_offset_mmc();
+}
+
 static int imx_bbu_update(struct bbu_handler *handler, struct bbu_data *data)
 {
 	struct imx_internal_bbu_handler *imx_handler =
@@ -606,9 +618,12 @@ static int imx_bbu_internal_mmcboot_register_handler(const char *name,
 						     unsigned long flags)
 {
 	struct imx_internal_bbu_handler *imx_handler;
+	unsigned long flash_header_offset;
+
+	flash_header_offset = imx_bbu_flash_header_offset_mmcboot(&flags);
 
 	imx_handler = __init_handler(name, devicefile, flags);
-	imx_handler->flash_header_offset = imx_bbu_flash_header_offset_mmc();
+	imx_handler->flash_header_offset = flash_header_offset;
 
 	imx_handler->handler.handler = imx_bbu_internal_mmcboot_update;
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Aug 30 04:51:55 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 30 Aug 2021 13:51:55 +0200
Subject: [PATCH v2 2/3] mci: imx-esdhc-pbl: support eMMC boot partitions on
 i.MX8MP
In-Reply-To: <20210830115156.21907-1-a.fatoum@pengutronix.de>
References: <20210830115156.21907-1-a.fatoum@pengutronix.de>
Message-ID: <20210830115156.21907-2-a.fatoum@pengutronix.de>

The i.MX header for SD/MMC starts at an offset to allow for a partition
table at offset 0. i.MX8MN/P bootrom did away with the offset for eMMC
boot partitions, which usually lack on-disk partition tables, but kept a
32-byte offset for SD and eMMC user partitions.

The i.MX8MN/P also introduced a ROM API that allows chainloading from
boot medium by calling back into ROM. This likely handles that
difference for us, but as we don't support it yet and we already have
the PBL eSDHC driver, teach it to detect whether boot is from eMMC boot
partition or not and use the appropriate offset.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - new patch. Without, barebox can be written, but not booted.
    Tested on i.MX8MN.
---
 drivers/mci/imx-esdhc-pbl.c | 39 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index e649eb8bbafb..66df4f6dfc74 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -25,6 +25,40 @@
 
 #define esdhc_send_cmd	__esdhc_send_cmd
 
+static u8 ext_csd[512] __aligned(64);
+
+static int esdhc_send_ext_csd(struct fsl_esdhc_host *host)
+{
+	struct mci_cmd cmd;
+	struct mci_data data;
+
+	cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
+	cmd.cmdarg = 0;
+	cmd.resp_type = MMC_RSP_R1;
+
+	data.dest = ext_csd;
+	data.blocks = 1;
+	data.blocksize = sizeof(ext_csd);
+	data.flags = MMC_DATA_READ;
+
+	return esdhc_send_cmd(host, &cmd, &data);
+}
+
+static bool esdhc_bootpart_active(struct fsl_esdhc_host *host)
+{
+	unsigned bootpart;
+
+	int ret = esdhc_send_ext_csd(host);
+	if (ret)
+		return false;
+
+	bootpart = (ext_csd[EXT_CSD_PARTITION_CONFIG] >> 3) & 0x7;
+	if (bootpart == 1 || bootpart == 2)
+		return true;
+
+	return false;
+}
+
 static int esdhc_read_blocks(struct fsl_esdhc_host *host, void *dst, size_t len)
 {
 	struct mci_cmd cmd;
@@ -338,14 +372,17 @@ int imx8mp_esdhc_load_image(int instance, bool start)
 {
 	struct esdhc_soc_data data;
 	struct fsl_esdhc_host host = { 0 };
+	u32 offset;
 	int ret;
 
 	ret = imx8m_esdhc_init(&host, &data, instance);
 	if (ret)
 		return ret;
 
+	offset = esdhc_bootpart_active(&host)? 0 : SZ_32K;
+
 	return esdhc_load_image(&host, MX8M_DDR_CSD1_BASE_ADDR,
-				MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K, 0, start);
+				MX8MQ_ATF_BL33_BASE_ADDR, offset, 0, start);
 }
 #endif
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Aug 30 04:53:25 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 30 Aug 2021 13:53:25 +0200
Subject: [PATCH] ARM: i.MX8MP: move SCTR enabling into imx8mp_cpu_lowlevel_init
Message-ID: <20210830115325.24905-1-a.fatoum@pengutronix.de>

We already do this SCTR poking in imx8mm_cpu_lowlevel_init. If the EVK
needs it, other boards should as well, thus move it to a more generic
place.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/boards/nxp-imx8mp-evk/lowlevel.c | 5 -----
 arch/arm/mach-imx/cpu_init.c              | 4 +---
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
index 3298ded5866d..6cb109ae1675 100644
--- a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
+++ b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c
@@ -179,11 +179,6 @@ static __noreturn noinline void nxp_imx8mp_evk_start(void)
 
 ENTRY_FUNCTION(start_nxp_imx8mp_evk, r0, r1, r2)
 {
-	void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
-
-	writel(IMX8M_CCM_CCGR_SETTINGn_NEEDED(0),
-	       ccm + IMX8M_CCM_CCGRn_SET(IMX8M_CCM_CCGR_SCTR));
-
 	imx8mp_cpu_lowlevel_init();
 
 	relocate_to_current_adr();
diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c
index a034b5a9a500..ea1c67469122 100644
--- a/arch/arm/mach-imx/cpu_init.c
+++ b/arch/arm/mach-imx/cpu_init.c
@@ -76,9 +76,7 @@ void imx8mm_cpu_lowlevel_init(void)
 }
 
 void imx8mp_cpu_lowlevel_init(void)
-{
-	imx8m_cpu_lowlevel_init();
-}
+	__alias(imx8mm_cpu_lowlevel_init);
 
 void imx8mq_cpu_lowlevel_init(void)
 {
-- 
2.30.2



From jmaselbas at kalray.eu  Mon Aug 30 07:48:35 2021
From: jmaselbas at kalray.eu (Jules Maselbas)
Date: Mon, 30 Aug 2021 16:48:35 +0200
Subject: [RFC PATCH] usb: gadget: dfu: Rework dfu command to use usbgadget
Message-ID: <20210830144835.27458-1-jmaselbas@kalray.eu>

The dfu command now uses the composite multi gadget to register the usb
functionality. This allows the removal of the usb composite driver from
dfu.c

As the dfu command is blocking the command slice must be released while
the dfu gadget is running in order to do operations on the file system.

The usb_dfu_register() function is replaced with usb_dfu_detached() for
the dfu command to return a different value depending on if it has been
interrupted with CTRL-C or if the gadget has been detached.

Signed-off-by: Jules Maselbas <jmaselbas at kalray.eu>
---
 commands/dfu.c           |  24 +++---
 drivers/usb/gadget/dfu.c | 163 +--------------------------------------
 include/usb/dfu.h        |   2 +-
 3 files changed, 15 insertions(+), 174 deletions(-)

diff --git a/commands/dfu.c b/commands/dfu.c
index 3132a7479d..0d8a703300 100644
--- a/commands/dfu.c
+++ b/commands/dfu.c
@@ -11,6 +11,7 @@
 #include <fs.h>
 #include <xfuncs.h>
 #include <usb/dfu.h>
+#include <usb/gadget-multi.h>
 #include <linux/err.h>
 
 /* dfu /dev/self0(bootloader)sr,/dev/nand0.root.bb(root)
@@ -20,28 +21,27 @@
  */
 static int do_dfu(int argc, char *argv[])
 {
-	struct f_dfu_opts opts;
 	char *argstr;
-	struct usb_dfu_dev *dfu_alts = NULL;
 	int ret;
 
 	if (argc != optind + 1)
 		return COMMAND_ERROR_USAGE;
 
 	argstr = argv[optind];
+	ret = usbgadget_register(true, argstr, false, NULL, false, false);
+	if (ret)
+		return ret;
 
-	opts.files = file_list_parse(argstr);
-	if (IS_ERR(opts.files)) {
-		ret = PTR_ERR(opts.files);
-		goto out;
+	command_slice_release();
+	while (!usb_dfu_detached()) {
+		if (ctrlc()) {
+			ret = -EINTR;
+			break;
+		}
 	}
+	command_slice_acquire();
 
-	ret = usb_dfu_register(&opts);
-
-	file_list_free(opts.files);
-out:
-
-	free(dfu_alts);
+	usb_multi_unregister();
 
 	return ret;
 }
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index fd0ec505dc..ba5fdd5b74 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -817,168 +817,9 @@ static void dfu_disable(struct usb_function *f)
 	dfu_abort(dfu);
 }
 
-#define STRING_MANUFACTURER_IDX		0
-#define STRING_PRODUCT_IDX		1
-#define STRING_DESCRIPTION_IDX		2
-
-static struct usb_string strings_dev[] = {
-	[STRING_MANUFACTURER_IDX].s = NULL,
-	[STRING_PRODUCT_IDX].s = NULL,
-	[STRING_DESCRIPTION_IDX].s = "USB Device Firmware Upgrade",
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings_dev,
-};
-
-static struct usb_gadget_strings *dev_strings[] = {
-	&stringtab_dev,
-	NULL,
-};
-
-static void dfu_unbind_config(struct usb_configuration *c)
-{
-	free(dfu_string_defs);
-}
-
-static struct usb_configuration dfu_config_driver = {
-	.label			= "USB DFU",
-	.unbind			= dfu_unbind_config,
-	.bConfigurationValue	= 1,
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-};
-
-static struct usb_device_descriptor dfu_dev_descriptor = {
-	.bLength		= USB_DT_DEVICE_SIZE,
-	.bDescriptorType	= USB_DT_DEVICE,
-	.bcdUSB			= 0x0100,
-	.bDeviceClass		= 0x00,
-	.bDeviceSubClass	= 0x00,
-	.bDeviceProtocol	= 0x00,
-/*	.idVendor		= dynamic */
-/*	.idProduct		= dynamic */
-	.bcdDevice		= 0x0000,
-	.bNumConfigurations	= 0x01,
-};
-
-static struct usb_function_instance *fi_dfu;
-static struct usb_function *f_dfu;
-
-static int dfu_driver_bind(struct usb_composite_dev *cdev)
+int usb_dfu_detached(void)
 {
-	struct usb_gadget *gadget = cdev->gadget;
-	int status;
-
-	if (gadget->vendor_id && gadget->product_id) {
-		dfu_dev_descriptor.idVendor = cpu_to_le16(gadget->vendor_id);
-		dfu_dev_descriptor.idProduct = cpu_to_le16(gadget->product_id);
-	} else {
-		dfu_dev_descriptor.idVendor = cpu_to_le16(0x1d50); /* Openmoko, Inc */
-		dfu_dev_descriptor.idProduct = cpu_to_le16(0x60a2); /* barebox bootloader USB DFU Mode */
-	}
-
-	strings_dev[STRING_MANUFACTURER_IDX].s = gadget->manufacturer;
-	strings_dev[STRING_PRODUCT_IDX].s = gadget->productname;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		goto fail;
-	strings_dev[STRING_MANUFACTURER_IDX].id = status;
-	dfu_dev_descriptor.iManufacturer = status;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		goto fail;
-	strings_dev[STRING_PRODUCT_IDX].id = status;
-	dfu_dev_descriptor.iProduct = status;
-
-	/* config description */
-	status = usb_string_id(cdev);
-	if (status < 0)
-		goto fail;
-	strings_dev[STRING_DESCRIPTION_IDX].id = status;
-	dfu_config_driver.iConfiguration = status;
-
-	status = usb_add_config_only(cdev, &dfu_config_driver);
-	if (status < 0)
-		goto fail;
-
-	fi_dfu = usb_get_function_instance("dfu");
-	if (IS_ERR(fi_dfu)) {
-		status = PTR_ERR(fi_dfu);
-		goto fail;
-	}
-
-	f_dfu = usb_get_function(fi_dfu);
-	if (IS_ERR(f_dfu)) {
-		status = PTR_ERR(f_dfu);
-		goto fail;
-	}
-
-	status = usb_add_function(&dfu_config_driver, f_dfu);
-	if (status)
-		goto fail;
-
-	return 0;
-fail:
-	return status;
-}
-
-static int dfu_driver_unbind(struct usb_composite_dev *cdev)
-{
-	usb_put_function(f_dfu);
-	usb_put_function_instance(fi_dfu);
-
-	return 0;
-}
-
-static struct usb_composite_driver dfu_driver = {
-	.name		= "g_dfu",
-	.dev		= &dfu_dev_descriptor,
-	.strings	= dev_strings,
-	.max_speed	= USB_SPEED_HIGH,
-	.bind		= dfu_driver_bind,
-	.unbind		= dfu_driver_unbind,
-};
-
-int usb_dfu_register(struct f_dfu_opts *opts)
-{
-	int ret;
-
-	if (dfu_files)
-		return -EBUSY;
-
-	dfu_files = opts->files;
-
-	ret = usb_composite_probe(&dfu_driver);
-	if (ret)
-		goto out;
-
-	while (1) {
-		ret = usb_gadget_poll();
-		if (ret < 0)
-			goto out1;
-
-		if (dfudetach) {
-			ret = 0;
-			goto out1;
-		}
-
-		if (ctrlc()) {
-			ret = -EINTR;
-			goto out1;
-		}
-	}
-
-out1:
-	dfudetach = 0;
-	usb_composite_unregister(&dfu_driver);
-out:
-	dfu_files = NULL;
-
-	return ret;
+	return dfudetach;
 }
 
 static void dfu_free_func(struct usb_function *f)
diff --git a/include/usb/dfu.h b/include/usb/dfu.h
index 560a0318fe..81425f7c62 100644
--- a/include/usb/dfu.h
+++ b/include/usb/dfu.h
@@ -29,6 +29,6 @@ struct f_dfu_opts {
 	struct file_list *files;
 };
 
-int usb_dfu_register(struct f_dfu_opts *);
+int usb_dfu_detached(void);
 
 #endif /* _USB_DFU_H */
-- 
2.17.1



From antonynpavlov at gmail.com  Mon Aug 30 21:07:10 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 31 Aug 2021 07:07:10 +0300
Subject: [PATCH RESEND v4 1/8] clocksource: timer-riscv: select CSR from
 device tree
In-Reply-To: <ce1667b1-e42f-3836-9747-393a5fd8afc7@pengutronix.de>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
 <20210817101104.114945-2-antonynpavlov@gmail.com>
 <ce1667b1-e42f-3836-9747-393a5fd8afc7@pengutronix.de>
Message-ID: <20210831070710.3b6200eff8e7adb22bdf1454@gmail.com>

On Mon, 23 Aug 2021 14:08:52 +0200
Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:

Hi Ahmad!

> On 17.08.21 12:10, Antony Pavlov wrote:
> > barebox timer-riscv driver supports one of user counters:
> > 
> >   * 'cycle', counter for RDCYCLE instruction (CSR 0xc00);
> >   * 'time', timer for RDTIME instruction (CSR 0xc01).
> > 
> > At the moment in M-mode timer-riscv uses the 'cycle' counter,
> > and in S-mode timer-riscv uses the 'time' timer.
> > 
> > Alas picorv32 CPU core supports only the 'cycle' counter.
> > VexRiscV CPU core in M-mode supports only the 'time' timer.
> > 
> > This patch makes it possible to use the 'time' timer
> > for VexRiscV CPU in M-mode.
> > 
> > See also http://lists.infradead.org/pipermail/barebox/2021-May/036067.html
> 
> Comment from earlier series:
> 
> "It also changes the default for M-Mode from cycle to time.
> 
> I can't comment on whether this is ok, I just copied the logic
> 
> from Linux."
> 
> Can you say why this is ok?

v4 patch removes riscv_mode() mention from timer-riscv code
so timer-riscv uses the 'time' timer by default disregarding
M-mode or S-mode is used.

I suppose that the 'time' timer is "more popular" than
the 'cycle' counter.
So IMHO it is ok to use "more popular" feature by default.

> 
> > 
> > Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> > ---
> >  arch/riscv/dts/erizo.dtsi         |  2 ++
> >  drivers/clocksource/timer-riscv.c | 24 ++++++++++++------------
> >  2 files changed, 14 insertions(+), 12 deletions(-)
> > 
> > diff --git a/arch/riscv/dts/erizo.dtsi b/arch/riscv/dts/erizo.dtsi
> > index 228711bd69..4eb92ae6f1 100644
> > --- a/arch/riscv/dts/erizo.dtsi
> > +++ b/arch/riscv/dts/erizo.dtsi
> > @@ -22,6 +22,8 @@
> >  
> >  		timebase-frequency = <24000000>;
> >  
> > +		barebox,csr-cycle;
> > +
> >  		cpu at 0 {
> >  			device_type = "cpu";
> >  			compatible = "cliffordwolf,picorv32", "riscv";
> > diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
> > index 5a517fe6b4..96637f988a 100644
> > --- a/drivers/clocksource/timer-riscv.c
> > +++ b/drivers/clocksource/timer-riscv.c
> > @@ -12,9 +12,8 @@
> >  #include <clock.h>
> >  #include <asm/timer.h>
> >  #include <asm/csr.h>
> > -#include <asm/system.h>
> >  
> > -static u64 notrace riscv_timer_get_count_sbi(void)
> > +static u64 notrace riscv_timer_get_count_time(void)
> >  {
> >  	__maybe_unused u32 hi, lo;
> >  
> > @@ -29,7 +28,7 @@ static u64 notrace riscv_timer_get_count_sbi(void)
> >  	return ((u64)hi << 32) | lo;
> >  }
> >  
> > -static u64 notrace riscv_timer_get_count_rdcycle(void)
> > +static u64 notrace riscv_timer_get_count_cycle(void)
> >  {
> >  	__maybe_unused u32 hi, lo;
> >  
> > @@ -44,24 +43,25 @@ static u64 notrace riscv_timer_get_count_rdcycle(void)
> >  	return ((u64)hi << 32) | lo;
> >  }
> >  
> > -static u64 notrace riscv_timer_get_count(void)
> > -{
> > -	if (riscv_mode() == RISCV_S_MODE)
> > -		return riscv_timer_get_count_sbi();
> > -	else
> > -		return riscv_timer_get_count_rdcycle();
> > -}
> > -
> >  static struct clocksource riscv_clocksource = {
> > -	.read		= riscv_timer_get_count,
> >  	.mask		= CLOCKSOURCE_MASK(64),
> >  	.priority	= 100,
> >  };
> >  
> >  static int riscv_timer_init(struct device_d* dev)
> >  {
> > +	struct device_node *cpu;
> > +
> >  	dev_dbg(dev, "running at %lu Hz\n", riscv_timebase);
> >  
> > +	cpu = of_find_node_by_path("/cpus");
> > +
> > +	if (of_property_read_bool(cpu, "barebox,csr-cycle")) {
> > +		riscv_clocksource.read = riscv_timer_get_count_cycle;
> > +	} else {
> > +		riscv_clocksource.read = riscv_timer_get_count_time;
> > +	}
> > +
> >  	riscv_clocksource.mult = clocksource_hz2mult(riscv_timebase, riscv_clocksource.shift);
> >  
> >  	return init_clock(&riscv_clocksource);
> > 
> 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


-- 
Best regards,
? Antony Pavlov


From antonynpavlov at gmail.com  Mon Aug 30 21:38:38 2021
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 31 Aug 2021 07:38:38 +0300
Subject: [PATCH RESEND v4 7/8] RISC-V: add LiteX SoC and
 linux-on-litex-vexriscv support
In-Reply-To: <f234164a-64b9-63ae-8ecc-97336d5c695c@pengutronix.de>
References: <20210817101104.114945-1-antonynpavlov@gmail.com>
 <20210817101104.114945-8-antonynpavlov@gmail.com>
 <f234164a-64b9-63ae-8ecc-97336d5c695c@pengutronix.de>
Message-ID: <20210831073838.176dd337f649dfeed2b2ec8f@gmail.com>

On Mon, 23 Aug 2021 14:06:09 +0200
Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:

Hi Ahmad!

> On 17.08.21 12:11, Antony Pavlov wrote:
> > LiteX is a Migen-based System on Chip, supporting softcore
> > VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU.
> > 
> > See https://github.com/enjoy-digital/litex and
> > https://github.com/litex-hub/linux-on-litex-vexriscv
> > for details.
> > 
> > Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> > ---
> >  arch/riscv/Kconfig.socs                  |  14 +++
> >  arch/riscv/boards/Makefile               |   1 +
> >  arch/riscv/boards/litex-linux/Makefile   |   3 +
> >  arch/riscv/boards/litex-linux/lowlevel.c |  22 ++++
> >  arch/riscv/dts/Makefile                  |   1 +
> >  arch/riscv/dts/litex-linux.dts           |  92 +++++++++++++++++
> >  arch/riscv/dts/litex_soc_linux.dtsi      |  49 +++++++++
> >  arch/riscv/include/asm/debug_ll.h        |   3 +
> >  arch/riscv/include/asm/debug_ll_litex.h  | 123 +++++++++++++++++++++++
> >  common/Kconfig                           |   4 +
> >  images/Makefile.riscv                    |   4 +
> >  11 files changed, 316 insertions(+)
> > 
> > diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> > index 221ea133d4..5c281918d5 100644
> > --- a/arch/riscv/Kconfig.socs
> > +++ b/arch/riscv/Kconfig.socs
> > @@ -95,4 +95,18 @@ config SIFIVE_L2
> >  	bool "SiFive L2 cache controller"
> >  	depends on CPU_SIFIVE
> >  
> > +config SOC_LITEX
> > +	bool "LiteX SoCs"
> > +	depends on ARCH_RV32I
> > +	select HAS_ASM_DEBUG_LL
> > +	select HAS_NMON
> > +	select USE_COMPRESSED_DTB
> > +	select RISCV_TIMER
> > +
> > +config BOARD_LITEX_LINUX
> > +	bool "litex linux board"
> > +	depends on SOC_LITEX
> > +	select RISCV_M_MODE
> > +	def_bool y
> > +
> >  endmenu
> > diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile
> > index cb28a25d8b..8d5d9d4fc6 100644
> > --- a/arch/riscv/boards/Makefile
> > +++ b/arch/riscv/boards/Makefile
> > @@ -2,3 +2,4 @@
> >  obj-$(CONFIG_BOARD_ERIZO_GENERIC)	+= erizo/
> >  obj-$(CONFIG_BOARD_HIFIVE)		+= hifive/
> >  obj-$(CONFIG_BOARD_BEAGLEV)		+= beaglev/
> > +obj-$(CONFIG_BOARD_LITEX_LINUX)		+= litex-linux/
> > diff --git a/arch/riscv/boards/litex-linux/Makefile b/arch/riscv/boards/litex-linux/Makefile
> > new file mode 100644
> > index 0000000000..3d217ffe0b
> > --- /dev/null
> > +++ b/arch/riscv/boards/litex-linux/Makefile
> > @@ -0,0 +1,3 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +pbl-y += lowlevel.o
> > diff --git a/arch/riscv/boards/litex-linux/lowlevel.c b/arch/riscv/boards/litex-linux/lowlevel.c
> > new file mode 100644
> > index 0000000000..da23ef5633
> > --- /dev/null
> > +++ b/arch/riscv/boards/litex-linux/lowlevel.c
> > @@ -0,0 +1,22 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +
> > +#include <common.h>
> > +#include <asm/barebox-riscv.h>
> > +#include <debug_ll.h>
> > +#include <asm/riscv_nmon.h>
> > +
> > +ENTRY_FUNCTION(start_litex_linux, a0, a1, a2)
> > +{
> > +	extern char __dtb_z_litex_linux_start[];
> > +	void *fdt;
> > +
> > +	barebox_nmon_entry();
> > +
> > +	putc_ll('>');
> > +
> > +	/* On POR, we are running from read-only memory here. */
> 
> Do we? I thought BIOS loads barebox to RAM first?

Yes, your are right. At the moment litex BIOS loads barebox to RAM first
and this comment must be dropped.

Please note there is a possibility to use barebox instead of litex BIOS
and start barebox on POR from ROM.
linux-on-litex-vexriscv bitstream for Arty board incorporates litex BIOS
so on Arty litex BIOS runs on POR unconditionally.
Litex BIOS is no more than 64K and "one does not simply push barebox into 64K".
But litex works on boards with tiny FPGA resources e.g. iCEBreaker-bitsy.
litex configuration for these tiny FPGA skips internal RAM/ROM and BIOS
starts from SPI flash so there is no limit on barebox image size.



> 
> > +
> > +	fdt = __dtb_z_litex_linux_start + get_runtime_offset();
> > +
> > +	barebox_riscv_machine_entry(0x40000000, SZ_256M, fdt);
> > +}
> > diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
> > index 4a15423b7f..17d7d249e4 100644
> > --- a/arch/riscv/dts/Makefile
> > +++ b/arch/riscv/dts/Makefile
> > @@ -8,5 +8,6 @@ pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o
> >  pbl-$(CONFIG_BOARD_HIFIVE) += hifive-unmatched-a00.dtb.o \
> >                                hifive-unleashed-a00.dtb.o
> >  pbl-$(CONFIG_BOARD_BEAGLEV) += jh7100-beaglev-starlight.dtb.o
> > +pbl-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux.dtb.o
> >  
> >  clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
> > diff --git a/arch/riscv/dts/litex-linux.dts b/arch/riscv/dts/litex-linux.dts
> > new file mode 100644
> > index 0000000000..d21fa57e30
> > --- /dev/null
> > +++ b/arch/riscv/dts/litex-linux.dts
> > @@ -0,0 +1,92 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +
> > +#include "litex_soc_linux.dtsi"
> > +
> > +#include <dt-bindings/gpio/gpio.h>
> > +
> > +/ {
> > +	model = "LiteX VexRiscV-SoC-Linux";
> > +	compatible = "litex,vexriscv-soc-linux";
> > +
> > +	aliases {
> > +		rom = &rom;
> > +		sram = &sram;
> > +	};
> > +
> > +	/* ARTY board */
> > +	rom: rom at 00000000 {
> 
> I can see why RAM is specific to ARTY, but why ROM?
> 
> > +		compatible = "mmio-sram";
> > +		reg = <0x00000000 0x00008000>;
> > +		read-only;
> > +	};
> > +
> > +	sram: sram at 20000000 {
> > +		compatible = "mmio-sram";
> > +		reg = <0x20000000 0x00004000>;
> > +	};
> > +
> > +	main_ram: memory at 40000000 {
> > +		device_type = "memory";
> > +		reg = <0x40000000 0x10000000>;
> > +	};
> > +};
> > +
> > +&uart0 {
> > +	status = "okay";
> > +};
> > +
> > +&mac0 {
> > +	status = "okay";
> > +};
> > +
> > +&spi0 {
> > +	status = "okay";
> > +
> > +	spiflash: w25q128 at 0 {
> > +		#address-cells = <1>;
> > +		#size-cells = <1>;
> > +		compatible = "winbond,w25q128", "jedec,spi-nor";
> > +		spi-max-frequency = <104000000>;
> > +		reg = <0>;
> > +	};
> > +};
> > +
> > +/ {
> > +	ledsgpio: gpio at f000a800 {
> > +		compatible = "ti,74175";
> > +		reg = <0xf000a800 0x4>;
> > +		gpio-controller;
> > +		#gpio-cells = <2>;
> > +	};
> > +
> > +	leds {
> > +		compatible = "gpio-leds";
> > +
> > +		ld0 {
> > +			label = "arty:green:ld0";
> > +			gpios = <&ledsgpio 0 GPIO_ACTIVE_HIGH>;
> > +		};
> > +
> > +		ld1 {
> > +			label = "arty:green:ld1";
> > +			gpios = <&ledsgpio 1 GPIO_ACTIVE_HIGH>;
> > +		};
> > +
> > +		ld2 {
> > +			label = "arty:green:ld2";
> > +			gpios = <&ledsgpio 2 GPIO_ACTIVE_HIGH>;
> > +		};
> > +
> > +		ld3 {
> > +			label = "arty:green:ld3";
> > +			gpios = <&ledsgpio 3 GPIO_ACTIVE_HIGH>;
> > +		};
> > +	};
> > +
> > +	swgpio: gpio at f0006000 {
> > +		compatible = "ti,74125";
> > +		reg = <0xf0006000 0x4>;
> > +		gpio-controller;
> > +		#gpio-cells = <2>;
> > +	};
> > +};
> > diff --git a/arch/riscv/dts/litex_soc_linux.dtsi b/arch/riscv/dts/litex_soc_linux.dtsi
> > new file mode 100644
> > index 0000000000..94a0ba29da
> > --- /dev/null
> > +++ b/arch/riscv/dts/litex_soc_linux.dtsi
> > @@ -0,0 +1,49 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +
> > +/dts-v1/;
> > +
> > +/ {
> > +	compatible = "litex,vexriscv-soc-linux";
> > +
> > +	#address-cells = <1>;
> > +	#size-cells = <1>;
> > +
> > +	cpus {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		timebase-frequency = <100000000>; // 100 MHz
> > +
> > +		cpu at 0 {
> > +			device_type = "cpu";
> > +			compatible = "spinalhdl,vexriscv", "riscv";
> > +			reg = <0>;
> > +		};
> > +	};
> > +
> > +	uart0: serial at f0001000 {
> > +		compatible = "litex,uart";
> > +		reg = <0xf0001000 0x18>;
> > +		status = "disabled";
> > +	};
> > +
> > +	mac0: mac at f0006800 {
> > +		compatible = "litex,liteeth";
> > +		reg = <0xf0006800 0x7c /* base */
> > +			0xf0007000 0x0a /* mdio_base */
> > +			0xb0000000 0x2000>; /* buf_base */
> > +		tx-fifo-depth = <2>;
> > +		rx-fifo-depth = <2>;
> > +		status = "disabled";
> > +	};
> > +
> > +	spi0: spi at f000b800 {
> > +		compatible = "litex,spiflash";
> > +
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		reg = <0xf000b800 0x100>;
> > +		status = "disabled";
> > +	};
> > +};
> > diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h
> > index b4caa0597a..a3b9c1c4bc 100644
> > --- a/arch/riscv/include/asm/debug_ll.h
> > +++ b/arch/riscv/include/asm/debug_ll.h
> > @@ -43,6 +43,9 @@ static inline void PUTC_LL(char ch)
> >  
> >  	writel(ch, uart0);
> >  }
> > +#elif defined CONFIG_DEBUG_LITEX
> > +
> > +#include <asm/debug_ll_litex.h>
> >  
> >  #endif
> >  
> > diff --git a/arch/riscv/include/asm/debug_ll_litex.h b/arch/riscv/include/asm/debug_ll_litex.h
> > new file mode 100644
> > index 0000000000..2fcdd9b0ec
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/debug_ll_litex.h
> > @@ -0,0 +1,123 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2019 Antony Pavlov <antonynpavlov at gmail.com>
> > + *
> > + * This file is part of barebox.
> > + *
> > + * 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.
> 
> Nitpick: That part could be dropped as the SPDX-License-Identifier
> above says as much.

ok.

> 
> > + *
> > + */
> > +
> > +#ifndef __ASM_DEBUG_LL_LITEX__
> > +#define __ASM_DEBUG_LL_LITEX__
> > +
> > +/** @file
> > + *  This File contains declaration for early output support
> > + */
> > +
> > +#include <linux/kconfig.h>
> > +
> > +#define DEBUG_LL_UART_ADDR	0xf0001000
> > +#define UART_RXTX	0x00
> > +#define UART_TXFULL	0x04
> > +#define UART_RXEMPTY	0x08
> > +#define UART_EV_PENDING	0x10
> > +#define  UART_EV_RX	(1 << 1)
> > +
> > +
> > +#ifndef __ASSEMBLY__
> > +
> > +/*
> > + * C macros
> > + */
> > +
> > +#include <asm/io.h>
> > +
> > +static inline void PUTC_LL(char ch)
> > +{
> > +#ifdef CONFIG_DEBUG_LL
> > +	/* wait for space */
> > +	while (__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_TXFULL))
> > +		;
> > +
> > +	__raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_RXTX);
> > +#endif /* CONFIG_DEBUG_LL */
> > +}
> > +#else /* __ASSEMBLY__ */
> > +/*
> > + * Macros for use in assembly language code
> > + */
> > +
> > +/*
> > + * output a character in a0
> > + */
> > +.macro	debug_ll_outc_a0
> > +#ifdef CONFIG_DEBUG_LL
> > +
> > +	li	t0, DEBUG_LL_UART_ADDR
> > +
> > +201:
> > +	lbu	t1, UART_TXFULL(t0)	/* uart tx full ? */
> > +	andi	t1, t1, 0xff
> > +	bnez	t1, 201b		/* try again */
> > +
> > +	sb	a0, UART_RXTX(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
> > +
> > +/*
> > + * 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 */
> > +	lbu	s0, UART_RXEMPTY(t0)
> > +	bnez    s0, 243f
> > +	li	s0, 1
> > +	j	244f
> > +243:	li	s0, 0
> > +244:	nop
> > +#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 */
> > +	lb	s0, UART_RXTX(t0)
> > +	li      t1, UART_EV_RX
> > +	sb	t1, UART_EV_PENDING(t0)
> > +
> > +#endif /* CONFIG_DEBUG_LL */
> > +.endm
> > +#endif /* __ASSEMBLY__ */
> > +
> > +#endif /* __ASM_DEBUG_LL_LITEX__ */
> > diff --git a/common/Kconfig b/common/Kconfig
> > index a9feae2ae8..cb8bd8b2bf 100644
> > --- a/common/Kconfig
> > +++ b/common/Kconfig
> > @@ -1399,6 +1399,10 @@ config DEBUG_SIFIVE
> >  	bool "SiFive serial0 port"
> >  	depends on SOC_SIFIVE
> >  
> > +config DEBUG_LITEX
> > +	bool "LiteX serial port"
> > +	depends on SOC_LITEX
> > +
> >  endchoice
> >  
> >  config DEBUG_LL_NS16550
> > diff --git a/images/Makefile.riscv b/images/Makefile.riscv
> > index 4410765cf6..0645238c43 100644
> > --- a/images/Makefile.riscv
> > +++ b/images/Makefile.riscv
> > @@ -19,3 +19,7 @@ image-$(CONFIG_BOARD_HIFIVE) += barebox-hifive-unmatched.img barebox-hifive-unle
> >  pblb-$(CONFIG_BOARD_BEAGLEV) += start_beaglev_starlight
> >  FILE_barebox-beaglev-starlight.img = start_beaglev_starlight.pblb
> >  image-$(CONFIG_BOARD_BEAGLEV) += barebox-beaglev-starlight.img
> > +
> > +pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux
> > +FILE_barebox-litex-linux.img = start_litex_linux.pblb
> > +image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img
> > 
> 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


-- 
Best regards,
? Antony Pavlov


From s.trumtrar at pengutronix.de  Mon Aug 30 23:47:15 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Tue, 31 Aug 2021 08:47:15 +0200
Subject: [PATCH v2] mci: sdhci: fix big-endian write for blockcount/size
Message-ID: <20210831064715.8392-1-s.trumtrar@pengutronix.de>

From: Steffen Trumtrar <str at pengutronix.de>

The patch

    0a47bce1b03fd236384e904dca005c0870ce8684
    mci: imx-esdhc: Use common DMA helpers

converted the imx-esdhc driver to use the DMA helpers introduced with

    60b608b2714472aa22862a20d04f267cbbac0863
    mci: sdhci: Add DMA transfer helpers

The common DMA helpers however break support for BE-variants (e.g.
Layerscape) as the BLKATTR register seems to be a 32-bit register which
internally switches bytes when used with two 16-bit write accesses.
As the alignment should also work for LE-SDHCI-variants convert the two
16-bit accesses to one 32-bit access.

Signed-off-by: Steffen Trumtrar <str at pengutronix.de>
---
 drivers/mci/sdhci.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c
index aca4a5a6f911..8b5520d6827a 100644
--- a/drivers/mci/sdhci.c
+++ b/drivers/mci/sdhci.c
@@ -129,9 +129,8 @@ void sdhci_setup_data_pio(struct sdhci *sdhci, struct mci_data *data)
 	if (!data)
 		return;
 
-	sdhci_write16(sdhci, SDHCI_BLOCK_SIZE, sdhci->sdma_boundary |
-		    SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize));
-	sdhci_write16(sdhci, SDHCI_BLOCK_COUNT, data->blocks);
+	sdhci_write32(sdhci, SDHCI_BLOCK_SIZE, sdhci->sdma_boundary |
+		      SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize) | data->blocks << 16);
 }
 
 void sdhci_setup_data_dma(struct sdhci *sdhci, struct mci_data *data,
-- 
2.30.2



From rcz at pengutronix.de  Tue Aug 31 02:42:19 2021
From: rcz at pengutronix.de (Rouven Czerwinski)
Date: Tue, 31 Aug 2021 11:42:19 +0200
Subject: [PATCH v2 1/3] ARM: i.MX8MP: bbu: fix wrong flash header offset
 for eMMC boot partition
In-Reply-To: <20210830115156.21907-1-a.fatoum@pengutronix.de>
References: <20210830115156.21907-1-a.fatoum@pengutronix.de>
Message-ID: <c4653e6641f43249c0a511b211e0ea08be56afb3.camel@pengutronix.de>

Hi,

On Mon, 2021-08-30 at 13:51 +0200, Ahmad Fatoum wrote:
> According to the reference manual of the i.MX8MP, the bootrom expects
> the bootloader to sit directly at the start of the eMMC boot partition.
> 
> The 32K offset is only valid for eMMC user partitions and SD.
> Tell barebox_update about this, so it can strip away the first 32K
> when writing to an eMMC boot partition.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
> v1 -> v2:
>   - fix wrong use of flash header offset: This refers to offset in file,
>     but we want to change offset on disk. There is a knob for that
>     (IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER), so use that instead
> 
> Tested on i.MX8MN.

Whole series is,

Tested-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>

on i.MX8MP-EVK.

Best Regards,
Rouven



From Oleg.Karfich at wago.com  Tue Aug 31 05:57:01 2021
From: Oleg.Karfich at wago.com (Karfich, Oleg)
Date: Tue, 31 Aug 2021 12:57:01 +0000
Subject: [PATCH] net: cpsw: fix ethernet bringup in case of a fixed-link phy
Message-ID: <1630414594-10601-1-git-send-email-oleg.karfich@wago.com>

In case of a fixed-link phy the cpsw_adjust_link() function is
called directly in phy_device_attach() and configures the MACCONTROL
register. Right after this configuration cpsw_init() is called and
resets the MACCONTROL register.
Fix this by initializing the slave before connecting the phy device in
cpsw_open().

Signed-off-by: Oleg Karfich <oleg.karfich at wago.com>
---
 drivers/net/cpsw.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index b01e7ac..4a8f9e6 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -901,13 +901,13 @@ static int cpsw_open(struct eth_device *edev)
 
 	dev_dbg(&slave->dev, "* %s\n", __func__);
 
+	cpsw_slave_init(slave, priv);
+
 	ret = phy_device_connect(edev, NULL, slave->phy_id,
 				 cpsw_adjust_link, 0, slave->phy_if);
 	if (ret)
 		return ret;
 
-	cpsw_slave_init(slave, priv);
-
 	return 0;
 }
 
-- 
2.7.4


From a.fatoum at pengutronix.de  Tue Aug 31 08:32:14 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 31 Aug 2021 17:32:14 +0200
Subject: [PATCH master] net: designware: eqos: fix MDIO regression for
 STM32MP1 boards
Message-ID: <20210831153214.31047-1-a.fatoum@pengutronix.de>

The STM32MP1 boards call their mdio subnode mdio0, which is now skipped
since ed8c7bdf8592 ("net: designware: eqos: set mdio bus device node").

Fix networking for them by only falling back to the mdio node name when a
child node with the correct compatible could not be found.

Fixes: ed8c7bdf8592 ("net: designware: eqos: set mdio bus device node")
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/net/designware_eqos.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
index f83ec127143c..5eee844e289a 100644
--- a/drivers/net/designware_eqos.c
+++ b/drivers/net/designware_eqos.c
@@ -824,6 +824,7 @@ static void eqos_probe_dt(struct device_d *dev, struct eqos *eqos)
 
 int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
 {
+	struct device_node *np = dev->device_node;
 	struct mii_bus *miibus;
 	struct resource *iores;
 	struct eqos *eqos;
@@ -862,7 +863,10 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
 	miibus->read = eqos_mdio_read;
 	miibus->write = eqos_mdio_write;
 	miibus->priv = eqos;
-	miibus->dev.device_node = of_get_child_by_name(dev->device_node, "mdio");
+
+	miibus->dev.device_node = of_get_compatible_child(np, "snps,dwmac-mdio");
+	if (!miibus->dev.device_node)
+		miibus->dev.device_node = of_get_child_by_name(np, "mdio");
 
 	ret = eqos_init(dev, eqos);
 	if (ret)
-- 
2.30.2



From a.fatoum at pengutronix.de  Tue Aug 31 09:11:39 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 31 Aug 2021 18:11:39 +0200
Subject: [PATCH master] of: overlay: don't do fixups on empty
 global.of.overlay.dir
Message-ID: <20210831161139.2988-1-a.fatoum@pengutronix.de>

$global.of.overlay.dir is dynamically prepended with the root of the
device currently being booted. This allows use of relative paths.

Because $global.of.overlay.filepattern is * by default, this means that
all files in the root of the device will be considered overlays and
barebox will try to unflatten them leading to an error message on boot:

  ERROR: of_overlay: Failed to unflatten /mnt/mmc0.4//.root_is_rw:
	Invalid argument

Fix this by not doing any fixups at all on empty global.of.overlay.dir.

If for whatever reason, a user wants overlays at /, they can

  global.of.overlay.dir=.

Fixes: 124c64af0982 ("overlay: Add filters to choose which overlays to apply")
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/overlay.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 42b309805fd2..25140eed31ed 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -460,6 +460,9 @@ static int of_overlay_global_fixup(struct device_node *root, void *data)
 	if (*of_overlay_dir == '/')
 		return of_overlay_apply_dir(root, of_overlay_dir, true);
 
+	if (*of_overlay_dir == '\0')
+		return 0;
+
 	dir = concat_path_file(of_overlay_basedir, of_overlay_dir);
 
 	ret = of_overlay_apply_dir(root, dir, true);
-- 
2.30.2



