mirror of
https://github.com/Fishwaldo/buildroot_bouffalo.git
synced 2025-03-16 03:41:21 +00:00
Add toolchain and Linux patches
This commit is contained in:
parent
22fce61235
commit
10ef70a311
13 changed files with 2177 additions and 0 deletions
293
board/pine64/ox64/linux_defconfig
Normal file
293
board/pine64/ox64/linux_defconfig
Normal 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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue