summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-10-07 08:51:11 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2021-10-07 08:51:11 +0200
commitab7647dbd8aa54fcb0178829ac9e5fccb053d4ef (patch)
tree907492c209e5639af4faac074df9939f78aa078d
parentb06ef2e54303443d21dd98a773a13289e66812fb (diff)
parent6fb511fa62efe3faa8be67800cd934c143405fca (diff)
downloadbarebox-ab7647dbd8aa54fcb0178829ac9e5fccb053d4ef.tar.gz
barebox-ab7647dbd8aa54fcb0178829ac9e5fccb053d4ef.tar.xz
Merge branch 'for-next/misc'
-rw-r--r--Documentation/boards/socfpga.rst2
-rw-r--r--Documentation/user/framebuffer.rst6
-rw-r--r--Documentation/user/virtio.rst2
-rw-r--r--arch/arm/boards/rockchip-rk3568-evb/board.c62
-rw-r--r--arch/arm/include/asm/io.h1
-rw-r--r--arch/arm/mach-mvebu/include/mach/barebox-arm-head.h25
-rw-r--r--arch/arm/mach-mxs/bcb.c10
-rw-r--r--arch/arm/mach-mxs/clocksource-imx23.c16
-rw-r--r--arch/arm/mach-mxs/clocksource-imx28.c15
-rw-r--r--arch/arm/mach-mxs/imx.c16
-rw-r--r--arch/arm/mach-mxs/include/mach/clock.h16
-rw-r--r--arch/arm/mach-mxs/include/mach/fb.h12
-rw-r--r--arch/arm/mach-mxs/include/mach/generic.h16
-rw-r--r--arch/arm/mach-mxs/include/mach/imx-regs.h16
-rw-r--r--arch/arm/mach-mxs/include/mach/imx23-regs.h15
-rw-r--r--arch/arm/mach-mxs/include/mach/imx28-regs.h12
-rw-r--r--arch/arm/mach-mxs/include/mach/iomux-imx23.h14
-rw-r--r--arch/arm/mach-mxs/include/mach/iomux-imx28.h12
-rw-r--r--arch/arm/mach-mxs/include/mach/iomux.h16
-rw-r--r--arch/arm/mach-mxs/include/mach/mci.h13
-rw-r--r--arch/arm/mach-mxs/include/mach/ssp.h15
-rw-r--r--arch/arm/mach-mxs/iomux-imx.c16
-rw-r--r--arch/arm/mach-mxs/ocotp.c17
-rw-r--r--arch/arm/mach-mxs/power.c17
-rw-r--r--arch/arm/mach-mxs/soc-imx23.c19
-rw-r--r--arch/arm/mach-mxs/soc-imx28.c19
-rw-r--r--arch/arm/mach-mxs/usb-imx23.c20
-rw-r--r--arch/arm/mach-mxs/usb-imx28.c21
-rw-r--r--arch/powerpc/include/asm/io.h10
-rw-r--r--arch/riscv/cpu/core.c12
-rw-r--r--arch/riscv/lib/sbi.c10
-rw-r--r--arch/sandbox/include/asm/io.h1
-rw-r--r--arch/x86/include/asm/io.h10
-rw-r--r--commands/dfu.c29
-rw-r--r--common/Kconfig36
-rw-r--r--common/console.c12
-rw-r--r--common/console_simple.c5
-rw-r--r--common/fastboot.c2
-rw-r--r--common/file-list.c16
-rw-r--r--common/hush.c23
-rw-r--r--common/startup.c5
-rw-r--r--common/state/backend_format_raw.c4
-rw-r--r--common/usbgadget.c24
-rw-r--r--drivers/mci/mci-bcm2835.c9
-rw-r--r--drivers/mci/mci-core.c2
-rw-r--r--drivers/mci/sdhci.c5
-rw-r--r--drivers/mtd/core.c22
-rw-r--r--drivers/net/Kconfig13
-rw-r--r--drivers/net/Makefile4
-rw-r--r--drivers/net/cpsw.c4
-rw-r--r--drivers/net/designware_eqos.c4
-rw-r--r--drivers/net/e1000/Makefile3
-rw-r--r--drivers/net/e1000/eeprom.c814
-rw-r--r--drivers/net/e1000/mtd.c835
-rw-r--r--drivers/net/virtio.c243
-rw-r--r--drivers/net/xgmac.c734
-rw-r--r--drivers/pinctrl/pinctrl-bcm2835.c24
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_sbi.c58
-rw-r--r--drivers/spi/ath79_spi.c6
-rw-r--r--drivers/usb/gadget/dfu.c163
-rw-r--r--drivers/video/simplefb-client.c27
-rw-r--r--fs/fs.c1
-rw-r--r--include/asm-generic/io.h2
-rw-r--r--include/console.h2
-rw-r--r--include/file-list.h1
-rw-r--r--include/fs.h1
-rw-r--r--include/linux/virtio_config.h7
-rw-r--r--include/uapi/linux/virtio_net.h358
-rw-r--r--include/usb/dfu.h2
-rw-r--r--net/dhcp.c10
-rw-r--r--net/fastboot.c19
-rw-r--r--scripts/Makefile.lib7
-rw-r--r--scripts/bareboxenv.c6
-rwxr-xr-xscripts/socfpga_import_preloader88
76 files changed, 2012 insertions, 2111 deletions
diff --git a/Documentation/boards/socfpga.rst b/Documentation/boards/socfpga.rst
index 19d6060300..7e7f0619ea 100644
--- a/Documentation/boards/socfpga.rst
+++ b/Documentation/boards/socfpga.rst
@@ -121,7 +121,7 @@ Now run the command:
.. code-block:: sh
- scripts/socfpga_import_preloader <EMBEDDED_SDK> <ISW_HANDOFF> <BOARD_DIRECTORY>
+ scripts/socfpga_import_preloader -e <EMBEDDED_SDK> -i <ISW_HANDOFF> -b <BOARD_DIRECTORY>
where `<SPL_GENERATED_DIR>` is the directory where the bsp-editor generated the files,
`<ISW_HANDOFF>` is the directory where Quartus generated the handoff files, and
diff --git a/Documentation/user/framebuffer.rst b/Documentation/user/framebuffer.rst
index 8b95ad6b87..d17df822f2 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
diff --git a/Documentation/user/virtio.rst b/Documentation/user/virtio.rst
index dde47d5f82..d944fa4821 100644
--- a/Documentation/user/virtio.rst
+++ b/Documentation/user/virtio.rst
@@ -35,7 +35,7 @@ queues configuration and buffer transfers are nearly identical. Both MMIO
and non-legacy PCI are supported in barebox.
The VirtIO spec defines a lots of VirtIO device types, however at present only
-block, console, input and RNG devices are supported.
+block, network, console, input and RNG devices are supported.
Build Instructions
------------------
diff --git a/arch/arm/boards/rockchip-rk3568-evb/board.c b/arch/arm/boards/rockchip-rk3568-evb/board.c
index 57c24ed3c6..9cd84d7fb9 100644
--- a/arch/arm/boards/rockchip-rk3568-evb/board.c
+++ b/arch/arm/boards/rockchip-rk3568-evb/board.c
@@ -1,8 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-only
+
+#define pr_fmt(fmt) "rk3568-evb: " fmt
+
#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 +20,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 +44,55 @@ 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 (!IS_ENABLED(CONFIG_AIODEV))
+ return 0;
+
+ if (!machine_is_rk3568_evb)
+ return 0;
+
+ evb_hwid_chan = aiochannel_by_name("aiodev0.in_value1_mV");
+ if (IS_ERR(evb_hwid_chan)) {
+ ret = PTR_ERR(evb_hwid_chan);
+ goto err_hwid;
+ }
+
+ ret = aiochannel_get_value(evb_hwid_chan, &evb_hwid_voltage);
+ if (ret)
+ goto err_hwid;
+
+ if (evb_hwid_voltage > 1650) {
+ evb_hwid = "1";
+ } else if (evb_hwid_voltage > 1350) {
+ evb_hwid = "2";
+ } else if (evb_hwid_voltage > 1050) {
+ evb_hwid = "3";
+ } else if (evb_hwid_voltage > 750) {
+ evb_hwid = "4";
+ } else if (evb_hwid_voltage > 450) {
+ evb_hwid = "5";
+ } else if (evb_hwid_voltage > 150) {
+ evb_hwid = "6";
+ } else {
+ evb_hwid = "7";
+ }
+ pr_info("Detected RK3568 EVB%s\n", evb_hwid);
+
+ globalvar_add_simple("board.hwid", evb_hwid);
+
+ return 0;
+
+err_hwid:
+ pr_err("couldn't retrieve hardware ID");
+ return ret;
+}
+late_initcall(rk3568_evb_detect_hwid);
+
+BAREBOX_MAGICVAR(global.board.hwid, "The board hardware ID");
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index b442a37b9c..0507db1a9c 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/arm/mach-mvebu/include/mach/barebox-arm-head.h b/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h
index 3035f40ddf..723e2ab4c8 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"
@@ -24,10 +25,22 @@ static inline void __barebox_arm_head(void)
"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();
diff --git a/arch/arm/mach-mxs/bcb.c b/arch/arm/mach-mxs/bcb.c
index 860508bde7..749cf29af6 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 8279ee2f2d..0a6716f879 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 4f38af68b4..ea6d4b5146 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@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@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 b7247b9b72..5af9cca4e9 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 adbc3304f8..2050b95913 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 ad28f79d57..8fcfe86520 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 d63fa48257..dc1b6ed4a0 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 f5abd8bf79..4aede1bc93 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 3fd2f3d15b..a9a295fcbc 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 1a90ec2aa5..67e1009a99 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 1e225f8fc5..78a55a47b1 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 6119f3caf9..9fefe3a2af 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 0091dbae11..47e843e43f 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 c47c24cba8..3383635dfc 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 5eee5c010a..b90a448205 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@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@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 68a4e3cbd6..6b96fc4ed9 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 a4df39c2e9..5f78d9d773 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 6febf5dbaa..342f7b0271 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@pengutronix.de>
- * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@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@pengutronix.de>, Pengutronix
+// SPDX-FileCopyrightText: 2012 Wolfram Sang <w.sang@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 8c47c766cc..16b1fda5ed 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@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@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 a214e2b7a6..e3d3cb1c0a 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@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@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 d9a54b66f8..6acf1bb786 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@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@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 a4e1bdb280..3793169b59 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@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@pengutronix.de>, Pengutronix
+
+/* i.MX28 USBPHY setup */
+
#include <common.h>
#include <io.h>
#include <errno.h>
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 8488c36f65..30d0987023 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/riscv/cpu/core.c b/arch/riscv/cpu/core.c
index 80730c05b5..1d5902a51f 100644
--- a/arch/riscv/cpu/core.c
+++ b/arch/riscv/cpu/core.c
@@ -33,6 +33,7 @@ static int riscv_request_stack(void)
coredevice_initcall(riscv_request_stack);
static struct device_d timer_dev;
+static struct device_d serial_sbi_dev;
static s64 hartid;
@@ -75,6 +76,17 @@ static int riscv_probe(struct device_d *parent)
return ret;
}
+ if (IS_ENABLED(CONFIG_SERIAL_SBI) && !serial_sbi_dev.parent) {
+ serial_sbi_dev.id = DEVICE_ID_SINGLE;
+ serial_sbi_dev.device_node = 0;
+ serial_sbi_dev.parent = parent;
+ dev_set_name(&serial_sbi_dev, "riscv-serial-sbi");
+
+ ret = platform_device_register(&serial_sbi_dev);
+ if (ret)
+ return ret;
+ }
+
hartid = riscv_hartid();
if (hartid >= 0)
globalvar_add_simple_uint64("hartid", &hartid, "%llu");
diff --git a/arch/riscv/lib/sbi.c b/arch/riscv/lib/sbi.c
index 45a04fb821..a57c834b41 100644
--- a/arch/riscv/lib/sbi.c
+++ b/arch/riscv/lib/sbi.c
@@ -64,3 +64,13 @@ static int sbi_init(void)
}
core_initcall(sbi_init);
+
+void sbi_console_putchar(int ch)
+{
+ sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0);
+}
+
+int sbi_console_getchar(void)
+{
+ return sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0, 0, 0, 0, 0, 0, 0).error;
+}
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 9f9cd3a42a..3e5c0580bc 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/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 5d19679b50..0971727bc6 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 */
diff --git a/commands/dfu.c b/commands/dfu.c
index 3132a7479d..1734947fe0 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,28 @@
*/
static int do_dfu(int argc, char *argv[])
{
- struct f_dfu_opts opts;
- char *argstr;
- struct usb_dfu_dev *dfu_alts = NULL;
+ struct usbgadget_funcs funcs = {};
int ret;
if (argc != optind + 1)
return COMMAND_ERROR_USAGE;
- argstr = argv[optind];
+ funcs.flags |= USBGADGET_DFU;
+ funcs.dfu_opts = argv[optind];
+ ret = usbgadget_register(&funcs);
+ 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/common/Kconfig b/common/Kconfig
index a9feae2ae8..70debb9cd5 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -812,6 +812,17 @@ config CONSOLE_ALLOW_COLOR
compile time default for colored console output. After boot it
can be controlled using global.allow_color.
+config CONSOLE_DISABLE_INPUT
+ prompt "Disable input on all consoles by default (non-interactive)"
+ def_bool CONSOLE_NONE
+ help
+ If enabled, all consoles are initially configured to not accept any input,
+ making the consoles effectively non-interactive.
+ The active device parameter can be used to override this on a per-console
+ basis.
+ CAUTION: this will also disable input devices by default, since they are
+ registered as consoles.
+
config PBL_CONSOLE
depends on PBL_IMAGE
depends on !CONSOLE_NONE
@@ -842,6 +853,7 @@ config ENV_HANDLING
startup) will bring them back. If unsure, say yes.
config DEFAULT_ENVIRONMENT
+ select CRC32
bool
default y if ENV_HANDLING
prompt "Compile in default environment"
@@ -1091,6 +1103,30 @@ config SYSTEMD_OF_WATCHDOG
in the kernel device tree. If the kernel is booted without a device
tree or with one that lacks aliases, nothing is added.
+config EXTERNAL_DTS_FRAGMENTS
+ string "external dts file fragments"
+ depends on OFTREE
+ help
+ List of dts fragment files that will be appended to Barebox's device
+ tree(s) source when building the dtb file(s). If multiple files are
+ listed, they will be appended in order. Relative filenames will use
+ the dtc include search path.
+
+ A preprocessor macro based on the name of the main dts will be
+ defined, which allows the dts fragments to based on which image of a
+ multi image build they are being used in. Given the dts filename
+ used for a board is "foo-board.dts" the external dts usage can be
+ limited to that board with
+
+ #ifdef foo_board_dts
+ ...
+ #endif
+
+ It not intended that this be put into into Barebox defconfig files.
+ Instead, it's an external build system, like Yocto or buildroot, to
+ add dts fragments from outside the Barebox source tree into the
+ Barebox build.
+
menu "OP-TEE loading"
config OPTEE_SIZE
diff --git a/common/console.c b/common/console.c
index ad1a6aaab2..0368c72d0b 100644
--- a/common/console.c
+++ b/common/console.c
@@ -328,7 +328,7 @@ int console_register(struct console_device *newcdev)
return of_platform_populate(serdev_node, NULL, dev);
if (newcdev->dev && of_device_is_stdout_path(newcdev->dev, &baudrate)) {
- activate = 1;
+ activate = CONSOLE_STDIOE;
console_set_stdoutpath(newcdev, baudrate);
}
@@ -349,16 +349,18 @@ int console_register(struct console_device *newcdev)
if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) {
if (list_empty(&console_list))
- activate = 1;
+ activate = CONSOLE_STDIOE;
} else if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_ALL)) {
- activate = 1;
+ activate = CONSOLE_STDIOE;
}
list_add_tail(&newcdev->list, &console_list);
+ if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_INPUT))
+ activate &= ~CONSOLE_STDIN;
+
if (activate)
- console_set_active(newcdev, CONSOLE_STDIN |
- CONSOLE_STDOUT | CONSOLE_STDERR);
+ console_set_active(newcdev, activate);
/* expose console as device in fs */
newcdev->devfs.name = basprintf("%s%d", newcdev->class_dev.name,
diff --git a/common/console_simple.c b/common/console_simple.c
index 42224842c5..3b95570e5e 100644
--- a/common/console_simple.c
+++ b/common/console_simple.c
@@ -92,7 +92,10 @@ int console_register(struct console_device *newcdev)
newcdev->setbrg(newcdev, newcdev->baudrate);
}
- newcdev->f_active = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
+ newcdev->f_active = CONSOLE_STDIOE;
+
+ if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_INPUT))
+ newcdev->f_active = ~CONSOLE_STDIN;
barebox_banner();
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;
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/hush.c b/common/hush.c
index 0475401321..d80df7a181 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;
}
diff --git a/common/startup.c b/common/startup.c
index 871696968a..f72902fc53 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -241,6 +241,11 @@ enum autoboot_state do_autoboot_countdown(void)
if (autoboot_state != AUTOBOOT_UNKNOWN)
return autoboot_state;
+ if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_INPUT)) {
+ printf("\nNon-interactive console, booting system\n");
+ return autoboot_state = AUTOBOOT_BOOT;
+ }
+
if (global_autoboot_state != AUTOBOOT_COUNTDOWN)
return global_autoboot_state;
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,
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/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c
index 0450f899c6..f2cb65231e 100644
--- a/drivers/mci/mci-bcm2835.c
+++ b/drivers/mci/mci-bcm2835.c
@@ -84,16 +84,20 @@ static u32 bcm2835_sdhci_read32(struct sdhci *sdhci, int reg)
return readl(host->regs + reg);
}
-static u32 bcm2835_mci_wait_command_done(struct bcm2835_mci_host *host)
+static int bcm2835_mci_wait_command_done(struct bcm2835_mci_host *host)
{
u32 interrupt = 0;
+ uint64_t start;
+ start = get_time_ns();
while (true) {
interrupt = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
if (interrupt & SDHCI_INT_INDEX)
return -EPERM;
if (interrupt & SDHCI_INT_CMD_COMPLETE)
break;
+ if (is_timeout(start, SECOND))
+ return -ETIMEDOUT;
}
return 0;
}
@@ -127,7 +131,8 @@ static void bcm2835_mci_reset_emmc(struct bcm2835_mci_host *host, u32 reset,
*/
static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd,
struct mci_data *data) {
- u32 command, block_data = 0, ret = 0, transfer_mode = 0;
+ u32 command, block_data = 0, transfer_mode = 0;
+ int ret;
u32 wait_inhibit_mask = SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA;
struct bcm2835_mci_host *host = to_bcm2835_host(mci);
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 92a73c8f1d..82e2f82f53 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1920,7 +1920,7 @@ int mci_register(struct mci_host *host)
host->supply = regulator_get(hw_dev, "vmmc");
if (IS_ERR(host->supply)) {
- dev_err(&mci->dev, "Failed to get 'vmmc' regulator.\n");
+ dev_warn(hw_dev, "Failed to get 'vmmc' regulator (ignored).\n");
host->supply = NULL;
}
diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c
index aca4a5a6f9..8b5520d682 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,
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 37fccda6be..c6c1e1e7cf 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -377,7 +377,7 @@ int mtd_block_markgood(struct mtd_info *mtd, loff_t ofs)
}
int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
- u_char *buf)
+ u_char *buf)
{
struct mtd_oob_ops ops = {
.len = len,
@@ -420,23 +420,23 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
}
int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
- const u_char *buf)
+ const u_char *buf)
{
- struct mtd_oob_ops ops = {
- .len = len,
- .datbuf = (u8 *)buf,
- };
- int ret;
+ struct mtd_oob_ops ops = {
+ .len = len,
+ .datbuf = (u8 *)buf,
+ };
+ int ret;
if (to < 0 || to >= mtd->size || len > mtd->size - to)
return -EINVAL;
if (!len)
return 0;
- ret = mtd_write_oob(mtd, to, &ops);
- *retlen = ops.retlen;
+ ret = mtd_write_oob(mtd, to, &ops);
+ *retlen = ops.retlen;
- return ret;
+ return ret;
}
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
@@ -757,7 +757,7 @@ err:
return ret;
}
-int del_mtd_device (struct mtd_info *mtd)
+int del_mtd_device(struct mtd_info *mtd)
{
struct mtddev_hook *hook;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 802169a86e..4947296f27 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
@@ -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
@@ -262,6 +258,13 @@ config DRIVER_NET_EFI_SNP
bool "EFI SNP ethernet driver"
depends on EFI_BOOTUP
+config DRIVER_NET_VIRTIO
+ bool "virtio net driver"
+ depends on VIRTIO
+ help
+ This is the virtual net driver for virtio. It can be used with
+ QEMU based targets.
+
config DRIVER_NET_AG71XX
bool "Atheros AG71xx ethernet driver"
depends on MACH_MIPS_ATH79
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fb3e3bdee4..1921d0d9f9 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
@@ -17,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
@@ -37,4 +36,5 @@ obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o
obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o
+obj-$(CONFIG_DRIVER_NET_VIRTIO) += virtio.o
obj-$(CONFIG_DRIVER_NET_AG71XX) += ag71xx.o
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index b01e7ac7a8..4a8f9e67d6 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;
}
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;
diff --git a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile
new file mode 100644
index 0000000000..91ef11cbe3
--- /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 5a7d8675ce..6bdf9db553 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 0000000000..93595cc88d
--- /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;
+}
diff --git a/drivers/net/virtio.c b/drivers/net/virtio.c
new file mode 100644
index 0000000000..ea4d552903
--- /dev/null
+++ b/drivers/net/virtio.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <net.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ring.h>
+#include <uapi/linux/virtio_net.h>
+
+/* Amount of buffers to keep in the RX virtqueue */
+#define VIRTIO_NET_NUM_RX_BUFS 32
+
+/*
+ * This value comes from the VirtIO spec: 1500 for maximum packet size,
+ * 14 for the Ethernet header, 12 for virtio_net_hdr. In total 1526 bytes.
+ */
+#define VIRTIO_NET_RX_BUF_SIZE 1526
+
+struct virtio_net_priv {
+ union {
+ struct virtqueue *vqs[2];
+ struct {
+ struct virtqueue *rx_vq;
+ struct virtqueue *tx_vq;
+ };
+ };
+
+ char rx_buff[VIRTIO_NET_NUM_RX_BUFS][VIRTIO_NET_RX_BUF_SIZE];
+ bool rx_running;
+ int net_hdr_len;
+ struct eth_device edev;
+ struct virtio_device *vdev;
+};
+
+static inline struct virtio_net_priv *to_priv(struct eth_device *edev)
+{
+ return container_of(edev, struct virtio_net_priv, edev);
+}
+
+static int virtio_net_start(struct eth_device *edev)
+{
+ struct virtio_net_priv *priv = to_priv(edev);
+ struct virtio_sg sg;
+ struct virtio_sg *sgs[] = { &sg };
+ int i;
+
+ if (!priv->rx_running) {
+ /* receive buffer length is always 1526 */
+ sg.length = VIRTIO_NET_RX_BUF_SIZE;
+
+ /* setup the receive buffer address */
+ for (i = 0; i < VIRTIO_NET_NUM_RX_BUFS; i++) {
+ sg.addr = priv->rx_buff[i];
+ virtqueue_add(priv->rx_vq, sgs, 0, 1);
+ }
+
+ virtqueue_kick(priv->rx_vq);
+
+ /* setup the receive queue only once */
+ priv->rx_running = true;
+ }
+
+ return 0;
+}
+
+static int virtio_net_send(struct eth_device *edev, void *packet, int length)
+{
+ struct virtio_net_priv *priv = to_priv(edev);
+ struct virtio_net_hdr_v1 hdr_v1;
+ struct virtio_net_hdr hdr;
+ struct virtio_sg hdr_sg;
+ struct virtio_sg data_sg = { packet, length };
+ struct virtio_sg *sgs[] = { &hdr_sg, &data_sg };
+ int ret;
+
+ if (priv->net_hdr_len == sizeof(struct virtio_net_hdr))
+ hdr_sg.addr = &hdr;
+ else
+ hdr_sg.addr = &hdr_v1;
+
+ hdr_sg.length = priv->net_hdr_len;
+ memset(hdr_sg.addr, 0, priv->net_hdr_len);
+
+ ret = virtqueue_add(priv->tx_vq, sgs, 2, 0);
+ if (ret)
+ return ret;
+
+ virtqueue_kick(priv->tx_vq);
+
+ while (1) {
+ if (virtqueue_get_buf(priv->tx_vq, NULL))
+ break;
+ }
+
+ return 0;
+}
+
+static int virtio_net_recv(struct eth_device *edev)
+{
+ struct virtio_net_priv *priv = to_priv(edev);
+ struct virtio_sg sg;
+ struct virtio_sg *sgs[] = { &sg };
+ unsigned int len;
+ void *buf;
+
+ sg.addr = virtqueue_get_buf(priv->rx_vq, &len);
+ if (!sg.addr)
+ return -EAGAIN;
+
+ sg.length = VIRTIO_NET_RX_BUF_SIZE;
+
+ buf = sg.addr + priv->net_hdr_len;
+ len -= priv->net_hdr_len;
+
+ net_receive(edev, buf, len);
+
+ /* Put the buffer back to the rx ring */
+ virtqueue_add(priv->rx_vq, sgs, 0, 1);
+
+ return 0;
+}
+
+static void virtio_net_stop(struct eth_device *dev)
+{
+ /*
+ * There is no way to stop the queue from running, unless we issue
+ * a reset to the virtio device, and re-do the queue initialization
+ * from the beginning.
+ */
+}
+
+static int virtio_net_write_hwaddr(struct eth_device *edev, const unsigned char *adr)
+{
+ struct virtio_net_priv *priv = to_priv(edev);
+ int i;
+
+ /*
+ * v1.0 compliant device's MAC address is set through control channel,
+ * which we don't support for now.
+ */
+ if (virtio_has_feature(priv->vdev, VIRTIO_F_VERSION_1))
+ return -ENOSYS;
+
+ for (i = 0; i < 6; i++)
+ virtio_cwrite8(priv->vdev, offsetof(struct virtio_net_config, mac) + i, adr[i]);
+
+ return 0;
+}
+
+static int virtio_net_read_rom_hwaddr(struct eth_device *edev, unsigned char *adr)
+{
+ struct virtio_net_priv *priv = to_priv(edev);
+
+ virtio_cread_bytes(priv->vdev, offsetof(struct virtio_net_config, mac), adr, 6);
+
+ return 0;
+}
+
+static int virtio_net_probe(struct virtio_device *vdev)
+{
+ struct virtio_net_priv *priv;
+ struct eth_device *edev;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+
+ vdev->priv = priv;
+
+ /*
+ * For v1.0 compliant device, it always assumes the member
+ * 'num_buffers' exists in the struct virtio_net_hdr while
+ * the legacy driver only presented 'num_buffers' when
+ * VIRTIO_NET_F_MRG_RXBUF was negotiated. Without that feature
+ * the structure was 2 bytes shorter.
+ */
+ if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
+ priv->net_hdr_len = sizeof(struct virtio_net_hdr_v1);
+ else
+ priv->net_hdr_len = sizeof(struct virtio_net_hdr);
+
+ ret = virtio_find_vqs(vdev, 2, priv->vqs);
+ if (ret < 0)
+ return ret;
+
+ priv->vdev = vdev;
+
+ edev = &priv->edev;
+ edev->priv = priv;
+ edev->parent = &vdev->dev;
+
+ edev->open = virtio_net_start;
+ edev->send = virtio_net_send;
+ edev->recv = virtio_net_recv;
+ edev->halt = virtio_net_stop;
+ edev->get_ethaddr = virtio_net_read_rom_hwaddr;
+ edev->set_ethaddr = virtio_net_write_hwaddr;
+
+ return eth_register(edev);
+}
+
+static void virtio_net_remove(struct virtio_device *vdev)
+{
+ struct virtio_net_priv *priv = vdev->priv;
+
+ vdev->config->reset(vdev);
+ eth_unregister(&priv->edev);
+ vdev->config->del_vqs(vdev);
+
+ free(priv);
+}
+
+/*
+ * For simplicity, the driver only negotiates the VIRTIO_NET_F_MAC feature.
+ * For the VIRTIO_NET_F_STATUS feature, we don't negotiate it, hence per spec
+ * we should assume the link is always active.
+ */
+static const u32 features[] = {
+ VIRTIO_NET_F_MAC
+};
+
+static const struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static struct virtio_driver virtio_net = {
+ .driver.name = "virtio_net",
+ .id_table = id_table,
+ .probe = virtio_net_probe,
+ .remove = virtio_net_remove,
+ .feature_table = features,
+ .feature_table_size = ARRAY_SIZE(features),
+ .feature_table_legacy = features,
+ .feature_table_size_legacy = ARRAY_SIZE(features),
+};
+device_virtio_driver(virtio_net);
diff --git a/drivers/net/xgmac.c b/drivers/net/xgmac.c
deleted file mode 100644
index 136d788043..0000000000
--- 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);
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index d62c735181..684ead2f8e 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -52,6 +52,10 @@ struct bcm2835_gpio_chip {
struct pinctrl_device pctl;
};
+struct plat_data {
+ unsigned ngpios;
+};
+
static int bcm2835_set_function(struct gpio_chip *chip, unsigned gpio, int function)
{
struct bcm2835_gpio_chip *bcmgpio = container_of(chip, struct bcm2835_gpio_chip, chip);
@@ -149,10 +153,13 @@ static struct pinctrl_ops bcm2835_pinctrl_ops = {
static int bcm2835_gpio_probe(struct device_d *dev)
{
+ const struct plat_data *plat_data;
struct resource *iores;
struct bcm2835_gpio_chip *bcmgpio;
int ret;
+ plat_data = device_get_match_data(dev);
+
bcmgpio = xzalloc(sizeof(*bcmgpio));
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
@@ -160,7 +167,8 @@ static int bcm2835_gpio_probe(struct device_d *dev)
bcmgpio->base = IOMEM(iores->start);
bcmgpio->chip.ops = &bcm2835_gpio_ops;
bcmgpio->chip.base = 0;
- bcmgpio->chip.ngpio = 54;
+ bcmgpio->chip.ngpio = plat_data->ngpios;
+
bcmgpio->chip.dev = dev;
bcmgpio->pctl.ops = &bcm2835_pinctrl_ops;
bcmgpio->pctl.dev = dev;
@@ -191,9 +199,21 @@ err:
return ret;
}
+static const struct plat_data bcm2835_plat_data = {
+ .ngpios = 54,
+};
+
+static const struct plat_data bcm2711_plat_data = {
+ .ngpios = 58,
+};
+
static __maybe_unused struct of_device_id bcm2835_gpio_dt_ids[] = {
{
.compatible = "brcm,bcm2835-gpio",
+ .data = &bcm2835_plat_data,
+ }, {
+ .compatible = "brcm,bcm2711-gpio",
+ .data = &bcm2711_plat_data,
}, {
/* sentinel */
}
@@ -205,4 +225,4 @@ static struct driver_d bcm2835_gpio_driver = {
.of_compatible = DRV_OF_COMPAT(bcm2835_gpio_dt_ids),
};
-coredevice_platform_driver(bcm2835_gpio_driver);
+core_platform_driver(bcm2835_gpio_driver);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b9750d1774..5e30ea388b 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -173,4 +173,12 @@ config SERIAL_SIFIVE
contains a SiFive UART IP block. This type of UART is present on
SiFive FU540 SoCs, among others.
+config SERIAL_SBI
+ tristate "RISCV Serial support over SBI's HTIF"
+ depends on OFDEVICE
+ depends on RISCV_SBI
+ help
+ Select this option if you are building barebox for a RISCV platform
+ that implements a serial over SBI.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5120b17376..b1de436ed6 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_SERIAL_SBI) += serial_sbi.o
diff --git a/drivers/serial/serial_sbi.c b/drivers/serial/serial_sbi.c
new file mode 100644
index 0000000000..2ea28fea5b
--- /dev/null
+++ b/drivers/serial/serial_sbi.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Marcelo Politzer <marcelo.politzer@cartesi.io>
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <asm/sbi.h>
+
+struct sbi_serial_priv {
+ struct console_device cdev;
+ uint8_t b[2], head, tail;
+};
+
+static int sbi_serial_getc(struct console_device *cdev)
+{
+ struct sbi_serial_priv *priv = cdev->dev->priv;
+ if (priv->head == priv->tail)
+ return -1;
+ return priv->b[priv->head++ & 0x1];
+}
+
+static void sbi_serial_putc(struct console_device *cdev, const char ch)
+{
+ sbi_console_putchar(ch);
+}
+
+static int sbi_serial_tstc(struct console_device *cdev)
+{
+ struct sbi_serial_priv *priv = cdev->dev->priv;
+ int c = sbi_console_getchar();
+
+ if (c != -1)
+ priv->b[priv->tail++ & 0x1] = c;
+ return priv->head != priv->tail;
+}
+
+static int sbi_serial_probe(struct device_d *dev)
+{
+ struct sbi_serial_priv *priv;
+
+ priv = dev->priv = xzalloc(sizeof(*priv));
+ priv->cdev.dev = dev;
+ priv->cdev.putc = sbi_serial_putc;
+ priv->cdev.getc = sbi_serial_getc;
+ priv->cdev.tstc = sbi_serial_tstc;
+ priv->cdev.flush = 0;
+ priv->cdev.setbrg = 0;
+
+ return console_register(&priv->cdev);
+}
+
+static struct driver_d serial_sbi_driver = {
+ .name = "riscv-serial-sbi",
+ .probe = sbi_serial_probe,
+};
+postcore_platform_driver(serial_sbi_driver);
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
index e47896be62..2a4e32a4cc 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)
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/drivers/video/simplefb-client.c b/drivers/video/simplefb-client.c
index 1f26ac5067..2367713ba4 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));
- info->xres = params.width;
- info->yres = params.height;
+ simplefb->mode.name = params.format->name;
+ simplefb->mode.xres = params.width;
+ simplefb->mode.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);
@@ -114,13 +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);
- 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);
if (ret < 0) {
@@ -128,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;
}
diff --git a/fs/fs.c b/fs/fs.c
index b6431227d6..e6fd57b8ac 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -813,7 +813,6 @@ int fsdev_open_cdev(struct fs_device_d *fsdev)
}
fsdev->dev.parent = fsdev->cdev->dev;
- fsdev->parent_device = fsdev->cdev->dev;
return 0;
}
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index a4b0dc4b43..47f8c3ec1b 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 */
diff --git a/include/console.h b/include/console.h
index a71d0da42e..5d5783ca66 100644
--- a/include/console.h
+++ b/include/console.h
@@ -18,6 +18,8 @@
#define CONSOLE_STDOUT (1 << 1)
#define CONSOLE_STDERR (1 << 2)
+#define CONSOLE_STDIOE (CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR)
+
enum console_mode {
CONSOLE_MODE_NORMAL,
CONSOLE_MODE_RS485,
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 *);
diff --git a/include/fs.h b/include/fs.h
index 5811199c01..cd5eb571e0 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -101,7 +101,6 @@ struct fs_device_d {
struct cdev *cdev;
bool loop;
char *path;
- struct device_d *parent_device;
struct list_head list;
char *options;
char *linux_rootarg;
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 8160f0952f..6bb1f768b6 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -232,8 +232,11 @@ static inline int virtio_get_config(struct virtio_device *vdev, unsigned int off
* @len: the length of the buffer
* @return 0 if OK, -ve on error
*/
-int virtio_set_config(struct virtio_device *vdev, unsigned int offset,
- void *buf, unsigned int len);
+static inline int virtio_set_config(struct virtio_device *vdev, unsigned int offset,
+ void *buf, unsigned int len)
+{
+ return vdev->config->set_config(vdev, offset, buf, len);
+}
/**
* virtio_find_vqs() - find virtqueues and instantiate them
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
new file mode 100644
index 0000000000..c1896b1cfc
--- /dev/null
+++ b/include/uapi/linux/virtio_net.h
@@ -0,0 +1,358 @@
+#ifndef _UAPI_LINUX_VIRTIO_NET_H
+#define _UAPI_LINUX_VIRTIO_NET_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+#include <linux/types.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_types.h>
+#include <net.h>
+
+/* The feature bitmap for virtio net */
+#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Dynamic offload configuration. */
+#define VIRTIO_NET_F_MTU 3 /* Initial MTU advice */
+#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
+#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
+#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
+#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */
+#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */
+#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */
+#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */
+#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */
+#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the
+ * network */
+#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow
+ * Steering */
+#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
+
+#define VIRTIO_NET_F_HASH_REPORT 57 /* Supports hash report */
+#define VIRTIO_NET_F_RSS 60 /* Supports RSS RX steering */
+#define VIRTIO_NET_F_RSC_EXT 61 /* extended coalescing info */
+#define VIRTIO_NET_F_STANDBY 62 /* Act as standby for another device
+ * with the same MAC.
+ */
+#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */
+
+#ifndef VIRTIO_NET_NO_LEGACY
+#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
+#endif /* VIRTIO_NET_NO_LEGACY */
+
+#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
+#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */
+
+/* supported/enabled hash types */
+#define VIRTIO_NET_RSS_HASH_TYPE_IPv4 (1 << 0)
+#define VIRTIO_NET_RSS_HASH_TYPE_TCPv4 (1 << 1)
+#define VIRTIO_NET_RSS_HASH_TYPE_UDPv4 (1 << 2)
+#define VIRTIO_NET_RSS_HASH_TYPE_IPv6 (1 << 3)
+#define VIRTIO_NET_RSS_HASH_TYPE_TCPv6 (1 << 4)
+#define VIRTIO_NET_RSS_HASH_TYPE_UDPv6 (1 << 5)
+#define VIRTIO_NET_RSS_HASH_TYPE_IP_EX (1 << 6)
+#define VIRTIO_NET_RSS_HASH_TYPE_TCP_EX (1 << 7)
+#define VIRTIO_NET_RSS_HASH_TYPE_UDP_EX (1 << 8)
+
+struct virtio_net_config {
+ /* The config defining mac address (if VIRTIO_NET_F_MAC) */
+ __u8 mac[ETH_ALEN];
+ /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
+ __virtio16 status;
+ /* Maximum number of each of transmit and receive queues;
+ * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
+ * Legal values are between 1 and 0x8000
+ */
+ __virtio16 max_virtqueue_pairs;
+ /* Default maximum transmit unit advice */
+ __virtio16 mtu;
+ /*
+ * speed, in units of 1Mb. All values 0 to INT_MAX are legal.
+ * Any other value stands for unknown.
+ */
+ __le32 speed;
+ /*
+ * 0x00 - half duplex
+ * 0x01 - full duplex
+ * Any other value stands for unknown.
+ */
+ __u8 duplex;
+ /* maximum size of RSS key */
+ __u8 rss_max_key_size;
+ /* maximum number of indirection table entries */
+ __le16 rss_max_indirection_table_length;
+ /* bitmask of supported VIRTIO_NET_RSS_HASH_ types */
+ __le32 supported_hash_types;
+} __attribute__((packed));
+
+/*
+ * This header comes first in the scatter-gather list. If you don't
+ * specify GSO or CSUM features, you can simply ignore the header.
+ *
+ * This is bitwise-equivalent to the legacy struct virtio_net_hdr_mrg_rxbuf,
+ * only flattened.
+ */
+struct virtio_net_hdr_v1 {
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */
+#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */
+#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc info in csum_ fields */
+ __u8 flags;
+#define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */
+#define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */
+#define VIRTIO_NET_HDR_GSO_UDP 3 /* GSO frame, IPv4 UDP (UFO) */
+#define VIRTIO_NET_HDR_GSO_TCPV6 4 /* GSO frame, IPv6 TCP */
+#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */
+ __u8 gso_type;
+ __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
+ __virtio16 gso_size; /* Bytes to append to hdr_len per frame */
+ union {
+ struct {
+ __virtio16 csum_start;
+ __virtio16 csum_offset;
+ };
+ /* Checksum calculation */
+ struct {
+ /* Position to start checksumming from */
+ __virtio16 start;
+ /* Offset after that to place checksum */
+ __virtio16 offset;
+ } csum;
+ /* Receive Segment Coalescing */
+ struct {
+ /* Number of coalesced segments */
+ __le16 segments;
+ /* Number of duplicated acks */
+ __le16 dup_acks;
+ } rsc;
+ };
+ __virtio16 num_buffers; /* Number of merged rx buffers */
+};
+
+struct virtio_net_hdr_v1_hash {
+ struct virtio_net_hdr_v1 hdr;
+ __le32 hash_value;
+#define VIRTIO_NET_HASH_REPORT_NONE 0
+#define VIRTIO_NET_HASH_REPORT_IPv4 1
+#define VIRTIO_NET_HASH_REPORT_TCPv4 2
+#define VIRTIO_NET_HASH_REPORT_UDPv4 3
+#define VIRTIO_NET_HASH_REPORT_IPv6 4
+#define VIRTIO_NET_HASH_REPORT_TCPv6 5
+#define VIRTIO_NET_HASH_REPORT_UDPv6 6
+#define VIRTIO_NET_HASH_REPORT_IPv6_EX 7
+#define VIRTIO_NET_HASH_REPORT_TCPv6_EX 8
+#define VIRTIO_NET_HASH_REPORT_UDPv6_EX 9
+ __le16 hash_report;
+ __le16 padding;
+};
+
+#ifndef VIRTIO_NET_NO_LEGACY
+/* This header comes first in the scatter-gather list.
+ * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must
+ * be the first element of the scatter-gather list. If you don't
+ * specify GSO or CSUM features, you can simply ignore the header. */
+struct virtio_net_hdr {
+ /* See VIRTIO_NET_HDR_F_* */
+ __u8 flags;
+ /* See VIRTIO_NET_HDR_GSO_* */
+ __u8 gso_type;
+ __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
+ __virtio16 gso_size; /* Bytes to append to hdr_len per frame */
+ __virtio16 csum_start; /* Position to start checksumming from */
+ __virtio16 csum_offset; /* Offset after that to place checksum */
+};
+
+/* This is the version of the header to use when the MRG_RXBUF
+ * feature has been negotiated. */
+struct virtio_net_hdr_mrg_rxbuf {
+ struct virtio_net_hdr hdr;
+ __virtio16 num_buffers; /* Number of merged rx buffers */
+};
+#endif /* ...VIRTIO_NET_NO_LEGACY */
+
+/*
+ * Control virtqueue data structures
+ *
+ * The control virtqueue expects a header in the first sg entry
+ * and an ack/status response in the last entry. Data for the
+ * command goes in between.
+ */
+struct virtio_net_ctrl_hdr {
+ __u8 class;
+ __u8 cmd;
+} __attribute__((packed));
+
+typedef __u8 virtio_net_ctrl_ack;
+
+#define VIRTIO_NET_OK 0
+#define VIRTIO_NET_ERR 1
+
+/*
+ * Control the RX mode, ie. promisucous, allmulti, etc...
+ * All commands require an "out" sg entry containing a 1 byte
+ * state value, zero = disable, non-zero = enable. Commands
+ * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
+ */
+#define VIRTIO_NET_CTRL_RX 0
+ #define VIRTIO_NET_CTRL_RX_PROMISC 0
+ #define VIRTIO_NET_CTRL_RX_ALLMULTI 1
+ #define VIRTIO_NET_CTRL_RX_ALLUNI 2
+ #define VIRTIO_NET_CTRL_RX_NOMULTI 3
+ #define VIRTIO_NET_CTRL_RX_NOUNI 4
+ #define VIRTIO_NET_CTRL_RX_NOBCAST 5
+
+/*
+ * Control the MAC
+ *
+ * The MAC filter table is managed by the hypervisor, the guest should
+ * assume the size is infinite. Filtering should be considered
+ * non-perfect, ie. based on hypervisor resources, the guest may
+ * received packets from sources not specified in the filter list.
+ *
+ * In addition to the class/cmd header, the TABLE_SET command requires
+ * two out scatterlists. Each contains a 4 byte count of entries followed
+ * by a concatenated byte stream of the ETH_ALEN MAC addresses. The
+ * first sg list contains unicast addresses, the second is for multicast.
+ * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
+ * is available.
+ *
+ * The ADDR_SET command requests one out scatterlist, it contains a
+ * 6 bytes MAC address. This functionality is present if the
+ * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
+ */
+struct virtio_net_ctrl_mac {
+ __virtio32 entries;
+ __u8 macs[][ETH_ALEN];
+} __attribute__((packed));
+
+#define VIRTIO_NET_CTRL_MAC 1
+ #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
+ #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
+
+/*
+ * Control VLAN filtering
+ *
+ * The VLAN filter table is controlled via a simple ADD/DEL interface.
+ * VLAN IDs not added may be filterd by the hypervisor. Del is the
+ * opposite of add. Both commands expect an out entry containing a 2
+ * byte VLAN ID. VLAN filterting is available with the
+ * VIRTIO_NET_F_CTRL_VLAN feature bit.
+ */
+#define VIRTIO_NET_CTRL_VLAN 2
+ #define VIRTIO_NET_CTRL_VLAN_ADD 0
+ #define VIRTIO_NET_CTRL_VLAN_DEL 1
+
+/*
+ * Control link announce acknowledgement
+ *
+ * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
+ * driver has recevied the notification; device would clear the
+ * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives
+ * this command.
+ */
+#define VIRTIO_NET_CTRL_ANNOUNCE 3
+ #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0
+
+/*
+ * Control Receive Flow Steering
+ */
+#define VIRTIO_NET_CTRL_MQ 4
+/*
+ * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
+ * enables Receive Flow Steering, specifying the number of the transmit and
+ * receive queues that will be used. After the command is consumed and acked by
+ * the device, the device will not steer new packets on receive virtqueues
+ * other than specified nor read from transmit virtqueues other than specified.
+ * Accordingly, driver should not transmit new packets on virtqueues other than
+ * specified.
+ */
+struct virtio_net_ctrl_mq {
+ __virtio16 virtqueue_pairs;
+};
+
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
+
+/*
+ * The command VIRTIO_NET_CTRL_MQ_RSS_CONFIG has the same effect as
+ * VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET does and additionally configures
+ * the receive steering to use a hash calculated for incoming packet
+ * to decide on receive virtqueue to place the packet. The command
+ * also provides parameters to calculate a hash and receive virtqueue.
+ */
+struct virtio_net_rss_config {
+ __le32 hash_types;
+ __le16 indirection_table_mask;
+ __le16 unclassified_queue;
+ __le16 indirection_table[1/* + indirection_table_mask */];
+ __le16 max_tx_vq;
+ __u8 hash_key_length;
+ __u8 hash_key_data[/* hash_key_length */];
+};
+
+ #define VIRTIO_NET_CTRL_MQ_RSS_CONFIG 1
+
+/*
+ * The command VIRTIO_NET_CTRL_MQ_HASH_CONFIG requests the device
+ * to include in the virtio header of the packet the value of the
+ * calculated hash and the report type of hash. It also provides
+ * parameters for hash calculation. The command requires feature
+ * VIRTIO_NET_F_HASH_REPORT to be negotiated to extend the
+ * layout of virtio header as defined in virtio_net_hdr_v1_hash.
+ */
+struct virtio_net_hash_config {
+ __le32 hash_types;
+ /* for compatibility with virtio_net_rss_config */
+ __le16 reserved[4];
+ __u8 hash_key_length;
+ __u8 hash_key_data[/* hash_key_length */];
+};
+
+ #define VIRTIO_NET_CTRL_MQ_HASH_CONFIG 2
+
+/*
+ * Control network offloads
+ *
+ * Reconfigures the network offloads that Guest can handle.
+ *
+ * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit.
+ *
+ * Command data format matches the feature bit mask exactly.
+ *
+ * See VIRTIO_NET_F_GUEST_* for the list of offloads
+ * that can be enabled/disabled.
+ */
+#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5
+#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0
+
+#endif /* _UAPI_LINUX_VIRTIO_NET_H */
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 */
diff --git a/net/dhcp.c b/net/dhcp.c
index e701a5f717..d28c37c693 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -444,6 +444,7 @@ static char *global_dhcp_user_class;
static char *global_dhcp_vendor_id;
static char *global_dhcp_client_uuid;
static char *global_dhcp_client_id;
+static char *global_dhcp_hostname;
static char *global_dhcp_bootfile;
static char *global_dhcp_oftree_file;
static char *global_dhcp_rootpath;
@@ -482,6 +483,12 @@ int dhcp_request(struct eth_device *edev, const struct dhcp_req_param *param,
dhcp_param.client_uuid = global_dhcp_client_uuid;
if (!dhcp_param.client_id)
dhcp_param.client_id = global_dhcp_client_id;
+ if (!dhcp_param.hostname) {
+ if (global_dhcp_hostname && strlen(global_dhcp_hostname))
+ dhcp_param.hostname = global_dhcp_hostname;
+ else
+ dhcp_param.hostname = (char *)barebox_get_hostname();
+ }
if (!dhcp_param.option224)
dhcp_param.option224 = global_dhcp_option224;
if (!dhcp_param.retries)
@@ -633,9 +640,12 @@ static int dhcp_global_init(void)
{
globalvar_add_simple_string("dhcp.bootfile", &global_dhcp_bootfile);
globalvar_add_simple_string("dhcp.rootpath", &global_dhcp_rootpath);
+
+ global_dhcp_vendor_id = strdup("barebox");
globalvar_add_simple_string("dhcp.vendor_id", &global_dhcp_vendor_id);
globalvar_add_simple_string("dhcp.client_uuid", &global_dhcp_client_uuid);
globalvar_add_simple_string("dhcp.client_id", &global_dhcp_client_id);
+ globalvar_add_simple_string("dhcp.hostname", &global_dhcp_hostname);
globalvar_add_simple_string("dhcp.user_class", &global_dhcp_user_class);
globalvar_add_simple_string("dhcp.oftree_file", &global_dhcp_oftree_file);
globalvar_add_simple_string("dhcp.tftp_server_name", &global_dhcp_tftp_server_name);
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,
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 80d76b177c..13b1789c01 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -201,6 +201,7 @@ cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y)
dtc_cpp_flags = -Wp,-MD,$(depfile).pre -nostdinc \
+ -Wp,-MT,$(basename $(notdir $@)).o \
-I$(srctree)/arch/$(SRCARCH)/dts/include \
-I$(srctree)/dts/include \
-I$(srctree)/include \
@@ -335,8 +336,12 @@ cmd_dt_S_dtb = $(srctree)/scripts/gen-dtb-s $(subst -,_,$(*F)) $< $(CONFIG_IMD)
$(obj)/%.dtb.S: $(obj)/%.dtb $(srctree)/scripts/gen-dtb-s FORCE
$(call if_changed,dt_S_dtb)
+dts-frags = $(subst $(quote),,$(CONFIG_EXTERNAL_DTS_FRAGMENTS))
quiet_cmd_dtc = DTC $@
-cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
+# For compatibility between make 4.2 and 4.3
+H := \#
+cmd_dtc = /bin/echo -e '$(H)define $(subst -,_,$(*F))_dts 1\n'$(foreach f,$< $(dts-frags),'$(H)include "$(f)"\n') | \
+ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) - ; \
$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
-i $(srctree)/arch/$(SRCARCH)/dts $(DTC_FLAGS) \
-i $(srctree)/dts/src/$(SRCARCH) \
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"
diff --git a/scripts/socfpga_import_preloader b/scripts/socfpga_import_preloader
index 23e3c380db..2bec9f2d21 100755
--- a/scripts/socfpga_import_preloader
+++ b/scripts/socfpga_import_preloader
@@ -1,16 +1,70 @@
#!/usr/bin/env bash
-if [ "$#" -lt "2" ]
-then
- echo "USAGE: $0 <EMBEDDED_SDK> <ISW_HANDOFF> <BOARD_DIRECTORY>"
- echo "EXAMPLE: $0 ~/altera-embedded-sdk/ ~/cv_soc_devkit_ghrd/hps_isw_handoff/soc_system_hps_0/ arch/arm/boards/altera-socdk"
+usage() {
+ echo "USAGE: $0
+ parameters:
+ -s|--spl-dir <SPL_GENERATED_DIR>
+ -i|--isw-handoff <ISW_HANDOFF>
+ -b|--board <BOARD_DIRECTORY>
+ optional:
+ -e|--embedded-sdk <ALTERA_EMBEDDED_SDK>"
+ echo "EXAMPLE: $0 -i ~/cv_soc_devkit_ghrd/hps_isw_handoff/soc_system_hps_0/ -b arch/arm/boards/altera-socdk -e ~/altera-embedded-sdk/"
exit 1
-fi
+}
+
+die() {
+ printf '%s\n' "$1" >&2
+ exit 1
+}
+
+generate=
+splroot=
+embeddedsw=
+handoff=
+boardroot=
+
+while :; do
+ case $1 in
+ -e|--embedded-sdk)
+ if [ "$2" ]; then
+ generate=1
+ splroot="$(mktemp -d)"
+ embeddedsw=${2}
+ shift
+ else
+ die 'ERROR: "--embedded-sdk" requires a non-empty option argument.'
+ fi
+ ;;
+ -s|--spl-dir)
+ if [ "$2" ]; then
+ splroot="$2"
+ shift
+ else
+ die 'ERROR: "--spl-dir" requires a non-empty option argument.'
+ fi
+ ;;
+ -i|--isw-handoff)
+ if [ "$2" ]; then
+ handoff="$2"
+ shift
+ else
+ die 'ERROR: "--isw-handoff" requires a non-empty option argument.'
+ fi
+ ;;
+ -b|--board)
+ if [ "$2" ]; then
+ boardroot="$2"
+ shift
+ else
+ die 'ERROR: "--board" requires a non-empty option argument.'
+ fi
+ ;;
+ *)
+ break
+ esac
+ shift
+done
-splroot="$(mktemp -d)"
-embeddedsw=$1
-handoff=$2
-boardroot=$3
bareboxsrc=.
cd ${bareboxsrc}
@@ -57,7 +111,17 @@ copy_source() {
sed -i 's/ $//g' $tgt
}
-python2.7 ${embeddedsw}/embedded/ip/altera/preloader/scripts/iswgen.py -i ${handoff} -o ${splroot}/
+generate_spl() {
+ python2.7 ${embeddedsw}/embedded/ip/altera/preloader/scripts/iswgen.py -i ${handoff} -o ${splroot}/
+}
+
+if [ -z $splroot ] || [ -z $boardroot ] || [ -z $handoff ]; then
+ usage
+fi
+
+if [ $generate ]; then
+ generate_spl
+fi
copy_source ${splroot}/iocsr_config_cyclone5.c ${boardroot}/iocsr_config_cyclone5.c
copy_source ${splroot}/pinmux_config_cyclone5.c ${boardroot}/pinmux_config.c
@@ -69,6 +133,8 @@ copy_source ${handoff}/sequencer_auto_ac_init.c ${boardroot}/sequencer_auto_ac_i
copy_source ${handoff}/sequencer_auto_inst_init.c ${boardroot}/sequencer_auto_inst_init.c
copy_source ${handoff}/sequencer_defines.h ${boardroot}/sequencer_defines.h
-rm -r ${splroot}
+if [ $generate ]; then
+ rm -r ${splroot}
+fi
echo "DONE"