From: Torsten Duwe <[email protected]>

MFD base driver for the RP1 chip, similar to Linux'
drivers/misc/rp1/rp1_pci.c

Signed-off-by: Torsten Duwe <[email protected]>
Co-authored-by: Oleksii Moisieiev <[email protected]>
---

Note that with interrupt code removed and U-Boot specifics added,
there is not much similarity, actually.

---
 configs/rpi_arm64_defconfig   |   1 +
 drivers/mfd/Kconfig           |  10 ++
 drivers/mfd/Makefile          |   1 +
 drivers/mfd/rp1.c             | 127 +++++++++++++++++++
 include/dt-bindings/mfd/rp1.h | 239 ++++++++++++++++++++++++++++++++++
 include/pci_ids.h             |   3 +
 6 files changed, 388 insertions(+)
 create mode 100644 drivers/mfd/rp1.c
 create mode 100644 include/dt-bindings/mfd/rp1.h

diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 81a5311e16a..fcd37cb4fc9 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -42,6 +42,7 @@ CONFIG_SYS_DFU_DATA_BUF_SIZE=0x100000
 CONFIG_SYS_DFU_MAX_FILE_SIZE=0x200000
 CONFIG_BCM2835_GPIO=y
 CONFIG_RP1_GPIO=y
+CONFIG_MFD_RP1=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_BCM2835=y
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 79f4db9849c..c22dfdb806b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2,3 +2,13 @@ config MFD_ATMEL_SMC
        bool "Atmel Static Memory Controller driver"
        help
          Say yes here to support Atmel Static Memory Controller driver.
+
+config MFD_RP1
+       tristate "RP1 MFD driver"
+       depends on PCI
+       help
+         Support for the RP1 peripheral chip.
+
+         This driver provides support for the Raspberry Pi RP1 peripheral chip.
+         It is responsible for enabling the Device Tree node once the PCIe 
endpoint
+         has been configureds.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 4454815a981..c81ee5789b5 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o
+obj-$(CONFIG_MFD_RP1) += rp1.o
diff --git a/drivers/mfd/rp1.c b/drivers/mfd/rp1.c
new file mode 100644
index 00000000000..5cb6249c055
--- /dev/null
+++ b/drivers/mfd/rp1.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 EPAM Systems
+ *
+ * Derived from linux rp1 driver
+ * Copyright (c) 2018-22 Raspberry Pi Ltd.
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/of_access.h>
+#include <dt-bindings/mfd/rp1.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <pci.h>
+
+#define RP1_B0_CHIP_ID 0x10001927
+#define RP1_C0_CHIP_ID 0x20001927
+
+#define RP1_PLATFORM_ASIC BIT(1)
+#define RP1_PLATFORM_FPGA BIT(0)
+
+#define RP1_DRIVER_NAME "rp1"
+
+#define PCI_DEVICE_REV_RP1_C0 2
+
+#define SYSINFO_CHIP_ID_OFFSET 0x00000000
+#define SYSINFO_PLATFORM_OFFSET        0x00000004
+
+struct rp1_dev {
+       phys_addr_t bar_start;
+};
+
+static inline dma_addr_t rp1_io_to_phys(struct rp1_dev *rp1, unsigned int 
offset)
+{
+       return rp1->bar_start + offset;
+}
+
+static u32 rp1_reg_read(struct rp1_dev *rp1, unsigned int base_addr, u32 
offset)
+{
+       resource_size_t phys = rp1_io_to_phys(rp1, base_addr);
+       void __iomem *regblock = ioremap(phys, 0x1000);
+       u32 value = readl(regblock + offset);
+
+       iounmap(regblock);
+       return value;
+}
+
+static int rp1_get_bar_region(struct udevice *dev, phys_addr_t *bar_start)
+{
+       *bar_start = (phys_addr_t)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, 0, 0,
+                       PCI_REGION_TYPE, PCI_REGION_MEM);
+       return 0;
+}
+
+static int rp1_probe(struct udevice *dev)
+{
+       int ret;
+       struct rp1_dev *rp1 = dev_get_priv(dev);
+       u32 chip_id, platform;
+
+       /* Turn on bus-mastering */
+       dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MASTER | 
PCI_COMMAND_MEMORY);
+
+       /*
+        * HACK: Set bar address in the correct order.
+        * Required for correct U-Boot operation.
+        */
+       dm_pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0);
+       dm_pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0x40000);
+
+       ret = rp1_get_bar_region(dev, &rp1->bar_start);
+       if (ret)
+               return ret;
+
+       /* Get chip id */
+       chip_id = rp1_reg_read(rp1, RP1_SYSINFO_BASE, SYSINFO_CHIP_ID_OFFSET);
+       platform = rp1_reg_read(rp1, RP1_SYSINFO_BASE, SYSINFO_PLATFORM_OFFSET);
+       dev_dbg(dev, "chip_id 0x%x%s\n", chip_id,
+               (platform & RP1_PLATFORM_FPGA) ? " FPGA" : "");
+
+       if (chip_id != RP1_C0_CHIP_ID) {
+               dev_err(dev, "wrong chip id (%x)\n", chip_id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rp1_bind(struct udevice *dev)
+{
+       device_set_name(dev, RP1_DRIVER_NAME);
+       return 0;
+}
+
+static const struct pci_device_id dev_id_table[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RPI_RP1_C0), },
+       { 0, }
+};
+
+static int rp1_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
+                               uint offset, ulong *valuep, enum pci_size_t 
size)
+{
+       /*
+        * Leaving this call because pci subsystem calls for read_config
+        * and produces error then this callback is not set.
+        * Just return 0 here.s
+        */
+       *valuep = 0;
+       return 0;
+}
+
+static const struct dm_pci_ops rp1_pcie_ops = {
+       .read_config    = rp1_pcie_read_config,
+};
+
+U_BOOT_DRIVER(rp1_driver) = {
+       .name                   = RP1_DRIVER_NAME,
+       .id                     = UCLASS_PCI_GENERIC,
+       .probe                  = rp1_probe,
+       .bind                   = rp1_bind,
+       .priv_auto              = sizeof(struct rp1_dev),
+       .ops                    = &rp1_pcie_ops,
+};
+
+U_BOOT_PCI_DEVICE(rp1_driver, dev_id_table);
diff --git a/include/dt-bindings/mfd/rp1.h b/include/dt-bindings/mfd/rp1.h
new file mode 100644
index 00000000000..fca5729deb6
--- /dev/null
+++ b/include/dt-bindings/mfd/rp1.h
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for the PY MFD.
+ *
+ * Copyright (c) 2024 EPAM Systems
+ *
+ * Derived from linux rp1.h.
+ */
+
+#ifndef _RP1_H
+#define _RP1_H
+
+/* Address map */
+#define RP1_SYSINFO_BASE 0x000000
+#define RP1_TBMAN_BASE 0x004000
+#define RP1_SYSCFG_BASE 0x008000
+#define RP1_OTP_BASE 0x00c000
+#define RP1_POWER_BASE 0x010000
+#define RP1_RESETS_BASE 0x014000
+#define RP1_CLOCKS_BANK_DEFAULT_BASE 0x018000
+#define RP1_CLOCKS_BANK_VIDEO_BASE 0x01c000
+#define RP1_PLL_SYS_BASE 0x020000
+#define RP1_PLL_AUDIO_BASE 0x024000
+#define RP1_PLL_VIDEO_BASE 0x028000
+#define RP1_UART0_BASE 0x030000
+#define RP1_UART1_BASE 0x034000
+#define RP1_UART2_BASE 0x038000
+#define RP1_UART3_BASE 0x03c000
+#define RP1_UART4_BASE 0x040000
+#define RP1_UART5_BASE 0x044000
+#define RP1_SPI8_BASE 0x04c000
+#define RP1_SPI0_BASE 0x050000
+#define RP1_SPI1_BASE 0x054000
+#define RP1_SPI2_BASE 0x058000
+#define RP1_SPI3_BASE 0x05c000
+#define RP1_SPI4_BASE 0x060000
+#define RP1_SPI5_BASE 0x064000
+#define RP1_SPI6_BASE 0x068000
+#define RP1_SPI7_BASE 0x06c000
+#define RP1_I2C0_BASE 0x070000
+#define RP1_I2C1_BASE 0x074000
+#define RP1_I2C2_BASE 0x078000
+#define RP1_I2C3_BASE 0x07c000
+#define RP1_I2C4_BASE 0x080000
+#define RP1_I2C5_BASE 0x084000
+#define RP1_I2C6_BASE 0x088000
+#define RP1_AUDIO_IN_BASE 0x090000
+#define RP1_AUDIO_OUT_BASE 0x094000
+#define RP1_PWM0_BASE 0x098000
+#define RP1_PWM1_BASE 0x09c000
+#define RP1_I2S0_BASE 0x0a0000
+#define RP1_I2S1_BASE 0x0a4000
+#define RP1_I2S2_BASE 0x0a8000
+#define RP1_TIMER_BASE 0x0ac000
+#define RP1_SDIO0_APBS_BASE 0x0b0000
+#define RP1_SDIO1_APBS_BASE 0x0b4000
+#define RP1_BUSFABRIC_MONITOR_BASE 0x0c0000
+#define RP1_BUSFABRIC_AXISHIM_BASE 0x0c4000
+#define RP1_ADC_BASE 0x0c8000
+#define RP1_IO_BANK0_BASE 0x0d0000
+#define RP1_IO_BANK1_BASE 0x0d4000
+#define RP1_IO_BANK2_BASE 0x0d8000
+#define RP1_SYS_RIO0_BASE 0x0e0000
+#define RP1_SYS_RIO1_BASE 0x0e4000
+#define RP1_SYS_RIO2_BASE 0x0e8000
+#define RP1_PADS_BANK0_BASE 0x0f0000
+#define RP1_PADS_BANK1_BASE 0x0f4000
+#define RP1_PADS_BANK2_BASE 0x0f8000
+#define RP1_PADS_ETH_BASE 0x0fc000
+#define RP1_ETH_IP_BASE 0x100000
+#define RP1_ETH_CFG_BASE 0x104000
+#define RP1_PCIE_APBS_BASE 0x108000
+#define RP1_MIPI0_CSIDMA_BASE 0x110000
+#define RP1_MIPI0_CSIHOST_BASE 0x114000
+#define RP1_MIPI0_DSIDMA_BASE 0x118000
+#define RP1_MIPI0_DSIHOST_BASE 0x11c000
+#define RP1_MIPI0_MIPICFG_BASE 0x120000
+#define RP1_MIPI0_ISP_BASE 0x124000
+#define RP1_MIPI1_CSIDMA_BASE 0x128000
+#define RP1_MIPI1_CSIHOST_BASE 0x12c000
+#define RP1_MIPI1_DSIDMA_BASE 0x130000
+#define RP1_MIPI1_DSIHOST_BASE 0x134000
+#define RP1_MIPI1_MIPICFG_BASE 0x138000
+#define RP1_MIPI1_ISP_BASE 0x13c000
+#define RP1_VIDEO_OUT_CFG_BASE 0x140000
+#define RP1_VIDEO_OUT_VEC_BASE 0x144000
+#define RP1_VIDEO_OUT_DPI_BASE 0x148000
+#define RP1_XOSC_BASE 0x150000
+#define RP1_WATCHDOG_BASE 0x154000
+#define RP1_DMA_TICK_BASE 0x158000
+#define RP1_SDIO_CLOCKS_BASE 0x15c000
+#define RP1_USBHOST0_APBS_BASE 0x160000
+#define RP1_USBHOST1_APBS_BASE 0x164000
+#define RP1_ROSC0_BASE 0x168000
+#define RP1_ROSC1_BASE 0x16c000
+#define RP1_VBUSCTRL_BASE 0x170000
+#define RP1_TICKS_BASE 0x174000
+#define RP1_PIO_APBS_BASE 0x178000
+#define RP1_SDIO0_AHBLS_BASE 0x180000
+#define RP1_SDIO1_AHBLS_BASE 0x184000
+#define RP1_DMA_BASE 0x188000
+#define RP1_RAM_BASE 0x1c0000
+#define RP1_RAM_SIZE 0x020000
+#define RP1_USBHOST0_AXIS_BASE 0x200000
+#define RP1_USBHOST1_AXIS_BASE 0x300000
+#define RP1_EXAC_BASE 0x400000
+
+/* Interrupts */
+
+#define RP1_INT_IO_BANK0 0
+#define RP1_INT_IO_BANK1 1
+#define RP1_INT_IO_BANK2 2
+#define RP1_INT_AUDIO_IN 3
+#define RP1_INT_AUDIO_OUT 4
+#define RP1_INT_PWM0 5
+#define RP1_INT_ETH 6
+#define RP1_INT_I2C0 7
+#define RP1_INT_I2C1 8
+#define RP1_INT_I2C2 9
+#define RP1_INT_I2C3 10
+#define RP1_INT_I2C4 11
+#define RP1_INT_I2C5 12
+#define RP1_INT_I2C6 13
+#define RP1_INT_I2S0 14
+#define RP1_INT_I2S1 15
+#define RP1_INT_I2S2 16
+#define RP1_INT_SDIO0 17
+#define RP1_INT_SDIO1 18
+#define RP1_INT_SPI0 19
+#define RP1_INT_SPI1 20
+#define RP1_INT_SPI2 21
+#define RP1_INT_SPI3 22
+#define RP1_INT_SPI4 23
+#define RP1_INT_SPI5 24
+#define RP1_INT_UART0 25
+#define RP1_INT_TIMER_0 26
+#define RP1_INT_TIMER_1 27
+#define RP1_INT_TIMER_2 28
+#define RP1_INT_TIMER_3 29
+#define RP1_INT_USBHOST0 30
+#define RP1_INT_USBHOST0_0 31
+#define RP1_INT_USBHOST0_1 32
+#define RP1_INT_USBHOST0_2 33
+#define RP1_INT_USBHOST0_3 34
+#define RP1_INT_USBHOST1 35
+#define RP1_INT_USBHOST1_0 36
+#define RP1_INT_USBHOST1_1 37
+#define RP1_INT_USBHOST1_2 38
+#define RP1_INT_USBHOST1_3 39
+#define RP1_INT_DMA 40
+#define RP1_INT_PWM1 41
+#define RP1_INT_UART1 42
+#define RP1_INT_UART2 43
+#define RP1_INT_UART3 44
+#define RP1_INT_UART4 45
+#define RP1_INT_UART5 46
+#define RP1_INT_MIPI0 47
+#define RP1_INT_MIPI1 48
+#define RP1_INT_VIDEO_OUT 49
+#define RP1_INT_PIO_0 50
+#define RP1_INT_PIO_1 51
+#define RP1_INT_ADC_FIFO 52
+#define RP1_INT_PCIE_OUT 53
+#define RP1_INT_SPI6 54
+#define RP1_INT_SPI7 55
+#define RP1_INT_SPI8 56
+#define RP1_INT_SYSCFG 58
+#define RP1_INT_CLOCKS_DEFAULT 59
+#define RP1_INT_VBUSCTRL 60
+#define RP1_INT_PROC_MISC 57
+#define RP1_INT_END 61
+
+/* DMA peripherals (for pacing) */
+#define RP1_DMA_I2C0_RX 0x0
+#define RP1_DMA_I2C0_TX 0x1
+#define RP1_DMA_I2C1_RX 0x2
+#define RP1_DMA_I2C1_TX 0x3
+#define RP1_DMA_I2C2_RX 0x4
+#define RP1_DMA_I2C2_TX 0x5
+#define RP1_DMA_I2C3_RX 0x6
+#define RP1_DMA_I2C3_TX 0x7
+#define RP1_DMA_I2C4_RX 0x8
+#define RP1_DMA_I2C4_TX 0x9
+#define RP1_DMA_I2C5_RX 0xa
+#define RP1_DMA_I2C5_TX 0xb
+#define RP1_DMA_SPI0_RX 0xc
+#define RP1_DMA_SPI0_TX 0xd
+#define RP1_DMA_SPI1_RX 0xe
+#define RP1_DMA_SPI1_TX 0xf
+#define RP1_DMA_SPI2_RX 0x10
+#define RP1_DMA_SPI2_TX 0x11
+#define RP1_DMA_SPI3_RX 0x12
+#define RP1_DMA_SPI3_TX 0x13
+#define RP1_DMA_SPI4_RX 0x14
+#define RP1_DMA_SPI4_TX 0x15
+#define RP1_DMA_SPI5_RX 0x16
+#define RP1_DMA_SPI5_TX 0x17
+#define RP1_DMA_PWM0 0x18
+#define RP1_DMA_UART0_RX 0x19
+#define RP1_DMA_UART0_TX 0x1a
+#define RP1_DMA_AUDIO_IN_CH0 0x1b
+#define RP1_DMA_AUDIO_IN_CH1 0x1c
+#define RP1_DMA_AUDIO_OUT 0x1d
+#define RP1_DMA_PWM1 0x1e
+#define RP1_DMA_I2S0_RX 0x1f
+#define RP1_DMA_I2S0_TX 0x20
+#define RP1_DMA_I2S1_RX 0x21
+#define RP1_DMA_I2S1_TX 0x22
+#define RP1_DMA_I2S2_RX 0x23
+#define RP1_DMA_I2S2_TX 0x24
+#define RP1_DMA_UART1_RX 0x25
+#define RP1_DMA_UART1_TX 0x26
+#define RP1_DMA_UART2_RX 0x27
+#define RP1_DMA_UART2_TX 0x28
+#define RP1_DMA_UART3_RX 0x29
+#define RP1_DMA_UART3_TX 0x2a
+#define RP1_DMA_UART4_RX 0x2b
+#define RP1_DMA_UART4_TX 0x2c
+#define RP1_DMA_UART5_RX 0x2d
+#define RP1_DMA_UART5_TX 0x2e
+#define RP1_DMA_ADC 0x2f
+#define RP1_DMA_DMA_TICK_TICK0 0x30
+#define RP1_DMA_DMA_TICK_TICK1 0x31
+#define RP1_DMA_SPI6_RX 0x32
+#define RP1_DMA_SPI6_TX 0x33
+#define RP1_DMA_SPI7_RX 0x34
+#define RP1_DMA_SPI7_TX 0x35
+#define RP1_DMA_SPI8_RX 0x36
+#define RP1_DMA_SPI8_TX 0x37
+#define RP1_DMA_PIO_CH0_TX 0x38
+#define RP1_DMA_PIO_CH0_RX 0x39
+#define RP1_DMA_PIO_CH1_TX 0x3a
+#define RP1_DMA_PIO_CH1_RX 0x3b
+#define RP1_DMA_PIO_CH2_TX 0x3c
+#define RP1_DMA_PIO_CH2_RX 0x3d
+#define RP1_DMA_PIO_CH3_TX 0x3e
+#define RP1_DMA_PIO_CH3_RX 0x3f
+
+#endif
diff --git a/include/pci_ids.h b/include/pci_ids.h
index cfff275daba..4651b1c003e 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -2555,6 +2555,9 @@
 #define PCI_VENDOR_ID_TEKRAM           0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290     0xdc29
 
+#define PCI_VENDOR_ID_RPI              0x1de4
+#define PCI_DEVICE_ID_RPI_RP1_C0               0x0001
+
 #define PCI_VENDOR_ID_TEHUTI           0x1fc9
 #define PCI_DEVICE_ID_TEHUTI_3009      0x3009
 #define PCI_DEVICE_ID_TEHUTI_3010      0x3010
-- 
2.51.0

Reply via email to