summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devel/porting.rst2
-rw-r--r--Documentation/user/booting-linux.rst2
-rw-r--r--Documentation/user/networking.rst10
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/cpu/board-dt-2nd.c2
-rw-r--r--arch/arm/include/asm/debug_ll.h11
-rw-r--r--arch/riscv/Makefile26
-rw-r--r--arch/riscv/boards/riscvemu/overlay-of-sram.dts197
-rw-r--r--common/Kconfig4
-rw-r--r--common/boards/qemu-virt/overlay-of-flash.dts159
-rw-r--r--drivers/dma/map.c26
-rw-r--r--drivers/firmware/Kconfig10
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/qemu_fw_cfg.c307
-rw-r--r--drivers/i2c/i2c.c13
-rw-r--r--drivers/mtd/nand/nand_omap_gpmc.c2
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/e1000/e1000.h2
-rw-r--r--drivers/net/e1000/main.c8
-rw-r--r--drivers/net/ks8851_mll.c2
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/rtl8139.c8
-rw-r--r--drivers/nvme/host/core.c5
-rw-r--r--drivers/spi/atmel-quadspi.c1
-rw-r--r--drivers/spi/atmel_spi.c2
-rw-r--r--drivers/spi/imx_spi.c2
-rw-r--r--drivers/spi/stm32_spi.c2
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/misc/Kconfig10
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/onboard_usb_hub.c86
-rw-r--r--drivers/usb/misc/onboard_usb_hub.h36
-rw-r--r--drivers/usb/musb/musb_core.h1
-rw-r--r--drivers/video/Kconfig6
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/ramfb.c191
-rw-r--r--fs/cramfs/cramfs.c2
-rw-r--r--fs/devfs-core.c20
-rw-r--r--fs/fs.c4
-rw-r--r--fs/nfs.c6
-rw-r--r--include/asm-generic/io.h3
-rw-r--r--include/driver.h1
-rw-r--r--include/filetype.h1
-rw-r--r--include/linux/mfd/core.h2
-rw-r--r--include/linux/stat.h3
-rw-r--r--include/of_gpio.h17
-rw-r--r--include/platform_data/eth-smc911x.h2
-rw-r--r--include/platform_data/serial-ns16550.h2
-rw-r--r--include/uapi/linux/qemu_fw_cfg.h100
-rw-r--r--include/usb/usb.h8
50 files changed, 1061 insertions, 252 deletions
diff --git a/Documentation/devel/porting.rst b/Documentation/devel/porting.rst
index 8af0456ab2..619c5e49e0 100644
--- a/Documentation/devel/porting.rst
+++ b/Documentation/devel/porting.rst
@@ -258,7 +258,7 @@ tree binding, you can write a driver that matches against your board's
{ /* sentinel */ },
};
- static struct driver_d my_board_driver = {
+ static struct driver my_board_driver = {
.name = "board-mine",
.probe = my_board_probe,
.of_compatible = my_board_of_match,
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index 60babb513c..1a95f87e77 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -232,6 +232,8 @@ device where the entry is found on. This makes it possible to use the same rootf
image on different devices without having to specify a different root= option each
time.
+.. _booting_linux_net:
+
Network boot
------------
diff --git a/Documentation/user/networking.rst b/Documentation/user/networking.rst
index 9231ebde56..2306cb6a60 100644
--- a/Documentation/user/networking.rst
+++ b/Documentation/user/networking.rst
@@ -45,15 +45,17 @@ device:
| | | any directly visible subnet. May be set |
| | | automatically by DHCP. |
+------------------------------+--------------+------------------------------------------------+
-| global.net.server | hostname or | The default server. If unspecified, may be set |
-| | ipv4 address | by DHCP |
+| global.net.server | hostname or | The default server used by the defaultenv boot |
+| | ipv4 address | scripts for NFS and TFTP; see |
+| | | :ref:`booting_linux_net`. |
+| | | If unspecified, may be set by DHCP. |
+------------------------------+--------------+------------------------------------------------+
| global.net.nameserver | ipv4 address | The DNS server used for resolving host names. |
-| | | May be set by DHCP |
+| | | May be set by DHCP. |
+------------------------------+--------------+------------------------------------------------+
| global.net.ifup_force_detect | boolean | Set to true if your network device is not |
| | | detected automatically during start (i.e. for |
-| | | USB network adapters) |
+| | | USB network adapters). |
+------------------------------+--------------+------------------------------------------------+
The first step for networking is configuring the network device. The network
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 759b29ee77..8183f6d546 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -292,6 +292,7 @@ config ARCH_ARM64_VIRT
select ARM_AMBA
select BOARD_ARM_VIRT
select HW_HAS_PCI
+ select HAS_ASM_DEBUG_LL
endchoice
diff --git a/arch/arm/cpu/board-dt-2nd.c b/arch/arm/cpu/board-dt-2nd.c
index 6f4a6f26a8..6f69a6dd27 100644
--- a/arch/arm/cpu/board-dt-2nd.c
+++ b/arch/arm/cpu/board-dt-2nd.c
@@ -19,6 +19,8 @@ void dt_2nd_aarch64(void *fdt)
{
unsigned long membase, memsize;
+ putc_ll('>');
+
/* entry point already set up stack */
arm_cpu_lowlevel_init();
diff --git a/arch/arm/include/asm/debug_ll.h b/arch/arm/include/asm/debug_ll.h
new file mode 100644
index 0000000000..d7b25a7fca
--- /dev/null
+++ b/arch/arm/include/asm/debug_ll.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_DEBUG_LL_H__
+#define __ASM_DEBUG_LL_H__
+
+#ifdef CONFIG_DEBUG_QEMU_ARM64_VIRT
+#define DEBUG_LL_UART_ADDR 0x9000000
+#include <debug_ll/pl011.h>
+#endif
+
+#endif
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 279db046c0..1371f17e7c 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -5,21 +5,27 @@ KBUILD_DEFCONFIG := rv64i_defconfig
KBUILD_CPPFLAGS += -fno-strict-aliasing
ifeq ($(CONFIG_ARCH_RV32I),y)
- riscv-cflags-y += -march=rv32im -mabi=ilp32
+ KBUILD_CPPFLAGS += -mabi=ilp32
riscv-ldflags-y += -melf32lriscv
else
- riscv-cflags-y += -march=rv64im -mabi=lp64
+ KBUILD_CPPFLAGS += -mabi=lp64
riscv-ldflags-y += -melf64lriscv
endif
-riscv-cflags-y += -Wstrict-prototypes -mcmodel=medany -fpic
-riscv-ldflags-y += -pie -static
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I) := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I) := rv64im
-PBL_CPPFLAGS += $(riscv-cflags-y)
-LDFLAGS_pbl += $(riscv-ldflags-y)
+# Newer binutils versions default to ISA spec version 20191213 which moves some
+# instructions from the I extension to the Zicsr and Zifencei extensions.
+toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
+riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
-cflags-y += $(riscv-cflags-y)
+KBUILD_CPPFLAGS += -march=$(riscv-march-y)
+KBUILD_CPPFLAGS += -Wstrict-prototypes -mcmodel=medany -fpic
+riscv-ldflags-y += -pie -static
+LDFLAGS_pbl += $(riscv-ldflags-y)
LDFLAGS_barebox += $(riscv-ldflags-y)
ifndef CONFIG_MODULES
@@ -29,6 +35,7 @@ LDFLAGS_barebox += -static --gc-sections
endif
KBUILD_BINARY := barebox.bin
+KBUILD_IMAGE := $(KBUILD_BINARY)
archprepare: maketools
@@ -41,11 +48,6 @@ common-y += arch/riscv/boot/
common-$(CONFIG_OFTREE) += arch/riscv/dts/
-KBUILD_CPPFLAGS += $(cflags-y)
-KBUILD_CFLAGS += $(cflags-y)
-
lds-y := arch/riscv/lib/barebox.lds
CLEAN_FILES += arch/riscv/lib/barebox.lds
-
-KBUILD_IMAGE := $(KBUILD_BINARY)
diff --git a/arch/riscv/boards/riscvemu/overlay-of-sram.dts b/arch/riscv/boards/riscvemu/overlay-of-sram.dts
index 506d45bde9..395fde84c1 100644
--- a/arch/riscv/boards/riscvemu/overlay-of-sram.dts
+++ b/arch/riscv/boards/riscvemu/overlay-of-sram.dts
@@ -3,127 +3,110 @@
/dts-v1/;
/plugin/;
-/ {
- fragment@0 {
- target-path = "/soc";
- __overlay__ {
- #address-cells = <2>;
- #size-cells = <2>;
- sram@0 {
- compatible = "mtd-ram";
- reg = <0 0x1000 0 0x10000>;
- #address-cells = <1>;
- #size-cells = <1>;
+&{/soc} {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ sram@1000 {
+ compatible = "mtd-ram";
+ reg = <0 0x1000 0 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bootrom";
+ reg = <0x0 0x40>;
+ };
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "bootrom";
- reg = <0x0 0x40>;
- };
-
- partition@40 {
- label = "fdt";
- reg = <0x40 0x1fc0>;
- };
-
- environment_sram: partition@3000 {
- label = "barebox-environment";
- reg = <0x3000 0xb000>;
- };
-
- backend_state_sram: partition@e000 {
- label = "barebox-state";
- reg = <0xe000 0x1000>;
- };
- };
+ partition@40 {
+ label = "fdt";
+ reg = <0x40 0x1fc0>;
+ };
+
+ environment_sram: partition@3000 {
+ label = "barebox-environment";
+ reg = <0x3000 0xb000>;
};
- };
- };
- fragment@2 {
- target-path = "/chosen";
- __overlay__ {
- environment {
- compatible = "barebox,environment";
- device-path = "/soc/sram@0/partitions/partition@3000";
+ backend_state_sram: partition@e000 {
+ label = "barebox-state";
+ reg = <0xe000 0x1000>;
};
};
};
+};
- fragment@3 {
- target-path = "/";
- __overlay__ {
- aliases {
- state = "/state";
- };
+&{/chosen} {
+ environment {
+ compatible = "barebox,environment";
+ device-path = "/soc/sram@1000/partitions/partition@3000";
+ };
+};
+
+&{/} {
+ aliases {
+ state = "/state";
+ };
+
+ state {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "barebox,state";
+ magic = <0x290cf8c6>;
+ backend-type = "raw";
+ backend = <&backend_state_sram>;
+ backend-stridesize = <64>;
+
+ bootstate {
+ #address-cells = <1>;
+ #size-cells = <1>;
- state {
+ system0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "barebox,state";
- magic = <0x290cf8c6>;
- backend-type = "raw";
- backend = <&backend_state_sram>;
- backend-stridesize = <64>;
-
- bootstate {
- #address-cells = <1>;
- #size-cells = <1>;
-
- system0 {
- #address-cells = <1>;
- #size-cells = <1>;
-
- remaining_attempts@0 {
- reg = <0x0 0x4>;
- type = "uint32";
- default = <3>;
- };
-
- priority@4 {
- reg = <0x4 0x4>;
- type = "uint32";
- default = <20>;
- };
- };
-
- system1 {
- #address-cells = <1>;
- #size-cells = <1>;
-
- remaining_attempts@8 {
- reg = <0x8 0x4>;
- type = "uint32";
- default = <3>;
- };
-
- priority@c {
- reg = <0xc 0x4>;
- type = "uint32";
- default = <21>;
- };
- };
-
- last_chosen@10 {
- reg = <0x10 0x4>;
- type = "uint32";
- };
+
+ remaining_attempts@0 {
+ reg = <0x0 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+
+ priority@4 {
+ reg = <0x4 0x4>;
+ type = "uint32";
+ default = <20>;
};
};
- };
- };
- fragment@4 {
- target-path = "/htif";
- #address-cells = <2>;
- #size-cells = <2>;
+ system1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
- __overlay__ {
- reg = <0 0x40008000 0 0x8>;
+ remaining_attempts@8 {
+ reg = <0x8 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+
+ priority@c {
+ reg = <0xc 0x4>;
+ type = "uint32";
+ default = <21>;
+ };
+ };
+
+ last_chosen@10 {
+ reg = <0x10 0x4>;
+ type = "uint32";
+ };
};
};
};
+
+&{/htif} {
+ reg = <0 0x40008000 0 0x8>;
+};
diff --git a/common/Kconfig b/common/Kconfig
index 9e175d36c4..d957970993 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1479,6 +1479,10 @@ config DEBUG_SUN20I
depends on SOC_ALLWINNER_SUN20I
select DEBUG_LL_NS16550
+config DEBUG_QEMU_ARM64_VIRT
+ bool "QEMU ARM64 Virt PL011 console"
+ depends on ARCH_ARM64_VIRT
+
endchoice
config DEBUG_LL_NS16550
diff --git a/common/boards/qemu-virt/overlay-of-flash.dts b/common/boards/qemu-virt/overlay-of-flash.dts
index 3f2beaac37..15c8cc450d 100644
--- a/common/boards/qemu-virt/overlay-of-flash.dts
+++ b/common/boards/qemu-virt/overlay-of-flash.dts
@@ -4,110 +4,99 @@
/plugin/;
#ifdef RISCV_VIRT
-#define PARTS_TARGET_PATH "/flash@20000000"
+#define PARTS_TARGET_PATH /flash@20000000
#define ENV_DEVICE_PATH "/flash@20000000/partitions/partition@3c00000"
#else
-#define PARTS_TARGET_PATH "/flash@0"
+#define PARTS_TARGET_PATH /flash@0
#define ENV_DEVICE_PATH "/flash@0/partitions/partition@3c00000"
#endif
-/ {
- fragment@0 {
- target-path = PARTS_TARGET_PATH;
- __overlay__ {
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
+&{PARTS_TARGET_PATH} {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
- partition@0 {
- label = "initramfs";
- reg = <0x0 0x3c00000>;
- };
+ partition@0 {
+ label = "initramfs";
+ reg = <0x0 0x3c00000>;
+ };
- environment_flash: partition@3c00000 {
- label = "barebox-environment";
- reg = <0x3c00000 0x200000>;
- };
+ environment_flash: partition@3c00000 {
+ label = "barebox-environment";
+ reg = <0x3c00000 0x200000>;
+ };
- backend_state_flash: partition@3e00000 {
- label = "barebox-state";
- reg = <0x3e00000 0x200000>;
- };
- };
+ backend_state_flash: partition@3e00000 {
+ label = "barebox-state";
+ reg = <0x3e00000 0x200000>;
};
};
+};
- fragment@1 {
- target-path = "/chosen";
- __overlay__ {
- environment {
- compatible = "barebox,environment";
- device-path = ENV_DEVICE_PATH;
- };
- };
+&{/chosen} {
+ environment {
+ compatible = "barebox,environment";
+ device-path = ENV_DEVICE_PATH;
+ };
+};
+
+&{/} {
+ aliases {
+ state = "/state";
};
- fragment@2 {
- target-path = "/";
- __overlay__ {
- aliases {
- state = "/state";
+ state {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "barebox,state";
+ magic = <0x290cf8c6>;
+ backend-type = "raw";
+ backend = < &backend_state_flash >;
+ backend-stridesize = <0x200>;
+
+ bootstate {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ system0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ remaining_attempts@0 {
+ reg = <0x0 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+
+ priority@4 {
+ reg = <0x4 0x4>;
+ type = "uint32";
+ default = <20>;
+ };
};
- state {
+ system1 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "barebox,state";
- magic = <0x290cf8c6>;
- backend-type = "raw";
- backend = < &backend_state_flash >;
- backend-stridesize = <0x200>;
-
- bootstate {
- #address-cells = <1>;
- #size-cells = <1>;
-
- system0 {
- #address-cells = <1>;
- #size-cells = <1>;
-
- remaining_attempts@0 {
- reg = <0x0 0x4>;
- type = "uint32";
- default = <3>;
- };
-
- priority@4 {
- reg = <0x4 0x4>;
- type = "uint32";
- default = <20>;
- };
- };
-
- system1 {
- #address-cells = <1>;
- #size-cells = <1>;
-
- remaining_attempts@8 {
- reg = <0x8 0x4>;
- type = "uint32";
- default = <3>;
- };
-
- priority@c {
- reg = <0xc 0x4>;
- type = "uint32";
- default = <21>;
- };
- };
-
- last_chosen@10 {
- reg = <0x10 0x4>;
- type = "uint32";
- };
+
+ remaining_attempts@8 {
+ reg = <0x8 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+
+ priority@c {
+ reg = <0xc 0x4>;
+ type = "uint32";
+ default = <21>;
};
};
+
+ last_chosen@10 {
+ reg = <0x10 0x4>;
+ type = "uint32";
+ };
};
};
};
diff --git a/drivers/dma/map.c b/drivers/dma/map.c
index a00abf6421..114c0f7db3 100644
--- a/drivers/dma/map.c
+++ b/drivers/dma/map.c
@@ -2,26 +2,22 @@
/* SPDX-FileCopyrightText: 2012 Marc Kleine-Budde <mkl@pengutronix.de> */
#include <dma.h>
+#include <asm/io.h>
-static inline dma_addr_t cpu_to_dma(struct device *dev,
- unsigned long cpu_addr)
+static inline dma_addr_t cpu_to_dma(struct device *dev, void *cpu_addr)
{
- dma_addr_t dma_addr = cpu_addr;
+ if (dev && dev->dma_offset)
+ return (unsigned long)cpu_addr - dev->dma_offset;
- if (dev)
- dma_addr -= dev->dma_offset;
-
- return dma_addr;
+ return virt_to_phys(cpu_addr);
}
-static inline unsigned long dma_to_cpu(struct device *dev, dma_addr_t addr)
+static inline void *dma_to_cpu(struct device *dev, dma_addr_t addr)
{
- unsigned long cpu_addr = addr;
-
- if (dev)
- cpu_addr += dev->dma_offset;
+ if (dev && dev->dma_offset)
+ return (void *)(addr + dev->dma_offset);
- return cpu_addr;
+ return phys_to_virt(addr);
}
dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
@@ -31,13 +27,13 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
dma_sync_single_for_device(addr, size, dir);
- return cpu_to_dma(dev, addr);
+ return cpu_to_dma(dev, ptr);
}
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
- unsigned long addr = dma_to_cpu(dev, dma_addr);
+ unsigned long addr = (unsigned long)dma_to_cpu(dev, dma_addr);
dma_sync_single_for_cpu(addr, size, dir);
}
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index d3cca41a7e..a6c564320e 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -32,4 +32,14 @@ config ARM_SCMI_PROTOCOL
set of operating system-independent software interfaces that are
used in system management.
+config QEMU_FW_CFG
+ bool "QEMU FW CFG interface"
+ help
+ This driver exposes the QEMU FW CFG conduit as a single
+ character device.
+
+ The selector key can be set via ioctl or device parameter
+ and read/writes are translated to the MMIO/IO port appropriate
+ for the platform.
+
endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 26d6f3275a..90f5113f53 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -2,4 +2,5 @@
obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o
obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o socfpga_sdr.o
obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o
+obj-$(CONFIG_QEMU_FW_CFG) += qemu_fw_cfg.o
obj-y += arm_scmi/
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
new file mode 100644
index 0000000000..3fad90bbde
--- /dev/null
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * qemu_fw_cfg.c - QEMU FW CFG character device
+ *
+ * Copyright (C) 2022 Adrian Negreanu
+ * Copyright (C) 2022 Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <fcntl.h>
+#include <dma.h>
+#include <linux/err.h>
+#include <linux/bitfield.h>
+#include <linux/qemu_fw_cfg.h>
+#include <asm/unaligned.h>
+#include <io-64-nonatomic-lo-hi.h>
+
+/* arch-specific ctrl & data register offsets are not available in ACPI, DT */
+#ifdef CONFIG_X86
+# define FW_CFG_CTRL_OFF 0x00
+# define FW_CFG_DATA_OFF 0x01
+# define FW_CFG_DMA_OFF 0x04
+#else
+# define FW_CFG_CTRL_OFF 0x08
+# define FW_CFG_DATA_OFF 0x00
+# define FW_CFG_DMA_OFF 0x10
+#endif
+
+/* fw_cfg DMA commands */
+#define FW_CFG_DMA_CTL_ERROR 0x01
+#define FW_CFG_DMA_CTL_READ 0x02
+#define FW_CFG_DMA_CTL_SKIP 0x04
+#define FW_CFG_DMA_CTL_SELECT 0x08
+#define FW_CFG_DMA_CTL_WRITE 0x10
+
+struct fw_cfg_dma {
+ __be32 control;
+ __be32 length;
+ __be64 address;
+} __packed;
+
+/* fw_cfg device i/o register addresses */
+struct fw_cfg {
+ struct resource *iores;
+ void __iomem *reg_ctrl;
+ void __iomem *reg_data;
+ void __iomem *reg_dma;
+ struct cdev cdev;
+ loff_t next_read_offset;
+ u32 sel;
+ bool is_mmio;
+ struct fw_cfg_dma __iomem *acc_virt;
+ dma_addr_t acc_dma;
+};
+
+static struct fw_cfg *to_fw_cfg(struct cdev *cdev)
+{
+ return container_of(cdev, struct fw_cfg, cdev);
+}
+
+/* pick appropriate endianness for selector key */
+static void fw_cfg_select(struct fw_cfg *fw_cfg)
+{
+ if (fw_cfg->is_mmio)
+ iowrite16be(fw_cfg->sel, fw_cfg->reg_ctrl);
+ else
+ iowrite16(fw_cfg->sel, fw_cfg->reg_ctrl);
+}
+
+/* clean up fw_cfg device i/o */
+static void fw_cfg_io_cleanup(struct fw_cfg *fw_cfg)
+{
+ release_region(fw_cfg->iores);
+}
+
+static int fw_cfg_ioctl(struct cdev *cdev, int request, void *buf)
+{
+ struct fw_cfg *fw_cfg = to_fw_cfg(cdev);
+ int ret = 0;
+
+ switch (request) {
+ case FW_CFG_SELECT:
+ fw_cfg->sel = *(u16 *)buf;
+ break;
+ default:
+ ret = -ENOTTY;
+ }
+
+ return 0;
+}
+
+#define __raw_readu64 __raw_readq
+#define __raw_readu32 __raw_readl
+#define __raw_readu16 __raw_readw
+#define __raw_readu8 __raw_readb
+
+#define fw_cfg_data_read_sized(fw_cfg, remaining, address, type) do { \
+ while (*remaining >= sizeof(type)) { \
+ val = __raw_read##type((fw_cfg)->reg_data); \
+ *remaining -= sizeof(type); \
+ if (*address) { \
+ put_unaligned(val, (type *)*address); \
+ *address += sizeof(type); \
+ } \
+ } \
+} while(0)
+
+static void fw_cfg_data_read(struct fw_cfg *fw_cfg, void *address, size_t remaining,
+ unsigned rdsize)
+{
+
+ u64 val;
+
+ if (fw_cfg->is_mmio) {
+ /*
+ * This is just a preference. If we can't honour it, we
+ * fall back to byte-sized copy
+ */
+ switch(rdsize) {
+ case 8:
+#ifdef CONFIG_64BIT
+ fw_cfg_data_read_sized(fw_cfg, &remaining, &address, u64);
+ break;
+#endif
+ case 4:
+ fw_cfg_data_read_sized(fw_cfg, &remaining, &address, u32);
+ break;
+ case 2:
+ fw_cfg_data_read_sized(fw_cfg, &remaining, &address, u16);
+ break;
+ }
+ }
+
+ fw_cfg_data_read_sized(fw_cfg, &remaining, &address, u8);
+}
+
+static ssize_t fw_cfg_read(struct cdev *cdev, void *buf, size_t count,
+ loff_t pos, unsigned long flags)
+{
+ struct fw_cfg *fw_cfg = to_fw_cfg(cdev);
+ unsigned rdsize = FIELD_GET(O_RWSIZE_MASK, flags);
+
+ if (!pos || pos != fw_cfg->next_read_offset) {
+ fw_cfg_select(fw_cfg);
+ fw_cfg->next_read_offset = 0;
+ }
+
+ if (!rdsize) {
+ if (pos % 8 == 0)
+ rdsize = 8;
+ else if (pos % 4 == 0)
+ rdsize = 4;
+ else if (pos % 2 == 0)
+ rdsize = 2;
+ else
+ rdsize = 1;
+ }
+
+ while (pos-- > fw_cfg->next_read_offset)
+ fw_cfg_data_read(fw_cfg, NULL, count, rdsize);
+
+ fw_cfg_data_read(fw_cfg, buf, count, rdsize);
+
+ fw_cfg->next_read_offset += count;
+ return count;
+}
+
+static ssize_t fw_cfg_write(struct cdev *cdev, const void *buf, size_t count,
+ loff_t pos, unsigned long flags)
+{
+ struct fw_cfg *fw_cfg = to_fw_cfg(cdev);
+ struct device_d *dev = cdev->dev;
+ struct fw_cfg_dma __iomem *acc = fw_cfg->acc_virt;
+ dma_addr_t mapping;
+
+ if (pos != 0)
+ return -EINVAL;
+
+ mapping = dma_map_single(dev, (void *)buf, count, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, mapping))
+ return -EFAULT;
+
+ fw_cfg->next_read_offset = 0;
+
+ acc->address = cpu_to_be64(mapping);
+ acc->length = cpu_to_be32(count);
+ acc->control = cpu_to_be32(FW_CFG_DMA_CTL_WRITE |
+ FW_CFG_DMA_CTL_SELECT | fw_cfg->sel << 16);
+
+ iowrite64be(fw_cfg->acc_dma, fw_cfg->reg_dma);
+
+ while (ioread32be(&acc->control) & ~FW_CFG_DMA_CTL_ERROR)
+ ;
+
+ dma_unmap_single(dev, mapping, count, DMA_FROM_DEVICE);
+
+ return count;
+}
+
+static struct cdev_operations fw_cfg_ops = {
+ .read = fw_cfg_read,
+ .write = fw_cfg_write,
+ .ioctl = fw_cfg_ioctl,
+};
+
+static int fw_cfg_param_select(struct param_d *p, void *priv)
+{
+ struct fw_cfg *fw_cfg = priv;
+
+ return fw_cfg->sel <= U16_MAX ? 0 : -EINVAL;
+}
+
+static int fw_cfg_probe(struct device_d *dev)
+{
+ struct device_node *np = dev_of_node(dev);
+ struct resource *parent_res, *iores;
+ char sig[FW_CFG_SIG_SIZE];
+ struct fw_cfg *fw_cfg;
+ int ret;
+
+ fw_cfg = xzalloc(sizeof(*fw_cfg));
+
+ /* acquire i/o range details */
+ fw_cfg->is_mmio = false;
+ iores = dev_get_resource(dev, IORESOURCE_IO, 0);
+ if (IS_ERR(iores)) {
+ fw_cfg->is_mmio = true;
+ iores = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (IS_ERR(iores))
+ return -EINVAL;
+ }
+
+ parent_res = fw_cfg->is_mmio ? &iomem_resource : &ioport_resource;
+ iores = __request_region(parent_res, iores->start, iores->end, dev_name(dev), 0);
+ if (IS_ERR(iores))
+ return -EBUSY;
+
+ /* use architecture-specific offsets */
+ fw_cfg->reg_ctrl = IOMEM(iores->start + FW_CFG_CTRL_OFF);
+ fw_cfg->reg_data = IOMEM(iores->start + FW_CFG_DATA_OFF);
+ fw_cfg->reg_dma = IOMEM(iores->start + FW_CFG_DMA_OFF);
+
+ fw_cfg->iores = iores;
+
+ /* verify fw_cfg device signature */
+ fw_cfg->sel = FW_CFG_SIGNATURE;
+ fw_cfg_read(&fw_cfg->cdev, sig, FW_CFG_SIG_SIZE, 0, 0);
+
+ if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
+ ret = np ? -EILSEQ : -ENODEV;
+ goto err;
+ }
+
+ fw_cfg->acc_virt = dma_alloc_coherent(sizeof(*fw_cfg->acc_virt), &fw_cfg->acc_dma);
+
+ fw_cfg->cdev.name = basprintf("fw_cfg%d", cdev_find_free_index("fw_cfg"));
+ fw_cfg->cdev.flags = DEVFS_IS_CHARACTER_DEV;
+ fw_cfg->cdev.size = 0;
+ fw_cfg->cdev.ops = &fw_cfg_ops;
+ fw_cfg->cdev.dev = dev;
+ fw_cfg->cdev.filetype = filetype_qemu_fw_cfg;
+
+ dev_set_name(dev, fw_cfg->cdev.name);
+
+ ret = devfs_create(&fw_cfg->cdev);
+ if (ret) {
+ dev_err(dev, "Failed to create corresponding cdev\n");
+ goto err;
+ }
+
+ cdev_create_default_automount(&fw_cfg->cdev);
+
+ dev_add_param_uint32(dev, "selector", fw_cfg_param_select,
+ NULL, &fw_cfg->sel, "%u", fw_cfg);
+
+ dev->priv = fw_cfg;
+
+ return 0;
+err:
+ fw_cfg_io_cleanup(fw_cfg);
+ return ret;
+}
+
+static const struct of_device_id qemu_fw_cfg_of_match[] = {
+ { .compatible = "qemu,fw-cfg-mmio", },
+ { /* sentinel */ },
+};
+
+static struct driver_d qemu_fw_cfg_drv = {
+ .name = "fw_cfg",
+ .probe = fw_cfg_probe,
+ .of_compatible = of_match_ptr(qemu_fw_cfg_of_match),
+};
+
+static int qemu_fw_cfg_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&qemu_fw_cfg_drv);
+ if (ret)
+ return ret;
+
+ return of_devices_ensure_probed_by_dev_id(qemu_fw_cfg_of_match);
+}
+postmmu_initcall(qemu_fw_cfg_init);
diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index f3efb62087..efcad29342 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -473,6 +473,14 @@ int of_i2c_register_devices_by_node(struct device_node *node)
static int i2c_bus_detect(struct device *dev)
{
+ struct i2c_adapter *adap = container_of(dev, struct i2c_adapter, dev);
+
+ of_i2c_register_devices(adap);
+ return 0;
+}
+
+static int i2c_hw_detect(struct device *dev)
+{
struct i2c_adapter *adap;
list_for_each_entry(adap, &i2c_adapter_list, list) {
@@ -712,6 +720,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter)
}
adapter->dev.id = adapter->nr;
+ adapter->dev.detect = i2c_bus_detect;
dev_set_name(&adapter->dev, "i2c");
ret = register_device(&adapter->dev);
@@ -726,8 +735,8 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter)
hw_dev = adapter->dev.parent;
if (hw_dev && dev_of_node(hw_dev)) {
if (!hw_dev->detect)
- hw_dev->detect = i2c_bus_detect;
- i2c_bus_detect(hw_dev);
+ hw_dev->detect = i2c_hw_detect;
+ i2c_hw_detect(hw_dev);
}
return 0;
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index e8e6903111..c7252ce72a 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -12,7 +12,7 @@
* A typical device registration is as follows:
*
* @code
- * static struct device_d my_nand_device = {
+ * static struct device my_nand_device = {
* .name = "gpmc_nand",
* .id = some identifier you need to show.. e.g. "gpmc_nand0"
* .resource[0].start = GPMC base address
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d0fabc4247..a9fc073d57 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -240,7 +240,6 @@ config DRIVER_NET_ORION
config DRIVER_NET_RTL8139
bool "RealTek RTL-8139 PCI Ethernet driver"
depends on PCI
- depends on MIPS
select PHYLIB
help
This is a driver for the Fast Ethernet PCI network cards based on
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 558a4ac271..d440d7540a 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -2183,7 +2183,9 @@ struct e1000_hw {
struct mii_bus miibus;
struct e1000_tx_desc *tx_base;
+ dma_addr_t tx_base_phys;
struct e1000_rx_desc *rx_base;
+ dma_addr_t rx_base_phys;
unsigned char *packet;
dma_addr_t packet_dma;
diff --git a/drivers/net/e1000/main.c b/drivers/net/e1000/main.c
index e00bc48417..c259d72f27 100644
--- a/drivers/net/e1000/main.c
+++ b/drivers/net/e1000/main.c
@@ -3267,7 +3267,7 @@ static void e1000_configure_tx(struct e1000_hw *hw)
unsigned long tctl;
unsigned long tipg, tarc;
uint32_t ipgr1, ipgr2;
- const unsigned long tx_base = (unsigned long)hw->tx_base;
+ const unsigned long tx_base = (unsigned long)hw->tx_base_phys;
e1000_write_reg(hw, E1000_TDBAL, lower_32_bits(tx_base));
e1000_write_reg(hw, E1000_TDBAH, upper_32_bits(tx_base));
@@ -3386,7 +3386,7 @@ static void e1000_setup_rctl(struct e1000_hw *hw)
static void e1000_configure_rx(struct e1000_hw *hw)
{
unsigned long rctl, ctrl_ext;
- const unsigned long rx_base = (unsigned long)hw->rx_base;
+ const unsigned long rx_base = (unsigned long)hw->rx_base_phys;
hw->rx_tail = 0;
/* make sure receives are disabled while setting up the descriptors */
@@ -3595,8 +3595,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hw = xzalloc(sizeof(*hw));
- hw->tx_base = dma_alloc_coherent(16 * sizeof(*hw->tx_base), DMA_ADDRESS_BROKEN);
- hw->rx_base = dma_alloc_coherent(16 * sizeof(*hw->rx_base), DMA_ADDRESS_BROKEN);
+ hw->tx_base = dma_alloc_coherent(16 * sizeof(*hw->tx_base), &hw->tx_base_phys);
+ hw->rx_base = dma_alloc_coherent(16 * sizeof(*hw->rx_base), &hw->rx_base_phys);
edev = &hw->edev;
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 972a127655..2120657bd9 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -353,7 +353,6 @@
* struct ks_net - KS8851 driver private data
* @hw_addr : start address of data register.
* @hw_addr_cmd : start address of command register.
- * @pdev : Pointer to platform device.
* @bus_width : i/o bus width.
* @extra_byte : number of extra byte prepended rx pkt.
*
@@ -364,7 +363,6 @@ struct ks_net {
struct mii_bus miibus;
void __iomem *hw_addr;
void __iomem *hw_addr_cmd;
- struct platform_device *pdev;
int bus_width;
void *rx_buf;
};
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2c3a96bfc5..54dbbca725 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -20,8 +20,6 @@
#include <linux/phy.h>
#include <linux/err.h>
-#define PHY_AN_TIMEOUT 10
-
static struct phy_driver genphy_driver;
/**
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
index 617a60bfcb..5c91c10fea 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8139.c
@@ -373,7 +373,6 @@ static int rtl8139_init_dev(struct eth_device *edev)
struct rtl8139_priv *priv = edev->priv;
rtl8139_chip_reset(priv);
- pci_set_master(priv->pci_dev);
return 0;
}
@@ -390,6 +389,8 @@ static int rtl8139_eth_open(struct eth_device *edev)
rtl8139_init_ring(priv);
rtl8139_hw_start(priv);
+ pci_set_master(priv->pci_dev);
+
ret = phy_device_connect(edev, &priv->miibus, 0, NULL, 0,
PHY_INTERFACE_MODE_NA);
@@ -408,6 +409,11 @@ static void rtl8139_eth_halt(struct eth_device *edev)
pci_clear_master(priv->pci_dev);
+ dma_free_coherent((void *)priv->tx_bufs, priv->tx_bufs_dma,
+ TX_BUF_TOT_LEN);
+ dma_free_coherent((void *)priv->rx_ring, priv->rx_ring_dma,
+ RX_BUF_TOT_LEN);
+
/* Green! Put the chip in low-power mode. */
RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
}
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 79a5f9325e..bf9176ce09 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <common.h>
+#include <disks.h>
#include "nvme.h"
@@ -372,6 +373,10 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
goto out_free_id;
}
+ ret = parse_partition_table(&ns->blk);
+ if (ret)
+ dev_warn(ctrl->dev, "No partition table found\n");
+
return;
out_free_id:
kfree(id);
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 189aab705d..e579fcaed6 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -157,7 +157,6 @@ struct atmel_qspi {
void __iomem *mem;
struct clk *pclk;
struct clk *qspick;
- struct platform_device *pdev;
const struct atmel_qspi_caps *caps;
u32 mr;
};
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 399c47c81d..9bf85874c5 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -408,7 +408,7 @@ static int atmel_spi_probe(struct device *dev)
master->num_chipselect = pdata->num_chipselect;
as->cs_pins = pdata->chipselect;
} else {
- master->num_chipselect = of_gpio_named_count(node, "cs-gpios");
+ master->num_chipselect = of_gpio_count_csgpios(node);
as->cs_pins = xzalloc(sizeof(u32) * master->num_chipselect);
for (i = 0; i < master->num_chipselect; i++) {
diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c
index eb30d757d5..f81d9e851f 100644
--- a/drivers/spi/imx_spi.c
+++ b/drivers/spi/imx_spi.c
@@ -568,7 +568,7 @@ static int imx_spi_dt_probe(struct imx_spi *imx)
if (!node)
return -ENODEV;
- imx->master.num_chipselect = of_gpio_named_count(node, "cs-gpios");
+ imx->master.num_chipselect = of_gpio_count_csgpios(node);
imx->cs_array = xzalloc(sizeof(u32) * imx->master.num_chipselect);
for (i = 0; i < imx->master.num_chipselect; i++)
diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c
index 821a95980f..0d7407c279 100644
--- a/drivers/spi/stm32_spi.c
+++ b/drivers/spi/stm32_spi.c
@@ -514,7 +514,7 @@ static void stm32_spi_dt_probe(struct stm32_spi_priv *priv)
struct device_node *node = priv->master.dev->of_node;
int i;
- priv->master.num_chipselect = of_gpio_named_count(node, "cs-gpios");
+ priv->master.num_chipselect = of_gpio_count_csgpios(node);
priv->cs_gpios = xzalloc(sizeof(u32) * priv->master.num_chipselect);
for (i = 0; i < priv->master.num_chipselect; i++)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 7c589ec06f..a974614c06 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -576,6 +576,8 @@ int usb_host_detect(struct usb_host *host)
{
int ret;
+ of_usb_host_probe_hubs(host);
+
if (!host->root_dev) {
if (host->init) {
ret = host->init(host);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 9799af4725..fde57fd743 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -14,3 +14,13 @@ config USB_HUB_USB251XB
Microchip USB251x/xBi USB 2.0 Hub Controller series. Configuration
parameters may be set in devicetree or platform data.
Say Y or M here if you need to configure such a device via SMBus.
+
+config USB_ONBOARD_HUB
+ bool "Onboard USB hub support"
+ depends on OFDEVICE || COMPILE_TEST
+ help
+ Say Y here if you want to support discrete onboard USB hubs that
+ don't require an additional control bus for initialization, but
+ need some non-trivial form of initialization, such as enabling a
+ power regulator. An example for such a hub is the Realtek
+ RTS5411.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index be5c044f5a..e00f66a5ed 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -4,3 +4,4 @@
# (the ones that don't fit into any other categories)
#
obj-$(CONFIG_USB_HUB_USB251XB) += usb251xb.o
+obj-$(CONFIG_USB_ONBOARD_HUB) += onboard_usb_hub.o
diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c
new file mode 100644
index 0000000000..0b847f06ad
--- /dev/null
+++ b/drivers/usb/misc/onboard_usb_hub.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for onboard USB hubs
+ *
+ * Copyright (c) 2022, Google LLC
+ */
+
+#include <driver.h>
+#include <gpiod.h>
+#include <init.h>
+#include <of.h>
+#include <linux/printk.h>
+#include <of_device.h>
+#include <regulator.h>
+#include <usb/usb.h>
+
+#include "onboard_usb_hub.h"
+
+void of_usb_host_probe_hubs(struct usb_host *host)
+{
+ struct device_node *np;
+
+ np = dev_of_node(host->hw_dev);
+ if (!np)
+ return;
+
+ of_platform_populate(np, onboard_hub_match, host->hw_dev);
+}
+
+struct onboard_hub {
+ struct regulator *vdd;
+ struct device *dev;
+ const struct onboard_hub_pdata *pdata;
+ int reset_gpio;
+};
+
+static int onboard_hub_power_on(struct onboard_hub *hub)
+{
+ int err;
+
+ err = regulator_enable(hub->vdd);
+ if (err) {
+ dev_err(hub->dev, "failed to enable regulator: %pe\n",
+ ERR_PTR(err));
+ return err;
+ }
+
+ udelay(hub->pdata->reset_us);
+ gpiod_set_value(hub->reset_gpio, 0);
+
+ return 0;
+}
+
+static int onboard_hub_probe(struct device *dev)
+{
+ struct onboard_hub *hub;
+
+ hub = xzalloc(sizeof(*hub));
+
+ hub->pdata = device_get_match_data(dev);
+ if (!hub->pdata)
+ return -EINVAL;
+
+ hub->vdd = regulator_get(dev, "vdd");
+ if (IS_ERR(hub->vdd))
+ return PTR_ERR(hub->vdd);
+
+ hub->reset_gpio = gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (hub->reset_gpio < 0 && hub->reset_gpio != -ENOENT)
+ return dev_err_probe(dev, hub->reset_gpio, "failed to get reset GPIO\n");
+
+ hub->dev = dev;
+
+ return onboard_hub_power_on(hub);
+}
+
+static struct driver onboard_hub_driver = {
+ .name = "onboard-usb-hub",
+ .probe = onboard_hub_probe,
+ .of_compatible = onboard_hub_match,
+};
+device_platform_driver(onboard_hub_driver);
+
+MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
+MODULE_DESCRIPTION("Driver for discrete onboard USB hubs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/misc/onboard_usb_hub.h b/drivers/usb/misc/onboard_usb_hub.h
new file mode 100644
index 0000000000..e90be47b67
--- /dev/null
+++ b/drivers/usb/misc/onboard_usb_hub.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022, Google LLC
+ */
+
+#ifndef _USB_MISC_ONBOARD_USB_HUB_H
+#define _USB_MISC_ONBOARD_USB_HUB_H
+
+struct onboard_hub_pdata {
+ unsigned long reset_us; /* reset pulse width in us */
+};
+
+static const struct onboard_hub_pdata microchip_usb424_data = {
+ .reset_us = 1,
+};
+
+static const struct onboard_hub_pdata realtek_rts5411_data = {
+ .reset_us = 0,
+};
+
+static const struct onboard_hub_pdata ti_tusb8041_data = {
+ .reset_us = 3000,
+};
+
+const struct of_device_id onboard_hub_match[] = {
+ { .compatible = "usb424,2514", .data = &microchip_usb424_data, },
+ { .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
+ { .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
+ { .compatible = "usbbda,411", .data = &realtek_rts5411_data, },
+ { .compatible = "usbbda,5411", .data = &realtek_rts5411_data, },
+ { .compatible = "usbbda,414", .data = &realtek_rts5411_data, },
+ { .compatible = "usbbda,5414", .data = &realtek_rts5411_data, },
+ {}
+};
+
+#endif /* _USB_MISC_ONBOARD_USB_HUB_H */
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index a0467ff3c4..a4e97c989b 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -324,7 +324,6 @@ struct musb {
u16 int_rx;
u16 int_tx;
- //struct device_d *phydev;
struct usb_host host;
struct usb_phy *xceiv;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index a20b7bbee9..01bdaf47bf 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -123,6 +123,12 @@ config DRIVER_VIDEO_SIMPLEFB
Add support for setting up the kernel's simple framebuffer driver
based on the active barebox framebuffer.
+config DRIVER_VIDEO_RAMFB
+ bool "QEMU RamFB support"
+ select QEMU_FW_CFG
+ help
+ Add support for setting up a QEMU RamFB driver.
+
config DRIVER_VIDEO_EDID
bool "Add EDID support"
help
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9ec0420cca..d50d2d3ba5 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o
obj-$(CONFIG_DRIVER_VIDEO_BCM283X) += bcm2835.o
obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB_CLIENT) += simplefb-client.o
obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb-fixup.o
+obj-$(CONFIG_DRIVER_VIDEO_RAMFB) += ramfb.o
obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/
obj-$(CONFIG_DRIVER_VIDEO_EFI_GOP) += efi_gop.o
obj-$(CONFIG_DRIVER_VIDEO_FB_SSD1307) += ssd1307fb.o
diff --git a/drivers/video/ramfb.c b/drivers/video/ramfb.c
new file mode 100644
index 0000000000..26e01196fc
--- /dev/null
+++ b/drivers/video/ramfb.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: (C) 2022 Adrian Negreanu
+
+#define pr_fmt(fmt) "ramfb: " fmt
+
+#include <common.h>
+#include <fb.h>
+#include <fcntl.h>
+#include <dma.h>
+#include <init.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fs.h>
+#include <linux/qemu_fw_cfg.h>
+#include <video/fourcc.h>
+
+struct ramfb {
+ int fd;
+ struct fb_info info;
+ dma_addr_t screen_dma;
+ struct fb_videomode mode;
+ u16 etcfb_select;
+};
+
+struct fw_cfg_etc_ramfb {
+ u64 addr;
+ u32 fourcc;
+ u32 flags;
+ u32 width;
+ u32 height;
+ u32 stride;
+} __packed;
+
+static int fw_cfg_find_file(struct device *dev, int fd, const char *filename)
+{
+ size_t filename_len = strlen(filename);
+ ssize_t ret;
+ __be32 count;
+ int i;
+
+ ioctl(fd, FW_CFG_SELECT, &(u16) { FW_CFG_FILE_DIR });
+
+ lseek(fd, 0, SEEK_SET);
+
+ ret = read(fd, &count, sizeof(count));
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < be32_to_cpu(count); i++) {
+ struct fw_cfg_file qfile;
+
+ read(fd, &qfile, sizeof(qfile));
+
+ dev_dbg(dev, "enumerating file %s\n", qfile.name);
+
+ if (memcmp(qfile.name, filename, filename_len))
+ continue;
+
+ return be16_to_cpu(qfile.select);
+ }
+
+ return -ENOENT;
+}
+
+static void ramfb_populate_modes(struct ramfb *ramfb)
+{
+ struct fb_info *info = &ramfb->info;
+
+ ramfb->mode.name = "x8r8g8b8";
+ info->xres = ramfb->mode.xres = 640;
+ info->yres = ramfb->mode.yres = 480;
+
+ info->mode = &ramfb->mode;
+ info->bits_per_pixel = 32;
+ info->red = (struct fb_bitfield) {16, 8};
+ info->green = (struct fb_bitfield) {8, 8};
+ info->blue = (struct fb_bitfield) {0, 8};
+ info->transp = (struct fb_bitfield) {0, 0};
+}
+
+static int ramfb_activate_var(struct fb_info *fbi)
+{
+ struct ramfb *ramfb = fbi->priv;
+
+ if (fbi->screen_base)
+ dma_free_coherent(fbi->screen_base, ramfb->screen_dma, fbi->screen_size);
+
+ fbi->screen_size = fbi->xres * fbi->yres * fbi->bits_per_pixel;
+ fbi->screen_base = dma_alloc_coherent(fbi->screen_size, &ramfb->screen_dma);
+
+ return 0;
+}
+
+static void ramfb_enable(struct fb_info *fbi)
+{
+ struct ramfb *ramfb = fbi->priv;
+ struct fw_cfg_etc_ramfb *etc_ramfb;
+
+ etc_ramfb = dma_alloc(sizeof(*etc_ramfb));
+
+ etc_ramfb->addr = cpu_to_be64(ramfb->screen_dma);
+ etc_ramfb->fourcc = cpu_to_be32(DRM_FORMAT_XRGB8888);
+ etc_ramfb->flags = cpu_to_be32(0);
+ etc_ramfb->width = cpu_to_be32(fbi->xres);
+ etc_ramfb->height = cpu_to_be32(fbi->yres);
+ etc_ramfb->stride = cpu_to_be32(fbi->line_length);
+
+ ioctl(ramfb->fd, FW_CFG_SELECT, &ramfb->etcfb_select);
+
+ pwrite(ramfb->fd, etc_ramfb, sizeof(*etc_ramfb), 0);
+
+ dma_free(etc_ramfb);
+}
+
+static struct fb_ops ramfb_ops = {
+ .fb_activate_var = ramfb_activate_var,
+ .fb_enable = ramfb_enable,
+};
+
+static int ramfb_probe(struct device *parent_dev, int fd)
+{
+ int ret;
+ struct ramfb *ramfb;
+ struct fb_info *fbi;
+
+ ret = -ENODEV;
+
+ ramfb = xzalloc(sizeof(*ramfb));
+
+ ramfb->fd = fd;
+
+ ret = fw_cfg_find_file(parent_dev, fd, "etc/ramfb");
+ if (ret < 0) {
+ dev_err(parent_dev, "ramfb: fw_cfg (etc/ramfb) file not found\n");
+ return -ENODEV;
+ }
+
+ ramfb->etcfb_select = ret;
+ dev_dbg(parent_dev, "etc/ramfb file at slot 0x%x\n", ramfb->etcfb_select);
+
+ fbi = &ramfb->info;
+ fbi->priv = ramfb;
+ fbi->fbops = &ramfb_ops;
+ fbi->dev.parent = parent_dev;
+
+ ramfb_populate_modes(ramfb);
+
+ ret = register_framebuffer(fbi);
+ if (ret < 0) {
+ dev_err(parent_dev, "Unable to register ramfb: %d\n", ret);
+ return ret;
+ }
+
+ dev_info(parent_dev, "ramfb registered\n");
+
+ return 0;
+}
+
+static int ramfb_driver_init(void)
+{
+ struct cdev *cdev;
+ int err = 0;
+
+ for_each_cdev(cdev) {
+ int fd, ret;
+
+ if (!strstarts(cdev->name, "fw_cfg"))
+ continue;
+
+ fd = cdev_fdopen(cdev, O_RDWR);
+ if (fd < 0) {
+ err = fd;
+ continue;
+ }
+
+ ret = ramfb_probe(cdev->dev, fd);
+ if (ret == 0)
+ continue;
+ if (ret != -ENODEV && ret != -ENXIO)
+ err = ret;
+
+ close(fd);
+ }
+
+ return err;
+}
+device_initcall(ramfb_driver_init);
+
+MODULE_AUTHOR("Adrian Negreanu <adrian.negreanu@nxp.com>");
+MODULE_DESCRIPTION("QEMU RamFB driver");
+MODULE_LICENSE("GPL v2");
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index 4676af8a55..2d1070f1a7 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -168,7 +168,7 @@ static int cramfs_read(struct device *_dev, FILE *f, void *buf, size_t size)
}
#if 0
-static int cramfs_info (struct device_d *dev)
+static int cramfs_info (struct device *dev)
{
if (cramfs_read_super (dev))
return 0;
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 2a259c2fe0..fbcf68e815 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -177,6 +177,26 @@ int cdev_open(struct cdev *cdev, unsigned long flags)
return 0;
}
+int cdev_fdopen(struct cdev *cdev, unsigned long flags)
+{
+ char *path;
+ int fd;
+
+ if (!cdev)
+ return -ENODEV;
+ if (IS_ERR(cdev))
+ return PTR_ERR(cdev);
+
+ path = basprintf("/dev/%s", cdev->name);
+ if (!path)
+ return -ENOMEM;
+
+ fd = open(path, flags);
+
+ free(path);
+ return fd;
+}
+
struct cdev *cdev_open_by_name(const char *name, unsigned long flags)
{
struct cdev *cdev;
diff --git a/fs/fs.c b/fs/fs.c
index c463466e1b..4837c4b701 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -160,9 +160,9 @@ void stat_print(const char *filename, const struct stat *st)
fdev = get_fsdevice_by_path(filename);
- printf("\nDevice: %s\tInode: %lu\tLinks: %u\n",
+ printf("\nDevice: %s\tInode: %lu\n",
fdev ? dev_name(&fdev->dev) : "<unknown>",
- st->st_ino, st->st_nlink);
+ st->st_ino);
printf("Access: (%04o/%s)\tUid: (%u)\tGid: (%u)\n",
st->st_mode & 07777, modestr, st->st_uid, st->st_gid);
diff --git a/fs/nfs.c b/fs/nfs.c
index 446d0f7946..1a0b28442d 100644
--- a/fs/nfs.c
+++ b/fs/nfs.c
@@ -571,6 +571,12 @@ static int rpc_lookup_req(struct nfs_priv *npriv, uint32_t prog, uint32_t ver)
nfs_free_packet(nfs_packet);
+ if (port == 0) {
+ pr_warn("No UDP port for RPC program %i! "
+ "Is your NFS server TCP only?\n", prog);
+ return -ENOENT;
+ }
+
return port;
}
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index acb70509d1..6e91c0aea6 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -12,6 +12,7 @@
#define __ASM_GENERIC_IO_H
#include <linux/string.h> /* for memset() and memcpy() */
+#include <linux/compiler.h>
#include <linux/types.h>
#include <asm/byteorder.h>
@@ -86,7 +87,7 @@ static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
#endif
#ifndef PCI_IOBASE
-#define PCI_IOBASE ((void __iomem *)0)
+#define PCI_IOBASE ((void __iomem *)RELOC_HIDE((void *)0, 0))
#endif
#ifndef IO_SPACE_LIMIT
diff --git a/include/driver.h b/include/driver.h
index f0a0b9d6ae..f53668711b 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -535,6 +535,7 @@ struct cdev *cdev_open_by_name(const char *name, unsigned long flags);
struct cdev *cdev_create_loop(const char *path, ulong flags, loff_t offset);
void cdev_remove_loop(struct cdev *cdev);
int cdev_open(struct cdev *, unsigned long flags);
+int cdev_fdopen(struct cdev *cdev, unsigned long flags);
void cdev_close(struct cdev *cdev);
int cdev_flush(struct cdev *cdev);
ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags);
diff --git a/include/filetype.h b/include/filetype.h
index 00d54e48d5..1a7d145555 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -58,6 +58,7 @@ enum filetype {
filetype_mxs_sd_image,
filetype_rockchip_rkns_image,
filetype_fip,
+ filetype_qemu_fw_cfg,
filetype_max,
};
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 5175bbe370..18ff16a642 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -12,7 +12,7 @@ struct device;
/*
* This struct describes the MFD part ("cell").
* After registration the copy of this structure will become the platform data
- * of the resulting device_d
+ * of the resulting device
*/
struct mfd_cell {
const char *name;
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 2bdf3ec9c9..fc3dd222a6 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -49,11 +49,8 @@ extern "C" {
struct stat {
unsigned long st_ino;
unsigned short st_mode;
- unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
- unsigned short st_rdev;
- unsigned short __pad2;
loff_t st_size;
};
diff --git a/include/of_gpio.h b/include/of_gpio.h
index 30ff204baf..794a9926cd 100644
--- a/include/of_gpio.h
+++ b/include/of_gpio.h
@@ -69,6 +69,23 @@ static inline int of_gpio_count(struct device_node *np)
return of_gpio_named_count(np, "gpios");
}
+/**
+ * of_gpio_count() - Count cs-gpios for a device
+ * @np: device node to count cs-gpios for
+ *
+ * Same as of_gpio_named_count, but hard coded to use the 'cs-gpios' property
+ * Returns 0 on error
+ */
+static inline int of_gpio_count_csgpios(struct device_node *np)
+{
+ int count = of_gpio_named_count(np, "cs-gpios");
+
+ if (count > 0)
+ return count;
+ else
+ return 0;
+}
+
static inline int of_get_gpio_flags(struct device_node *np, int index,
enum of_gpio_flags *flags)
{
diff --git a/include/platform_data/eth-smc911x.h b/include/platform_data/eth-smc911x.h
index c97a2967c9..77b4f44633 100644
--- a/include/platform_data/eth-smc911x.h
+++ b/include/platform_data/eth-smc911x.h
@@ -9,7 +9,7 @@
/**
* @brief Platform dependent feature:
- * Pass pointer to this structure as part of device_d -> platform_data
+ * Pass pointer to this structure as part of device -> platform_data
*/
struct smc911x_plat {
u32 shift;
diff --git a/include/platform_data/serial-ns16550.h b/include/platform_data/serial-ns16550.h
index ccf950b077..11a5e9c7a3 100644
--- a/include/platform_data/serial-ns16550.h
+++ b/include/platform_data/serial-ns16550.h
@@ -28,7 +28,7 @@
/**
* @brief Platform dependent feature:
- * Pass pointer to this structure as part of device_d -> platform_data
+ * Pass pointer to this structure as part of device -> platform_data
*/
struct NS16550_plat {
/** Clock speed */
diff --git a/include/uapi/linux/qemu_fw_cfg.h b/include/uapi/linux/qemu_fw_cfg.h
new file mode 100644
index 0000000000..97a720c383
--- /dev/null
+++ b/include/uapi/linux/qemu_fw_cfg.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+#ifndef _LINUX_FW_CFG_H
+#define _LINUX_FW_CFG_H
+
+#include <linux/types.h>
+#include <ioctl.h>
+
+#define FW_CFG_ACPI_DEVICE_ID "QEMU0002"
+
+/* selector key values for "well-known" fw_cfg entries */
+#define FW_CFG_SIGNATURE 0x00
+#define FW_CFG_ID 0x01
+#define FW_CFG_UUID 0x02
+#define FW_CFG_RAM_SIZE 0x03
+#define FW_CFG_NOGRAPHIC 0x04
+#define FW_CFG_NB_CPUS 0x05
+#define FW_CFG_MACHINE_ID 0x06
+#define FW_CFG_KERNEL_ADDR 0x07
+#define FW_CFG_KERNEL_SIZE 0x08
+#define FW_CFG_KERNEL_CMDLINE 0x09
+#define FW_CFG_INITRD_ADDR 0x0a
+#define FW_CFG_INITRD_SIZE 0x0b
+#define FW_CFG_BOOT_DEVICE 0x0c
+#define FW_CFG_NUMA 0x0d
+#define FW_CFG_BOOT_MENU 0x0e
+#define FW_CFG_MAX_CPUS 0x0f
+#define FW_CFG_KERNEL_ENTRY 0x10
+#define FW_CFG_KERNEL_DATA 0x11
+#define FW_CFG_INITRD_DATA 0x12
+#define FW_CFG_CMDLINE_ADDR 0x13
+#define FW_CFG_CMDLINE_SIZE 0x14
+#define FW_CFG_CMDLINE_DATA 0x15
+#define FW_CFG_SETUP_ADDR 0x16
+#define FW_CFG_SETUP_SIZE 0x17
+#define FW_CFG_SETUP_DATA 0x18
+#define FW_CFG_FILE_DIR 0x19
+
+#define FW_CFG_FILE_FIRST 0x20
+#define FW_CFG_FILE_SLOTS_MIN 0x10
+
+#define FW_CFG_WRITE_CHANNEL 0x4000
+#define FW_CFG_ARCH_LOCAL 0x8000
+#define FW_CFG_ENTRY_MASK (~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL))
+
+#define FW_CFG_INVALID 0xffff
+
+/* width in bytes of fw_cfg control register */
+#define FW_CFG_CTL_SIZE 0x02
+
+/* fw_cfg "file name" is up to 56 characters (including terminating nul) */
+#define FW_CFG_MAX_FILE_PATH 56
+
+/* size in bytes of fw_cfg signature */
+#define FW_CFG_SIG_SIZE 4
+
+/* FW_CFG_ID bits */
+#define FW_CFG_VERSION 0x01
+#define FW_CFG_VERSION_DMA 0x02
+
+/* fw_cfg file directory entry type */
+struct fw_cfg_file {
+ __be32 size;
+ __be16 select;
+ __u16 reserved;
+ char name[FW_CFG_MAX_FILE_PATH];
+};
+
+/* FW_CFG_DMA_CONTROL bits */
+#define FW_CFG_DMA_CTL_ERROR 0x01
+#define FW_CFG_DMA_CTL_READ 0x02
+#define FW_CFG_DMA_CTL_SKIP 0x04
+#define FW_CFG_DMA_CTL_SELECT 0x08
+#define FW_CFG_DMA_CTL_WRITE 0x10
+
+#define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */
+
+/* Control as first field allows for different structures selected by this
+ * field, which might be useful in the future
+ */
+struct fw_cfg_dma_access {
+ __be32 control;
+ __be32 length;
+ __be64 address;
+};
+
+#define FW_CFG_VMCOREINFO_FILENAME "etc/vmcoreinfo"
+
+#define FW_CFG_VMCOREINFO_FORMAT_NONE 0x0
+#define FW_CFG_VMCOREINFO_FORMAT_ELF 0x1
+
+struct fw_cfg_vmcoreinfo {
+ __le16 host_format;
+ __le16 guest_format;
+ __le32 size;
+ __le64 paddr;
+};
+
+#define FW_CFG_SELECT _IOW('Q', 1, __u16)
+
+#endif
diff --git a/include/usb/usb.h b/include/usb/usb.h
index 9b36122436..717bcf935a 100644
--- a/include/usb/usb.h
+++ b/include/usb/usb.h
@@ -484,4 +484,12 @@ extern struct list_head usb_device_list;
bool usb_hub_is_root_hub(struct usb_device *hdev);
+#ifdef CONFIG_USB_ONBOARD_HUB
+void of_usb_host_probe_hubs(struct usb_host *host);
+#else
+static inline void of_usb_host_probe_hubs(struct usb_host *host)
+{
+}
+#endif
+
#endif /*_USB_H_ */