Add toolchain and Linux patches

This commit is contained in:
Marek Kraus 2023-01-15 12:32:34 +01:00
parent 22fce61235
commit 10ef70a311
13 changed files with 2177 additions and 0 deletions

View file

@ -0,0 +1,293 @@
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
CONFIG_USER_NS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_PERF_EVENTS=y
CONFIG_SOC_BOUFFALOLAB=y
CONFIG_SOC_VIRT=y
CONFIG_ERRATA_THEAD=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_RISCV_SBI_V01=y
# CONFIG_COMPAT is not set
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_CMDLINE_PARTITION=y
CONFIG_PAGE_REPORTING=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_DNS_RESOLVER=y
CONFIG_NETLINK_DIAG=y
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK_RO=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_ROM=y
CONFIG_MTD_ABSENT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_PHYSMAP_VERSATILE=y
CONFIG_MTD_PHYSMAP_GEMINI=y
CONFIG_MTD_PLATRAM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_VIRTIO_BLK=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_VIRTIO=y
CONFIG_NETDEVICES=y
CONFIG_VIRTIO_NET=y
# CONFIG_ETHERNET is not set
CONFIG_MDIO_DEVICE=y
# CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=y
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_SERIAL_BFLB=y
CONFIG_SERIAL_BFLB_CONSOLE=y
CONFIG_SERIAL_SIFIVE=y
CONFIG_SERIAL_SIFIVE_CONSOLE=y
CONFIG_HVC_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_XILINX=y
CONFIG_I2C_SLAVE=y
CONFIG_I2C_SLAVE_EEPROM=y
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_HID_A4TECH is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CYPRESS is not set
# CONFIG_HID_EZKEY is not set
# CONFIG_HID_ITE is not set
# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_REDRAGON is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
CONFIG_SYNC_FILE=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_GENERIC_PHY=y
CONFIG_AUTOFS4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_CONFIGFS_FS=y
# CONFIG_EFIVAR_FS is not set
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_KEYS=y
CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity"
CONFIG_CRYPTO=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_CRC16=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_VM_PGTABLE=y
CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_FUNCTION_ERROR_INJECTION=y
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_MEMTEST=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
CONFIG_USER_NS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_PERF_EVENTS=y
CONFIG_SOC_BOUFFALOLAB=y
CONFIG_SOC_VIRT=y
CONFIG_ERRATA_THEAD=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_RISCV_SBI_V01=y
# CONFIG_COMPAT is not set
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_CMDLINE_PARTITION=y
CONFIG_PAGE_REPORTING=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_DNS_RESOLVER=y
CONFIG_NETLINK_DIAG=y
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK_RO=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_ROM=y
CONFIG_MTD_ABSENT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_PHYSMAP_VERSATILE=y
CONFIG_MTD_PHYSMAP_GEMINI=y
CONFIG_MTD_PLATRAM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_VIRTIO_BLK=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_VIRTIO=y
CONFIG_NETDEVICES=y
CONFIG_VIRTIO_NET=y
# CONFIG_ETHERNET is not set
CONFIG_MDIO_DEVICE=y
# CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=y
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_SERIAL_BFLB=y
CONFIG_SERIAL_BFLB_CONSOLE=y
CONFIG_SERIAL_SIFIVE=y
CONFIG_SERIAL_SIFIVE_CONSOLE=y
CONFIG_HVC_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_XILINX=y
CONFIG_I2C_SLAVE=y
CONFIG_I2C_SLAVE_EEPROM=y
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_HID_A4TECH is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CYPRESS is not set
# CONFIG_HID_EZKEY is not set
# CONFIG_HID_ITE is not set
# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_REDRAGON is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
CONFIG_SYNC_FILE=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_GENERIC_PHY=y
CONFIG_AUTOFS4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_CONFIGFS_FS=y
# CONFIG_EFIVAR_FS is not set
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_KEYS=y
CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity"
CONFIG_CRYPTO=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_CRC16=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_VM_PGTABLE=y
CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_FUNCTION_ERROR_INJECTION=y
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_MEMTEST=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_BFLB=y
CONFIG_GENERIC_IRQ_DEBUGFS=y
CONFIG_MAILBOX=y
CONFIG_BFLB_IPC=y

View file

@ -0,0 +1,73 @@
From d54c88d19380488afecbf0257fea7f5adb60ed7f Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:08 +0800
Subject: [PATCH 01/15] dt-bindings: serial: add bindings doc for Bouffalolab
uart driver
Add bindings doc for Bouffalolab UART Driver
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
.../bindings/serial/bouffalolab,uart.yaml | 50 +++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 Documentation/devicetree/bindings/serial/bouffalolab,uart.yaml
diff --git a/Documentation/devicetree/bindings/serial/bouffalolab,uart.yaml b/Documentation/devicetree/bindings/serial/bouffalolab,uart.yaml
new file mode 100644
index 000000000000..6cef956d33d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/bouffalolab,uart.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/serial/bouffalolab,uart.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Bouffalolab UART Controller
+
+maintainers:
+ - Jisheng Zhang <jszhang@kernel.org>
+
+allOf:
+ - $ref: serial.yaml#
+
+properties:
+ compatible:
+ const: bouffalolab,uart
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ aliases {
+ serial0 = &uart0;
+ };
+
+ uart0: serial@30002000 {
+ compatible = "bouffalolab,uart";
+ reg = <0x30002000 0x1000>;
+ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal>;
+ };
+...
--
2.39.0

View file

@ -0,0 +1,740 @@
From 350729c7e8e9a0764bc8d943b07f651e2c3f4183 Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:09 +0800
Subject: [PATCH 02/15] serial: bflb_uart: add Bouffalolab UART Driver
Add the driver for Bouffalolab UART IP which is found in Bouffalolab
SoCs such as bl808.
UART driver probe will create path named "/dev/ttySx".
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
drivers/tty/serial/Kconfig | 18 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/bflb_uart.c | 659 +++++++++++++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
4 files changed, 681 insertions(+)
create mode 100644 drivers/tty/serial/bflb_uart.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index c55b947f3cdb..4b1eb61436ae 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -179,6 +179,24 @@ config SERIAL_ATMEL_TTYAT
Say Y if you have an external 8250/16C550 UART. If unsure, say N.
+config SERIAL_BFLB
+ tristate "Bouffalolab serial port support"
+ select SERIAL_CORE
+ depends on COMMON_CLK
+ help
+ This enables the driver for the Bouffalolab's serial.
+
+config SERIAL_BFLB_CONSOLE
+ bool "Support for console on Bouffalolab serial port"
+ depends on SERIAL_BFLB
+ select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
+ help
+ Say Y here if you wish to use a Bouffalolab UART as the
+ system console (the system console is the device which
+ receives all kernel messages and warnings and which allows
+ logins in single user mode) as /dev/ttySn.
+
config SERIAL_KGDB_NMI
bool "Serial console over KGDB NMI debugger port"
depends on KGDB_SERIAL_CONSOLE
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 238a9557b487..8509cdc11d87 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+obj-$(CONFIG_SERIAL_BFLB) += bflb_uart.o
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
diff --git a/drivers/tty/serial/bflb_uart.c b/drivers/tty/serial/bflb_uart.c
new file mode 100644
index 000000000000..65f98ccf8fa8
--- /dev/null
+++ b/drivers/tty/serial/bflb_uart.c
@@ -0,0 +1,659 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Based on bflb_uart.c, by Bouffalolab team
+ *
+ * Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#define UART_UTX_CONFIG 0x00
+#define UART_CR_UTX_EN BIT(0)
+#define UART_CR_UTX_CTS_EN BIT(1)
+#define UART_CR_UTX_FRM_EN BIT(2)
+#define UART_CR_UTX_PRT_EN BIT(4)
+#define UART_CR_UTX_PRT_SEL BIT(5)
+#define UART_CR_UTX_BIT_CNT_D_SFT 8
+#define UART_CR_UTX_BIT_CNT_D_MSK GENMASK(10, 8)
+#define UART_CR_UTX_BIT_CNT_P_SFT 11
+#define UART_CR_UTX_BIT_CNT_P_MSK GENMASK(12, 11)
+#define UART_URX_CONFIG 0x04
+#define UART_CR_URX_EN BIT(0)
+#define UART_CR_URX_PRT_EN BIT(4)
+#define UART_CR_URX_PRT_SEL BIT(5)
+#define UART_CR_URX_BIT_CNT_D_SFT 8
+#define UART_CR_URX_BIT_CNT_D_MSK GENMASK(10, 8)
+#define UART_BIT_PRD 0x08
+#define UART_CR_UTX_BIT_PRD GENMASK(15, 0)
+#define UART_CR_URX_BIT_PRD GENMASK(31, 16)
+#define UART_DATA_CONFIG 0x0c
+#define UART_CR_UART_BIT_INV BIT(0)
+#define UART_URX_RTO_TIMER 0x18
+#define UART_CR_URX_RTO_VALUE_MSK GENMASK(7, 0)
+#define UART_SW_MODE 0x1c
+#define UART_INT_STS (0x20)
+#define UART_UTX_END_INT BIT(0)
+#define UART_URX_END_INT BIT(1)
+#define UART_UTX_FIFO_INT BIT(2)
+#define UART_URX_FIFO_INT BIT(3)
+#define UART_URX_RTO_INT BIT(4)
+#define UART_URX_PCE_INT BIT(5)
+#define UART_UTX_FER_INT BIT(6)
+#define UART_URX_FER_INT BIT(7)
+#define UART_URX_LSE_INT BIT(8)
+#define UART_INT_MASK 0x24
+#define UART_INT_CLEAR 0x28
+#define UART_INT_EN 0x2c
+#define UART_STATUS 0x30
+#define UART_STS_UTX_BUS_BUSY BIT(0)
+#define UART_FIFO_CONFIG_0 (0x80)
+#define UART_DMA_TX_EN BIT(0)
+#define UART_DMA_RX_EN BIT(1)
+#define UART_TX_FIFO_CLR BIT(2)
+#define UART_RX_FIFO_CLR BIT(3)
+#define UART_TX_FIFO_OVERFLOW BIT(4)
+#define UART_TX_FIFO_UNDERFLOW BIT(5)
+#define UART_RX_FIFO_OVERFLOW BIT(6)
+#define UART_RX_FIFO_UNDERFLOW BIT(7)
+#define UART_FIFO_CONFIG_1 (0x84)
+#define UART_TX_FIFO_CNT_SFT 0
+#define UART_TX_FIFO_CNT_MSK GENMASK(5, 0)
+#define UART_RX_FIFO_CNT_MSK GENMASK(13, 8)
+#define UART_TX_FIFO_TH_SFT 16
+#define UART_TX_FIFO_TH_MSK GENMASK(20, 16)
+#define UART_RX_FIFO_TH_SFT 24
+#define UART_RX_FIFO_TH_MSK GENMASK(28, 24)
+#define UART_FIFO_WDATA 0x88
+#define UART_FIFO_RDATA 0x8c
+#define UART_FIFO_RDATA_MSK GENMASK(7, 0)
+
+#define BFLB_UART_MAXPORTS 8
+#define BFLB_UART_BAUD 2000000
+#define BFLB_UART_RX_FIFO_TH 7
+
+struct bflb_uart_port {
+ struct uart_port port;
+ struct clk *clk;
+};
+
+static struct bflb_uart_port *bflb_uart_ports[BFLB_UART_MAXPORTS];
+
+static inline u32 rdl(struct uart_port *port, u32 reg)
+{
+ return readl_relaxed(port->membase + reg);
+}
+
+static inline void wrl(struct uart_port *port, u32 reg, u32 value)
+{
+ writel_relaxed(value, port->membase + reg);
+}
+
+static inline void wrb(struct uart_port *port, u32 reg, u8 value)
+{
+ writeb_relaxed(value, port->membase + reg);
+}
+
+static unsigned int bflb_uart_tx_empty(struct uart_port *port)
+{
+ return (rdl(port, UART_FIFO_CONFIG_1) & UART_TX_FIFO_CNT_MSK) ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int bflb_uart_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+static void bflb_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
+{
+}
+
+static void bflb_uart_start_tx(struct uart_port *port)
+{
+ u32 val;
+
+ val = rdl(port, UART_UTX_CONFIG);
+ val |= UART_CR_UTX_EN;
+ wrl(port, UART_UTX_CONFIG, val);
+
+ val = rdl(port, UART_INT_MASK);
+ val &= ~UART_UTX_END_INT;
+ wrl(port, UART_INT_MASK, val);
+
+ val = rdl(port, UART_FIFO_CONFIG_1);
+ val &= ~UART_TX_FIFO_TH_MSK;
+ val |= 15 << UART_TX_FIFO_TH_SFT;
+ wrl(port, UART_FIFO_CONFIG_1, val);
+
+ val = rdl(port, UART_INT_MASK);
+ val &= ~UART_UTX_FIFO_INT;
+ wrl(port, UART_INT_MASK, val);
+}
+
+static void bflb_uart_stop_tx(struct uart_port *port)
+{
+ u32 val;
+
+ val = rdl(port, UART_INT_MASK);
+ val |= UART_UTX_END_INT | UART_UTX_FIFO_INT;
+ wrl(port, UART_INT_MASK, val);
+}
+
+static void bflb_uart_stop_rx(struct uart_port *port)
+{
+ u32 val;
+
+ val = rdl(port, UART_URX_CONFIG);
+ val &= ~UART_CR_URX_EN;
+ wrl(port, UART_URX_CONFIG, val);
+
+ val = rdl(port, UART_INT_MASK);
+ val |= UART_URX_FIFO_INT | UART_URX_RTO_INT |
+ UART_URX_FER_INT;
+ wrl(port, UART_INT_MASK, val);
+}
+
+static void bflb_uart_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static void bflb_uart_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ const struct ktermios *old)
+{
+ unsigned long flags;
+ u32 valt, valr, val;
+ unsigned int baud, min;
+
+ valt = valr = 0;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* set data length */
+ val = tty_get_char_size(termios->c_cflag) - 1;
+ valt |= (val << UART_CR_UTX_BIT_CNT_D_SFT);
+
+ /* calculate parity */
+ termios->c_cflag &= ~CMSPAR; /* no support mark/space */
+ if (termios->c_cflag & PARENB) {
+ valt |= UART_CR_UTX_PRT_EN;
+ if (termios->c_cflag & PARODD)
+ valr |= UART_CR_UTX_PRT_SEL;
+ }
+
+ valr = valt;
+
+ /* calculate stop bits */
+ if (termios->c_cflag & CSTOPB)
+ val = 2;
+ else
+ val = 1;
+ valt |= (val << UART_CR_UTX_BIT_CNT_P_SFT);
+
+ /* flow control */
+ if (termios->c_cflag & CRTSCTS)
+ valt |= UART_CR_UTX_CTS_EN;
+
+ /* enable TX freerunning mode */
+ valt |= UART_CR_UTX_FRM_EN;
+
+ valt |= UART_CR_UTX_EN;
+ valr |= UART_CR_URX_EN;
+
+ wrl(port, UART_UTX_CONFIG, valt);
+ wrl(port, UART_URX_CONFIG, valr);
+
+ min = port->uartclk / (UART_CR_UTX_BIT_PRD + 1);
+ baud = uart_get_baud_rate(port, termios, old, min, 4000000);
+
+ val = DIV_ROUND_CLOSEST(port->uartclk, baud) - 1;
+ val &= UART_CR_UTX_BIT_PRD;
+ val |= (val << 16);
+ wrl(port, UART_BIT_PRD, val);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void bflb_uart_rx_chars(struct uart_port *port)
+{
+ unsigned char ch, flag;
+ unsigned long status;
+
+ while ((status = rdl(port, UART_FIFO_CONFIG_1)) & UART_RX_FIFO_CNT_MSK) {
+ ch = rdl(port, UART_FIFO_RDATA) & UART_FIFO_RDATA_MSK;
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (uart_handle_sysrq_char(port, ch))
+ continue;
+ uart_insert_char(port, 0, 0, ch, flag);
+ }
+
+ spin_unlock(&port->lock);
+ tty_flip_buffer_push(&port->state->port);
+ spin_lock(&port->lock);
+}
+
+static void bflb_uart_tx_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned int pending, count;
+
+ if (port->x_char) {
+ /* Send special char - probably flow control */
+ wrl(port, UART_FIFO_WDATA, port->x_char);
+ port->x_char = 0;
+ port->icount.tx++;
+ return;
+ }
+
+ pending = uart_circ_chars_pending(xmit);
+ if (pending > 0) {
+ count = (rdl(port, UART_FIFO_CONFIG_1) &
+ UART_TX_FIFO_CNT_MSK) >> UART_TX_FIFO_CNT_SFT;
+ if (count > pending)
+ count = pending;
+ if (count > 0) {
+ pending -= count;
+ while (count--) {
+ wrl(port, UART_FIFO_WDATA, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+ if (pending < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+ }
+ }
+
+ if (pending == 0)
+ bflb_uart_stop_tx(port);
+}
+
+static irqreturn_t bflb_uart_interrupt(int irq, void *data)
+{
+ struct uart_port *port = data;
+ u32 isr, val;
+
+ isr = rdl(port, UART_INT_STS);
+ wrl(port, UART_INT_CLEAR, isr);
+
+ isr &= ~rdl(port, UART_INT_MASK);
+
+ spin_lock(&port->lock);
+
+ if (isr & UART_URX_FER_INT) {
+ /* RX FIFO error interrupt */
+ val = rdl(port, UART_FIFO_CONFIG_0);
+ if (val & UART_RX_FIFO_OVERFLOW)
+ port->icount.overrun++;
+
+ val |= UART_RX_FIFO_CLR;
+ wrl(port, UART_FIFO_CONFIG_0, val);
+ }
+
+ if (isr & (UART_URX_FIFO_INT | UART_URX_RTO_INT)) {
+ bflb_uart_rx_chars(port);
+ }
+ if (isr & (UART_UTX_FIFO_INT | UART_UTX_END_INT)) {
+ bflb_uart_tx_chars(port);
+ }
+
+ spin_unlock(&port->lock);
+
+ return IRQ_RETVAL(isr);
+}
+
+static void bflb_uart_config_port(struct uart_port *port, int flags)
+{
+ u32 val;
+
+ port->type = PORT_BFLB;
+
+ /* Clear mask, so no surprise interrupts. */
+ val = rdl(port, UART_INT_MASK);
+ val |= UART_UTX_END_INT;
+ val |= UART_UTX_FIFO_INT;
+ val |= UART_URX_FIFO_INT;
+ val |= UART_URX_RTO_INT;
+ val |= UART_URX_FER_INT;
+ wrl(port, UART_INT_MASK, val);
+}
+
+static int bflb_uart_startup(struct uart_port *port)
+{
+ unsigned long flags;
+ int ret;
+ u32 val;
+
+ ret = devm_request_irq(port->dev, port->irq, bflb_uart_interrupt,
+ IRQF_SHARED, port->name, port);
+ if (ret) {
+ dev_err(port->dev, "fail to request serial irq %d, ret=%d\n",
+ port->irq, ret);
+ return ret;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ val = rdl(port, UART_INT_MASK);
+ val |= 0xfff;
+ wrl(port, UART_INT_MASK, val);
+
+ wrl(port, UART_DATA_CONFIG, 0);
+ wrl(port, UART_SW_MODE, 0);
+ wrl(port, UART_URX_RTO_TIMER, 0x4f);
+
+ val = rdl(port, UART_FIFO_CONFIG_1);
+ val &= ~UART_RX_FIFO_TH_MSK;
+ val |= BFLB_UART_RX_FIFO_TH << UART_RX_FIFO_TH_SFT;
+ wrl(port, UART_FIFO_CONFIG_1, val);
+
+ /* Unmask RX interrupts now */
+ val = rdl(port, UART_INT_MASK);
+ val &= ~UART_URX_FIFO_INT;
+ val &= ~UART_URX_RTO_INT;
+ val &= ~UART_URX_FER_INT;
+ wrl(port, UART_INT_MASK, val);
+
+ val = rdl(port, UART_UTX_CONFIG);
+ val |= UART_CR_UTX_EN;
+ wrl(port, UART_UTX_CONFIG, val);
+ val = rdl(port, UART_URX_CONFIG);
+ val |= UART_CR_URX_EN;
+ wrl(port, UART_URX_CONFIG, val);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+static void bflb_uart_shutdown(struct uart_port *port)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ /* mask all interrupts now */
+ wrl(port, UART_INT_MASK, UART_UTX_END_INT | UART_URX_END_INT);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *bflb_uart_type(struct uart_port *port)
+{
+ return (port->type == PORT_BFLB) ? "BFLB UART" : NULL;
+}
+
+static int bflb_uart_request_port(struct uart_port *port)
+{
+ /* UARTs always present */
+ return 0;
+}
+
+static void bflb_uart_release_port(struct uart_port *port)
+{
+ /* Nothing to release... */
+}
+
+static int bflb_uart_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_BFLB)
+ return -EINVAL;
+ return 0;
+}
+
+static const struct uart_ops bflb_uart_ops = {
+ .tx_empty = bflb_uart_tx_empty,
+ .get_mctrl = bflb_uart_get_mctrl,
+ .set_mctrl = bflb_uart_set_mctrl,
+ .start_tx = bflb_uart_start_tx,
+ .stop_tx = bflb_uart_stop_tx,
+ .stop_rx = bflb_uart_stop_rx,
+ .break_ctl = bflb_uart_break_ctl,
+ .startup = bflb_uart_startup,
+ .shutdown = bflb_uart_shutdown,
+ .set_termios = bflb_uart_set_termios,
+ .type = bflb_uart_type,
+ .request_port = bflb_uart_request_port,
+ .release_port = bflb_uart_release_port,
+ .config_port = bflb_uart_config_port,
+ .verify_port = bflb_uart_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_BFLB_CONSOLE
+static void bflb_console_putchar(struct uart_port *port, unsigned char ch)
+{
+ while (!(rdl(port, UART_FIFO_CONFIG_1) & UART_TX_FIFO_CNT_MSK))
+ cpu_relax();
+ wrb(port, UART_FIFO_WDATA, ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void bflb_uart_console_write(struct console *co, const char *s,
+ u_int count)
+{
+ struct uart_port *port = &bflb_uart_ports[co->index]->port;
+ u32 status, reg, mask;
+
+ /* save then disable interrupts */
+ mask = rdl(port, UART_INT_MASK);
+ reg = -1;
+ wrl(port, UART_INT_MASK, reg);
+
+ /* Make sure that tx is enabled */
+ reg = rdl(port, UART_UTX_CONFIG);
+ reg |= UART_CR_UTX_EN;
+ wrl(port, UART_UTX_CONFIG, reg);
+
+ uart_console_write(port, s, count, bflb_console_putchar);
+
+ /* wait for TX done */
+ do {
+ status = rdl(port, UART_STATUS);
+ } while ((status & UART_STS_UTX_BUS_BUSY));
+
+ /* restore IRQ mask */
+ wrl(port, UART_INT_MASK, mask);
+}
+
+static int bflb_uart_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ struct bflb_uart_port *bp;
+ int baud = BFLB_UART_BAUD;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+ u32 val;
+
+ if (co->index >= BFLB_UART_MAXPORTS || co->index < 0)
+ return -EINVAL;
+
+ bp = bflb_uart_ports[co->index];
+ if (!bp)
+ /* Port not initialized yet - delay setup */
+ return -ENODEV;
+
+ port = &bp->port;
+
+ val = rdl(port, UART_UTX_CONFIG);
+ val |= UART_CR_UTX_EN;
+ wrl(port, UART_UTX_CONFIG, val);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver bflb_uart_driver;
+static struct console bflb_uart_console = {
+ .name = "ttyS",
+ .write = bflb_uart_console_write,
+ .device = uart_console_device,
+ .setup = bflb_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &bflb_uart_driver,
+};
+
+static int __init bflb_uart_console_init(void)
+{
+ register_console(&bflb_uart_console);
+ return 0;
+}
+console_initcall(bflb_uart_console_init);
+
+#define BFLB_UART_CONSOLE (&bflb_uart_console)
+
+static void bflb_uart_earlycon_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct earlycon_device *dev = co->data;
+
+ uart_console_write(&dev->port, s, count, bflb_console_putchar);
+}
+
+static int __init bflb_uart_earlycon_setup(struct earlycon_device *dev,
+ const char *options)
+{
+ if (!dev->port.membase)
+ return -ENODEV;
+
+ dev->con->write = bflb_uart_earlycon_write;
+
+ return 0;
+}
+OF_EARLYCON_DECLARE(bflb_uart, "bouffalolab,uart", bflb_uart_earlycon_setup);
+
+#else
+
+#define BFLB_UART_CONSOLE NULL
+
+#endif /* CONFIG_SERIAL_BFLB_CONSOLE */
+
+static struct uart_driver bflb_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "bflb_uart",
+ .dev_name = "ttyS",
+ .nr = BFLB_UART_MAXPORTS,
+ .cons = BFLB_UART_CONSOLE,
+};
+
+static int bflb_uart_probe(struct platform_device *pdev)
+{
+ struct uart_port *port;
+ struct bflb_uart_port *bp;
+ struct resource *res;
+ int index, irq;
+
+ index = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (unlikely(index < 0 || index >= BFLB_UART_MAXPORTS)) {
+ dev_err(&pdev->dev, "got a wrong serial alias id %d\n", index);
+ return -EINVAL;
+ }
+
+ bp = devm_kzalloc(&pdev->dev, sizeof(*bp), GFP_KERNEL);
+ if (!bp)
+ return -ENOMEM;
+
+ bflb_uart_ports[index] = bp;
+ platform_set_drvdata(pdev, bp);
+ port = &bp->port;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ port->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ port->mapbase = res->start;
+ port->irq = irq;
+ port->line = index;
+ port->type = PORT_BFLB;
+ port->iotype = UPIO_MEM;
+ port->fifosize = 32;
+ port->ops = &bflb_uart_ops;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->dev = &pdev->dev;
+ port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_BFLB_CONSOLE);
+
+ bp->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(bp->clk))
+ return PTR_ERR(bp->clk);
+ port->uartclk = clk_get_rate(bp->clk);
+
+ return uart_add_one_port(&bflb_uart_driver, port);
+}
+
+static int bflb_uart_remove(struct platform_device *pdev)
+{
+ struct bflb_uart_port *bp = platform_get_drvdata(pdev);
+
+ uart_remove_one_port(&bflb_uart_driver, &bp->port);
+ bflb_uart_ports[bp->port.line] = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id bflb_uart_match[] = {
+ {
+ .compatible = "bouffalolab,uart",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bflb_uart_match);
+
+static struct platform_driver bflb_uart_platform_driver = {
+ .probe = bflb_uart_probe,
+ .remove = bflb_uart_remove,
+ .driver = {
+ .name = "bflb_uart",
+ .of_match_table = of_match_ptr(bflb_uart_match),
+ },
+};
+
+static int __init bflb_uart_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&bflb_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&bflb_uart_platform_driver);
+ if (ret)
+ uart_unregister_driver(&bflb_uart_driver);
+
+ return ret;
+}
+
+static void __exit bflb_uart_exit(void)
+{
+ platform_driver_unregister(&bflb_uart_platform_driver);
+ uart_unregister_driver(&bflb_uart_driver);
+}
+
+module_init(bflb_uart_init);
+module_exit(bflb_uart_exit);
+
+MODULE_DESCRIPTION("Bouffalolab UART driver");
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 3ba34d8378bd..dabbb5ea2857 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -276,4 +276,7 @@
/* Sunplus UART */
#define PORT_SUNPLUS 123
+/* Bouffalolab UART */
+#define PORT_BFLB 124
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
2.39.0

View file

@ -0,0 +1,33 @@
From 4b71f54a5821e1ae0fac8c2a44e25123530c5e76 Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:10 +0800
Subject: [PATCH 03/15] MAINTAINERS: add myself as a reviewer for Bouffalolab
uart driver
I want to maintain this Bouffalolab uart driver from now on.
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ea941dc469fa..dce6b97c4ed4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3785,6 +3785,12 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
F: drivers/iio/accel/bma400*
+BOUFFALOLAB UART DRIVER
+M: Jisheng Zhang <jszhang@kernel.org>
+S: Maintained
+F: Documentation/devicetree/bindings/serial/bouffalolab,uart.yaml
+F: drivers/tty/serial/bflb_uart.c
+
BPF [GENERAL] (Safe Dynamic Programs and Tools)
M: Alexei Starovoitov <ast@kernel.org>
M: Daniel Borkmann <daniel@iogearbox.net>
--
2.39.0

View file

@ -0,0 +1,32 @@
From 87e493b1d6b25ef51ccf4edadbebe38bd8583222 Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:11 +0800
Subject: [PATCH 04/15] riscv: add the Bouffalolab SoC family Kconfig option
The Bouffalolab bl808 SoC contains three riscv CPUs, namely M0, D0 and
LP. The D0 is 64bit RISC-V GC compatible, so can run linux.
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
arch/riscv/Kconfig.socs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 4b6deb2715f1..a68ab2172230 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -1,5 +1,11 @@
menu "SoC selection"
+config SOC_BOUFFALOLAB
+ bool "Bouffalolab SoCs"
+ select SIFIVE_PLIC
+ help
+ This enables support for Bouffalolab SoC platforms.
+
config SOC_MICROCHIP_POLARFIRE
bool "Microchip PolarFire SoCs"
select MCHP_CLK_MPFS
--
2.39.0

View file

@ -0,0 +1,108 @@
From 9492a693822a8c51351eaa04fca0666db140fe15 Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:12 +0800
Subject: [PATCH 05/15] riscv: dts: bouffalolab: add the bl808 SoC base device
tree
Add a baisc dtsi for the bouffalolab bl808 SoC.
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/bouffalolab/bl808.dtsi | 74 ++++++++++++++++++++++
2 files changed, 75 insertions(+)
create mode 100644 arch/riscv/boot/dts/bouffalolab/bl808.dtsi
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index b0ff5fbabb0c..2d4376810bcc 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+subdir-y += bouffalolab
subdir-y += sifive
subdir-y += starfive
subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808.dtsi b/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
new file mode 100644
index 000000000000..c98ebb14ee10
--- /dev/null
+++ b/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ compatible = "bouffalolab,bl808";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ timebase-frequency = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "thead,c906", "riscv";
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-block-size = <64>;
+ d-cache-sets = <256>;
+ d-cache-size = <32768>;
+ i-cache-block-size = <64>;
+ i-cache-sets = <128>;
+ i-cache-size = <32768>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdc";
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ xtal: xtal-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <40000000>;
+ clock-output-names = "xtal";
+ #clock-cells = <0>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges;
+ interrupt-parent = <&plic>;
+ dma-noncoherent;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ uart0: serial@30002000 {
+ compatible = "bouffalolab,uart";
+ reg = <0x30002000 0x1000>;
+ interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&xtal>;
+ status = "disabled";
+ };
+
+ plic: interrupt-controller@e0000000 {
+ compatible = "thead,c900-plic";
+ reg = <0xe0000000 0x4000000>;
+ interrupts-extended = <&cpu0_intc 0xffffffff>,
+ <&cpu0_intc 9>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ riscv,ndev = <64>;
+ };
+ };
+};
--
2.39.0

View file

@ -0,0 +1,63 @@
From d22d4a678ec3fb88015e458077de5e933d860513 Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:13 +0800
Subject: [PATCH 06/15] riscv: dts: bouffalolab: add Sipeed M1S dock devicetree
Sipeed manufactures a M1S system-on-module and dock board, add basic
support for them.
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
arch/riscv/boot/dts/bouffalolab/Makefile | 2 ++
.../boot/dts/bouffalolab/bl808-sipeed-m1s.dts | 30 +++++++++++++++++++
2 files changed, 32 insertions(+)
create mode 100644 arch/riscv/boot/dts/bouffalolab/Makefile
create mode 100644 arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
diff --git a/arch/riscv/boot/dts/bouffalolab/Makefile b/arch/riscv/boot/dts/bouffalolab/Makefile
new file mode 100644
index 000000000000..42e17e1a97bd
--- /dev/null
+++ b/arch/riscv/boot/dts/bouffalolab/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_SOC_BOUFFALOLAB) += bl808-sipeed-m1s.dtb
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
new file mode 100644
index 000000000000..64421fb2ad67
--- /dev/null
+++ b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2022 Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "bl808.dtsi"
+
+/ {
+ model = "Sipeed M1S";
+ compatible = "sipeed,m1s", "bouffalolab,bl808";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:2000000n8";
+ };
+
+ memory@50000000 {
+ device_type = "memory";
+ reg = <0x50000000 0x04000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
--
2.39.0

View file

@ -0,0 +1,33 @@
From e1525068345d782bc4626b5927781760639bd6aa Mon Sep 17 00:00:00 2001
From: Jisheng Zhang <jszhang@kernel.org>
Date: Sun, 20 Nov 2022 16:21:14 +0800
Subject: [PATCH 07/15] MAINTAINERS: add myself as Bouffalolab SoC entry
maintainer
I want to maintain this Bouffalolab riscv SoC entry from now on.
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index dce6b97c4ed4..9508391b8dbe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17961,6 +17961,12 @@ F: arch/riscv/
N: riscv
K: riscv
+RISC-V BOUFFALOLAB SOC SUPPORT
+M: Jisheng Zhang <jszhang@kernel.org>
+L: linux-riscv at lists.infradead.org
+S: Maintained
+F: arch/riscv/boot/dts/bouffalolab/
+
RISC-V MICROCHIP FPGA SUPPORT
M: Conor Dooley <conor.dooley@microchip.com>
M: Daire McNamara <daire.mcnamara@microchip.com>
--
2.39.0

View file

@ -0,0 +1,26 @@
From 8e81e9413aaa7c01a73294df771e9e3b5d34289c Mon Sep 17 00:00:00 2001
From: Allen Martin <armartin@gmail.com>
Date: Sun, 8 Jan 2023 02:25:29 -0800
Subject: [PATCH 09/15] riscv: dts: bouffalolab: add bootargs/initrd
---
arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
index 64421fb2ad67..84e5aac6cbf8 100644
--- a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
+++ b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
@@ -17,6 +17,9 @@ aliases {
chosen {
stdout-path = "serial0:2000000n8";
+ bootargs = "console=ttyS0,2000000 loglevel=8 earlycon=sbi root=/dev/mtdblock0 ro rootfstype=squashfs";
+ linux,initrd-start = <0x0 0x52000000>;
+ linux,initrd-end = <0x0 0x52941784>;
};
memory@50000000 {
--
2.39.0

View file

@ -0,0 +1,37 @@
From c32fe195358bd4ad3c0e9653432150393e7cbaed Mon Sep 17 00:00:00 2001
From: Allen Martin <armartin@gmail.com>
Date: Sun, 8 Jan 2023 02:26:04 -0800
Subject: [PATCH 10/15] riscv: dts: bouffalolab: add xip_flash
---
.../boot/dts/bouffalolab/bl808-sipeed-m1s.dts | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
index 84e5aac6cbf8..bdb502ea5a54 100644
--- a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
+++ b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
@@ -26,6 +26,20 @@ memory@50000000 {
device_type = "memory";
reg = <0x50000000 0x04000000>;
};
+
+ xip_flash@58500000 {
+ compatible = "mtd-rom";
+ reg = <0x58500000 0x400000>;
+ linux,mtd-name = "xip-flash.0";
+ erase-size = <0x10000>;
+ bank-width = <4>;
+
+ rootfs@0 {
+ label = "rootfs";
+ reg = <0x00000 0x280000>;
+ read-only;
+ };
+ };
};
&uart0 {
--
2.39.0

View file

@ -0,0 +1,500 @@
From 986848ef501b28ccbe48336dfa201ad54b0e1e34 Mon Sep 17 00:00:00 2001
From: Allen Martin <armartin@gmail.com>
Date: Wed, 11 Jan 2023 18:14:53 -0800
Subject: [PATCH 11/15] WIP: add BFLB MBOX interrupt controller driver
---
.../boot/dts/bouffalolab/bl808-sipeed-m1s.dts | 4 +
arch/riscv/boot/dts/bouffalolab/bl808.dtsi | 14 +
drivers/mailbox/Kconfig | 9 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/bflb-ipc.c | 381 ++++++++++++++++++
include/dt-bindings/mailbox/bflb-ipc.h | 16 +
6 files changed, 426 insertions(+)
create mode 100644 drivers/mailbox/bflb-ipc.c
create mode 100644 include/dt-bindings/mailbox/bflb-ipc.h
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
index bdb502ea5a54..70259bad7dfd 100644
--- a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
+++ b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
@@ -45,3 +45,7 @@ rootfs@0 {
&uart0 {
status = "okay";
};
+
+&ipclic {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808.dtsi b/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
index c98ebb14ee10..c5cda8d74ccd 100644
--- a/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
+++ b/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/mailbox/bflb-ipc.h>
/ {
compatible = "bouffalolab,bl808";
@@ -60,6 +61,19 @@ uart0: serial@30002000 {
status = "disabled";
};
+ ipclic: mailbox@30005000 {
+ compatible = "bouffalolab,bflb-ipc";
+ reg = <0x30005000 0x20>,
+ <0x30005020 0x20>,
+ <0x2000a800 0x20>,
+ <0x2000a820 0x20>;
+ interrupts = <54 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
plic: interrupt-controller@e0000000 {
compatible = "thead,c900-plic";
reg = <0xe0000000 0x4000000>;
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 1495965bc394..c215da153fd7 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -295,4 +295,13 @@ config QCOM_IPCC
acts as an interrupt controller for receiving interrupts from clients.
Say Y here if you want to build this driver.
+config BFLB_IPC
+ tristate "Bouffalo Lab IPC driver"
+ depends on OF
+ help
+ (IPC) driver for BL808 devices. The driver provides mailbox support for
+ sending interrupts to the clients. On the other hand, the driver also
+ acts as an interrupt controller for receiving interrupts from clients.
+ Say Y here if you want to build this driver.
+
endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index fc9376117111..02bba5d03d4b 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -62,3 +62,5 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
obj-$(CONFIG_APPLE_MAILBOX) += apple-mailbox.o
+
+obj-$(CONFIG_BFLB_IPC) += bflb-ipc.o
diff --git a/drivers/mailbox/bflb-ipc.c b/drivers/mailbox/bflb-ipc.c
new file mode 100644
index 000000000000..692dd20e35a8
--- /dev/null
+++ b/drivers/mailbox/bflb-ipc.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Allen Martin <armartin@gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/mailbox/bflb-ipc.h>
+
+/* IPC Register offsets */
+#define IPC_REG_ISWR 0x00 /* Interrupt Set Write Register */
+#define IPC_REG_IRSRR 0x04 /* Interrupt raw status Register */
+#define IPC_REG_ICR 0x08 /* Interrupt Clear Register */
+#define IPC_REG_IUSR 0x0c /* Interrupt Unmask Set Register */
+#define IPC_REG_IUCR 0x10 /* Interrupt Unmask Clear Register */
+#define IPC_REG_ILSLR 0x14 /* Interrupt Line Sel Low Register */
+#define IPC_REG_ILSHR 0x18 /* Interrupt Line Sel High Register */
+#define IPC_REG_ISR 0x1c /* Interrupt status Register */
+
+/**
+ * struct bflb_ipc_chan_info - Per-mailbox-channel info
+ * @client_id: The client-id to which the interrupt has to be triggered
+ * @signal_id: The signal-id to which the interrupt has to be triggered
+ */
+struct bflb_ipc_chan_info {
+ u16 client_id;
+ u16 signal_id;
+};
+
+/**
+ * struct bflb_ipc - Holder for the mailbox driver
+ * @dev: Device associated with this instance
+ * @base: Base address of each IPC frame (LP, M0)
+ * @irq_domain: The irq_domain associated with this instance
+ * @chans: The mailbox channels array
+ * @mchan: The per-mailbox channel info array
+ * @mbox: The mailbox controller
+ * @num_chans: Number of @chans elements
+ * @irq: Summary irq
+ */
+struct bflb_ipc {
+ struct device *dev;
+ void __iomem *base[4];
+ struct irq_domain *irq_domain;
+ struct mbox_chan *chans;
+ struct bflb_ipc_chan_info *mchan;
+ struct mbox_controller mbox;
+ int num_chans;
+ int irq;
+};
+
+static inline struct bflb_ipc *to_bflb_ipc(struct mbox_controller *mbox)
+{
+ return container_of(mbox, struct bflb_ipc, mbox);
+}
+
+static inline u32 bflb_ipc_get_hwirq(u16 source, u16 device)
+{
+ pr_debug("%s: source: %u, device: %u\n", __func__, source, device);
+
+ return device;
+}
+
+#if 0
+static void bflb_ipc_dump_regs(struct bflb_ipc *ipc)
+{
+ int i;
+ for (i=0; i<4; i++) {
+ dev_dbg(ipc->dev, "base %px\n", ipc->base[i]);
+ dev_dbg(ipc->dev, "ISWR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ISWR));
+ dev_dbg(ipc->dev, "IRSRR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_IRSRR));
+ dev_dbg(ipc->dev, "ICR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ICR));
+ dev_dbg(ipc->dev, "IUSR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_IUSR));
+ dev_dbg(ipc->dev, "IUCR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_IUCR));
+ dev_dbg(ipc->dev, "ILSLR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ILSLR));
+ dev_dbg(ipc->dev, "ILSHR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ILSHR));
+ dev_dbg(ipc->dev, "ISR: 0x%08x\n", readl(ipc->base[i] + IPC_REG_ISR));
+ }
+}
+#endif
+
+static irqreturn_t bflb_ipc_irq_fn(int irq, void *data)
+{
+ struct bflb_ipc *ipc = data;
+ unsigned long stat;
+ int pos;
+
+ stat = readl(ipc->base[1] + IPC_REG_ISR);
+ for_each_set_bit(pos, &stat, 32)
+ generic_handle_domain_irq(ipc->irq_domain, pos);
+ writel(stat, ipc->base[1] + IPC_REG_ICR);
+
+ /* EOI the irqs */
+ writel(stat, ipc->base[2] + IPC_REG_ISWR);
+
+ return IRQ_HANDLED;
+}
+
+static void bflb_ipc_mask_irq(struct irq_data *irqd)
+{
+ struct bflb_ipc *ipc = irq_data_get_irq_chip_data(irqd);
+ irq_hw_number_t hwirq = irqd_to_hwirq(irqd);
+
+ writel(BIT(hwirq), ipc->base[1] + IPC_REG_IUCR);
+}
+
+static void bflb_ipc_unmask_irq(struct irq_data *irqd)
+{
+ struct bflb_ipc *ipc = irq_data_get_irq_chip_data(irqd);
+ irq_hw_number_t hwirq = irqd_to_hwirq(irqd);
+
+ writel(BIT(hwirq), ipc->base[1] + IPC_REG_IUSR);
+}
+
+static struct irq_chip bflb_ipc_irq_chip = {
+ .name = "BFLB MBOXIC",
+ .irq_mask = bflb_ipc_mask_irq,
+ .irq_unmask = bflb_ipc_unmask_irq,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int bflb_ipc_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct bflb_ipc *ipc = d->host_data;
+
+ irq_set_chip_and_handler(irq, &bflb_ipc_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, ipc);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static int bflb_ipc_domain_xlate(struct irq_domain *d,
+ struct device_node *node, const u32 *intspec,
+ unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ if (intsize != 3)
+ return -EINVAL;
+
+ *out_hwirq = bflb_ipc_get_hwirq(intspec[0], intspec[1]);
+ *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+
+ return 0;
+}
+
+static const struct irq_domain_ops bflb_ipc_irq_ops = {
+ .map = bflb_ipc_domain_map,
+ .xlate = bflb_ipc_domain_xlate,
+};
+
+static int bflb_ipc_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+ struct bflb_ipc *ipc = to_bflb_ipc(chan->mbox);
+ struct bflb_ipc_chan_info *mchan = chan->con_priv;
+ u32 hwirq;
+
+ hwirq = bflb_ipc_get_hwirq(mchan->client_id, mchan->signal_id);
+
+ dev_dbg(ipc->dev, "%s: hwirq: %u\n", __func__, hwirq);
+
+// writel(hwirq, ipc->base + IPC_REG_SEND_ID);
+
+ return 0;
+}
+
+static void bflb_ipc_mbox_shutdown(struct mbox_chan *chan)
+{
+ pr_debug("%s\n", __func__);
+ chan->con_priv = NULL;
+}
+
+static struct mbox_chan *bflb_ipc_mbox_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *ph)
+{
+ struct bflb_ipc *ipc = to_bflb_ipc(mbox);
+ struct bflb_ipc_chan_info *mchan;
+ struct mbox_chan *chan;
+ struct device *dev;
+ int chan_id;
+
+ dev = ipc->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (ph->args_count != 2)
+ return ERR_PTR(-EINVAL);
+
+ for (chan_id = 0; chan_id < mbox->num_chans; chan_id++) {
+ chan = &ipc->chans[chan_id];
+ mchan = chan->con_priv;
+
+ if (!mchan)
+ break;
+ else if (mchan->client_id == ph->args[0] &&
+ mchan->signal_id == ph->args[1])
+ return ERR_PTR(-EBUSY);
+ }
+
+ if (chan_id >= mbox->num_chans)
+ return ERR_PTR(-EBUSY);
+
+ mchan = devm_kzalloc(dev, sizeof(*mchan), GFP_KERNEL);
+ if (!mchan)
+ return ERR_PTR(-ENOMEM);
+
+ mchan->client_id = ph->args[0];
+ mchan->signal_id = ph->args[1];
+ chan->con_priv = mchan;
+
+ return chan;
+}
+
+static const struct mbox_chan_ops ipc_mbox_chan_ops = {
+ .send_data = bflb_ipc_mbox_send_data,
+ .shutdown = bflb_ipc_mbox_shutdown,
+};
+
+static int bflb_ipc_setup_mbox(struct bflb_ipc *ipc,
+ struct device_node *controller_dn)
+{
+ struct of_phandle_args curr_ph;
+ struct device_node *client_dn;
+ struct mbox_controller *mbox;
+ struct device *dev = ipc->dev;
+ int i, j, ret;
+
+ /*
+ * Find out the number of clients interested in this mailbox
+ * and create channels accordingly.
+ */
+ ipc->num_chans = 0;
+ for_each_node_with_property(client_dn, "mboxes") {
+ if (!of_device_is_available(client_dn))
+ continue;
+ i = of_count_phandle_with_args(client_dn,
+ "mboxes", "#mbox-cells");
+ for (j = 0; j < i; j++) {
+ ret = of_parse_phandle_with_args(client_dn, "mboxes",
+ "#mbox-cells", j, &curr_ph);
+ of_node_put(curr_ph.np);
+ if (!ret && curr_ph.np == controller_dn) {
+ ipc->num_chans++;
+ break;
+ }
+ }
+ }
+
+ /* If no clients are found, skip registering as a mbox controller */
+ if (!ipc->num_chans)
+ return 0;
+
+ ipc->chans = devm_kcalloc(dev, ipc->num_chans,
+ sizeof(struct mbox_chan), GFP_KERNEL);
+ if (!ipc->chans)
+ return -ENOMEM;
+
+ mbox = &ipc->mbox;
+ mbox->dev = dev;
+ mbox->num_chans = ipc->num_chans;
+ mbox->chans = ipc->chans;
+ mbox->ops = &ipc_mbox_chan_ops;
+ mbox->of_xlate = bflb_ipc_mbox_xlate;
+ mbox->txdone_irq = false;
+ mbox->txdone_poll = false;
+
+ return devm_mbox_controller_register(dev, mbox);
+}
+
+static int bflb_ipc_pm_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int bflb_ipc_probe(struct platform_device *pdev)
+{
+ struct bflb_ipc *ipc;
+ static int id;
+ int i;
+ char *name;
+ int ret;
+
+ ipc = devm_kzalloc(&pdev->dev, sizeof(*ipc), GFP_KERNEL);
+ if (!ipc)
+ return -ENOMEM;
+
+ ipc->dev = &pdev->dev;
+
+ for (i=0; i<4; i++) {
+ ipc->base[i] = devm_platform_ioremap_resource(pdev, i);
+ if (IS_ERR(ipc->base[i]))
+ return PTR_ERR(ipc->base[i]);
+ }
+
+ ipc->irq = platform_get_irq(pdev, 0);
+ if (ipc->irq < 0)
+ return ipc->irq;
+
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "mboxic%d", id++);
+ if (!name)
+ return -ENOMEM;
+
+ ipc->irq_domain = irq_domain_add_tree(pdev->dev.of_node,
+ &bflb_ipc_irq_ops, ipc);
+ if (!ipc->irq_domain)
+ return -ENOMEM;
+
+ ret = bflb_ipc_setup_mbox(ipc, pdev->dev.of_node);
+ if (ret)
+ goto err_mbox;
+
+ ret = devm_request_irq(&pdev->dev, ipc->irq, bflb_ipc_irq_fn,
+ IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND |
+ IRQF_NO_THREAD, name, ipc);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register the irq: %d\n", ret);
+ goto err_req_irq;
+ }
+
+ platform_set_drvdata(pdev, ipc);
+
+ dev_info(&pdev->dev, "Bouffalo Lab IPC mailbox interrupt controller");
+ return 0;
+
+err_req_irq:
+ if (ipc->num_chans)
+ mbox_controller_unregister(&ipc->mbox);
+err_mbox:
+ irq_domain_remove(ipc->irq_domain);
+
+ return ret;
+}
+
+static int bflb_ipc_remove(struct platform_device *pdev)
+{
+ struct bflb_ipc *ipc = platform_get_drvdata(pdev);
+
+ disable_irq_wake(ipc->irq);
+ irq_domain_remove(ipc->irq_domain);
+
+ return 0;
+}
+
+static const struct of_device_id bflb_ipc_of_match[] = {
+ { .compatible = "bouffalolab,bflb-ipc"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, bflb_ipc_of_match);
+
+static const struct dev_pm_ops bflb_ipc_dev_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, bflb_ipc_pm_resume)
+};
+
+static struct platform_driver bflb_ipc_driver = {
+ .probe = bflb_ipc_probe,
+ .remove = bflb_ipc_remove,
+ .driver = {
+ .name = "bflb-ipc",
+ .of_match_table = bflb_ipc_of_match,
+ .suppress_bind_attrs = true,
+ .pm = pm_sleep_ptr(&bflb_ipc_dev_pm_ops),
+ },
+};
+
+static int __init bflb_ipc_init(void)
+{
+ return platform_driver_register(&bflb_ipc_driver);
+}
+arch_initcall(bflb_ipc_init);
+
+MODULE_AUTHOR("Allen Martin <armartin@gmail.com>");
+MODULE_DESCRIPTION("Bouffalo Lab IPC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/dt-bindings/mailbox/bflb-ipc.h b/include/dt-bindings/mailbox/bflb-ipc.h
new file mode 100644
index 000000000000..1d4c4be6292e
--- /dev/null
+++ b/include/dt-bindings/mailbox/bflb-ipc.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2023 Allen Martin <armartin@gmail.com>
+ */
+
+#ifndef __DT_BINDINGS_MAILBOX_BFLB_IPC_H
+#define __DT_BINDINGS_MAILBOX_BFLB_IPC_H
+
+/* Source processor */
+#define BFLB_IPC_SOURCE_M0 0
+#define BFLB_IPC_SOURCE_LP 1
+
+/* Peripheral device ID */
+#define BFLB_IPC_DEVICE_SDHCI 0
+
+#endif
--
2.39.0

View file

@ -0,0 +1,214 @@
From 14d10e1f6fd28f9c760c46b5fd1becd2f2b20f9a Mon Sep 17 00:00:00 2001
From: Allen Martin <armartin@gmail.com>
Date: Wed, 11 Jan 2023 18:16:51 -0800
Subject: [PATCH 12/15] WIP: sdhci: add BFLB sdhci driver
---
.../boot/dts/bouffalolab/bl808-sipeed-m1s.dts | 4 +
arch/riscv/boot/dts/bouffalolab/bl808.dtsi | 11 ++
drivers/mmc/host/Kconfig | 14 +++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-bflb.c | 117 ++++++++++++++++++
5 files changed, 147 insertions(+)
create mode 100644 drivers/mmc/host/sdhci-bflb.c
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
index 70259bad7dfd..effaeda67c3f 100644
--- a/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
+++ b/arch/riscv/boot/dts/bouffalolab/bl808-sipeed-m1s.dts
@@ -46,6 +46,10 @@ &uart0 {
status = "okay";
};
+&sdhci0 {
+ status = "okay";
+};
+
&ipclic {
status = "okay";
};
diff --git a/arch/riscv/boot/dts/bouffalolab/bl808.dtsi b/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
index c5cda8d74ccd..6f859194f82c 100644
--- a/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
+++ b/arch/riscv/boot/dts/bouffalolab/bl808.dtsi
@@ -61,6 +61,17 @@ uart0: serial@30002000 {
status = "disabled";
};
+ sdhci0: sdhci@20060000 {
+ compatible = "bouffalolab,bflb-sdhci";
+ reg = <0x20060000 0x100>;
+ interrupts-extended = <&ipclic BFLB_IPC_SOURCE_M0
+ BFLB_IPC_DEVICE_SDHCI
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipclic BFLB_IPC_SOURCE_M0 BFLB_IPC_DEVICE_SDHCI>;
+ clocks = <&xtal>;
+ status = "disabled";
+ };
+
ipclic: mailbox@30005000 {
compatible = "bouffalolab,bflb-ipc";
reg = <0x30005000 0x20>,
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5e19a961c34d..f3c4654bb376 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -413,6 +413,20 @@ config MMC_SDHCI_F_SDH30
If unsure, say N.
+config MMC_SDHCI_BFLB
+ tristate "SDHCI support on Bouffalo Lab BL808 SoC"
+ depends on MMC_SDHCI_PLTFM
+ depends on OF
+ depends on COMMON_CLK
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Secure Digital Host Controller Interface in
+ Bouffalo Lab BL808 SoC.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_MILBEAUT
tristate "SDHCI support for Socionext Milbeaut Serieas using F_SDH30"
depends on MMC_SDHCI_PLTFM
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index ba0c6d0cd85d..626875dfb629 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -103,6 +103,7 @@ cqhci-y += cqhci-core.o
cqhci-$(CONFIG_MMC_CRYPTO) += cqhci-crypto.o
obj-$(CONFIG_MMC_HSQ) += mmc_hsq.o
obj-$(CONFIG_MMC_LITEX) += litex_mmc.o
+obj-$(CONFIG_MMC_SDHCI_BFLB) += sdhci-bflb.o
ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG
diff --git a/drivers/mmc/host/sdhci-bflb.c b/drivers/mmc/host/sdhci-bflb.c
new file mode 100644
index 000000000000..a67ecb2a380d
--- /dev/null
+++ b/drivers/mmc/host/sdhci-bflb.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include "sdhci-pltfm.h"
+
+static u16 sdhci_bflb_readw(struct sdhci_host *host, int reg)
+{
+ u16 ret;
+
+ switch (reg) {
+ case SDHCI_HOST_VERSION:
+ case SDHCI_SLOT_INT_STATUS:
+ /* those registers don't exist */
+ return 0;
+ default:
+ ret = readw(host->ioaddr + reg);
+ }
+ return ret;
+}
+
+static u32 sdhci_bflb_readl(struct sdhci_host *host, int reg)
+{
+ u32 ret;
+
+ ret = readl(host->ioaddr + reg);
+
+ switch (reg) {
+ case SDHCI_CAPABILITIES:
+ /* Mask the support for 3.0V */
+ ret &= ~SDHCI_CAN_VDD_300;
+ break;
+ }
+ return ret;
+}
+
+static const struct sdhci_ops sdhci_bflb_ops = {
+ .read_w = sdhci_bflb_readw,
+ .read_l = sdhci_bflb_readl,
+ .set_clock = sdhci_set_clock,
+ .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_bflb_pdata = {
+ .ops = &sdhci_bflb_ops,
+ .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
+ SDHCI_QUIRK_NO_BUSY_IRQ |
+ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ SDHCI_QUIRK_NO_HISPD_BIT |
+ SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+ SDHCI_QUIRK_BROKEN_DMA |
+ SDHCI_QUIRK_BROKEN_ADMA |
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+};
+
+static int sdhci_bflb_probe(struct platform_device *pdev)
+{
+ struct sdhci_host *host;
+ struct sdhci_pltfm_host *pltfm_host;
+ int ret;
+
+ host = sdhci_pltfm_init(pdev, &sdhci_bflb_pdata, 0);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+ pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
+
+ if (!IS_ERR(pltfm_host->clk))
+ clk_prepare_enable(pltfm_host->clk);
+
+ ret = mmc_of_parse(host->mmc);
+ if (ret)
+ goto err_sdhci_add;
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ goto err_sdhci_add;
+
+ return 0;
+
+err_sdhci_add:
+ clk_disable_unprepare(pltfm_host->clk);
+ sdhci_pltfm_free(pdev);
+ return ret;
+}
+
+static const struct of_device_id sdhci_bflb_of_match_table[] = {
+ { .compatible = "bouffalolab,bflb-sdhci", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sdhci_bflb_of_match_table);
+
+static struct platform_driver sdhci_bflb_driver = {
+ .driver = {
+ .name = "sdhci-bflb",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .pm = &sdhci_pltfm_pmops,
+ .of_match_table = sdhci_bflb_of_match_table,
+ },
+ .probe = sdhci_bflb_probe,
+ .remove = sdhci_pltfm_unregister,
+};
+
+module_platform_driver(sdhci_bflb_driver);
+
+MODULE_DESCRIPTION("SDHCI driver for Bflb");
+MODULE_LICENSE("GPL v2");
--
2.39.0

View file

@ -1 +1,26 @@
BR2_riscv=y
BR2_riscv_custom=y
BR2_RISCV_ISA_CUSTOM_RVM=y
BR2_RISCV_ISA_CUSTOM_RVF=y
BR2_RISCV_ISA_CUSTOM_RVC=y
BR2_RISCV_ABI_LP64=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y
BR2_TOOLCHAIN_EXTERNAL_URL="https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142514282/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1-20220906.tar.gz"
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="riscv64-unknown-linux-gnu"
BR2_TOOLCHAIN_EXTERNAL_GCC_10=y
BR2_TOOLCHAIN_EXTERNAL_HEADERS_5_10=y
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y
# BR2_TOOLCHAIN_EXTERNAL_INET_RPC is not set
BR2_TOOLCHAIN_EXTERNAL_CXX=y
BR2_CPAN_MIRROR="http://cpan.metacpan.org"
BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_BOUFFALO_BR_PATH)/board/pine64/ox64/patches/"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="v6.2-rc2"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_BOUFFALO_BR_PATH)/board/pine64/ox64/linux_defconfig"
BR2_LINUX_KERNEL_LZ4=y
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_DTB_IS_SELF_BUILT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bouffalolab/bl808-sipeed-m1s.dts"