summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2023-05-08 14:31:04 -0400
committerTom Rini <[email protected]>2023-05-08 14:31:04 -0400
commit11910550b65e6072b9542d462c0aa93f4ca81836 (patch)
tree8308c98ffad76d9693654a28090b03f270a7d250 /drivers
parent9876c8c147144db2c120fcc9ffa6de27f6894441 (diff)
parentf1d33a44ca04fdca241c1d89fd79e2e56c930c7e (diff)
Merge branch 'master' into next
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/ata/Kconfig9
-rw-r--r--drivers/ata/ahci.c11
-rw-r--r--drivers/block/Kconfig18
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/blk-uclass.c2
-rw-r--r--drivers/block/blkmap.c519
-rw-r--r--drivers/block/host_dev.c3
-rw-r--r--drivers/block/ide.c827
-rw-r--r--drivers/cache/cache-sifive-ccache.c1
-rw-r--r--drivers/clk/Kconfig9
-rw-r--r--drivers/clk/Makefile3
-rw-r--r--drivers/clk/mpc83xx_clk.c7
-rw-r--r--drivers/clk/renesas/Kconfig18
-rw-r--r--drivers/clk/renesas/Makefile2
-rw-r--r--drivers/clk/renesas/clk-rcar-gen3.c109
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c20
-rw-r--r--drivers/clk/renesas/r8a779f0-cpg-mssr.c250
-rw-r--r--drivers/clk/renesas/r8a779g0-cpg-mssr.c312
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.h28
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.h28
-rw-r--r--drivers/clk/rockchip/clk_rk3288.c1
-rw-r--r--drivers/clk/rockchip/clk_rk3568.c2
-rw-r--r--drivers/clk/rockchip/clk_rk3588.c127
-rw-r--r--drivers/clk/starfive/Kconfig17
-rw-r--r--drivers/clk/starfive/Makefile4
-rw-r--r--drivers/clk/starfive/clk-jh7110-pll.c321
-rw-r--r--drivers/clk/starfive/clk-jh7110.c603
-rw-r--r--drivers/clk/starfive/clk.h57
-rw-r--r--drivers/clk/sunxi/clk_a10.c2
-rw-r--r--drivers/clk/sunxi/clk_a10s.c2
-rw-r--r--drivers/clk/sunxi/clk_a23.c3
-rw-r--r--drivers/clk/sunxi/clk_a31.c6
-rw-r--r--drivers/clk/sunxi/clk_a64.c3
-rw-r--r--drivers/clk/sunxi/clk_a80.c8
-rw-r--r--drivers/clk/sunxi/clk_a83t.c3
-rw-r--r--drivers/clk/sunxi/clk_h3.c3
-rw-r--r--drivers/clk/sunxi/clk_h6.c5
-rw-r--r--drivers/clk/sunxi/clk_h616.c5
-rw-r--r--drivers/clk/sunxi/clk_r40.c3
-rw-r--r--drivers/core/fdtaddr.c6
-rw-r--r--drivers/core/of_access.c2
-rw-r--r--drivers/core/uclass.c50
-rw-r--r--drivers/ddr/marvell/a38x/mv_ddr_plat.c7
-rw-r--r--drivers/extcon/Kconfig31
-rw-r--r--drivers/extcon/Makefile7
-rw-r--r--drivers/extcon/extcon-max14526.c151
-rw-r--r--drivers/extcon/extcon-sandbox.c17
-rw-r--r--drivers/extcon/extcon-uclass.c16
-rw-r--r--drivers/fastboot/Kconfig14
-rw-r--r--drivers/fastboot/fb_common.c33
-rw-r--r--drivers/fastboot/fb_mmc.c19
-rw-r--r--drivers/firmware/psci.c1
-rw-r--r--drivers/firmware/scmi/scmi_agent-uclass.c2
-rw-r--r--drivers/gpio/Kconfig18
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/axp_gpio.c21
-rw-r--r--drivers/gpio/gpio-rcar.c1
-rw-r--r--drivers/gpio/gpio-uclass.c2
-rw-r--r--drivers/gpio/qe_gpio.c170
-rw-r--r--drivers/gpio/rk_gpio.c114
-rw-r--r--drivers/gpio/sh_pfc.c2
-rw-r--r--drivers/gpio/sunxi_gpio.c6
-rw-r--r--drivers/i2c/Kconfig2
-rw-r--r--drivers/i2c/designware_i2c_pci.c14
-rw-r--r--drivers/i2c/fsl_i2c.c16
-rw-r--r--drivers/i2c/i2c-uclass.c4
-rw-r--r--drivers/i2c/imx_lpi2c.c4
-rw-r--r--drivers/i2c/rcar_i2c.c1
-rw-r--r--drivers/misc/Kconfig7
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/esm_pmic.c9
-rw-r--r--drivers/misc/qcom-geni-se.c41
-rw-r--r--drivers/misc/rockchip-efuse.c12
-rw-r--r--drivers/misc/rockchip-otp.c12
-rw-r--r--drivers/misc/usb251xb.c4
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/hi6220_dw_mmc.c2
-rw-r--r--drivers/mmc/mmc.c3
-rw-r--r--drivers/mmc/mmc_write.c34
-rw-r--r--drivers/mmc/mv_sdhci.c55
-rw-r--r--drivers/mmc/npcm_sdhci.c2
-rw-r--r--drivers/mmc/renesas-sdhi.c1
-rw-r--r--drivers/mmc/rockchip_sdhci.c305
-rw-r--r--drivers/mmc/sdhci.c13
-rw-r--r--drivers/mmc/tmio-common.c59
-rw-r--r--drivers/mmc/tmio-common.h2
-rw-r--r--drivers/mtd/Kconfig2
-rw-r--r--drivers/mtd/Makefile1
-rw-r--r--drivers/mtd/nand/raw/Kconfig7
-rw-r--r--drivers/mtd/nand/raw/brcmnand/Makefile1
-rw-r--r--drivers/mtd/nand/raw/brcmnand/iproc_nand.c148
-rw-r--r--drivers/mtd/nand/raw/nand_base.c29
-rw-r--r--drivers/mtd/nand/raw/octeontx_bch.c2
-rw-r--r--drivers/mtd/nand/raw/octeontx_nand.c2
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c3
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c173
-rw-r--r--drivers/mtd/nvmxip/Kconfig19
-rw-r--r--drivers/mtd/nvmxip/Makefile8
-rw-r--r--drivers/mtd/nvmxip/nvmxip-uclass.c74
-rw-r--r--drivers/mtd/nvmxip/nvmxip.c119
-rw-r--r--drivers/mtd/nvmxip/nvmxip.h32
-rw-r--r--drivers/mtd/nvmxip/nvmxip_qspi.c70
-rw-r--r--drivers/mtd/spi/sandbox.c1
-rw-r--r--drivers/mtd/spi/spi-nor-core.c117
-rw-r--r--drivers/net/Kconfig10
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/dwc_eth_qos.c18
-rw-r--r--drivers/net/fsl-mc/mc.c29
-rw-r--r--drivers/net/ksz9477.c33
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c7
-rw-r--r--drivers/net/mvpp2.c61
-rw-r--r--drivers/net/phy/Kconfig5
-rw-r--r--drivers/net/phy/Makefile3
-rw-r--r--drivers/net/phy/adin.c9
-rw-r--r--drivers/net/phy/aquantia.c33
-rw-r--r--drivers/net/phy/atheros.c15
-rw-r--r--drivers/net/phy/b53.c9
-rw-r--r--drivers/net/phy/broadcom.c32
-rw-r--r--drivers/net/phy/ca_phy.c11
-rw-r--r--drivers/net/phy/cortina.c11
-rw-r--r--drivers/net/phy/davicom.c9
-rw-r--r--drivers/net/phy/dp83867.c10
-rw-r--r--drivers/net/phy/dp83869.c8
-rw-r--r--drivers/net/phy/et1011c.c9
-rw-r--r--drivers/net/phy/ethernet_id.c2
-rw-r--r--drivers/net/phy/fixed.c8
-rw-r--r--drivers/net/phy/generic_10g.c2
-rw-r--r--drivers/net/phy/intel_xway.c9
-rw-r--r--drivers/net/phy/lxt.c9
-rw-r--r--drivers/net/phy/marvell.c84
-rw-r--r--drivers/net/phy/marvell10g.c605
-rw-r--r--drivers/net/phy/meson-gxl.c9
-rw-r--r--drivers/net/phy/micrel_ksz8xxx.c29
-rw-r--r--drivers/net/phy/micrel_ksz90x1.c14
-rw-r--r--drivers/net/phy/mscc.c27
-rw-r--r--drivers/net/phy/mv88e61xx.c15
-rw-r--r--drivers/net/phy/natsemi.c15
-rw-r--r--drivers/net/phy/ncsi.c8
-rw-r--r--drivers/net/phy/nxp-c45-tja11xx.c8
-rw-r--r--drivers/net/phy/nxp-tja11xx.c12
-rw-r--r--drivers/net/phy/phy.c228
-rw-r--r--drivers/net/phy/realtek.c36
-rw-r--r--drivers/net/phy/smsc.c24
-rw-r--r--drivers/net/phy/teranetics.c9
-rw-r--r--drivers/net/phy/ti_phy_init.c38
-rw-r--r--drivers/net/phy/vitesse.c45
-rw-r--r--drivers/net/phy/xilinx_gmii2rgmii.c18
-rw-r--r--drivers/net/phy/xilinx_phy.c10
-rw-r--r--drivers/net/ravb.c1
-rw-r--r--drivers/net/rswitch.c1139
-rw-r--r--drivers/net/rtl8169.c52
-rw-r--r--drivers/net/sun8i_emac.c96
-rw-r--r--drivers/pci/pci_auto.c4
-rw-r--r--drivers/pci/pci_mpc85xx.c51
-rw-r--r--drivers/pci/pcie_fsl.c14
-rw-r--r--drivers/pci/pcie_layerscape_rc.c1
-rw-r--r--drivers/phy/Kconfig1
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c6
-rw-r--r--drivers/phy/phy-ti-am654.c1
-rw-r--r--drivers/phy/phy-uclass.c22
-rw-r--r--drivers/phy/renesas/Kconfig9
-rw-r--r--drivers/phy/renesas/Makefile1
-rw-r--r--drivers/phy/renesas/r8a779f0-ether-serdes.c384
-rw-r--r--drivers/phy/rockchip/Kconfig8
-rw-r--r--drivers/phy/rockchip/Makefile1
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c680
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c4
-rw-r--r--drivers/pinctrl/pinctrl_stm32.c19
-rw-r--r--drivers/pinctrl/renesas/Kconfig12
-rw-r--r--drivers/pinctrl/renesas/Makefile2
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a779f0.c2106
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a779g0.c4265
-rw-r--r--drivers/pinctrl/renesas/pfc.c28
-rw-r--r--drivers/pinctrl/renesas/sh_pfc.h5
-rw-r--r--drivers/pinctrl/rockchip/Makefile1
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rk3568.c66
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rk3588.c353
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rockchip.h187
-rw-r--r--drivers/pinctrl/starfive/Kconfig28
-rw-r--r--drivers/pinctrl/starfive/Makefile6
-rw-r--r--drivers/pinctrl/starfive/pinctrl-jh7110-aon.c113
-rw-r--r--drivers/pinctrl/starfive/pinctrl-jh7110-sys.c399
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive.c398
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive.h55
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c13
-rw-r--r--drivers/power/regulator/Kconfig7
-rw-r--r--drivers/power/regulator/Makefile1
-rw-r--r--drivers/power/regulator/axp_usb_power.c49
-rw-r--r--drivers/ram/Kconfig1
-rw-r--r--drivers/ram/Makefile4
-rw-r--r--drivers/ram/k3-am654-ddrss.c5
-rw-r--r--drivers/ram/rockchip/sdram_rk3399.c4
-rw-r--r--drivers/ram/starfive/Kconfig5
-rw-r--r--drivers/ram/starfive/Makefile11
-rw-r--r--drivers/ram/starfive/ddrcsr_boot.c339
-rw-r--r--drivers/ram/starfive/ddrphy_start.c279
-rw-r--r--drivers/ram/starfive/ddrphy_train.c383
-rw-r--r--drivers/ram/starfive/ddrphy_utils.c1955
-rw-r--r--drivers/ram/starfive/starfive_ddr.c161
-rw-r--r--drivers/ram/starfive/starfive_ddr.h65
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_interactive.c2
-rw-r--r--drivers/remoteproc/ti_k3_arm64_rproc.c62
-rw-r--r--drivers/reset/Kconfig16
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/reset-jh7110.c158
-rw-r--r--drivers/rng/Kconfig5
-rw-r--r--drivers/rng/rockchip_rng.c120
-rw-r--r--drivers/scsi/Kconfig2
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/serial-uclass.c24
-rw-r--r--drivers/serial/serial_mpc8xx.c24
-rw-r--r--drivers/serial/serial_msm_geni.c65
-rw-r--r--drivers/serial/serial_sh.c6
-rw-r--r--drivers/serial/serial_sh.h28
-rw-r--r--drivers/soc/Kconfig2
-rw-r--r--drivers/soc/soc_ti_k3.c34
-rw-r--r--drivers/spi/Kconfig3
-rw-r--r--drivers/spi/cadence_qspi.c16
-rw-r--r--drivers/spi/cadence_qspi_apb.c56
-rw-r--r--drivers/spi/mpc8xx_spi.c8
-rw-r--r--drivers/spi/mpc8xxx_spi.c13
-rw-r--r--drivers/spi/npcm_fiu_spi.c72
-rw-r--r--drivers/spi/spi-mem.c8
-rw-r--r--drivers/spi/spi-sn-f-ospi.c2
-rw-r--r--drivers/spi/spi-synquacer.c4
-rw-r--r--drivers/spi/stm32_qspi.c27
-rw-r--r--drivers/sysreset/sysreset_gpio.c7
-rw-r--r--drivers/sysreset/sysreset_psci.c7
-rw-r--r--drivers/sysreset/sysreset_sandbox.c1
-rw-r--r--drivers/tee/sandbox.c15
-rw-r--r--drivers/usb/emul/sandbox_flash.c1
-rw-r--r--drivers/usb/emul/sandbox_hub.c30
-rw-r--r--drivers/usb/gadget/composite.c2
-rw-r--r--drivers/usb/gadget/f_mass_storage.c3
-rw-r--r--drivers/usb/gadget/f_sdp.c1
-rw-r--r--drivers/usb/host/ehci-mx6.c10
-rw-r--r--drivers/video/Kconfig272
-rw-r--r--drivers/video/Makefile22
-rw-r--r--drivers/video/bridge/Kconfig7
-rw-r--r--drivers/video/bridge/Makefile1
-rw-r--r--drivers/video/bridge/ssd2825.c520
-rw-r--r--drivers/video/console_core.c6
-rw-r--r--drivers/video/dw_mipi_dsi.c9
-rw-r--r--drivers/video/endeavoru-panel.c252
-rw-r--r--drivers/video/lm3533_backlight.c134
-rw-r--r--drivers/video/orisetech_otm8009a.c4
-rw-r--r--drivers/video/raydium-rm68200.c4
-rw-r--r--drivers/video/renesas-r61307.c302
-rw-r--r--drivers/video/renesas-r69328.c238
-rw-r--r--drivers/video/rockchip/Kconfig8
-rw-r--r--drivers/video/rockchip/Makefile1
-rw-r--r--drivers/video/rockchip/dw_mipi_dsi_rockchip.c898
-rw-r--r--drivers/video/rockchip/rk_vop.c3
-rw-r--r--drivers/video/simple_panel.c51
-rw-r--r--drivers/video/sunxi/sunxi_dw_hdmi.c36
-rw-r--r--drivers/video/tdo-tl070wsh30.c4
-rw-r--r--drivers/video/tegra20/Kconfig24
-rw-r--r--drivers/video/tegra20/Makefile5
-rw-r--r--drivers/video/tegra20/mipi-phy.c134
-rw-r--r--drivers/video/tegra20/mipi-phy.h48
-rw-r--r--drivers/video/tegra20/tegra-dc.c (renamed from drivers/video/tegra.c)123
-rw-r--r--drivers/video/tegra20/tegra-dsi.c864
-rw-r--r--drivers/video/tegra20/tegra-pwm-backlight.c156
-rw-r--r--drivers/video/tidss/Kconfig6
-rw-r--r--drivers/video/tidss/Makefile2
-rw-r--r--drivers/video/vidconsole-uclass.c2
-rw-r--r--drivers/video/video-uclass.c14
-rw-r--r--drivers/video/video_bmp.c8
-rw-r--r--drivers/virtio/virtio-uclass.c8
-rw-r--r--drivers/virtio/virtio_pci_modern.c38
-rw-r--r--drivers/virtio/virtio_ring.c101
-rw-r--r--drivers/watchdog/Kconfig50
-rw-r--r--drivers/watchdog/Makefile5
-rw-r--r--drivers/watchdog/arm_smc_wdt.c123
-rw-r--r--drivers/watchdog/bcm2835_wdt.c132
-rw-r--r--drivers/watchdog/ftwdt010_wdt.c132
-rw-r--r--drivers/watchdog/mpc8xx_wdt.c75
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c112
-rw-r--r--drivers/xen/Kconfig2
-rw-r--r--drivers/xen/hypervisor.c7
286 files changed, 24458 insertions, 2181 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9101e538b09..75937fbb6d9 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -36,6 +36,8 @@ source "drivers/dfu/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/extcon/Kconfig"
+
source "drivers/fastboot/Kconfig"
source "drivers/firmware/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 58be410135d..29be78a3f28 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)DM) += core/
obj-$(CONFIG_$(SPL_TPL_)DMA) += dma/
obj-$(CONFIG_$(SPL_TPL_)DMA_LEGACY) += dma/
obj-$(CONFIG_$(SPL_TPL_)DFU) += dfu/
+obj-$(CONFIG_$(SPL_TPL_)EXTCON) += extcon/
obj-$(CONFIG_$(SPL_TPL_)GPIO) += gpio/
obj-$(CONFIG_$(SPL_TPL_)DRIVERS_MISC) += misc/
obj-$(CONFIG_$(SPL_TPL_)SYSRESET) += sysreset/
@@ -61,6 +62,7 @@ obj-$(CONFIG_SPL_USB_HOST) += usb/host/
obj-$(CONFIG_SPL_SATA) += ata/ scsi/
obj-$(CONFIG_SPL_LEGACY_BLOCK) += block/
obj-$(CONFIG_SPL_THERMAL) += thermal/
+obj-$(CONFIG_SPL_VIDEO) +=video/
endif
endif
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 3fe53d6d4f3..049f7efd10b 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -20,6 +20,14 @@ config SATA
See also CMD_SATA which provides command-line support.
+config SYS_SATA_MAX_PORTS
+ int "Maximum supported SATA ports"
+ depends on SCSI_AHCI && !DM_SCSI
+ default 1
+ help
+ Sets the maximum number of ports to scan when looking for devices.
+ Ports from 0 to (this value - 1) are scanned.
+
config LIBATA
bool
help
@@ -37,6 +45,7 @@ config AHCI_PCI
bool "Support for PCI-based AHCI controller"
depends on PCI
depends on DM_SCSI
+ depends on SCSI_AHCI
help
Enables support for the PCI-based AHCI controller.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 272c48b8e57..cb2c648a91f 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -211,8 +211,8 @@ static int ahci_host_init(struct ahci_uc_priv *uc_priv)
uc_priv->cap, uc_priv->port_map, uc_priv->n_ports);
#if !defined(CONFIG_DM_SCSI)
- if (uc_priv->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID)
- uc_priv->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID;
+ if (uc_priv->n_ports > CONFIG_SYS_SATA_MAX_PORTS)
+ uc_priv->n_ports = CONFIG_SYS_SATA_MAX_PORTS;
#endif
for (i = 0; i < uc_priv->n_ports; i++) {
@@ -1152,7 +1152,12 @@ int ahci_probe_scsi(struct udevice *ahci_dev, ulong base)
int ahci_probe_scsi_pci(struct udevice *ahci_dev)
{
ulong base;
- u16 vendor, device;
+ u16 vendor, device, cmd;
+
+ /* Enable bus mastering */
+ dm_pci_read_config16(ahci_dev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER;
+ dm_pci_write_config16(ahci_dev, PCI_COMMAND, cmd);
base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5, 0, 0,
PCI_REGION_TYPE, PCI_REGION_MEM);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index e95da48bdc0..5a1aeb3d2b4 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -67,6 +67,24 @@ config BLOCK_CACHE
it will prevent repeated reads from directory structures and other
filesystem data structures.
+config BLKMAP
+ bool "Composable virtual block devices (blkmap)"
+ depends on BLK
+ help
+ Create virtual block devices that are backed by various sources,
+ e.g. RAM, or parts of an existing block device. Though much more
+ rudimentary, it borrows a lot of ideas from Linux's device mapper
+ subsystem.
+
+ Example use-cases:
+ - Treat a region of RAM as a block device, i.e. a RAM disk. This let's
+ you extract files from filesystem images stored in RAM (perhaps as a
+ result of a TFTP transfer).
+ - Create a virtual partition on an existing device. This let's you
+ access filesystems that aren't stored at an exact partition
+ boundary. A common example is a filesystem image embedded in an FIT
+ image.
+
config SPL_BLOCK_CACHE
bool "Use block device cache in SPL"
depends on SPL_BLK
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index f12447d78d8..a161d145fd3 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_IDE) += ide.o
endif
obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o host_dev.o
obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o
+obj-$(CONFIG_BLKMAP) += blkmap.o
obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o
obj-$(CONFIG_EFI_MEDIA_SANDBOX) += sb_efi_media.o
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index c69fc4d5182..614b975e25c 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -28,10 +28,12 @@ static struct {
{ UCLASS_AHCI, "sata" },
{ UCLASS_HOST, "host" },
{ UCLASS_NVME, "nvme" },
+ { UCLASS_NVMXIP, "nvmxip" },
{ UCLASS_EFI_MEDIA, "efi" },
{ UCLASS_EFI_LOADER, "efiloader" },
{ UCLASS_VIRTIO, "virtio" },
{ UCLASS_PVBLOCK, "pvblock" },
+ { UCLASS_BLKMAP, "blkmap" },
};
static enum uclass_id uclass_name_to_iftype(const char *uclass_idname)
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
new file mode 100644
index 00000000000..2bb0acc20f2
--- /dev/null
+++ b/drivers/block/blkmap.c
@@ -0,0 +1,519 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Addiva Elektronik
+ * Author: Tobias Waldekranz <[email protected]>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <blkmap.h>
+#include <dm.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <part.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+struct blkmap;
+
+/**
+ * struct blkmap_slice - Region mapped to a blkmap
+ *
+ * Common data for a region mapped to a blkmap, specialized by each
+ * map type.
+ *
+ * @node: List node used to associate this slice with a blkmap
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks covered by this mapping
+ */
+struct blkmap_slice {
+ struct list_head node;
+
+ lbaint_t blknr;
+ lbaint_t blkcnt;
+
+ /**
+ * @read: - Read from slice
+ *
+ * @read.bm: Blkmap to which this slice belongs
+ * @read.bms: This slice
+ * @read.blknr: Start block number to read from
+ * @read.blkcnt: Number of blocks to read
+ * @read.buffer: Buffer to store read data to
+ */
+ ulong (*read)(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer);
+
+ /**
+ * @write: - Write to slice
+ *
+ * @write.bm: Blkmap to which this slice belongs
+ * @write.bms: This slice
+ * @write.blknr: Start block number to write to
+ * @write.blkcnt: Number of blocks to write
+ * @write.buffer: Data to be written
+ */
+ ulong (*write)(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, const void *buffer);
+
+ /**
+ * @destroy: - Tear down slice
+ *
+ * @read.bm: Blkmap to which this slice belongs
+ * @read.bms: This slice
+ */
+ void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms);
+};
+
+/**
+ * struct blkmap - Block map
+ *
+ * Data associated with a blkmap.
+ *
+ * @label: Human readable name of this blkmap
+ * @blk: Underlying block device
+ * @slices: List of slices associated with this blkmap
+ */
+struct blkmap {
+ char *label;
+ struct udevice *blk;
+ struct list_head slices;
+};
+
+static bool blkmap_slice_contains(struct blkmap_slice *bms, lbaint_t blknr)
+{
+ return (blknr >= bms->blknr) && (blknr < (bms->blknr + bms->blkcnt));
+}
+
+static bool blkmap_slice_available(struct blkmap *bm, struct blkmap_slice *new)
+{
+ struct blkmap_slice *bms;
+ lbaint_t first, last;
+
+ first = new->blknr;
+ last = new->blknr + new->blkcnt - 1;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (blkmap_slice_contains(bms, first) ||
+ blkmap_slice_contains(bms, last) ||
+ blkmap_slice_contains(new, bms->blknr) ||
+ blkmap_slice_contains(new, bms->blknr + bms->blkcnt - 1))
+ return false;
+ }
+
+ return true;
+}
+
+static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new)
+{
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ struct list_head *insert = &bm->slices;
+ struct blkmap_slice *bms;
+
+ if (!blkmap_slice_available(bm, new))
+ return -EBUSY;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (bms->blknr < new->blknr)
+ continue;
+
+ insert = &bms->node;
+ break;
+ }
+
+ list_add_tail(&new->node, insert);
+
+ /* Disk might have grown, update the size */
+ bms = list_last_entry(&bm->slices, struct blkmap_slice, node);
+ bd->lba = bms->blknr + bms->blkcnt;
+ return 0;
+}
+
+/**
+ * struct blkmap_linear - Linear mapping to other block device
+ *
+ * @slice: Common map data
+ * @blk: Target block device of this mapping
+ * @blknr: Start block number of the target device
+ */
+struct blkmap_linear {
+ struct blkmap_slice slice;
+
+ struct udevice *blk;
+ lbaint_t blknr;
+};
+
+static ulong blkmap_linear_read(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct blkmap_linear *bml = container_of(bms, struct blkmap_linear, slice);
+
+ return blk_read(bml->blk, bml->blknr + blknr, blkcnt, buffer);
+}
+
+static ulong blkmap_linear_write(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct blkmap_linear *bml = container_of(bms, struct blkmap_linear, slice);
+
+ return blk_write(bml->blk, bml->blknr + blknr, blkcnt, buffer);
+}
+
+int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ struct udevice *lblk, lbaint_t lblknr)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_linear *linear;
+ struct blk_desc *bd, *lbd;
+ int err;
+
+ bd = dev_get_uclass_plat(bm->blk);
+ lbd = dev_get_uclass_plat(lblk);
+ if (lbd->blksz != bd->blksz)
+ /* We could support block size translation, but we
+ * don't yet.
+ */
+ return -EINVAL;
+
+ linear = malloc(sizeof(*linear));
+ if (!linear)
+ return -ENOMEM;
+
+ *linear = (struct blkmap_linear) {
+ .slice = {
+ .blknr = blknr,
+ .blkcnt = blkcnt,
+
+ .read = blkmap_linear_read,
+ .write = blkmap_linear_write,
+ },
+
+ .blk = lblk,
+ .blknr = lblknr,
+ };
+
+ err = blkmap_slice_add(bm, &linear->slice);
+ if (err)
+ free(linear);
+
+ return err;
+}
+
+/**
+ * struct blkmap_mem - Memory mapping
+ *
+ * @slice: Common map data
+ * @addr: Target memory region of this mapping
+ * @remapped: True if @addr is backed by a physical to virtual memory
+ * mapping that must be torn down at the end of this mapping's
+ * lifetime.
+ */
+struct blkmap_mem {
+ struct blkmap_slice slice;
+ void *addr;
+ bool remapped;
+};
+
+static ulong blkmap_mem_read(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice);
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ char *src;
+
+ src = bmm->addr + (blknr << bd->log2blksz);
+ memcpy(buffer, src, blkcnt << bd->log2blksz);
+ return blkcnt;
+}
+
+static ulong blkmap_mem_write(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice);
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ char *dst;
+
+ dst = bmm->addr + (blknr << bd->log2blksz);
+ memcpy(dst, buffer, blkcnt << bd->log2blksz);
+ return blkcnt;
+}
+
+static void blkmap_mem_destroy(struct blkmap *bm, struct blkmap_slice *bms)
+{
+ struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice);
+
+ if (bmm->remapped)
+ unmap_sysmem(bmm->addr);
+}
+
+int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *addr, bool remapped)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_mem *bmm;
+ int err;
+
+ bmm = malloc(sizeof(*bmm));
+ if (!bmm)
+ return -ENOMEM;
+
+ *bmm = (struct blkmap_mem) {
+ .slice = {
+ .blknr = blknr,
+ .blkcnt = blkcnt,
+
+ .read = blkmap_mem_read,
+ .write = blkmap_mem_write,
+ .destroy = blkmap_mem_destroy,
+ },
+
+ .addr = addr,
+ .remapped = remapped,
+ };
+
+ err = blkmap_slice_add(bm, &bmm->slice);
+ if (err)
+ free(bmm);
+
+ return err;
+}
+
+int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *addr)
+{
+ return __blkmap_map_mem(dev, blknr, blkcnt, addr, false);
+}
+
+int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ phys_addr_t paddr)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ void *addr;
+ int err;
+
+ addr = map_sysmem(paddr, blkcnt << bd->log2blksz);
+ if (!addr)
+ return -ENOMEM;
+
+ err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true);
+ if (err)
+ unmap_sysmem(addr);
+
+ return err;
+}
+
+static ulong blkmap_blk_read_slice(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+{
+ lbaint_t nr, cnt;
+
+ nr = blknr - bms->blknr;
+ cnt = (blkcnt < bms->blkcnt) ? blkcnt : bms->blkcnt;
+ return bms->read(bm, bms, nr, cnt, buffer);
+}
+
+static ulong blkmap_blk_read(struct udevice *dev, lbaint_t blknr,
+ lbaint_t blkcnt, void *buffer)
+{
+ struct blk_desc *bd = dev_get_uclass_plat(dev);
+ struct blkmap *bm = dev_get_plat(dev->parent);
+ struct blkmap_slice *bms;
+ lbaint_t cnt, total = 0;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (!blkmap_slice_contains(bms, blknr))
+ continue;
+
+ cnt = blkmap_blk_read_slice(bm, bms, blknr, blkcnt, buffer);
+ blknr += cnt;
+ blkcnt -= cnt;
+ buffer += cnt << bd->log2blksz;
+ total += cnt;
+ }
+
+ return total;
+}
+
+static ulong blkmap_blk_write_slice(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ lbaint_t nr, cnt;
+
+ nr = blknr - bms->blknr;
+ cnt = (blkcnt < bms->blkcnt) ? blkcnt : bms->blkcnt;
+ return bms->write(bm, bms, nr, cnt, buffer);
+}
+
+static ulong blkmap_blk_write(struct udevice *dev, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct blk_desc *bd = dev_get_uclass_plat(dev);
+ struct blkmap *bm = dev_get_plat(dev->parent);
+ struct blkmap_slice *bms;
+ lbaint_t cnt, total = 0;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (!blkmap_slice_contains(bms, blknr))
+ continue;
+
+ cnt = blkmap_blk_write_slice(bm, bms, blknr, blkcnt, buffer);
+ blknr += cnt;
+ blkcnt -= cnt;
+ buffer += cnt << bd->log2blksz;
+ total += cnt;
+ }
+
+ return total;
+}
+
+static const struct blk_ops blkmap_blk_ops = {
+ .read = blkmap_blk_read,
+ .write = blkmap_blk_write,
+};
+
+U_BOOT_DRIVER(blkmap_blk) = {
+ .name = "blkmap_blk",
+ .id = UCLASS_BLK,
+ .ops = &blkmap_blk_ops,
+};
+
+int blkmap_dev_bind(struct udevice *dev)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blk_desc *bd;
+ int err;
+
+ err = blk_create_devicef(dev, "blkmap_blk", "blk", UCLASS_BLKMAP,
+ dev_seq(dev), 512, 0, &bm->blk);
+ if (err)
+ return log_msg_ret("blk", err);
+
+ INIT_LIST_HEAD(&bm->slices);
+
+ bd = dev_get_uclass_plat(bm->blk);
+ snprintf(bd->vendor, BLK_VEN_SIZE, "U-Boot");
+ snprintf(bd->product, BLK_PRD_SIZE, "blkmap");
+ snprintf(bd->revision, BLK_REV_SIZE, "1.0");
+
+ /* EFI core isn't keen on zero-sized disks, so we lie. This is
+ * updated with the correct size once the user adds a
+ * mapping.
+ */
+ bd->lba = 1;
+
+ return 0;
+}
+
+int blkmap_dev_unbind(struct udevice *dev)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_slice *bms, *tmp;
+ int err;
+
+ list_for_each_entry_safe(bms, tmp, &bm->slices, node) {
+ list_del(&bms->node);
+ free(bms);
+ }
+
+ err = device_remove(bm->blk, DM_REMOVE_NORMAL);
+ if (err)
+ return err;
+
+ return device_unbind(bm->blk);
+}
+
+U_BOOT_DRIVER(blkmap_root) = {
+ .name = "blkmap_dev",
+ .id = UCLASS_BLKMAP,
+ .bind = blkmap_dev_bind,
+ .unbind = blkmap_dev_unbind,
+ .plat_auto = sizeof(struct blkmap),
+};
+
+struct udevice *blkmap_from_label(const char *label)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ struct blkmap *bm;
+
+ uclass_id_foreach_dev(UCLASS_BLKMAP, dev, uc) {
+ bm = dev_get_plat(dev);
+ if (bm->label && !strcmp(label, bm->label))
+ return dev;
+ }
+
+ return NULL;
+}
+
+int blkmap_create(const char *label, struct udevice **devp)
+{
+ char *hname, *hlabel;
+ struct udevice *dev;
+ struct blkmap *bm;
+ size_t namelen;
+ int err;
+
+ dev = blkmap_from_label(label);
+ if (dev) {
+ err = -EBUSY;
+ goto err;
+ }
+
+ hlabel = strdup(label);
+ if (!hlabel) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ namelen = strlen("blkmap-") + strlen(label) + 1;
+ hname = malloc(namelen);
+ if (!hname) {
+ err = -ENOMEM;
+ goto err_free_hlabel;
+ }
+
+ strlcpy(hname, "blkmap-", namelen);
+ strlcat(hname, label, namelen);
+
+ err = device_bind_driver(dm_root(), "blkmap_dev", hname, &dev);
+ if (err)
+ goto err_free_hname;
+
+ device_set_name_alloced(dev);
+ bm = dev_get_plat(dev);
+ bm->label = hlabel;
+
+ if (devp)
+ *devp = dev;
+
+ return 0;
+
+err_free_hname:
+ free(hname);
+err_free_hlabel:
+ free(hlabel);
+err:
+ return err;
+}
+
+int blkmap_destroy(struct udevice *dev)
+{
+ int err;
+
+ err = device_remove(dev, DM_REMOVE_NORMAL);
+ if (err)
+ return err;
+
+ return device_unbind(dev);
+}
+
+UCLASS_DRIVER(blkmap) = {
+ .id = UCLASS_BLKMAP,
+ .name = "blkmap",
+};
diff --git a/drivers/block/host_dev.c b/drivers/block/host_dev.c
index 5885fc358a5..64422417b74 100644
--- a/drivers/block/host_dev.c
+++ b/drivers/block/host_dev.c
@@ -24,7 +24,8 @@ static int host_sb_attach_file(struct udevice *dev, const char *filename)
struct host_sb_plat *plat = dev_get_plat(dev);
struct blk_desc *desc;
struct udevice *blk;
- int ret, fd, size;
+ int ret, fd;
+ off_t size;
char *fname;
if (!filename)
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 1ad9b6c1267..89201dd4d22 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -36,9 +36,8 @@ ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = {
#endif
};
-static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS];
-
-struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
+#define ATA_CURR_BASE(dev) (CONFIG_SYS_ATA_BASE_ADDR + \
+ ide_bus_offset[IDE_BUS(dev)])
#define IDE_TIME_OUT 2000 /* 2 sec timeout */
@@ -46,35 +45,57 @@ struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
-#ifdef CONFIG_IDE_RESET
-extern void ide_set_reset(int idereset);
-
static void ide_reset(void)
{
- int i;
+ if (IS_ENABLED(CONFIG_IDE_RESET)) {
+ /* assert reset */
+ ide_set_reset(1);
- for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i)
- ide_bus_ok[i] = 0;
- for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i)
- ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
+ /* the reset signal shall be asserted for et least 25 us */
+ udelay(25);
- ide_set_reset(1); /* assert reset */
+ schedule();
- /* the reset signal shall be asserted for et least 25 us */
- udelay(25);
+ /* de-assert RESET signal */
+ ide_set_reset(0);
- schedule();
+ mdelay(250);
+ }
+}
- /* de-assert RESET signal */
- ide_set_reset(0);
+static void ide_outb(int dev, int port, u8 val)
+{
+ log_debug("(dev= %d, port= %#x, val= 0x%02x) : @ 0x%08lx\n",
+ dev, port, val, ATA_CURR_BASE(dev) + port);
- /* wait 250 ms */
- for (i = 0; i < 250; ++i)
- udelay(1000);
+ outb(val, ATA_CURR_BASE(dev) + port);
+}
+
+static u8 ide_inb(int dev, int port)
+{
+ uchar val;
+
+ val = inb(ATA_CURR_BASE(dev) + port);
+
+ log_debug("(dev= %d, port= %#x) : @ 0x%08lx -> 0x%02x\n",
+ dev, port, ATA_CURR_BASE(dev) + port, val);
+ return val;
+}
+
+static void ide_input_swap_data(int dev, ulong *sect_buf, int words)
+{
+ uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ ushort *dbuf = (ushort *)sect_buf;
+
+ log_debug("in input swap data base for read is %p\n", (void *)paddr);
+
+ while (words--) {
+ EIEIO;
+ *dbuf++ = be16_to_cpu(inw(paddr));
+ EIEIO;
+ *dbuf++ = be16_to_cpu(inw(paddr));
+ }
}
-#else
-#define ide_reset() /* dummy */
-#endif /* CONFIG_IDE_RESET */
/*
* Wait until Busy bit is off, or timeout (in ms)
@@ -87,7 +108,7 @@ static uchar ide_wait(int dev, ulong t)
while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
udelay(100);
- if (delay-- == 0)
+ if (!delay--)
break;
}
return c;
@@ -98,10 +119,9 @@ static uchar ide_wait(int dev, ulong t)
* terminate the string
* "len" is the size of available memory including the terminating '\0'
*/
-static void ident_cpy(unsigned char *dst, unsigned char *src,
- unsigned int len)
+static void ident_cpy(u8 *dst, u8 *src, uint len)
{
- unsigned char *end, *last;
+ u8 *end, *last;
last = dst;
end = src + len - 1;
@@ -124,21 +144,20 @@ OUT:
*last = '\0';
}
-#ifdef CONFIG_ATAPI
/****************************************************************************
* ATAPI Support
*/
/* since ATAPI may use commands with not 4 bytes alligned length
* we have our own transfer functions, 2 bytes alligned */
-__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
+static void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
{
- uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ uintptr_t paddr = ATA_CURR_BASE(dev) + ATA_DATA_REG;
ushort *dbuf;
dbuf = (ushort *)sect_buf;
- debug("in output data shorts base for read is %p\n", (void *)paddr);
+ log_debug("in output data shorts base for read is %p\n", (void *)paddr);
while (shorts--) {
EIEIO;
@@ -146,14 +165,14 @@ __weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
}
}
-__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
+static void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
{
- uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ uintptr_t paddr = ATA_CURR_BASE(dev) + ATA_DATA_REG;
ushort *dbuf;
dbuf = (ushort *)sect_buf;
- debug("in input data shorts base for read is %p\n", (void *)paddr);
+ log_debug("in input data shorts base for read is %p\n", (void *)paddr);
while (shorts--) {
EIEIO;
@@ -175,12 +194,12 @@ static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
/* prevents to read the status before valid */
c = ide_inb(dev, ATA_DEV_CTL);
- while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
+ while (c = ide_inb(dev, ATA_STATUS) & mask, c != res) {
/* break if error occurs (doesn't make sense to wait more) */
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR)
break;
udelay(100);
- if (delay-- == 0)
+ if (!delay--)
break;
}
return c;
@@ -189,10 +208,9 @@ static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
/*
* issue an atapi command
*/
-unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
- unsigned char *buffer, int buflen)
+static u8 atapi_issue(int device, u8 *ccb, int ccblen, u8 *buffer, int buflen)
{
- unsigned char c, err, mask, res;
+ u8 c, err, mask, res;
int n;
/* Select device
@@ -202,18 +220,17 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
if ((c & mask) != res) {
- printf("ATAPI_ISSUE: device %d not ready status %X\n", device,
+ printf("ATAPI_ISSUE: device %d not ready status %x\n", device,
c);
- err = 0xFF;
+ err = 0xff;
goto AI_OUT;
}
/* write taskfile */
ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
ide_outb(device, ATA_SECT_CNT, 0);
ide_outb(device, ATA_SECT_NUM, 0);
- ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF));
- ide_outb(device, ATA_CYL_HIGH,
- (unsigned char) ((buflen >> 8) & 0xFF));
+ ide_outb(device, ATA_CYL_LOW, (u8)(buflen & 0xff));
+ ide_outb(device, ATA_CYL_HIGH, (u8)((buflen >> 8) & 0xff));
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, ATA_CMD_PACKET);
@@ -224,17 +241,17 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */
- printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",
+ printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status %#02x\n",
device, c);
- err = 0xFF;
+ err = 0xff;
goto AI_OUT;
}
/* write command block */
- ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2);
+ ide_output_data_shorts(device, (ushort *)ccb, ccblen / 2);
/* ATAPI Command written wait for completition */
- udelay(5000); /* device must set bsy */
+ mdelay(5); /* device must set bsy */
mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
/*
@@ -248,12 +265,12 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
if ((c & mask) != res) {
if (c & ATA_STAT_ERR) {
err = (ide_inb(device, ATA_ERROR_REG)) >> 4;
- debug("atapi_issue 1 returned sense key %X status %02X\n",
- err, c);
+ log_debug("1 returned sense key %x status %02x\n",
+ err, c);
} else {
- printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n",
+ printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status %#02x\n",
ccb[0], c);
- err = 0xFF;
+ err = 0xff;
}
goto AI_OUT;
}
@@ -266,38 +283,36 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
err = 0xff;
goto AI_OUT;
}
- if ((n == 0) && (buflen < 0)) {
+ if (!n && buflen < 0) {
printf("ERROR, transfer bytes %d requested %d\n", n, buflen);
err = 0xff;
goto AI_OUT;
}
if (n != buflen) {
- debug("WARNING, transfer bytes %d not equal with requested %d\n",
- n, buflen);
+ log_debug("WARNING, transfer bytes %d not equal with requested %d\n",
+ n, buflen);
}
- if (n != 0) { /* data transfer */
- debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
+ if (n) { /* data transfer */
+ log_debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
/* we transfer shorts */
n >>= 1;
/* ok now decide if it is an in or output */
- if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) {
- debug("Write to device\n");
- ide_output_data_shorts(device, (unsigned short *)buffer,
- n);
+ if (!(ide_inb(device, ATA_SECT_CNT) & 0x02)) {
+ log_debug("Write to device\n");
+ ide_output_data_shorts(device, (ushort *)buffer, n);
} else {
- debug("Read from device @ %p shorts %d\n", buffer, n);
- ide_input_data_shorts(device, (unsigned short *)buffer,
- n);
+ log_debug("Read from device @ %p shorts %d\n", buffer,
+ n);
+ ide_input_data_shorts(device, (ushort *)buffer, n);
}
}
- udelay(5000); /* seems that some CD ROMs need this... */
+ mdelay(5); /* seems that some CD ROMs need this... */
mask = ATA_STAT_BUSY | ATA_STAT_ERR;
res = 0;
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
err = (ide_inb(device, ATA_ERROR_REG) >> 4);
- debug("atapi_issue 2 returned sense key %X status %X\n", err,
- c);
+ log_debug("2 returned sense key %x status %x\n", err, c);
} else {
err = 0;
}
@@ -313,13 +328,11 @@ AI_OUT:
#define ATAPI_DRIVE_NOT_READY 100
#define ATAPI_UNIT_ATTN 10
-unsigned char atapi_issue_autoreq(int device,
- unsigned char *ccb,
- int ccblen,
- unsigned char *buffer, int buflen)
+static u8 atapi_issue_autoreq(int device, u8 *ccb, int ccblen, u8 *buffer,
+ int buflen)
{
- unsigned char sense_data[18], sense_ccb[12];
- unsigned char res, key, asc, ascq;
+ u8 sense_data[18], sense_ccb[12];
+ u8 res, key, asc, ascq;
int notready, unitattn;
unitattn = ATAPI_UNIT_ATTN;
@@ -327,13 +340,13 @@ unsigned char atapi_issue_autoreq(int device,
retry:
res = atapi_issue(device, ccb, ccblen, buffer, buflen);
- if (res == 0)
+ if (!res)
return 0; /* Ok */
- if (res == 0xFF)
- return 0xFF; /* error */
+ if (res == 0xff)
+ return 0xff; /* error */
- debug("(auto_req)atapi_issue returned sense key %X\n", res);
+ log_debug("(auto_req)atapi_issue returned sense key %x\n", res);
memset(sense_ccb, 0, sizeof(sense_ccb));
memset(sense_data, 0, sizeof(sense_data));
@@ -341,29 +354,29 @@ retry:
sense_ccb[4] = 18; /* allocation Length */
res = atapi_issue(device, sense_ccb, 12, sense_data, 18);
- key = (sense_data[2] & 0xF);
+ key = (sense_data[2] & 0xf);
asc = (sense_data[12]);
ascq = (sense_data[13]);
- debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
- debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
- sense_data[0], key, asc, ascq);
+ log_debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
+ log_debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
+ sense_data[0], key, asc, ascq);
- if ((key == 0))
+ if (!key)
return 0; /* ok device ready */
- if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */
+ if (key == 6 || asc == 0x29 || asc == 0x28) { /* Unit Attention */
if (unitattn-- > 0) {
- udelay(200 * 1000);
+ mdelay(200);
goto retry;
}
printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN);
goto error;
}
- if ((asc == 0x4) && (ascq == 0x1)) {
+ if (asc == 0x4 && ascq == 0x1) {
/* not ready, but will be ready soon */
if (notready-- > 0) {
- udelay(200 * 1000);
+ mdelay(200);
goto retry;
}
printf("Drive not ready, tried %d times\n",
@@ -371,15 +384,15 @@ retry:
goto error;
}
if (asc == 0x3a) {
- debug("Media not present\n");
+ log_debug("Media not present\n");
goto error;
}
printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc,
ascq);
error:
- debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
- return 0xFF;
+ log_debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
+ return 0xff;
}
/*
@@ -391,16 +404,17 @@ error:
#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */
#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
-ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- void *buffer)
+static ulong atapi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
{
- int device = block_dev->devnum;
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
+ int device = desc->devnum;
ulong n = 0;
- unsigned char ccb[12]; /* Command descriptor block */
+ u8 ccb[12]; /* Command descriptor block */
ulong cnt;
- debug("atapi_read dev %d start " LBAF " blocks " LBAF
- " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer);
+ log_debug("%d start " LBAF " blocks " LBAF " buffer at %lx\n", device,
+ blknr, blkcnt, (ulong)buffer);
do {
if (blkcnt > ATAPI_READ_MAX_BLOCK)
@@ -410,143 +424,141 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
ccb[0] = ATAPI_CMD_READ_12;
ccb[1] = 0; /* reserved */
- ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */
- ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */
- ccb[4] = (unsigned char) (blknr >> 8) & 0xFF;
- ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */
- ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */
- ccb[7] = (unsigned char) (cnt >> 16) & 0xFF;
- ccb[8] = (unsigned char) (cnt >> 8) & 0xFF;
- ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */
+ ccb[2] = (u8)(blknr >> 24) & 0xff; /* MSB Block */
+ ccb[3] = (u8)(blknr >> 16) & 0xff; /* */
+ ccb[4] = (u8)(blknr >> 8) & 0xff;
+ ccb[5] = (u8)blknr & 0xff; /* LSB Block */
+ ccb[6] = (u8)(cnt >> 24) & 0xff; /* MSB Block cnt */
+ ccb[7] = (u8)(cnt >> 16) & 0xff;
+ ccb[8] = (u8)(cnt >> 8) & 0xff;
+ ccb[9] = (u8)cnt & 0xff; /* LSB Block */
ccb[10] = 0; /* reserved */
ccb[11] = 0; /* reserved */
if (atapi_issue_autoreq(device, ccb, 12,
- (unsigned char *)buffer,
- cnt * ATAPI_READ_BLOCK_SIZE)
- == 0xFF) {
+ (u8 *)buffer,
+ cnt * ATAPI_READ_BLOCK_SIZE) == 0xff)
return n;
- }
n += cnt;
blkcnt -= cnt;
blknr += cnt;
- buffer += (cnt * ATAPI_READ_BLOCK_SIZE);
+ buffer += cnt * ATAPI_READ_BLOCK_SIZE;
} while (blkcnt > 0);
return n;
}
-static void atapi_inquiry(struct blk_desc *dev_desc)
+static void atapi_inquiry(struct blk_desc *desc)
{
- unsigned char ccb[12]; /* Command descriptor block */
- unsigned char iobuf[64]; /* temp buf */
- unsigned char c;
+ u8 ccb[12]; /* Command descriptor block */
+ u8 iobuf[64]; /* temp buf */
+ u8 c;
int device;
- device = dev_desc->devnum;
- dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
+ device = desc->devnum;
+ desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
ccb[0] = ATAPI_CMD_INQUIRY;
ccb[4] = 40; /* allocation Legnth */
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40);
+ c = atapi_issue_autoreq(device, ccb, 12, (u8 *)iobuf, 40);
- debug("ATAPI_CMD_INQUIRY returned %x\n", c);
- if (c != 0)
+ log_debug("ATAPI_CMD_INQUIRY returned %x\n", c);
+ if (c)
return;
/* copy device ident strings */
- ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8);
- ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16);
- ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5);
+ ident_cpy((u8 *)desc->vendor, &iobuf[8], 8);
+ ident_cpy((u8 *)desc->product, &iobuf[16], 16);
+ ident_cpy((u8 *)desc->revision, &iobuf[32], 5);
- dev_desc->lun = 0;
- dev_desc->lba = 0;
- dev_desc->blksz = 0;
- dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
- dev_desc->type = iobuf[0] & 0x1f;
+ desc->lun = 0;
+ desc->lba = 0;
+ desc->blksz = 0;
+ desc->log2blksz = LOG2_INVALID(typeof(desc->log2blksz));
+ desc->type = iobuf[0] & 0x1f;
- if ((iobuf[1] & 0x80) == 0x80)
- dev_desc->removable = 1;
+ if (iobuf[1] & 0x80)
+ desc->removable = 1;
else
- dev_desc->removable = 0;
+ desc->removable = 0;
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
ccb[0] = ATAPI_CMD_START_STOP;
ccb[4] = 0x03; /* start */
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0);
+ c = atapi_issue_autoreq(device, ccb, 12, (u8 *)iobuf, 0);
- debug("ATAPI_CMD_START_STOP returned %x\n", c);
- if (c != 0)
+ log_debug("ATAPI_CMD_START_STOP returned %x\n", c);
+ if (c)
return;
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0);
+ c = atapi_issue_autoreq(device, ccb, 12, (u8 *)iobuf, 0);
- debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
- if (c != 0)
+ log_debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
+ if (c)
return;
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
ccb[0] = ATAPI_CMD_READ_CAP;
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8);
- debug("ATAPI_CMD_READ_CAP returned %x\n", c);
- if (c != 0)
+ c = atapi_issue_autoreq(device, ccb, 12, (u8 *)iobuf, 8);
+ log_debug("ATAPI_CMD_READ_CAP returned %x\n", c);
+ if (c)
return;
- debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
- iobuf[0], iobuf[1], iobuf[2], iobuf[3],
- iobuf[4], iobuf[5], iobuf[6], iobuf[7]);
+ log_debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
+ iobuf[0], iobuf[1], iobuf[2], iobuf[3],
+ iobuf[4], iobuf[5], iobuf[6], iobuf[7]);
+
+ desc->lba = (ulong)iobuf[0] << 24 | (ulong)iobuf[1] << 16 |
+ (ulong)iobuf[2] << 8 | (ulong)iobuf[3];
+ desc->blksz = (ulong)iobuf[4] << 24 | (ulong)iobuf[5] << 16 |
+ (ulong)iobuf[6] << 8 | (ulong)iobuf[7];
+ desc->log2blksz = LOG2(desc->blksz);
- dev_desc->lba = ((unsigned long) iobuf[0] << 24) +
- ((unsigned long) iobuf[1] << 16) +
- ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]);
- dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
- ((unsigned long) iobuf[5] << 16) +
- ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
- dev_desc->log2blksz = LOG2(dev_desc->blksz);
-#ifdef CONFIG_LBA48
/* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
- dev_desc->lba48 = 0;
-#endif
- return;
+ desc->lba48 = false;
}
-#endif /* CONFIG_ATAPI */
-
-static void ide_ident(struct blk_desc *dev_desc)
+/**
+ * ide_ident() - Identify an IDE device
+ *
+ * @device: Device number to use
+ * @desc: Block descriptor to fill in
+ * Returns: 0 if OK, -ENOENT if no device is found
+ */
+static int ide_ident(int device, struct blk_desc *desc)
{
- unsigned char c;
hd_driveid_t iop;
-#ifdef CONFIG_ATAPI
bool is_atapi = false;
- int retries = 0;
-#endif
- int device;
+ int tries = 1;
+ u8 c;
- device = dev_desc->devnum;
+ memset(desc, '\0', sizeof(*desc));
+ desc->devnum = device;
+ desc->type = DEV_TYPE_UNKNOWN;
+ desc->uclass_id = UCLASS_IDE;
+ desc->log2blksz = LOG2_INVALID(typeof(desc->log2blksz));
printf(" Device %d: ", device);
/* Select device
*/
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
- dev_desc->uclass_id = UCLASS_IDE;
-#ifdef CONFIG_ATAPI
-
- retries = 0;
+ if (IS_ENABLED(CONFIG_ATAPI))
+ tries = 2;
- /* Warning: This will be tricky to read */
- while (retries <= 1) {
+ while (tries) {
/* check signature */
- if ((ide_inb(device, ATA_SECT_CNT) == 0x01) &&
- (ide_inb(device, ATA_SECT_NUM) == 0x01) &&
- (ide_inb(device, ATA_CYL_LOW) == 0x14) &&
- (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) {
+ if (IS_ENABLED(CONFIG_ATAPI) &&
+ ide_inb(device, ATA_SECT_CNT) == 0x01 &&
+ ide_inb(device, ATA_SECT_NUM) == 0x01 &&
+ ide_inb(device, ATA_CYL_LOW) == 0x14 &&
+ ide_inb(device, ATA_CYL_HIGH) == 0xeb) {
/* ATAPI Signature found */
is_atapi = true;
/*
@@ -558,9 +570,7 @@ static void ide_ident(struct blk_desc *dev_desc)
* to become ready
*/
c = ide_wait(device, ATAPI_TIME_OUT);
- } else
-#endif
- {
+ } else {
/*
* Start Ident Command
*/
@@ -572,86 +582,70 @@ static void ide_ident(struct blk_desc *dev_desc)
c = ide_wait(device, IDE_TIME_OUT);
}
- if (((c & ATA_STAT_DRQ) == 0) ||
- ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) {
-#ifdef CONFIG_ATAPI
- {
- /*
- * Need to soft reset the device
- * in case it's an ATAPI...
- */
- debug("Retrying...\n");
- ide_outb(device, ATA_DEV_HD,
- ATA_LBA | ATA_DEVICE(device));
- udelay(100000);
- ide_outb(device, ATA_COMMAND, 0x08);
- udelay(500000); /* 500 ms */
- }
+ if ((c & ATA_STAT_DRQ) &&
+ !(c & (ATA_STAT_FAULT | ATA_STAT_ERR))) {
+ break;
+ } else if (IS_ENABLED(CONFIG_ATAPI)) {
/*
- * Select device
+ * Need to soft reset the device
+ * in case it's an ATAPI...
*/
+ log_debug("Retrying...\n");
+ ide_outb(device, ATA_DEV_HD,
+ ATA_LBA | ATA_DEVICE(device));
+ mdelay(100);
+ ide_outb(device, ATA_COMMAND, 0x08);
+ mdelay(500);
+ /* Select device */
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
- retries++;
-#else
- return;
-#endif
}
-#ifdef CONFIG_ATAPI
- else
- break;
- } /* see above - ugly to read */
+ tries--;
+ }
- if (retries == 2) /* Not found */
- return;
-#endif
+ if (!tries) /* Not found */
+ return -ENOENT;
ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
- ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev,
- sizeof(dev_desc->revision));
- ident_cpy((unsigned char *)dev_desc->vendor, iop.model,
- sizeof(dev_desc->vendor));
- ident_cpy((unsigned char *)dev_desc->product, iop.serial_no,
- sizeof(dev_desc->product));
+ ident_cpy((u8 *)desc->revision, iop.fw_rev, sizeof(desc->revision));
+ ident_cpy((u8 *)desc->vendor, iop.model, sizeof(desc->vendor));
+ ident_cpy((u8 *)desc->product, iop.serial_no, sizeof(desc->product));
- if ((iop.config & 0x0080) == 0x0080)
- dev_desc->removable = 1;
+ if (iop.config & 0x0080)
+ desc->removable = 1;
else
- dev_desc->removable = 0;
+ desc->removable = 0;
-#ifdef CONFIG_ATAPI
- if (is_atapi) {
- atapi_inquiry(dev_desc);
- return;
+ if (IS_ENABLED(CONFIG_ATAPI) && is_atapi) {
+ desc->atapi = true;
+ atapi_inquiry(desc);
+ return 0;
}
-#endif /* CONFIG_ATAPI */
iop.lba_capacity[0] = be16_to_cpu(iop.lba_capacity[0]);
iop.lba_capacity[1] = be16_to_cpu(iop.lba_capacity[1]);
- dev_desc->lba =
- ((unsigned long)iop.lba_capacity[0]) |
- ((unsigned long)iop.lba_capacity[1] << 16);
+ desc->lba = (ulong)iop.lba_capacity[0] |
+ (ulong)iop.lba_capacity[1] << 16;
-#ifdef CONFIG_LBA48
- if (iop.command_set_2 & 0x0400) { /* LBA 48 support */
- dev_desc->lba48 = 1;
+ if (IS_ENABLED(CONFIG_LBA48) && (iop.command_set_2 & 0x0400)) {
+ /* LBA 48 support */
+ desc->lba48 = true;
for (int i = 0; i < 4; i++)
iop.lba48_capacity[i] = be16_to_cpu(iop.lba48_capacity[i]);
- dev_desc->lba =
- ((unsigned long long)iop.lba48_capacity[0] |
- ((unsigned long long)iop.lba48_capacity[1] << 16) |
- ((unsigned long long)iop.lba48_capacity[2] << 32) |
- ((unsigned long long)iop.lba48_capacity[3] << 48));
+ desc->lba = (unsigned long long)iop.lba48_capacity[0] |
+ (unsigned long long)iop.lba48_capacity[1] << 16 |
+ (unsigned long long)iop.lba48_capacity[2] << 32 |
+ (unsigned long long)iop.lba48_capacity[3] << 48;
} else {
- dev_desc->lba48 = 0;
+ desc->lba48 = false;
}
-#endif /* CONFIG_LBA48 */
+
/* assuming HD */
- dev_desc->type = DEV_TYPE_HARDDISK;
- dev_desc->blksz = ATA_BLOCKSIZE;
- dev_desc->log2blksz = LOG2(dev_desc->blksz);
- dev_desc->lun = 0; /* just to fill something in... */
+ desc->type = DEV_TYPE_HARDDISK;
+ desc->blksz = ATA_BLOCKSIZE;
+ desc->log2blksz = LOG2(desc->blksz);
+ desc->lun = 0; /* just to fill something in... */
#if 0 /* only used to test the powersaving mode,
* if enabled, the drive goes after 5 sec
@@ -667,123 +661,58 @@ static void ide_ident(struct blk_desc *dev_desc)
udelay(50);
c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
#endif
-}
-__weak void ide_outb(int dev, int port, unsigned char val)
-{
- debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
- dev, port, val, ATA_CURR_BASE(dev) + port);
-
- outb(val, ATA_CURR_BASE(dev) + port);
-}
-
-__weak unsigned char ide_inb(int dev, int port)
-{
- uchar val;
-
- val = inb(ATA_CURR_BASE(dev) + port);
-
- debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
- dev, port, ATA_CURR_BASE(dev) + port, val);
- return val;
+ return 0;
}
-void ide_init(void)
+/**
+ * ide_init_one() - Init one IDE device
+ *
+ * @bus: Bus to use
+ * Return: 0 iuf OK, -EIO if not available, -ETIMEDOUT if timed out
+ */
+static int ide_init_one(int bus)
{
- struct udevice *dev;
- unsigned char c;
- int i, bus;
-
- schedule();
-
- /* ATAPI Drives seems to need a proper IDE Reset */
- ide_reset();
-
- /*
- * Wait for IDE to get ready.
- * According to spec, this can take up to 31 seconds!
- */
- for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
- int dev =
- bus * (CONFIG_SYS_IDE_MAXDEVICE /
- CONFIG_SYS_IDE_MAXBUS);
-
- printf("Bus %d: ", bus);
-
- ide_bus_ok[bus] = 0;
-
- /* Select device
- */
- udelay(100000); /* 100 ms */
- ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
- udelay(100000); /* 100 ms */
- i = 0;
- do {
- udelay(10000); /* 10 ms */
+ int dev = bus * CONFIG_SYS_IDE_MAXDEVICE / CONFIG_SYS_IDE_MAXBUS;
+ int i;
+ u8 c;
- c = ide_inb(dev, ATA_STATUS);
- i++;
- if (i > (ATA_RESET_TIME * 100)) {
- puts("** Timeout **\n");
- return;
- }
- if ((i >= 100) && ((i % 100) == 0))
- putc('.');
+ printf("Bus %d: ", bus);
- } while (c & ATA_STAT_BUSY);
+ /* Select device */
+ mdelay(100);
+ ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
+ mdelay(100);
+ i = 0;
+ do {
+ mdelay(10);
- if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
- puts("not available ");
- debug("Status = 0x%02X ", c);
-#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
- } else if ((c & ATA_STAT_READY) == 0) {
- puts("not available ");
- debug("Status = 0x%02X ", c);
-#endif
- } else {
- puts("OK ");
- ide_bus_ok[bus] = 1;
+ c = ide_inb(dev, ATA_STATUS);
+ i++;
+ if (i > (ATA_RESET_TIME * 100)) {
+ puts("** Timeout **\n");
+ return -ETIMEDOUT;
}
- schedule();
- }
+ if (i >= 100 && !(i % 100))
+ putc('.');
+ } while (c & ATA_STAT_BUSY);
- putc('\n');
-
- for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
- ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
- ide_dev_desc[i].uclass_id = UCLASS_IDE;
- ide_dev_desc[i].devnum = i;
- ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
- ide_dev_desc[i].blksz = 0;
- ide_dev_desc[i].log2blksz =
- LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
- ide_dev_desc[i].lba = 0;
- if (!ide_bus_ok[IDE_BUS(i)])
- continue;
- ide_ident(&ide_dev_desc[i]);
- dev_print(&ide_dev_desc[i]);
+ if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
+ puts("not available ");
+ log_debug("Status = %#02X ", c);
+ return -EIO;
+ } else if (IS_ENABLED(CONFIG_ATAPI) && !(c & ATA_STAT_READY)) {
+ /* ATAPI Devices do not set DRDY */
+ puts("not available ");
+ log_debug("Status = %#02X ", c);
+ return -EIO;
}
- schedule();
+ puts("OK ");
- uclass_first_device(UCLASS_IDE, &dev);
-}
-
-__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
-{
- uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
- ushort *dbuf = (ushort *)sect_buf;
-
- debug("in input swap data base for read is %p\n", (void *)paddr);
-
- while (words--) {
- EIEIO;
- *dbuf++ = be16_to_cpu(inw(paddr));
- EIEIO;
- *dbuf++ = be16_to_cpu(inw(paddr));
- }
+ return 0;
}
-__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
+static void ide_output_data(int dev, const ulong *sect_buf, int words)
{
uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf;
@@ -797,14 +726,14 @@ __weak void ide_output_data(int dev, const ulong *sect_buf, int words)
}
}
-__weak void ide_input_data(int dev, ulong *sect_buf, int words)
+static void ide_input_data(int dev, ulong *sect_buf, int words)
{
uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf;
dbuf = (ushort *)sect_buf;
- debug("in input data base for read is %p\n", (void *)paddr);
+ log_debug("in input data base for read is %p\n", (void *)paddr);
while (words--) {
EIEIO;
@@ -814,25 +743,23 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words)
}
}
-ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
- void *buffer)
+static ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
{
- struct blk_desc *block_dev = dev_get_uclass_plat(dev);
- int device = block_dev->devnum;
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
+ int device = desc->devnum;
+ bool lba48 = false;
ulong n = 0;
- unsigned char c;
- unsigned char pwrsave = 0; /* power save */
-
-#ifdef CONFIG_LBA48
- unsigned char lba48 = 0;
+ u8 pwrsave = 0; /* power save */
+ u8 c;
- if (blknr & 0x0000fffff0000000ULL) {
+ if (IS_ENABLED(CONFIG_LBA48) && (blknr & 0x0000fffff0000000ULL)) {
/* more than 28 bits used, use 48bit mode */
- lba48 = 1;
+ lba48 = true;
}
-#endif
- debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
- device, blknr, blkcnt, (ulong) buffer);
+
+ log_debug("dev %d start " LBAF ", blocks " LBAF " buffer at %lx\n",
+ device, blknr, blkcnt, (ulong)buffer);
/* Select device
*/
@@ -856,11 +783,11 @@ ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
goto IDE_READ_E;
}
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
- printf("No Powersaving mode %X\n", c);
+ printf("No Powersaving mode %x\n", c);
} else {
c = ide_inb(device, ATA_SECT_CNT);
- debug("Powersaving %02X\n", c);
- if (c == 0)
+ log_debug("Powersaving %02X\n", c);
+ if (!c)
pwrsave = 1;
}
@@ -872,36 +799,31 @@ ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
printf("IDE read: device %d not ready\n", device);
break;
}
-#ifdef CONFIG_LBA48
- if (lba48) {
+ if (IS_ENABLED(CONFIG_LBA48) && lba48) {
/* write high bits */
ide_outb(device, ATA_SECT_CNT, 0);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xff);
#ifdef CONFIG_SYS_64BIT_LBA
- ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
+ ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xff);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xff);
#else
ide_outb(device, ATA_LBA_MID, 0);
ide_outb(device, ATA_LBA_HIGH, 0);
#endif
}
-#endif
ide_outb(device, ATA_SECT_CNT, 1);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
- ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xff);
+ ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xff);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xff);
-#ifdef CONFIG_LBA48
- if (lba48) {
+ if (IS_ENABLED(CONFIG_LBA48) && lba48) {
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_READ_EXT);
- } else
-#endif
- {
+ } else {
ide_outb(device, ATA_DEV_HD, ATA_LBA |
- ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
+ ATA_DEVICE(device) | ((blknr >> 24) & 0xf));
ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_READ);
}
@@ -934,22 +856,19 @@ IDE_READ_E:
return n;
}
-ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
- const void *buffer)
+static ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
{
- struct blk_desc *block_dev = dev_get_uclass_plat(dev);
- int device = block_dev->devnum;
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
+ int device = desc->devnum;
ulong n = 0;
- unsigned char c;
-
-#ifdef CONFIG_LBA48
- unsigned char lba48 = 0;
+ bool lba48 = false;
+ u8 c;
- if (blknr & 0x0000fffff0000000ULL) {
+ if (IS_ENABLED(CONFIG_LBA48) && (blknr & 0x0000fffff0000000ULL)) {
/* more than 28 bits used, use 48bit mode */
- lba48 = 1;
+ lba48 = true;
}
-#endif
/* Select device
*/
@@ -962,36 +881,31 @@ ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
printf("IDE read: device %d not ready\n", device);
goto WR_OUT;
}
-#ifdef CONFIG_LBA48
- if (lba48) {
+ if (IS_ENABLED(CONFIG_LBA48) && lba48) {
/* write high bits */
ide_outb(device, ATA_SECT_CNT, 0);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xff);
#ifdef CONFIG_SYS_64BIT_LBA
- ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
+ ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xff);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xff);
#else
ide_outb(device, ATA_LBA_MID, 0);
ide_outb(device, ATA_LBA_HIGH, 0);
#endif
}
-#endif
ide_outb(device, ATA_SECT_CNT, 1);
- ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
- ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
- ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+ ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xff);
+ ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xff);
+ ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xff);
-#ifdef CONFIG_LBA48
- if (lba48) {
+ if (IS_ENABLED(CONFIG_LBA48) && lba48) {
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_WRITE_EXT);
- } else
-#endif
- {
+ } else {
ide_outb(device, ATA_DEV_HD, ATA_LBA |
- ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
+ ATA_DEVICE(device) | ((blknr >> 24) & 0xf));
ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_WRITE);
}
@@ -1017,35 +931,19 @@ WR_OUT:
return n;
}
-#if defined(CONFIG_OF_IDE_FIXUP)
-int ide_device_present(int dev)
+ulong ide_or_atapi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
{
- if (dev >= CONFIG_SYS_IDE_MAXBUS)
- return 0;
- return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1;
-}
-#endif
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
-static int ide_blk_probe(struct udevice *udev)
-{
- struct blk_desc *desc = dev_get_uclass_plat(udev);
+ if (IS_ENABLED(CONFIG_ATAPI) && desc->atapi)
+ return atapi_read(dev, blknr, blkcnt, buffer);
- /* fill in device vendor/product/rev strings */
- strncpy(desc->vendor, ide_dev_desc[desc->devnum].vendor,
- BLK_VEN_SIZE);
- desc->vendor[BLK_VEN_SIZE] = '\0';
- strncpy(desc->product, ide_dev_desc[desc->devnum].product,
- BLK_PRD_SIZE);
- desc->product[BLK_PRD_SIZE] = '\0';
- strncpy(desc->revision, ide_dev_desc[desc->devnum].revision,
- BLK_REV_SIZE);
- desc->revision[BLK_REV_SIZE] = '\0';
-
- return 0;
+ return ide_read(dev, blknr, blkcnt, buffer);
}
static const struct blk_ops ide_blk_ops = {
- .read = ide_read,
+ .read = ide_or_atapi_read,
.write = ide_write,
};
@@ -1053,7 +951,6 @@ U_BOOT_DRIVER(ide_blk) = {
.name = "ide_blk",
.id = UCLASS_BLK,
.ops = &ide_blk_ops,
- .probe = ide_blk_probe,
};
static int ide_bootdev_bind(struct udevice *dev)
@@ -1067,7 +964,9 @@ static int ide_bootdev_bind(struct udevice *dev)
static int ide_bootdev_hunt(struct bootdev_hunter *info, bool show)
{
- ide_init();
+ struct udevice *dev;
+
+ uclass_first_device(UCLASS_IDE, &dev);
return 0;
}
@@ -1097,40 +996,72 @@ BOOTDEV_HUNTER(ide_bootdev_hunter) = {
static int ide_probe(struct udevice *udev)
{
- struct udevice *blk_dev;
- char name[20];
- int blksz;
- lbaint_t size;
- int i;
- int ret;
+ bool bus_ok[CONFIG_SYS_IDE_MAXBUS];
+ int i, bus;
+
+ schedule();
+
+ /* ATAPI Drives seems to need a proper IDE Reset */
+ ide_reset();
+
+ /*
+ * Wait for IDE to get ready.
+ * According to spec, this can take up to 31 seconds!
+ */
+ for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
+ bus_ok[bus] = !ide_init_one(bus);
+ schedule();
+ }
+
+ putc('\n');
+
+ schedule();
for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; i++) {
- if (ide_dev_desc[i].type != DEV_TYPE_UNKNOWN) {
- sprintf(name, "blk#%d", i);
+ struct blk_desc *desc, pdesc;
+ struct udevice *blk;
+ char name[20];
+ int ret;
+
+ if (!bus_ok[IDE_BUS(i)])
+ continue;
- blksz = ide_dev_desc[i].blksz;
- size = blksz * ide_dev_desc[i].lba;
+ ret = ide_ident(i, &pdesc);
+ dev_print(&pdesc);
- /*
- * With CDROM, if there is no CD inserted, blksz will
- * be zero, don't bother to create IDE block device.
- */
- if (!blksz)
- continue;
- ret = blk_create_devicef(udev, "ide_blk", name,
- UCLASS_IDE, i,
- blksz, size, &blk_dev);
- if (ret)
- return ret;
+ if (ret)
+ continue;
- ret = blk_probe_or_unbind(blk_dev);
- if (ret)
- return ret;
+ sprintf(name, "blk#%d", i);
- ret = bootdev_setup_for_dev(udev, "ide_bootdev");
- if (ret)
- return log_msg_ret("bootdev", ret);
- }
+ /*
+ * With CDROM, if there is no CD inserted, blksz will
+ * be zero, don't bother to create IDE block device.
+ */
+ if (!pdesc.blksz)
+ continue;
+ ret = blk_create_devicef(udev, "ide_blk", name, UCLASS_IDE, i,
+ pdesc.blksz, pdesc.lba, &blk);
+ if (ret)
+ return ret;
+
+ ret = blk_probe_or_unbind(blk);
+ if (ret)
+ return ret;
+
+ /* fill in device vendor/product/rev strings */
+ desc = dev_get_uclass_plat(blk);
+ strlcpy(desc->vendor, pdesc.vendor, BLK_VEN_SIZE);
+ strlcpy(desc->product, pdesc.product, BLK_PRD_SIZE);
+ strlcpy(desc->revision, pdesc.revision, BLK_REV_SIZE);
+ desc->removable = pdesc.removable;
+ desc->atapi = pdesc.atapi;
+ desc->lba48 = pdesc.lba48;
+ desc->type = pdesc.type;
+
+ ret = bootdev_setup_for_dev(udev, "ide_bootdev");
+ if (ret)
+ return log_msg_ret("bootdev", ret);
}
return 0;
diff --git a/drivers/cache/cache-sifive-ccache.c b/drivers/cache/cache-sifive-ccache.c
index c8766f62427..521df40466f 100644
--- a/drivers/cache/cache-sifive-ccache.c
+++ b/drivers/cache/cache-sifive-ccache.c
@@ -62,6 +62,7 @@ static int sifive_ccache_probe(struct udevice *dev)
static const struct udevice_id sifive_ccache_ids[] = {
{ .compatible = "sifive,fu540-c000-ccache" },
{ .compatible = "sifive,fu740-c000-ccache" },
+ { .compatible = "sifive,ccache0" },
{}
};
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 42280cbf83a..3ad5af964f3 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -166,6 +166,14 @@ config CLK_SCMI
by a SCMI agent based on SCMI clock protocol communication
with a SCMI server.
+config SPL_CLK_SCMI
+ bool "Enable SCMI clock driver in SPL"
+ depends on SCMI_FIRMWARE && SPL_FIRMWARE
+ help
+ Enable this option if you want to support clock devices exposed
+ by a SCMI agent based on SCMI clock protocol communication
+ with a SCMI server in SPL.
+
config CLK_HSDK
bool "Enable cgu clock driver for HSDK boards"
depends on CLK && TARGET_HSDK
@@ -235,6 +243,7 @@ source "drivers/clk/owl/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/sunxi/Kconfig"
source "drivers/clk/sifive/Kconfig"
+source "drivers/clk/starfive/Kconfig"
source "drivers/clk/stm32/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c274cda77c6..e22c8cf291f 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o
obj-y += analogbits/
obj-y += imx/
+obj-$(CONFIG_CLK_JH7110) += starfive/
obj-y += tegra/
obj-y += ti/
obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/
@@ -39,7 +40,7 @@ obj-$(CONFIG_CLK_MVEBU) += mvebu/
obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o
obj-$(CONFIG_CLK_OWL) += owl/
obj-$(CONFIG_CLK_RENESAS) += renesas/
-obj-$(CONFIG_CLK_SCMI) += clk_scmi.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_SCMI) += clk_scmi.o
obj-$(CONFIG_CLK_SIFIVE) += sifive/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o
diff --git a/drivers/clk/mpc83xx_clk.c b/drivers/clk/mpc83xx_clk.c
index 0255ccaf8a4..cc734450ef0 100644
--- a/drivers/clk/mpc83xx_clk.c
+++ b/drivers/clk/mpc83xx_clk.c
@@ -346,8 +346,10 @@ static int mpc83xx_clk_probe(struct udevice *dev)
type = dev_get_driver_data(dev);
+#ifdef CONFIG_FSL_ESDHC
if (mpc83xx_has_sdhc(type))
gd->arch.sdhc_clk = priv->speed[MPC83XX_CLK_SDHC];
+#endif
gd->arch.core_clk = priv->speed[MPC83XX_CLK_CORE];
gd->arch.i2c1_clk = priv->speed[MPC83XX_CLK_I2C1];
@@ -362,6 +364,11 @@ static int mpc83xx_clk_probe(struct udevice *dev)
gd->cpu_clk = priv->speed[MPC83XX_CLK_CORE];
gd->bus_clk = priv->speed[MPC83XX_CLK_CSB];
+#ifdef CONFIG_QE
+ gd->arch.qe_clk = priv->speed[MPC83XX_CLK_QE];
+ gd->arch.brg_clk = priv->speed[MPC83XX_CLK_BRG];
+#endif
+
return 0;
}
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index d58e897ca1b..45671c69251 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -45,13 +45,13 @@ config CLK_R8A7794
Enable this to support the clocks on Renesas R8A7794 SoC.
config CLK_RCAR_GEN3
- bool "Renesas RCar Gen3 clock driver"
- def_bool y if RCAR_GEN3
+ bool "Renesas RCar Gen3 and Gen4 clock driver"
+ def_bool y if RCAR_64
depends on CLK_RENESAS
select CLK_RCAR_CPG_LIB
select DM_RESET
help
- Enable this to support the clocks on Renesas RCar Gen3 SoC.
+ Enable this to support the clocks on Renesas RCar Gen3 and Gen4 SoCs.
config CLK_R8A774A1
bool "Renesas R8A774A1 clock driver"
@@ -131,3 +131,15 @@ config CLK_R8A779A0
depends on CLK_RCAR_GEN3
help
Enable this to support the clocks on Renesas R8A779A0 SoC.
+
+config CLK_R8A779F0
+ bool "Renesas R8A779F0 clock driver"
+ depends on CLK_RCAR_GEN3
+ help
+ Enable this to support the clocks on Renesas R8A779F0 SoC.
+
+config CLK_R8A779G0
+ bool "Renesas R8A779G0 clock driver"
+ depends on CLK_RCAR_GEN3
+ help
+ Enable this to support the clocks on Renesas R8A779G0 SoC.
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 8f82a7aa3e0..fe0391e520c 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -20,3 +20,5 @@ obj-$(CONFIG_CLK_R8A77980) += r8a77980-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o
obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779G0) += r8a779g0-cpg-mssr.o
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index 1697867ff0b..c8a5512b65e 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -35,10 +35,16 @@
#define CPG_PLL2CR 0x002c
#define CPG_PLL4CR 0x01f4
-static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+#define SD0CKCR1 0x08a4
+
+static const struct clk_div_table gen3_cpg_rpcsrc_div_table[] = {
{ 2, 5 }, { 3, 6 }, { 0, 0 },
};
+static const struct clk_div_table gen4_cpg_rpcsrc_div_table[] = {
+ { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
static const struct clk_div_table r8a77970_cpg_sd0h_div_table[] = {
{ 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
{ 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
@@ -181,8 +187,10 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
struct cpg_mssr_info *info = priv->info;
struct clk parent;
const struct cpg_core_clk *core;
- const struct rcar_gen3_cpg_pll_config *pll_config =
- priv->cpg_pll_config;
+ const struct rcar_gen3_cpg_pll_config *gen3_pll_config =
+ priv->gen3_cpg_pll_config;
+ const struct rcar_gen4_cpg_pll_config *gen4_pll_config =
+ priv->gen4_cpg_pll_config;
u32 value, div;
u64 rate = 0;
u8 shift;
@@ -227,7 +235,7 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
case CLK_TYPE_GEN3_MAIN:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- 0, 1, pll_config->extal_div,
+ 0, 1, gen3_pll_config->extal_div,
"MAIN");
case CLK_TYPE_GEN3_PLL0:
@@ -236,8 +244,9 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
case CLK_TYPE_GEN3_PLL1:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- 0, pll_config->pll1_mult,
- pll_config->pll1_div, "PLL1");
+ 0, gen3_pll_config->pll1_mult,
+ gen3_pll_config->pll1_div,
+ "PLL1");
case CLK_TYPE_GEN3_PLL2:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
@@ -245,8 +254,9 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
case CLK_TYPE_GEN3_PLL3:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- 0, pll_config->pll3_mult,
- pll_config->pll3_div, "PLL3");
+ 0, gen3_pll_config->pll3_mult,
+ gen3_pll_config->pll3_div,
+ "PLL3");
case CLK_TYPE_GEN3_PLL4:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
@@ -254,25 +264,48 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
case CLK_TYPE_GEN4_MAIN:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- 0, 1, pll_config->extal_div,
- "V3U_MAIN");
+ 0, 1, gen4_pll_config->extal_div,
+ "MAIN");
case CLK_TYPE_GEN4_PLL1:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- 0, pll_config->pll1_mult,
- pll_config->pll1_div,
- "V3U_PLL1");
+ 0, gen4_pll_config->pll1_mult,
+ gen4_pll_config->pll1_div,
+ "PLL1");
+
+ case CLK_TYPE_GEN4_PLL2:
+ return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+ 0, gen4_pll_config->pll2_mult,
+ gen4_pll_config->pll2_div,
+ "PLL2");
case CLK_TYPE_GEN4_PLL2X_3X:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- core->offset, 0, 0,
- "V3U_PLL2X_3X");
+ core->offset, 0, 0, "PLL2X_3X");
+
+ case CLK_TYPE_GEN4_PLL3:
+ return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+ 0, gen4_pll_config->pll3_mult,
+ gen4_pll_config->pll3_div,
+ "PLL3");
+
+ case CLK_TYPE_GEN4_PLL4:
+ return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+ 0, gen4_pll_config->pll4_mult,
+ gen4_pll_config->pll4_div,
+ "PLL4");
case CLK_TYPE_GEN4_PLL5:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
- 0, pll_config->pll5_mult,
- pll_config->pll5_div,
- "V3U_PLL5");
+ 0, gen4_pll_config->pll5_mult,
+ gen4_pll_config->pll5_div,
+ "PLL5");
+
+ case CLK_TYPE_GEN4_PLL6:
+ return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+ 0, gen4_pll_config->pll6_mult,
+ gen4_pll_config->pll6_div,
+ "PLL6");
case CLK_TYPE_FF:
return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
@@ -288,6 +321,13 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
div, rate);
return rate;
+ case CLK_TYPE_GEN4_SDSRC:
+ div = ((readl(priv->base + SD0CKCR1) >> 29) & 0x03) + 4;
+ rate = gen3_clk_get_rate64(&parent) / div;
+ debug("%s[%i] SDSRC clk: parent=%i div=%u => rate=%llu\n",
+ __func__, __LINE__, core->parent, div, rate);
+ return rate;
+
case CLK_TYPE_GEN3_SDH: /* Fixed factor 1:1 */
fallthrough;
case CLK_TYPE_GEN4_SDH: /* Fixed factor 1:1 */
@@ -321,7 +361,16 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
gen3_clk_get_rate64(&parent),
priv->base + CPG_RPCCKCR,
CPG_RPCCKCR_DIV_POST_MASK,
- cpg_rpcsrc_div_table, "RPCSRC");
+ gen3_cpg_rpcsrc_div_table,
+ "RPCSRC");
+
+ case CLK_TYPE_GEN4_RPCSRC:
+ return rcar_clk_get_rate64_div_table(core->parent,
+ gen3_clk_get_rate64(&parent),
+ priv->base + CPG_RPCCKCR,
+ CPG_RPCCKCR_DIV_POST_MASK,
+ gen4_cpg_rpcsrc_div_table,
+ "RPCSRC");
case CLK_TYPE_GEN3_D3_RPCSRC:
case CLK_TYPE_GEN3_E3_RPCSRC:
@@ -409,6 +458,7 @@ static int gen3_clk_probe(struct udevice *dev)
struct gen3_clk_priv *priv = dev_get_priv(dev);
struct cpg_mssr_info *info =
(struct cpg_mssr_info *)dev_get_driver_data(dev);
+ const void *pll_config;
fdt_addr_t rst_base;
int ret;
@@ -427,21 +477,24 @@ static int gen3_clk_probe(struct udevice *dev)
priv->cpg_mode = readl(rst_base + info->reset_modemr_offset);
- priv->cpg_pll_config =
- (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(priv->cpg_mode);
- if (!priv->cpg_pll_config->extal_div)
- return -EINVAL;
+ pll_config = info->get_pll_config(priv->cpg_mode);
if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
priv->info->status_regs = mstpsr;
priv->info->control_regs = smstpcr;
priv->info->reset_regs = srcr;
priv->info->reset_clear_regs = srstclr;
- } else if (info->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
- priv->info->status_regs = mstpsr_for_v3u;
- priv->info->control_regs = mstpcr_for_v3u;
- priv->info->reset_regs = srcr_for_v3u;
- priv->info->reset_clear_regs = srstclr_for_v3u;
+ priv->gen3_cpg_pll_config = pll_config;
+ if (!priv->gen3_cpg_pll_config->extal_div)
+ return -EINVAL;
+ } else if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
+ priv->info->status_regs = mstpsr_for_gen4;
+ priv->info->control_regs = mstpcr_for_gen4;
+ priv->info->reset_regs = srcr_for_gen4;
+ priv->info->reset_clear_regs = srstclr_for_gen4;
+ priv->gen4_cpg_pll_config = pll_config;
+ if (!priv->gen4_cpg_pll_config->extal_div)
+ return -EINVAL;
} else {
return -EINVAL;
}
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
index a9c941b6dbf..6b7ec36ab05 100644
--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -232,11 +232,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] = {
/*
* CPG Clock Data
*/
-
/*
* MD EXTAL PLL1 PLL20 PLL30 PLL4 PLL5 OSC
* 14 13 (MHz) 21 31
- * --------------------------------------------------------
+ * ----------------------------------------------------------------
* 0 0 16.66 x 1 x128 x216 x128 x144 x192 /16
* 0 1 20 x 1 x106 x180 x106 x120 x160 /19
* 1 0 Prohibited setting
@@ -244,13 +243,12 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] = {
*/
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
(((md) & BIT(13)) >> 13))
-
-static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[4] = {
- /* EXTAL div PLL1 mult/div Not used OSC prediv PLL5 mult/div */
- { 1, 128, 1, 128, 1, 16, 192, 1, },
- { 1, 106, 1, 106, 1, 19, 160, 1, },
- { 0, 0, 0, 0, 0, 0, 0, 0, },
- { 2, 128, 1, 128, 1, 32, 192, 1, },
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+ /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
+ { 1, 128, 1, 0, 0, 0, 0, 144, 1, 192, 1, 0, 0, 16, },
+ { 1, 106, 1, 0, 0, 0, 0, 120, 1, 160, 1, 0, 0, 19, },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ { 2, 128, 1, 0, 0, 0, 0, 144, 1, 192, 1, 0, 0, 32, },
};
/*
@@ -292,13 +290,13 @@ static const struct cpg_mssr_info r8a779a0_cpg_mssr_info = {
.mstp_table = r8a779a0_mstp_table,
.mstp_table_size = ARRAY_SIZE(r8a779a0_mstp_table),
.reset_node = "renesas,r8a779a0-rst",
- .reset_modemr_offset = 0x00,
+ .reset_modemr_offset = CPG_RST_MODEMR0,
.extalr_node = "extalr",
.mod_clk_base = MOD_CLK_BASE,
.clk_extal_id = CLK_EXTAL,
.clk_extalr_id = CLK_EXTALR,
.get_pll_config = r8a779a0_get_pll_config,
- .reg_layout = CLK_REG_LAYOUT_RCAR_V3U,
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
};
static const struct udevice_id r8a779a0_cpg_ids[] = {
diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
new file mode 100644
index 00000000000..7aac28ed496
--- /dev/null
+++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779f0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on r8a779a0-cpg-mssr.c
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+
+#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A779F0_CLK_R,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL5,
+ CLK_PLL6,
+ CLK_PLL1_DIV2,
+ CLK_PLL2_DIV2,
+ CLK_PLL3_DIV2,
+ CLK_PLL5_DIV2,
+ CLK_PLL5_DIV4,
+ CLK_PLL6_DIV2,
+ CLK_S0,
+ CLK_SASYNCPER,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779f0_core_clks[] = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
+ DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
+ DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
+ DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+
+ /* Core Clock Outputs */
+ DEF_GEN4_Z("z0", R8A779F0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 0),
+ DEF_GEN4_Z("z1", R8A779F0_CLK_Z1, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 8),
+ DEF_FIXED("s0d2", R8A779F0_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A779F0_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A779F0_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m", R8A779F0_CLK_CL16M, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_mm", R8A779F0_CLK_S0D2_MM, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_mm", R8A779F0_CLK_S0D3_MM, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_mm", R8A779F0_CLK_S0D4_MM, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m_mm", R8A779F0_CLK_CL16M_MM, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_rt", R8A779F0_CLK_S0D2_RT, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_rt", R8A779F0_CLK_S0D3_RT, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_rt", R8A779F0_CLK_S0D4_RT, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_rt", R8A779F0_CLK_S0D6_RT, CLK_S0, 6, 1),
+ DEF_FIXED("cl16m_rt", R8A779F0_CLK_CL16M_RT, CLK_S0, 48, 1),
+ DEF_FIXED("s0d3_per", R8A779F0_CLK_S0D3_PER, CLK_S0, 3, 1),
+ DEF_FIXED("s0d6_per", R8A779F0_CLK_S0D6_PER, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_per", R8A779F0_CLK_S0D12_PER, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24_per", R8A779F0_CLK_S0D24_PER, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_per", R8A779F0_CLK_CL16M_PER, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_hsc", R8A779F0_CLK_S0D2_HSC, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_hsc", R8A779F0_CLK_S0D3_HSC, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_hsc", R8A779F0_CLK_S0D4_HSC, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_hsc", R8A779F0_CLK_S0D6_HSC, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_hsc", R8A779F0_CLK_S0D12_HSC, CLK_S0, 12, 1),
+ DEF_FIXED("cl16m_hsc", R8A779F0_CLK_CL16M_HSC, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_cc", R8A779F0_CLK_S0D2_CC, CLK_S0, 2, 1),
+ DEF_FIXED("rsw2", R8A779F0_CLK_RSW2, CLK_PLL5_DIV2, 5, 1),
+ DEF_FIXED("cbfusa", R8A779F0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A779F0_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_FIXED("sasyncrt", R8A779F0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
+ DEF_FIXED("sasyncperd1",R8A779F0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
+ DEF_FIXED("sasyncperd2",R8A779F0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
+ DEF_FIXED("sasyncperd4",R8A779F0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
+
+ DEF_GEN4_SDH("sd0h", R8A779F0_CLK_SD0H, CLK_SDSRC, 0x870),
+ DEF_GEN4_SD("sd0", R8A779F0_CLK_SD0, R8A779F0_CLK_SD0H, 0x870),
+
+ DEF_BASE("rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A779F0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC),
+
+ DEF_DIV6P1("mso", R8A779F0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
+
+ DEF_GEN4_OSC("osc", R8A779F0_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN4_MDSEL("r", R8A779F0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779f0_mod_clks[] = {
+ DEF_MOD("hscif0", 514, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif1", 515, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif2", 516, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif3", 517, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("i2c0", 518, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c1", 519, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c2", 520, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c3", 521, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c4", 522, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c5", 523, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("msiof0", 618, R8A779F0_CLK_MSO),
+ DEF_MOD("msiof1", 619, R8A779F0_CLK_MSO),
+ DEF_MOD("msiof2", 620, R8A779F0_CLK_MSO),
+ DEF_MOD("msiof3", 621, R8A779F0_CLK_MSO),
+ DEF_MOD("pcie0", 624, R8A779F0_CLK_S0D2),
+ DEF_MOD("pcie1", 625, R8A779F0_CLK_S0D2),
+ DEF_MOD("scif0", 702, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("sdhi0", 706, R8A779F0_CLK_SD0),
+ DEF_MOD("sys-dmac0", 709, R8A779F0_CLK_S0D3_PER),
+ DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER),
+ DEF_MOD("tmu0", 713, R8A779F0_CLK_SASYNCRT),
+ DEF_MOD("tmu1", 714, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu2", 715, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu3", 716, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu4", 717, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("wdt", 907, R8A779F0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779F0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779F0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779F0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779F0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779F0_CLK_CL16M),
+ DEF_MOD("tsc", 919, R8A779F0_CLK_CL16M),
+ DEF_MOD("rswitch2", 1505, R8A779F0_CLK_RSW2),
+ DEF_MOD("ether-serdes", 1506, R8A779F0_CLK_S0D2_HSC),
+ DEF_MOD("ufs", 1514, R8A779F0_CLK_S0D4_HSC),
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC
+ * 14 13 (MHz)
+ * ------------------------------------------------------------------------
+ * 0 0 16 / 1 x200 x150 x200 n/a x200 x134 /15
+ * 0 1 20 / 1 x160 x120 x160 n/a x160 x106 /19
+ * 1 0 Prohibited setting
+ * 1 1 40 / 2 x160 x120 x160 n/a x160 x106 /38
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+ /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
+ { 1, 200, 1, 150, 1, 200, 1, 0, 0, 200, 1, 134, 1, 15, },
+ { 1, 160, 1, 120, 1, 160, 1, 0, 0, 160, 1, 106, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ { 2, 160, 1, 120, 1, 160, 1, 0, 0, 160, 1, 106, 1, 38, },
+};
+
+/*
+ * Note that the only clock left running before booting Linux are now
+ * MFIS, INTC-AP, INTC-EX and HSCIF0/SCIF3 on S4
+ */
+#define MSTPCR5_HSCIF0 BIT(14)
+#define MSTPCR7_SCIF3 BIT(4) /* No information: MFIS, INTC-AP, INTC-EX */
+static const struct mstp_stop_table r8a779f0_mstp_table[] = {
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00800000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x0003c000, MSTPCR5_HSCIF0, 0x0, 0x0 },
+ { 0x03000000, 0x0, 0x0, 0x0 },
+ { 0x1ffbe040, MSTPCR7_SCIF3, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00003c78, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x9e800000, 0x0, 0x0, 0x0 },
+ { 0x00000027, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00005800, 0x0, 0x0, 0x0 },
+};
+
+static const void *r8a779f0_get_pll_config(const u32 cpg_mode)
+{
+ return &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+}
+
+static const struct cpg_mssr_info r8a779f0_cpg_mssr_info = {
+ .core_clk = r8a779f0_core_clks,
+ .core_clk_size = ARRAY_SIZE(r8a779f0_core_clks),
+ .mod_clk = r8a779f0_mod_clks,
+ .mod_clk_size = ARRAY_SIZE(r8a779f0_mod_clks),
+ .mstp_table = r8a779f0_mstp_table,
+ .mstp_table_size = ARRAY_SIZE(r8a779f0_mstp_table),
+ .reset_node = "renesas,r8a779f0-rst",
+ .reset_modemr_offset = CPG_RST_MODEMR0,
+ .extalr_node = "extalr",
+ .mod_clk_base = MOD_CLK_BASE,
+ .clk_extal_id = CLK_EXTAL,
+ .clk_extalr_id = CLK_EXTALR,
+ .get_pll_config = r8a779f0_get_pll_config,
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
+
+static const struct udevice_id r8a779f0_cpg_ids[] = {
+ {
+ .compatible = "renesas,r8a779f0-cpg-mssr",
+ .data = (ulong)&r8a779f0_cpg_mssr_info
+ },
+ { }
+};
+
+U_BOOT_DRIVER(cpg_r8a779f0) = {
+ .name = "cpg_r8a779f0",
+ .id = UCLASS_NOP,
+ .of_match = r8a779f0_cpg_ids,
+ .bind = gen3_cpg_bind,
+};
diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
new file mode 100644
index 00000000000..8625e8a2d36
--- /dev/null
+++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779g0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ *
+ * Based on r8a779f0-cpg-mssr.c
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+
+#include <dt-bindings/clock/r8a779g0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A779G0_CLK_R,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL5,
+ CLK_PLL6,
+ CLK_PLL1_DIV2,
+ CLK_PLL2_DIV2,
+ CLK_PLL3_DIV2,
+ CLK_PLL4_DIV2,
+ CLK_PLL5_DIV2,
+ CLK_PLL5_DIV4,
+ CLK_PLL6_DIV2,
+ CLK_S0,
+ CLK_S0_VIO,
+ CLK_S0_VC,
+ CLK_S0_HSC,
+ CLK_SASYNCPER,
+ CLK_SV_VIP,
+ CLK_SV_IR,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_VIO,
+ CLK_VC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779g0_core_clks[] = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN4_PLL4, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
+ DEF_FIXED(".pll4_div2", CLK_PLL4_DIV2, CLK_PLL4, 2, 1),
+ DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
+ DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vio", CLK_S0_VIO, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vc", CLK_S0_VC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_hsc", CLK_S0_HSC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
+ DEF_FIXED(".sv_vip", CLK_SV_VIP, CLK_PLL1, 5, 1),
+ DEF_FIXED(".sv_ir", CLK_SV_IR, CLK_PLL1, 5, 1),
+ DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+ DEF_FIXED(".vio", CLK_VIO, CLK_PLL5_DIV2, 3, 1),
+ DEF_FIXED(".vc", CLK_VC, CLK_PLL5_DIV2, 3, 1),
+
+ /* Core Clock Outputs */
+ DEF_GEN4_Z("z0", R8A779G0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 0),
+ DEF_FIXED("s0d2", R8A779G0_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A779G0_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A779G0_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m", R8A779G0_CLK_CL16M, CLK_S0, 48, 1),
+ DEF_FIXED("s0d1_vio", R8A779G0_CLK_S0D1_VIO, CLK_S0_VIO, 1, 1),
+ DEF_FIXED("s0d2_vio", R8A779G0_CLK_S0D2_VIO, CLK_S0_VIO, 2, 1),
+ DEF_FIXED("s0d4_vio", R8A779G0_CLK_S0D4_VIO, CLK_S0_VIO, 4, 1),
+ DEF_FIXED("s0d8_vio", R8A779G0_CLK_S0D8_VIO, CLK_S0_VIO, 8, 1),
+ DEF_FIXED("s0d1_vc", R8A779G0_CLK_S0D1_VC, CLK_S0_VC, 1, 1),
+ DEF_FIXED("s0d2_vc", R8A779G0_CLK_S0D2_VC, CLK_S0_VC, 2, 1),
+ DEF_FIXED("s0d4_vc", R8A779G0_CLK_S0D4_VC, CLK_S0_VC, 4, 1),
+ DEF_FIXED("s0d2_mm", R8A779G0_CLK_S0D2_MM, CLK_S0, 2, 1),
+ DEF_FIXED("s0d4_mm", R8A779G0_CLK_S0D4_MM, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m_mm", R8A779G0_CLK_CL16M_MM, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_u3dg", R8A779G0_CLK_S0D2_U3DG, CLK_S0, 2, 1),
+ DEF_FIXED("s0d4_u3dg", R8A779G0_CLK_S0D4_U3DG, CLK_S0, 4, 1),
+ DEF_FIXED("s0d2_rt", R8A779G0_CLK_S0D2_RT, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_rt", R8A779G0_CLK_S0D3_RT, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_rt", R8A779G0_CLK_S0D4_RT, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_rt", R8A779G0_CLK_S0D6_RT, CLK_S0, 6, 1),
+ DEF_FIXED("s0d24_rt", R8A779G0_CLK_S0D24_RT, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_rt", R8A779G0_CLK_CL16M_RT, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_per", R8A779G0_CLK_S0D2_PER, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_per", R8A779G0_CLK_S0D3_PER, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_per", R8A779G0_CLK_S0D4_PER, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_per", R8A779G0_CLK_S0D6_PER, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_per", R8A779G0_CLK_S0D12_PER, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24_per", R8A779G0_CLK_S0D24_PER, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_per", R8A779G0_CLK_CL16M_PER, CLK_S0, 48, 1),
+ DEF_FIXED("s0d1_hsc", R8A779G0_CLK_S0D1_HSC, CLK_S0_HSC, 1, 1),
+ DEF_FIXED("s0d2_hsc", R8A779G0_CLK_S0D2_HSC, CLK_S0_HSC, 2, 1),
+ DEF_FIXED("s0d4_hsc", R8A779G0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1),
+ DEF_FIXED("cl16m_hsc", R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1),
+ DEF_FIXED("s0d2_cc", R8A779G0_CLK_S0D2_CC, CLK_S0, 2, 1),
+ DEF_FIXED("sasyncrt", R8A779G0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
+ DEF_FIXED("sasyncperd1",R8A779G0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
+ DEF_FIXED("sasyncperd2",R8A779G0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
+ DEF_FIXED("sasyncperd4",R8A779G0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
+ DEF_FIXED("svd1_ir", R8A779G0_CLK_SVD1_IR, CLK_SV_IR, 1, 1),
+ DEF_FIXED("svd2_ir", R8A779G0_CLK_SVD2_IR, CLK_SV_IR, 2, 1),
+ DEF_FIXED("svd1_vip", R8A779G0_CLK_SVD1_VIP, CLK_SV_VIP, 1, 1),
+ DEF_FIXED("svd2_vip", R8A779G0_CLK_SVD2_VIP, CLK_SV_VIP, 2, 1),
+ DEF_FIXED("cbfusa", R8A779G0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A779G0_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("viobus", R8A779G0_CLK_VIOBUS, CLK_VIO, 1, 1),
+ DEF_FIXED("viobusd2", R8A779G0_CLK_VIOBUSD2, CLK_VIO, 2, 1),
+ DEF_FIXED("vcbus", R8A779G0_CLK_VCBUS, CLK_VC, 1, 1),
+ DEF_FIXED("vcbusd2", R8A779G0_CLK_VCBUSD2, CLK_VC, 2, 1),
+ DEF_DIV6P1("canfd", R8A779G0_CLK_CANFD, CLK_PLL5_DIV4, 0x878),
+ DEF_FIXED("dsiref", R8A779G0_CLK_DSIREF, CLK_PLL5_DIV4, 48, 1),
+ DEF_DIV6P1("dsiext", R8A779G0_CLK_DSIEXT, CLK_PLL5_DIV4, 0x884),
+
+ DEF_GEN4_SDH("sd0h", R8A779G0_CLK_SD0H, CLK_SDSRC, 0x870),
+ DEF_GEN4_SD("sd0", R8A779G0_CLK_SD0, R8A779G0_CLK_SD0H, 0x870),
+ DEF_DIV6P1("mso", R8A779G0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
+
+ DEF_BASE("rpc", R8A779G0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A779G0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779G0_CLK_RPC),
+
+ DEF_GEN4_OSC("osc", R8A779G0_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN4_MDSEL("r", R8A779G0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779g0_mod_clks[] = {
+ DEF_MOD("avb0", 211, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("avb1", 212, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("avb2", 213, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("canfd0", 328, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("dis0", 411, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("dsitxlink0", 415, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("dsitxlink1", 416, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("fcpvd0", 508, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("fcpvd1", 509, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("hscif0", 514, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif1", 515, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif2", 516, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif3", 517, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("i2c0", 518, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c1", 519, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c2", 520, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c3", 521, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c4", 522, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c5", 523, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("irqc", 611, R8A779G0_CLK_CL16M),
+ DEF_MOD("msi0", 618, R8A779G0_CLK_MSO),
+ DEF_MOD("msi1", 619, R8A779G0_CLK_MSO),
+ DEF_MOD("msi2", 620, R8A779G0_CLK_MSO),
+ DEF_MOD("msi3", 621, R8A779G0_CLK_MSO),
+ DEF_MOD("msi4", 622, R8A779G0_CLK_MSO),
+ DEF_MOD("msi5", 623, R8A779G0_CLK_MSO),
+ DEF_MOD("pwm", 628, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("rpc-if", 629, R8A779G0_CLK_RPCD2),
+ DEF_MOD("scif0", 702, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("sdhi", 706, R8A779G0_CLK_SD0),
+ DEF_MOD("sys-dmac0", 709, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("sys-dmac1", 710, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("tmu0", 713, R8A779G0_CLK_SASYNCRT),
+ DEF_MOD("tmu1", 714, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu2", 715, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu3", 716, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu4", 717, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tpu0", 718, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("vspd0", 830, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("vspd1", 831, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("wdt1:wdt0", 907, R8A779G0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779G0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779G0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779G0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779G0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779G0_CLK_CL16M),
+ DEF_MOD("pfc1", 916, R8A779G0_CLK_CL16M),
+ DEF_MOD("pfc2", 917, R8A779G0_CLK_CL16M),
+ DEF_MOD("pfc3", 918, R8A779G0_CLK_CL16M),
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC
+ * 14 13 (MHz)
+ * ------------------------------------------------------------------------
+ * 0 0 16.66 / 1 x192 x204 x192 x144 x192 x168 /16
+ * 0 1 20 / 1 x160 x170 x160 x120 x160 x140 /19
+ * 1 0 Prohibited setting
+ * 1 1 33.33 / 2 x192 x204 x192 x144 x192 x168 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+ /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
+ { 1, 192, 1, 204, 1, 192, 1, 144, 1, 192, 1, 168, 1, 16, },
+ { 1, 160, 1, 170, 1, 160, 1, 120, 1, 160, 1, 140, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ { 2, 192, 1, 204, 1, 192, 1, 144, 1, 192, 1, 168, 1, 32, },
+};
+
+/*
+ * Note that the only clock left running before booting Linux are now
+ * MFIS, INTC-AP, INTC-EX, SCIF0, HSCIF0 on V4H
+ */
+#define MSTPCR5_HSCIF0 BIT(14) /* No information: MFIS, INTC-AP */
+#define MSTPCR6_INTCEX BIT(11) /* No information: MFIS, INTC-AP */
+#define MSTPCR7_SCIF0 BIT(2) /* No information: MFIS, INTC-AP */
+static const struct mstp_stop_table r8a779g0_mstp_table[] = {
+ { 0x0FC302A1, 0x0, 0x0, 0x0 },
+ { 0x00D50038, 0x0, 0x0, 0x0 },
+ { 0x00003800, 0x0, 0x0, 0x0 },
+ { 0xF0000000, 0x0, 0x0, 0x0 },
+ { 0x0001CE01, 0x0, 0x0, 0x0 },
+ { 0xEEFFE380, MSTPCR5_HSCIF0, 0x0, 0x0 },
+ { 0xF3FD3901, MSTPCR6_INTCEX, 0x0, 0x0 },
+ { 0xE007E6FF, MSTPCR7_SCIF0, 0x0, 0x0 },
+ { 0xC0003FFF, 0x0, 0x0, 0x0 },
+ { 0x001FBCF8, 0x0, 0x0, 0x0 },
+ { 0x30000000, 0x0, 0x0, 0x0 },
+ { 0x000000C3, 0x0, 0x0, 0x0 },
+ { 0xDE800000, 0x0, 0x0, 0x0 },
+ { 0x00000017, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x00000000, 0x0, 0x0, 0x0 },
+ { 0x000033C0, 0x0, 0x0, 0x0 },
+ { 0x402A001E, 0x0, 0x0, 0x0 },
+ { 0x0C010080, 0x0, 0x0, 0x0 },
+};
+
+static const void *r8a779g0_get_pll_config(const u32 cpg_mode)
+{
+ return &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+}
+
+static const struct cpg_mssr_info r8a779g0_cpg_mssr_info = {
+ .core_clk = r8a779g0_core_clks,
+ .core_clk_size = ARRAY_SIZE(r8a779g0_core_clks),
+ .mod_clk = r8a779g0_mod_clks,
+ .mod_clk_size = ARRAY_SIZE(r8a779g0_mod_clks),
+ .mstp_table = r8a779g0_mstp_table,
+ .mstp_table_size = ARRAY_SIZE(r8a779g0_mstp_table),
+ .reset_node = "renesas,r8a779g0-rst",
+ .reset_modemr_offset = CPG_RST_MODEMR0,
+ .extalr_node = "extalr",
+ .mod_clk_base = MOD_CLK_BASE,
+ .clk_extal_id = CLK_EXTAL,
+ .clk_extalr_id = CLK_EXTALR,
+ .get_pll_config = r8a779g0_get_pll_config,
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
+
+static const struct udevice_id r8a779g0_cpg_ids[] = {
+ {
+ .compatible = "renesas,r8a779g0-cpg-mssr",
+ .data = (ulong)&r8a779g0_cpg_mssr_info
+ },
+ { }
+};
+
+U_BOOT_DRIVER(cpg_r8a779g0) = {
+ .name = "cpg_r8a779g0",
+ .id = UCLASS_NOP,
+ .of_match = r8a779g0_cpg_ids,
+ .bind = gen3_cpg_bind,
+};
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
index 894e3765495..06318c81acd 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.h
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -34,8 +34,13 @@ enum rcar_gen3_clk_types {
CLK_TYPE_GEN4_MAIN,
CLK_TYPE_GEN4_PLL1,
- CLK_TYPE_GEN4_PLL2X_3X, /* PLL[23][01] */
+ CLK_TYPE_GEN4_PLL2,
+ CLK_TYPE_GEN4_PLL2X_3X, /* R8A779A0 only */
+ CLK_TYPE_GEN4_PLL3,
CLK_TYPE_GEN4_PLL5,
+ CLK_TYPE_GEN4_PLL4,
+ CLK_TYPE_GEN4_PLL6,
+ CLK_TYPE_GEN4_SDSRC,
CLK_TYPE_GEN4_SDH,
CLK_TYPE_GEN4_SD,
CLK_TYPE_GEN4_MDSEL, /* Select parent/divider using mode pin */
@@ -107,11 +112,27 @@ struct rcar_gen3_cpg_pll_config {
u8 pll3_mult;
u8 pll3_div;
u8 osc_prediv;
+};
+
+struct rcar_gen4_cpg_pll_config {
+ u8 extal_div;
+ u8 pll1_mult;
+ u8 pll1_div;
+ u8 pll2_mult;
+ u8 pll2_div;
+ u8 pll3_mult;
+ u8 pll3_div;
+ u8 pll4_mult;
+ u8 pll4_div;
u8 pll5_mult;
u8 pll5_div;
+ u8 pll6_mult;
+ u8 pll6_div;
+ u8 osc_prediv;
};
#define CPG_RST_MODEMR 0x060
+#define CPG_RST_MODEMR0 0x000
#define CPG_SDCKCR_STPnHCK BIT(9)
#define CPG_SDCKCR_STPnCK BIT(8)
@@ -133,7 +154,10 @@ struct gen3_clk_priv {
struct clk clk_extal;
struct clk clk_extalr;
u32 cpg_mode;
- const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ union {
+ const struct rcar_gen3_cpg_pll_config *gen3_cpg_pll_config;
+ const struct rcar_gen4_cpg_pll_config *gen4_cpg_pll_config;
+ };
};
int gen3_cpg_bind(struct udevice *parent);
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index e0895d2c2f8..10bd54d6002 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -128,7 +128,7 @@ int renesas_clk_remove(void __iomem *base, struct cpg_mssr_info *info)
info->mstp_table[i].sdis,
info->mstp_table[i].sen);
- if (info->reg_layout == CLK_REG_LAYOUT_RCAR_V3U)
+ if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4)
continue;
clrsetbits_le32(base + RMSTPCR(i),
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
index 519f88548f8..71e409f3eb0 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.h
+++ b/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -17,7 +17,7 @@
enum clk_reg_layout {
CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
- CLK_REG_LAYOUT_RCAR_V3U,
+ CLK_REG_LAYOUT_RCAR_GEN4,
};
struct cpg_mssr_info {
@@ -134,7 +134,7 @@ int renesas_clk_remove(void __iomem *base, struct cpg_mssr_info *info);
* Module Standby and Software Reset register offets.
*
* If the registers exist, these are valid for SH-Mobile, R-Mobile,
- * R-Car Gen2, R-Car Gen3, and RZ/G1.
+ * R-Car Gen2, R-Car Gen3, R-Car Gen4 and RZ/G1.
* These are NOT valid for R-Car Gen1 and RZ/A1!
*/
@@ -147,9 +147,11 @@ static const u16 mstpsr[] = {
0x9A0, 0x9A4, 0x9A8, 0x9AC,
};
-static const u16 mstpsr_for_v3u[] = {
+static const u16 mstpsr_for_gen4[] = {
0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
- 0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38,
+ 0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, 0x2E3C,
+ 0x2E40, 0x2E44, 0x2E48, 0x2E4C, 0x2E50, 0x2E54, 0x2E58, 0x2E5C,
+ 0x2E60, 0x2E64, 0x2E68, 0x2E6C,
};
/*
@@ -161,9 +163,11 @@ static const u16 smstpcr[] = {
0x990, 0x994, 0x998, 0x99C,
};
-static const u16 mstpcr_for_v3u[] = {
+static const u16 mstpcr_for_gen4[] = {
0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
- 0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38,
+ 0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, 0x2D3C,
+ 0x2D40, 0x2D44, 0x2D48, 0x2D4C, 0x2D50, 0x2D54, 0x2D58, 0x2D5C,
+ 0x2D60, 0x2D64, 0x2D68, 0x2D6C,
};
/*
@@ -175,9 +179,11 @@ static const u16 srcr[] = {
0x920, 0x924, 0x928, 0x92C,
};
-static const u16 srcr_for_v3u[] = {
+static const u16 srcr_for_gen4[] = {
0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
- 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38,
+ 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, 0x2C3C,
+ 0x2C40, 0x2C44, 0x2C48, 0x2C4C, 0x2C50, 0x2C54, 0x2C58, 0x2C5C,
+ 0x2C60, 0x2C64, 0x2C68, 0x2C6C,
};
/* Realtime Module Stop Control Register offsets */
@@ -193,9 +199,11 @@ static const u16 srstclr[] = {
0x960, 0x964, 0x968, 0x96C,
};
-static const u16 srstclr_for_v3u[] = {
+static const u16 srstclr_for_gen4[] = {
0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
- 0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8,
+ 0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, 0x2CBC,
+ 0x2CC0, 0x2CC4, 0x2CC8, 0x2CCC, 0x2CD0, 0x2CD4, 0x2CD8, 0x2CDC,
+ 0x2CE0, 0x2CE4, 0x2CE8, 0x2CEC,
};
#endif /* __DRIVERS_CLK_RENESAS_CPG_MSSR__ */
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 3b29992c3e5..ef744c06f3e 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -778,6 +778,7 @@ static ulong rk3288_clk_get_rate(struct clk *clk)
case PCLK_I2C5:
return gclk_rate;
case PCLK_PWM:
+ case PCLK_RKPWM:
return PD_BUS_PCLK_HZ;
case SCLK_SARADC:
new_rate = rockchip_saradc_get_clk(priv->cru);
diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c
index 1c6adc56f91..cefc263971a 100644
--- a/drivers/clk/rockchip/clk_rk3568.c
+++ b/drivers/clk/rockchip/clk_rk3568.c
@@ -2838,6 +2838,8 @@ static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
case ACLK_RKVDEC_PRE:
case CLK_RKVDEC_CORE:
return rk3568_rkvdec_set_parent(clk, parent);
+ case I2S1_MCLKOUT_TX:
+ break;
default:
return -ENOENT;
}
diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c
index a7df553e875..d0cc19b4788 100644
--- a/drivers/clk/rockchip/clk_rk3588.c
+++ b/drivers/clk/rockchip/clk_rk3588.c
@@ -9,6 +9,7 @@
#include <clk-uclass.h>
#include <dm.h>
#include <errno.h>
+#include <scmi_protocols.h>
#include <syscon.h>
#include <asm/arch-rockchip/cru_rk3588.h>
#include <asm/arch-rockchip/clock.h>
@@ -1552,6 +1553,7 @@ static ulong rk3588_clk_get_rate(struct clk *clk)
case DCLK_DECOM:
rate = rk3588_mmc_get_clk(priv, clk->id);
break;
+ case TMCLK_EMMC:
case TCLK_WDT0:
rate = OSC_HZ;
break;
@@ -1701,6 +1703,7 @@ static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate)
case DCLK_DECOM:
ret = rk3588_mmc_set_clk(priv, clk->id, rate);
break;
+ case TMCLK_EMMC:
case TCLK_WDT0:
ret = OSC_HZ;
break;
@@ -1994,3 +1997,127 @@ U_BOOT_DRIVER(rockchip_rk3588_cru) = {
.bind = rk3588_clk_bind,
.probe = rk3588_clk_probe,
};
+
+#ifdef CONFIG_SPL_BUILD
+#define SCRU_BASE 0xfd7d0000
+
+static ulong rk3588_scru_clk_get_rate(struct clk *clk)
+{
+ u32 con, div, sel, parent;
+
+ switch (clk->id) {
+ case SCMI_CCLK_SD:
+ con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
+ sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
+ div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
+ if (sel == SCMI_CCLK_SD_SEL_GPLL)
+ parent = GPLL_HZ;
+ else if (sel == SCMI_CCLK_SD_SEL_SPLL)
+ parent = SPLL_HZ;
+ else
+ parent = OSC_HZ;
+ return DIV_TO_RATE(parent, div);
+ case SCMI_HCLK_SD:
+ con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
+ sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
+ if (sel == SCMI_HCLK_SD_SEL_150M)
+ return 150 * MHz;
+ else if (sel == SCMI_HCLK_SD_SEL_100M)
+ return 100 * MHz;
+ else if (sel == SCMI_HCLK_SD_SEL_50M)
+ return 50 * MHz;
+ else
+ return OSC_HZ;
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
+{
+ u32 div, sel;
+
+ switch (clk->id) {
+ case SCMI_CCLK_SD:
+ if ((OSC_HZ % rate) == 0) {
+ sel = SCMI_CCLK_SD_SEL_24M;
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ } else if ((SPLL_HZ % rate) == 0) {
+ sel = SCMI_CCLK_SD_SEL_SPLL;
+ div = DIV_ROUND_UP(SPLL_HZ, rate);
+ } else {
+ sel = SCMI_CCLK_SD_SEL_GPLL;
+ div = DIV_ROUND_UP(GPLL_HZ, rate);
+ }
+ rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
+ SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
+ sel << SCMI_CCLK_SD_SEL_SHIFT |
+ (div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
+ break;
+ case SCMI_HCLK_SD:
+ if (rate >= 150 * MHz)
+ sel = SCMI_HCLK_SD_SEL_150M;
+ else if (rate >= 100 * MHz)
+ sel = SCMI_HCLK_SD_SEL_100M;
+ else if (rate >= 50 * MHz)
+ sel = SCMI_HCLK_SD_SEL_50M;
+ else
+ sel = SCMI_HCLK_SD_SEL_24M;
+ rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
+ SCMI_HCLK_SD_SEL_MASK,
+ sel << SCMI_HCLK_SD_SEL_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rk3588_scru_clk_get_rate(clk);
+}
+
+static const struct clk_ops rk3588_scru_clk_ops = {
+ .get_rate = rk3588_scru_clk_get_rate,
+ .set_rate = rk3588_scru_clk_set_rate,
+};
+
+U_BOOT_DRIVER(rockchip_rk3588_scru) = {
+ .name = "rockchip_rk3588_scru",
+ .id = UCLASS_CLK,
+ .ops = &rk3588_scru_clk_ops,
+};
+
+static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
+{
+ ofnode node;
+ u32 protocol_id;
+ const char *name;
+
+ dev_for_each_subnode(node, dev) {
+ if (!ofnode_is_enabled(node))
+ continue;
+
+ if (ofnode_read_u32(node, "reg", &protocol_id))
+ continue;
+
+ if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
+ continue;
+
+ name = ofnode_get_name(node);
+ return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
+ name, node, NULL);
+ }
+
+ return -ENOENT;
+}
+
+static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
+ { .compatible = "arm,scmi-smc" },
+ { }
+};
+
+U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
+ .name = "rk3588_scmi_spl_glue",
+ .id = UCLASS_NOP,
+ .of_match = rk3588_scmi_spl_glue_ids,
+ .bind = rk3588_scmi_spl_glue_bind,
+};
+#endif
diff --git a/drivers/clk/starfive/Kconfig b/drivers/clk/starfive/Kconfig
new file mode 100644
index 00000000000..9399ef6d517
--- /dev/null
+++ b/drivers/clk/starfive/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+config SPL_CLK_JH7110
+ bool "SPL clock support for JH7110"
+ depends on STARFIVE_JH7110 && SPL
+ select SPL_CLK
+ select SPL_CLK_CCF
+ help
+ This enables SPL DM support for clock driver in JH7110.
+
+config CLK_JH7110
+ bool "StarFive JH7110 clock support"
+ depends on STARFIVE_JH7110
+ select CLK
+ select CLK_CCF
+ help
+ This enables support clock driver for StarFive JH7110 SoC platform.
diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
new file mode 100644
index 00000000000..ec0d1570946
--- /dev/null
+++ b/drivers/clk/starfive/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += clk-jh7110.o
+obj-y += clk-jh7110-pll.o
diff --git a/drivers/clk/starfive/clk-jh7110-pll.c b/drivers/clk/starfive/clk-jh7110-pll.c
new file mode 100644
index 00000000000..02e6d9000e2
--- /dev/null
+++ b/drivers/clk/starfive/clk-jh7110-pll.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022-23 StarFive Technology Co., Ltd.
+ *
+ * Author: Yanhong Wang <[email protected]>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <div64.h>
+#include <dm/device.h>
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+#define UBOOT_DM_CLK_JH7110_PLLX "jh7110_clk_pllx"
+
+#define PLL_PD_OFF 1
+#define PLL_PD_ON 0
+
+#define CLK_DDR_BUS_MASK GENMASK(29, 24)
+#define CLK_DDR_BUS_OFFSET 0xAC
+#define CLK_DDR_BUS_OSC_DIV2 0
+#define CLK_DDR_BUS_PLL1_DIV2 1
+#define CLK_DDR_BUS_PLL1_DIV4 2
+#define CLK_DDR_BUS_PLL1_DIV8 3
+
+struct clk_jh7110_pllx {
+ struct clk clk;
+ void __iomem *base;
+ void __iomem *sysreg;
+ enum starfive_pll_type type;
+ const struct starfive_pllx_offset *offset;
+ const struct starfive_pllx_rate *rate_table;
+ int rate_count;
+};
+
+#define getbits_le32(addr, mask) ((in_le32(addr) & (mask)) >> __ffs((mask)))
+
+#define PLLX_SET(offset, mask, val) do {\
+ reg = readl((ulong *)((ulong)pll->base + (offset))); \
+ reg &= ~(mask); \
+ reg |= (mask) & ((val) << __ffs(mask)); \
+ writel(reg, (ulong *)((ulong)pll->base + (offset))); \
+ } while (0)
+
+#define PLLX_RATE(_rate, _pd, _fd) \
+ { \
+ .rate = (_rate), \
+ .prediv = (_pd), \
+ .fbdiv = (_fd), \
+ }
+
+#define to_clk_pllx(_clk) container_of(_clk, struct clk_jh7110_pllx, clk)
+
+static const struct starfive_pllx_rate jh7110_pll0_tbl[] = {
+ PLLX_RATE(375000000UL, 8, 125),
+ PLLX_RATE(500000000UL, 6, 125),
+ PLLX_RATE(625000000UL, 24, 625),
+ PLLX_RATE(750000000UL, 4, 125),
+ PLLX_RATE(875000000UL, 24, 875),
+ PLLX_RATE(1000000000UL, 3, 125),
+ PLLX_RATE(1250000000UL, 12, 625),
+ PLLX_RATE(1375000000UL, 24, 1375),
+ PLLX_RATE(1500000000UL, 2, 125),
+ PLLX_RATE(1625000000UL, 24, 1625),
+ PLLX_RATE(1750000000UL, 12, 875),
+ PLLX_RATE(1800000000UL, 3, 225),
+};
+
+static const struct starfive_pllx_rate jh7110_pll1_tbl[] = {
+ PLLX_RATE(1066000000UL, 12, 533),
+ PLLX_RATE(1200000000UL, 1, 50),
+ PLLX_RATE(1400000000UL, 6, 350),
+ PLLX_RATE(1600000000UL, 3, 200),
+};
+
+static const struct starfive_pllx_rate jh7110_pll2_tbl[] = {
+ PLLX_RATE(1228800000UL, 15, 768),
+ PLLX_RATE(1188000000UL, 2, 99),
+};
+
+static const struct starfive_pllx_offset jh7110_pll0_offset = {
+ .pd = 0x20,
+ .prediv = 0x24,
+ .fbdiv = 0x1c,
+ .frac = 0x20,
+ .postdiv1 = 0x20,
+ .dacpd = 0x18,
+ .dsmpd = 0x18,
+ .pd_mask = BIT(27),
+ .prediv_mask = GENMASK(5, 0),
+ .fbdiv_mask = GENMASK(11, 0),
+ .frac_mask = GENMASK(23, 0),
+ .postdiv1_mask = GENMASK(29, 28),
+ .dacpd_mask = BIT(24),
+ .dsmpd_mask = BIT(25)
+};
+
+static const struct starfive_pllx_offset jh7110_pll1_offset = {
+ .pd = 0x28,
+ .prediv = 0x2c,
+ .fbdiv = 0x24,
+ .frac = 0x28,
+ .postdiv1 = 0x28,
+ .dacpd = 0x24,
+ .dsmpd = 0x24,
+ .pd_mask = BIT(27),
+ .prediv_mask = GENMASK(5, 0),
+ .fbdiv_mask = GENMASK(28, 17),
+ .frac_mask = GENMASK(23, 0),
+ .postdiv1_mask = GENMASK(29, 28),
+ .dacpd_mask = BIT(15),
+ .dsmpd_mask = BIT(16)
+};
+
+static const struct starfive_pllx_offset jh7110_pll2_offset = {
+ .pd = 0x30,
+ .prediv = 0x34,
+ .fbdiv = 0x2c,
+ .frac = 0x30,
+ .postdiv1 = 0x30,
+ .dacpd = 0x2c,
+ .dsmpd = 0x2c,
+ .pd_mask = BIT(27),
+ .prediv_mask = GENMASK(5, 0),
+ .fbdiv_mask = GENMASK(28, 17),
+ .frac_mask = GENMASK(23, 0),
+ .postdiv1_mask = GENMASK(29, 28),
+ .dacpd_mask = BIT(15),
+ .dsmpd_mask = BIT(16)
+};
+
+struct starfive_pllx_clk starfive_jh7110_pll0 __initdata = {
+ .type = PLL0,
+ .offset = &jh7110_pll0_offset,
+ .rate_table = jh7110_pll0_tbl,
+ .rate_count = ARRAY_SIZE(jh7110_pll0_tbl),
+};
+
+struct starfive_pllx_clk starfive_jh7110_pll1 __initdata = {
+ .type = PLL1,
+ .offset = &jh7110_pll1_offset,
+ .rate_table = jh7110_pll1_tbl,
+ .rate_count = ARRAY_SIZE(jh7110_pll1_tbl),
+};
+
+struct starfive_pllx_clk starfive_jh7110_pll2 __initdata = {
+ .type = PLL2,
+ .offset = &jh7110_pll2_offset,
+ .rate_table = jh7110_pll2_tbl,
+ .rate_count = ARRAY_SIZE(jh7110_pll2_tbl),
+};
+
+static const struct starfive_pllx_rate *
+jh7110_get_pll_settings(struct clk_jh7110_pllx *pll, unsigned long rate)
+{
+ for (int i = 0; i < pll->rate_count; i++)
+ if (rate == pll->rate_table[i].rate)
+ return &pll->rate_table[i];
+
+ return NULL;
+}
+
+static void jh7110_pll_set_rate(struct clk_jh7110_pllx *pll,
+ const struct starfive_pllx_rate *rate)
+{
+ u32 reg;
+ bool set = (pll->type == PLL1) ? true : false;
+
+ if (set) {
+ reg = readl((ulong *)((ulong)pll->sysreg + CLK_DDR_BUS_OFFSET));
+ reg &= ~CLK_DDR_BUS_MASK;
+ reg |= CLK_DDR_BUS_OSC_DIV2 << __ffs(CLK_DDR_BUS_MASK);
+ writel(reg, (ulong *)((ulong)pll->sysreg + CLK_DDR_BUS_OFFSET));
+ }
+
+ PLLX_SET(pll->offset->pd, pll->offset->pd_mask, PLL_PD_OFF);
+ PLLX_SET(pll->offset->dacpd, pll->offset->dacpd_mask, 1);
+ PLLX_SET(pll->offset->dsmpd, pll->offset->dsmpd_mask, 1);
+ PLLX_SET(pll->offset->prediv, pll->offset->prediv_mask, rate->prediv);
+ PLLX_SET(pll->offset->fbdiv, pll->offset->fbdiv_mask, rate->fbdiv);
+ PLLX_SET(pll->offset->postdiv1, pll->offset->postdiv1, 0);
+ PLLX_SET(pll->offset->pd, pll->offset->pd_mask, PLL_PD_ON);
+
+ if (set) {
+ udelay(100);
+ reg = readl((ulong *)((ulong)pll->sysreg + CLK_DDR_BUS_OFFSET));
+ reg &= ~CLK_DDR_BUS_MASK;
+ reg |= CLK_DDR_BUS_PLL1_DIV2 << __ffs(CLK_DDR_BUS_MASK);
+ writel(reg, (ulong *)((ulong)pll->sysreg + CLK_DDR_BUS_OFFSET));
+ }
+}
+
+static ulong jh7110_pllx_recalc_rate(struct clk *clk)
+{
+ struct clk_jh7110_pllx *pll = to_clk_pllx(dev_get_clk_ptr(clk->dev));
+ u64 refclk = clk_get_parent_rate(clk);
+ u32 dacpd, dsmpd;
+ u32 prediv, fbdiv, postdiv1;
+ u64 frac;
+
+ dacpd = getbits_le32((ulong)pll->base + pll->offset->dacpd,
+ pll->offset->dacpd_mask);
+ dsmpd = getbits_le32((ulong)pll->base + pll->offset->dsmpd,
+ pll->offset->dsmpd_mask);
+ prediv = getbits_le32((ulong)pll->base + pll->offset->prediv,
+ pll->offset->prediv_mask);
+ fbdiv = getbits_le32((ulong)pll->base + pll->offset->fbdiv,
+ pll->offset->fbdiv_mask);
+ postdiv1 = 1 << getbits_le32((ulong)pll->base + pll->offset->postdiv1,
+ pll->offset->postdiv1_mask);
+ frac = (u64)getbits_le32((ulong)pll->base + pll->offset->frac,
+ pll->offset->frac_mask);
+
+ /* Integer Multiple Mode
+ * Both dacpd and dsmpd should be set as 1 while integer multiple mode.
+ *
+ * The frequency of outputs can be figured out as below.
+ *
+ * Fvco = Fref*Nl/M
+ * NI is integer frequency dividing ratio of feedback divider, set by fbdiv1[11:0] ,
+ * NI = 8, 9, 10, 12.13....4095
+ * M is frequency dividing ratio of pre-divider, set by prediv[5:0],M = 1,2...63
+ *
+ * Fclko1 = Fvco/Q1
+ * Q1 is frequency dividing ratio of post divider, set by postdiv1[1:0],Q1= 1,2,4,8
+ *
+ * Fraction Multiple Mode
+ *
+ * Both dacpd and dsmpd should be set as 0 while integer multiple mode.
+ *
+ * Fvco = Fref*(NI+NF)/M
+ * NI is integer frequency dividing ratio of feedback divider, set by fbdiv[11:0] ,
+ * NI = 8, 9, 10, 12.13....4095
+ * NF is fractional frequency dividing ratio, set by frac[23:0], NF =frac[23:0]/2^24= 0~0.99999994
+ * M is frequency dividing ratio of pre-divider, set by prediv[5:0],M = 1,2...63
+ *
+ * Fclko1 = Fvco/Q1
+ * Q1 is frequency dividing ratio of post divider, set by postdivl[1:0],Q1= 1,2,4,8
+ */
+ if (dacpd == 1 && dsmpd == 1)
+ frac = 0;
+ else if (dacpd == 0 && dsmpd == 0)
+ do_div(frac, 1 << 24);
+ else
+ return -EINVAL;
+
+ refclk *= (fbdiv + frac);
+ do_div(refclk, prediv * postdiv1);
+
+ return refclk;
+}
+
+static ulong jh7110_pllx_set_rate(struct clk *clk, ulong drate)
+{
+ struct clk_jh7110_pllx *pll = to_clk_pllx(dev_get_clk_ptr(clk->dev));
+ const struct starfive_pllx_rate *rate;
+
+ rate = jh7110_get_pll_settings(pll, drate);
+ if (!rate)
+ return -EINVAL;
+
+ jh7110_pll_set_rate(pll, rate);
+
+ return jh7110_pllx_recalc_rate(clk);
+}
+
+static const struct clk_ops clk_jh7110_ops = {
+ .set_rate = jh7110_pllx_set_rate,
+ .get_rate = jh7110_pllx_recalc_rate,
+};
+
+struct clk *starfive_jh7110_pll(const char *name, const char *parent_name,
+ void __iomem *base, void __iomem *sysreg,
+ const struct starfive_pllx_clk *pll_clk)
+{
+ struct clk_jh7110_pllx *pll;
+ struct clk *clk;
+ int ret;
+
+ if (!pll_clk || !base || !sysreg)
+ return ERR_PTR(-EINVAL);
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ pll->base = base;
+ pll->sysreg = sysreg;
+ pll->type = pll_clk->type;
+ pll->offset = pll_clk->offset;
+ pll->rate_table = pll_clk->rate_table;
+ pll->rate_count = pll_clk->rate_count;
+
+ clk = &pll->clk;
+ ret = clk_register(clk, UBOOT_DM_CLK_JH7110_PLLX, name, parent_name);
+ if (ret) {
+ kfree(pll);
+ return ERR_PTR(ret);
+ }
+
+ if (IS_ENABLED(CONFIG_SPL_BUILD) && pll->type == PLL0)
+ jh7110_pllx_set_rate(clk, 1000000000);
+
+ if (IS_ENABLED(CONFIG_SPL_BUILD) && pll->type == PLL2)
+ jh7110_pllx_set_rate(clk, 1188000000);
+
+ return clk;
+}
+
+U_BOOT_DRIVER(jh7110_clk_pllx) = {
+ .name = UBOOT_DM_CLK_JH7110_PLLX,
+ .id = UCLASS_CLK,
+ .ops = &clk_jh7110_ops,
+};
diff --git a/drivers/clk/starfive/clk-jh7110.c b/drivers/clk/starfive/clk-jh7110.c
new file mode 100644
index 00000000000..a74b70906a6
--- /dev/null
+++ b/drivers/clk/starfive/clk-jh7110.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022-23 StarFive Technology Co., Ltd.
+ *
+ * Author: Yanhong Wang <[email protected]>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/devres.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/starfive,jh7110-crg.h>
+#include <log.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+#define STARFIVE_CLK_ENABLE_SHIFT 31 /* [31] */
+#define STARFIVE_CLK_INVERT_SHIFT 30 /* [30] */
+#define STARFIVE_CLK_MUX_SHIFT 24 /* [29:24] */
+#define STARFIVE_CLK_DIV_SHIFT 0 /* [23:0] */
+
+#define OFFSET(id) ((id) * 4)
+#define AONOFFSET(id) (((id) - JH7110_SYSCLK_END) * 4)
+#define STGOFFSET(id) (((id) - JH7110_AONCLK_END) * 4)
+
+typedef int (*jh1710_init_fn)(struct udevice *dev);
+
+struct jh7110_clk_priv {
+ void __iomem *reg;
+ jh1710_init_fn init;
+};
+
+static const char *cpu_root_sels[2] = {
+ [0] = "oscillator",
+ [1] = "pll0_out",
+};
+
+static const char *perh_root_sels[2] = {
+ [0] = "pll0_out",
+ [1] = "pll2_out",
+};
+
+static const char *bus_root_sels[2] = {
+ [0] = "oscillator",
+ [1] = "pll2_out",
+};
+
+static const char *qspi_ref_sels[2] = {
+ [0] = "oscillator",
+ [1] = "qspi_ref_src",
+};
+
+static const char *gmac1_tx_sels[2] = {
+ [0] = "gmac1_gtxclk",
+ [1] = "gmac1_rmii_rtx",
+};
+
+static const char *gmac0_tx_sels[2] = {
+ [0] = "gmac0_gtxclk",
+ [1] = "gmac0_rmii_rtx",
+};
+
+static const char *apb_func_sels[2] = {
+ [0] = "osc_div4",
+ [1] = "oscillator",
+};
+
+static const char *gmac1_rx_sels[2] = {
+ [0] = "gmac1-rgmii-rxin-clock",
+ [1] = "gmac1_rmii_rtx",
+};
+
+static struct clk *starfive_clk_mux(void __iomem *reg,
+ const char *name,
+ unsigned int offset,
+ u8 width,
+ const char * const *parent_names,
+ u8 num_parents)
+{
+ return clk_register_mux(NULL, name, parent_names, num_parents, 0,
+ reg + offset, STARFIVE_CLK_MUX_SHIFT,
+ width, 0);
+}
+
+static struct clk *starfive_clk_gate(void __iomem *reg,
+ const char *name,
+ const char *parent_name,
+ unsigned int offset)
+{
+ return clk_register_gate(NULL, name, parent_name, 0, reg + offset,
+ STARFIVE_CLK_ENABLE_SHIFT, 0, NULL);
+}
+
+static struct clk *starfive_clk_inv(void __iomem *reg,
+ const char *name,
+ const char *parent_name,
+ unsigned int offset)
+{
+ return clk_register_gate(NULL, name, parent_name, 0, reg + offset,
+ STARFIVE_CLK_INVERT_SHIFT, 0, NULL);
+}
+
+static struct clk *starfive_clk_divider(void __iomem *reg,
+ const char *name,
+ const char *parent_name,
+ unsigned int offset,
+ u8 width)
+{
+ return clk_register_divider(NULL, name, parent_name, 0, reg + offset,
+ 0, width, CLK_DIVIDER_ONE_BASED);
+}
+
+static struct clk *starfive_clk_composite(void __iomem *reg,
+ const char *name,
+ const char * const *parent_names,
+ unsigned int num_parents,
+ unsigned int offset,
+ unsigned int mux_width,
+ unsigned int gate_width,
+ unsigned int div_width)
+{
+ struct clk *clk = ERR_PTR(-ENOMEM);
+ struct clk_divider *div = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_mux *mux = NULL;
+ int mask_arry[4] = {0x1, 0x3, 0x7, 0xF};
+ int mask;
+
+ if (mux_width) {
+ if (mux_width > 4)
+ goto fail;
+ else
+ mask = mask_arry[mux_width - 1];
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ goto fail;
+
+ mux->reg = reg + offset;
+ mux->mask = mask;
+ mux->shift = STARFIVE_CLK_MUX_SHIFT;
+ mux->num_parents = num_parents;
+ mux->flags = 0;
+ mux->parent_names = parent_names;
+ }
+
+ if (gate_width) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+
+ if (!gate)
+ goto fail;
+
+ gate->reg = reg + offset;
+ gate->bit_idx = STARFIVE_CLK_ENABLE_SHIFT;
+ gate->flags = 0;
+ }
+
+ if (div_width) {
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ goto fail;
+
+ div->reg = reg + offset;
+
+ if (offset == OFFSET(JH7110_SYSCLK_UART3_CORE) ||
+ offset == OFFSET(JH7110_SYSCLK_UART4_CORE) ||
+ offset == OFFSET(JH7110_SYSCLK_UART5_CORE)) {
+ div->shift = 8;
+ div->width = 8;
+ } else {
+ div->shift = STARFIVE_CLK_DIV_SHIFT;
+ div->width = div_width;
+ }
+ div->flags = CLK_DIVIDER_ONE_BASED;
+ div->table = NULL;
+ }
+
+ clk = clk_register_composite(NULL, name,
+ parent_names, num_parents,
+ &mux->clk, &clk_mux_ops,
+ &div->clk, &clk_divider_ops,
+ &gate->clk, &clk_gate_ops, 0);
+
+ if (IS_ERR(clk))
+ goto fail;
+
+ return clk;
+
+fail:
+ kfree(gate);
+ kfree(div);
+ kfree(mux);
+ return ERR_CAST(clk);
+}
+
+static struct clk *starfive_clk_fix_parent_composite(void __iomem *reg,
+ const char *name,
+ const char *parent_names,
+ unsigned int offset,
+ unsigned int mux_width,
+ unsigned int gate_width,
+ unsigned int div_width)
+{
+ const char * const *parents;
+
+ parents = &parent_names;
+
+ return starfive_clk_composite(reg, name, parents, 1, offset,
+ mux_width, gate_width, div_width);
+}
+
+static struct clk *starfive_clk_gate_divider(void __iomem *reg,
+ const char *name,
+ const char *parent,
+ unsigned int offset,
+ unsigned int width)
+{
+ const char * const *parent_names;
+
+ parent_names = &parent;
+
+ return starfive_clk_composite(reg, name, parent_names, 1,
+ offset, 0, 1, width);
+}
+
+static int jh7110_syscrg_init(struct udevice *dev)
+{
+ struct jh7110_clk_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args args;
+ fdt_addr_t addr;
+ struct clk *pclk;
+ int ret;
+
+ ret = ofnode_parse_phandle_with_args(dev->node_, "starfive,sys-syscon", NULL, 0, 0, &args);
+ if (ret)
+ return ret;
+
+ addr = ofnode_get_addr(args.node);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ clk_dm(JH7110_SYSCLK_PLL0_OUT,
+ starfive_jh7110_pll("pll0_out", "oscillator", (void __iomem *)addr,
+ priv->reg, &starfive_jh7110_pll0));
+ clk_dm(JH7110_SYSCLK_PLL1_OUT,
+ starfive_jh7110_pll("pll1_out", "oscillator", (void __iomem *)addr,
+ priv->reg, &starfive_jh7110_pll1));
+ clk_dm(JH7110_SYSCLK_PLL2_OUT,
+ starfive_jh7110_pll("pll2_out", "oscillator", (void __iomem *)addr,
+ priv->reg, &starfive_jh7110_pll2));
+ clk_dm(JH7110_SYSCLK_CPU_ROOT,
+ starfive_clk_mux(priv->reg, "cpu_root",
+ OFFSET(JH7110_SYSCLK_CPU_ROOT), 1,
+ cpu_root_sels, ARRAY_SIZE(cpu_root_sels)));
+ clk_dm(JH7110_SYSCLK_CPU_CORE,
+ starfive_clk_divider(priv->reg,
+ "cpu_core", "cpu_root",
+ OFFSET(JH7110_SYSCLK_CPU_CORE), 3));
+ clk_dm(JH7110_SYSCLK_CPU_BUS,
+ starfive_clk_divider(priv->reg,
+ "cpu_bus", "cpu_core",
+ OFFSET(JH7110_SYSCLK_CPU_BUS), 2));
+ clk_dm(JH7110_SYSCLK_PERH_ROOT,
+ starfive_clk_composite(priv->reg,
+ "perh_root",
+ perh_root_sels, ARRAY_SIZE(perh_root_sels),
+ OFFSET(JH7110_SYSCLK_PERH_ROOT), 1, 0, 2));
+ clk_dm(JH7110_SYSCLK_BUS_ROOT,
+ starfive_clk_mux(priv->reg, "bus_root",
+ OFFSET(JH7110_SYSCLK_BUS_ROOT), 1,
+ bus_root_sels, ARRAY_SIZE(bus_root_sels)));
+ clk_dm(JH7110_SYSCLK_NOCSTG_BUS,
+ starfive_clk_divider(priv->reg,
+ "nocstg_bus", "bus_root",
+ OFFSET(JH7110_SYSCLK_NOCSTG_BUS), 3));
+ clk_dm(JH7110_SYSCLK_AXI_CFG0,
+ starfive_clk_divider(priv->reg,
+ "axi_cfg0", "bus_root",
+ OFFSET(JH7110_SYSCLK_AXI_CFG0), 2));
+ clk_dm(JH7110_SYSCLK_STG_AXIAHB,
+ starfive_clk_divider(priv->reg,
+ "stg_axiahb", "axi_cfg0",
+ OFFSET(JH7110_SYSCLK_STG_AXIAHB), 2));
+ clk_dm(JH7110_SYSCLK_AHB0,
+ starfive_clk_gate(priv->reg,
+ "ahb0", "stg_axiahb",
+ OFFSET(JH7110_SYSCLK_AHB0)));
+ clk_dm(JH7110_SYSCLK_AHB1,
+ starfive_clk_gate(priv->reg,
+ "ahb1", "stg_axiahb",
+ OFFSET(JH7110_SYSCLK_AHB1)));
+ clk_dm(JH7110_SYSCLK_APB_BUS,
+ starfive_clk_divider(priv->reg,
+ "apb_bus", "stg_axiahb",
+ OFFSET(JH7110_SYSCLK_APB_BUS), 4));
+ clk_dm(JH7110_SYSCLK_APB0,
+ starfive_clk_gate(priv->reg,
+ "apb0", "apb_bus",
+ OFFSET(JH7110_SYSCLK_APB0)));
+ clk_dm(JH7110_SYSCLK_QSPI_AHB,
+ starfive_clk_gate(priv->reg,
+ "qspi_ahb", "ahb1",
+ OFFSET(JH7110_SYSCLK_QSPI_AHB)));
+ clk_dm(JH7110_SYSCLK_QSPI_APB,
+ starfive_clk_gate(priv->reg,
+ "qspi_apb", "apb_bus",
+ OFFSET(JH7110_SYSCLK_QSPI_APB)));
+ clk_dm(JH7110_SYSCLK_QSPI_REF_SRC,
+ starfive_clk_divider(priv->reg,
+ "qspi_ref_src", "pll0_out",
+ OFFSET(JH7110_SYSCLK_QSPI_REF_SRC), 5));
+ clk_dm(JH7110_SYSCLK_QSPI_REF,
+ starfive_clk_composite(priv->reg,
+ "qspi_ref",
+ qspi_ref_sels, ARRAY_SIZE(qspi_ref_sels),
+ OFFSET(JH7110_SYSCLK_QSPI_REF), 1, 1, 0));
+ clk_dm(JH7110_SYSCLK_SDIO0_AHB,
+ starfive_clk_gate(priv->reg,
+ "sdio0_ahb", "ahb0",
+ OFFSET(JH7110_SYSCLK_SDIO0_AHB)));
+ clk_dm(JH7110_SYSCLK_SDIO1_AHB,
+ starfive_clk_gate(priv->reg,
+ "sdio1_ahb", "ahb0",
+ OFFSET(JH7110_SYSCLK_SDIO1_AHB)));
+ clk_dm(JH7110_SYSCLK_SDIO0_SDCARD,
+ starfive_clk_fix_parent_composite(priv->reg,
+ "sdio0_sdcard", "axi_cfg0",
+ OFFSET(JH7110_SYSCLK_SDIO0_SDCARD), 0, 1, 4));
+ clk_dm(JH7110_SYSCLK_SDIO1_SDCARD,
+ starfive_clk_fix_parent_composite(priv->reg,
+ "sdio1_sdcard", "axi_cfg0",
+ OFFSET(JH7110_SYSCLK_SDIO1_SDCARD), 0, 1, 4));
+ clk_dm(JH7110_SYSCLK_USB_125M,
+ starfive_clk_divider(priv->reg,
+ "usb_125m", "pll0_out",
+ OFFSET(JH7110_SYSCLK_USB_125M), 4));
+ clk_dm(JH7110_SYSCLK_NOC_BUS_STG_AXI,
+ starfive_clk_gate(priv->reg,
+ "noc_bus_stg_axi", "nocstg_bus",
+ OFFSET(JH7110_SYSCLK_NOC_BUS_STG_AXI)));
+ clk_dm(JH7110_SYSCLK_GMAC1_AHB,
+ starfive_clk_gate(priv->reg,
+ "gmac1_ahb", "ahb0",
+ OFFSET(JH7110_SYSCLK_GMAC1_AHB)));
+ clk_dm(JH7110_SYSCLK_GMAC1_AXI,
+ starfive_clk_gate(priv->reg,
+ "gmac1_axi", "stg_axiahb",
+ OFFSET(JH7110_SYSCLK_GMAC1_AXI)));
+ clk_dm(JH7110_SYSCLK_GMAC_SRC,
+ starfive_clk_divider(priv->reg,
+ "gmac_src", "pll0_out",
+ OFFSET(JH7110_SYSCLK_GMAC_SRC), 3));
+ clk_dm(JH7110_SYSCLK_GMAC1_GTXCLK,
+ starfive_clk_divider(priv->reg,
+ "gmac1_gtxclk", "pll0_out",
+ OFFSET(JH7110_SYSCLK_GMAC1_GTXCLK), 4));
+ clk_dm(JH7110_SYSCLK_GMAC1_GTXC,
+ starfive_clk_gate(priv->reg,
+ "gmac1_gtxc", "gmac1_gtxclk",
+ OFFSET(JH7110_SYSCLK_GMAC1_GTXC)));
+ clk_dm(JH7110_SYSCLK_GMAC1_RMII_RTX,
+ starfive_clk_divider(priv->reg,
+ "gmac1_rmii_rtx", "gmac1-rmii-refin-clock",
+ OFFSET(JH7110_SYSCLK_GMAC1_RMII_RTX), 5));
+ clk_dm(JH7110_SYSCLK_GMAC1_PTP,
+ starfive_clk_gate_divider(priv->reg,
+ "gmac1_ptp", "gmac_src",
+ OFFSET(JH7110_SYSCLK_GMAC1_PTP), 5));
+ clk_dm(JH7110_SYSCLK_GMAC1_RX,
+ starfive_clk_mux(priv->reg, "gmac1_rx",
+ OFFSET(JH7110_SYSCLK_GMAC1_RX), 1,
+ gmac1_rx_sels, ARRAY_SIZE(gmac1_rx_sels)));
+ clk_dm(JH7110_SYSCLK_GMAC1_TX,
+ starfive_clk_composite(priv->reg,
+ "gmac1_tx",
+ gmac1_tx_sels, ARRAY_SIZE(gmac1_tx_sels),
+ OFFSET(JH7110_SYSCLK_GMAC1_TX), 1, 1, 0));
+ clk_dm(JH7110_SYSCLK_GMAC1_TX_INV,
+ starfive_clk_inv(priv->reg,
+ "gmac1_tx_inv", "gmac1_tx",
+ OFFSET(JH7110_SYSCLK_GMAC1_TX_INV)));
+ clk_dm(JH7110_SYSCLK_GMAC0_GTXCLK,
+ starfive_clk_gate_divider(priv->reg,
+ "gmac0_gtxclk", "pll0_out",
+ OFFSET(JH7110_SYSCLK_GMAC0_GTXCLK), 4));
+ clk_dm(JH7110_SYSCLK_GMAC0_PTP,
+ starfive_clk_gate_divider(priv->reg,
+ "gmac0_ptp", "gmac_src",
+ OFFSET(JH7110_SYSCLK_GMAC0_PTP), 5));
+ clk_dm(JH7110_SYSCLK_GMAC0_GTXC,
+ starfive_clk_gate(priv->reg,
+ "gmac0_gtxc", "gmac0_gtxclk",
+ OFFSET(JH7110_SYSCLK_GMAC0_GTXC)));
+ clk_dm(JH7110_SYSCLK_UART0_APB,
+ starfive_clk_gate(priv->reg,
+ "uart0_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_UART0_APB)));
+ clk_dm(JH7110_SYSCLK_UART0_CORE,
+ starfive_clk_gate(priv->reg,
+ "uart0_core", "oscillator",
+ OFFSET(JH7110_SYSCLK_UART0_CORE)));
+ clk_dm(JH7110_SYSCLK_UART1_APB,
+ starfive_clk_gate(priv->reg,
+ "uart1_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_UART1_APB)));
+ clk_dm(JH7110_SYSCLK_UART1_CORE,
+ starfive_clk_gate(priv->reg,
+ "uart1_core", "oscillator",
+ OFFSET(JH7110_SYSCLK_UART1_CORE)));
+ clk_dm(JH7110_SYSCLK_UART2_APB,
+ starfive_clk_gate(priv->reg,
+ "uart2_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_UART2_APB)));
+ clk_dm(JH7110_SYSCLK_UART2_CORE,
+ starfive_clk_gate(priv->reg,
+ "uart2_core", "oscillator",
+ OFFSET(JH7110_SYSCLK_UART2_CORE)));
+ clk_dm(JH7110_SYSCLK_UART3_APB,
+ starfive_clk_gate(priv->reg,
+ "uart3_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_UART3_APB)));
+ clk_dm(JH7110_SYSCLK_UART3_CORE,
+ starfive_clk_gate_divider(priv->reg,
+ "uart3_core", "perh_root",
+ OFFSET(JH7110_SYSCLK_UART3_CORE), 8));
+ clk_dm(JH7110_SYSCLK_UART4_APB,
+ starfive_clk_gate(priv->reg,
+ "uart4_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_UART4_APB)));
+ clk_dm(JH7110_SYSCLK_UART4_CORE,
+ starfive_clk_gate_divider(priv->reg,
+ "uart4_core", "perh_root",
+ OFFSET(JH7110_SYSCLK_UART4_CORE), 8));
+ clk_dm(JH7110_SYSCLK_UART5_APB,
+ starfive_clk_gate(priv->reg,
+ "uart5_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_UART5_APB)));
+ clk_dm(JH7110_SYSCLK_UART5_CORE,
+ starfive_clk_gate_divider(priv->reg,
+ "uart5_core", "perh_root",
+ OFFSET(JH7110_SYSCLK_UART5_CORE), 8));
+ clk_dm(JH7110_SYSCLK_I2C2_APB,
+ starfive_clk_gate(priv->reg,
+ "i2c2_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_I2C2_APB)));
+ clk_dm(JH7110_SYSCLK_I2C5_APB,
+ starfive_clk_gate(priv->reg,
+ "i2c5_apb", "apb0",
+ OFFSET(JH7110_SYSCLK_I2C5_APB)));
+
+ /* enable noc_bus_stg_axi clock */
+ if (!clk_get_by_id(JH7110_SYSCLK_NOC_BUS_STG_AXI, &pclk))
+ clk_enable(pclk);
+
+ return 0;
+}
+
+static int jh7110_aoncrg_init(struct udevice *dev)
+{
+ struct jh7110_clk_priv *priv = dev_get_priv(dev);
+
+ clk_dm(JH7110_AONCLK_OSC_DIV4,
+ starfive_clk_divider(priv->reg,
+ "osc_div4", "oscillator",
+ AONOFFSET(JH7110_AONCLK_OSC_DIV4), 5));
+ clk_dm(JH7110_AONCLK_APB_FUNC,
+ starfive_clk_mux(priv->reg, "apb_func",
+ AONOFFSET(JH7110_AONCLK_APB_FUNC), 1,
+ apb_func_sels, ARRAY_SIZE(apb_func_sels)));
+ clk_dm(JH7110_AONCLK_GMAC0_AHB,
+ starfive_clk_gate(priv->reg,
+ "gmac0_ahb", "stg_axiahb",
+ AONOFFSET(JH7110_AONCLK_GMAC0_AHB)));
+ clk_dm(JH7110_AONCLK_GMAC0_AXI,
+ starfive_clk_gate(priv->reg,
+ "gmac0_axi", "stg_axiahb",
+ AONOFFSET(JH7110_AONCLK_GMAC0_AXI)));
+ clk_dm(JH7110_AONCLK_GMAC0_RMII_RTX,
+ starfive_clk_divider(priv->reg,
+ "gmac0_rmii_rtx", "gmac0-rmii-refin-clock",
+ AONOFFSET(JH7110_AONCLK_GMAC0_RMII_RTX), 5));
+ clk_dm(JH7110_AONCLK_GMAC0_TX,
+ starfive_clk_composite(priv->reg,
+ "gmac0_tx", gmac0_tx_sels,
+ ARRAY_SIZE(gmac0_tx_sels),
+ AONOFFSET(JH7110_AONCLK_GMAC0_TX), 1, 1, 0));
+ clk_dm(JH7110_AONCLK_GMAC0_TX_INV,
+ starfive_clk_inv(priv->reg,
+ "gmac0_tx_inv", "gmac0_tx",
+ AONOFFSET(JH7110_AONCLK_GMAC0_TX_INV)));
+ clk_dm(JH7110_AONCLK_OTPC_APB,
+ starfive_clk_gate(priv->reg,
+ "otpc_apb", "apb_bus",
+ AONOFFSET(JH7110_AONCLK_OTPC_APB)));
+
+ return 0;
+}
+
+static int jh7110_stgcrg_init(struct udevice *dev)
+{
+ struct jh7110_clk_priv *priv = dev_get_priv(dev);
+
+ clk_dm(JH7110_STGCLK_USB_APB,
+ starfive_clk_gate(priv->reg,
+ "usb_apb", "apb_bus",
+ STGOFFSET(JH7110_STGCLK_USB_APB)));
+ clk_dm(JH7110_STGCLK_USB_UTMI_APB,
+ starfive_clk_gate(priv->reg,
+ "usb_utmi_apb", "apb_bus",
+ STGOFFSET(JH7110_STGCLK_USB_UTMI_APB)));
+ clk_dm(JH7110_STGCLK_USB_AXI,
+ starfive_clk_gate(priv->reg,
+ "usb_axi", "stg_axiahb",
+ STGOFFSET(JH7110_STGCLK_USB_AXI)));
+ clk_dm(JH7110_STGCLK_USB_LPM,
+ starfive_clk_gate_divider(priv->reg,
+ "usb_lpm", "oscillator",
+ STGOFFSET(JH7110_STGCLK_USB_LPM), 2));
+ clk_dm(JH7110_STGCLK_USB_STB,
+ starfive_clk_gate_divider(priv->reg,
+ "usb_stb", "oscillator",
+ STGOFFSET(JH7110_STGCLK_USB_STB), 3));
+ clk_dm(JH7110_STGCLK_USB_APP_125,
+ starfive_clk_gate(priv->reg,
+ "usb_app_125", "usb_125m",
+ STGOFFSET(JH7110_STGCLK_USB_APP_125)));
+ clk_dm(JH7110_STGCLK_USB_REFCLK,
+ starfive_clk_divider(priv->reg, "usb_refclk", "oscillator",
+ STGOFFSET(JH7110_STGCLK_USB_REFCLK), 2));
+ clk_dm(JH7110_STGCLK_PCIE0_AXI,
+ starfive_clk_gate(priv->reg,
+ "pcie0_axi", "stg_axiahb",
+ STGOFFSET(JH7110_STGCLK_PCIE0_AXI)));
+ clk_dm(JH7110_STGCLK_PCIE0_APB,
+ starfive_clk_gate(priv->reg,
+ "pcie0_apb", "apb_bus",
+ STGOFFSET(JH7110_STGCLK_PCIE0_APB)));
+ clk_dm(JH7110_STGCLK_PCIE0_TL,
+ starfive_clk_gate(priv->reg,
+ "pcie0_tl", "stg_axiahb",
+ STGOFFSET(JH7110_STGCLK_PCIE0_TL)));
+ clk_dm(JH7110_STGCLK_PCIE1_AXI,
+ starfive_clk_gate(priv->reg,
+ "pcie1_axi", "stg_axiahb",
+ STGOFFSET(JH7110_STGCLK_PCIE1_AXI)));
+ clk_dm(JH7110_STGCLK_PCIE1_APB,
+ starfive_clk_gate(priv->reg,
+ "pcie1_apb", "apb_bus",
+ STGOFFSET(JH7110_STGCLK_PCIE1_APB)));
+ clk_dm(JH7110_STGCLK_PCIE1_TL,
+ starfive_clk_gate(priv->reg,
+ "pcie1_tl", "stg_axiahb",
+ STGOFFSET(JH7110_STGCLK_PCIE1_TL)));
+
+ return 0;
+}
+
+static int jh7110_clk_probe(struct udevice *dev)
+{
+ struct jh7110_clk_priv *priv = dev_get_priv(dev);
+
+ priv->init = (jh1710_init_fn)dev_get_driver_data(dev);
+ priv->reg = (void __iomem *)dev_read_addr_ptr(dev);
+
+ if (priv->init)
+ return priv->init(dev);
+
+ return 0;
+}
+
+static int jh7110_clk_bind(struct udevice *dev)
+{
+ /* The reset driver does not have a device node, so bind it here */
+ return device_bind_driver_to_node(dev, "jh7110_reset", dev->name,
+ dev_ofnode(dev), NULL);
+}
+
+static const struct udevice_id jh7110_clk_of_match[] = {
+ { .compatible = "starfive,jh7110-syscrg",
+ .data = (ulong)&jh7110_syscrg_init
+ },
+ { .compatible = "starfive,jh7110-stgcrg",
+ .data = (ulong)&jh7110_stgcrg_init
+ },
+ { .compatible = "starfive,jh7110-aoncrg",
+ .data = (ulong)&jh7110_aoncrg_init
+ },
+ { }
+};
+
+U_BOOT_DRIVER(jh7110_clk) = {
+ .name = "jh7110_clk",
+ .id = UCLASS_CLK,
+ .of_match = jh7110_clk_of_match,
+ .probe = jh7110_clk_probe,
+ .ops = &ccf_clk_ops,
+ .priv_auto = sizeof(struct jh7110_clk_priv),
+ .bind = jh7110_clk_bind,
+};
diff --git a/drivers/clk/starfive/clk.h b/drivers/clk/starfive/clk.h
new file mode 100644
index 00000000000..4dee12fe895
--- /dev/null
+++ b/drivers/clk/starfive/clk.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 Starfive, Inc.
+ * Author: Yanhong Wang <[email protected]>
+ *
+ */
+
+#ifndef __CLK_STARFIVE_H
+#define __CLK_STARFIVE_H
+
+enum starfive_pll_type {
+ PLL0 = 0,
+ PLL1,
+ PLL2,
+ PLL_MAX = PLL2
+};
+
+struct starfive_pllx_rate {
+ u64 rate;
+ u32 prediv;
+ u32 fbdiv;
+ u32 frac;
+};
+
+struct starfive_pllx_offset {
+ u32 pd;
+ u32 prediv;
+ u32 fbdiv;
+ u32 frac;
+ u32 postdiv1;
+ u32 dacpd;
+ u32 dsmpd;
+ u32 pd_mask;
+ u32 prediv_mask;
+ u32 fbdiv_mask;
+ u32 frac_mask;
+ u32 postdiv1_mask;
+ u32 dacpd_mask;
+ u32 dsmpd_mask;
+};
+
+struct starfive_pllx_clk {
+ enum starfive_pll_type type;
+ const struct starfive_pllx_offset *offset;
+ const struct starfive_pllx_rate *rate_table;
+ int rate_count;
+ int flags;
+};
+
+extern struct starfive_pllx_clk starfive_jh7110_pll0;
+extern struct starfive_pllx_clk starfive_jh7110_pll1;
+extern struct starfive_pllx_clk starfive_jh7110_pll2;
+
+struct clk *starfive_jh7110_pll(const char *name, const char *parent_name,
+ void __iomem *base, void __iomem *sysreg,
+ const struct starfive_pllx_clk *pll_clk);
+#endif
diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
index abd4e8b7389..f27306fe33b 100644
--- a/drivers/clk/sunxi/clk_a10.c
+++ b/drivers/clk/sunxi/clk_a10.c
@@ -23,6 +23,7 @@ static struct ccu_clk_gate a10_gates[] = {
[CLK_AHB_MMC1] = GATE(0x060, BIT(9)),
[CLK_AHB_MMC2] = GATE(0x060, BIT(10)),
[CLK_AHB_MMC3] = GATE(0x060, BIT(11)),
+ [CLK_AHB_NAND] = GATE(0x060, BIT(13)),
[CLK_AHB_EMAC] = GATE(0x060, BIT(17)),
[CLK_AHB_SPI0] = GATE(0x060, BIT(20)),
[CLK_AHB_SPI1] = GATE(0x060, BIT(21)),
@@ -47,6 +48,7 @@ static struct ccu_clk_gate a10_gates[] = {
[CLK_APB1_UART6] = GATE(0x06c, BIT(22)),
[CLK_APB1_UART7] = GATE(0x06c, BIT(23)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
[CLK_SPI2] = GATE(0x0a8, BIT(31)),
diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
index e486cedd48d..16ac589bb2b 100644
--- a/drivers/clk/sunxi/clk_a10s.c
+++ b/drivers/clk/sunxi/clk_a10s.c
@@ -20,6 +20,7 @@ static struct ccu_clk_gate a10s_gates[] = {
[CLK_AHB_MMC0] = GATE(0x060, BIT(8)),
[CLK_AHB_MMC1] = GATE(0x060, BIT(9)),
[CLK_AHB_MMC2] = GATE(0x060, BIT(10)),
+ [CLK_AHB_NAND] = GATE(0x060, BIT(13)),
[CLK_AHB_EMAC] = GATE(0x060, BIT(17)),
[CLK_AHB_SPI0] = GATE(0x060, BIT(20)),
[CLK_AHB_SPI1] = GATE(0x060, BIT(21)),
@@ -35,6 +36,7 @@ static struct ccu_clk_gate a10s_gates[] = {
[CLK_APB1_UART2] = GATE(0x06c, BIT(18)),
[CLK_APB1_UART3] = GATE(0x06c, BIT(19)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
[CLK_SPI2] = GATE(0x0a8, BIT(31)),
diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
index d94fecadd59..45d5ba75bf5 100644
--- a/drivers/clk/sunxi/clk_a23.c
+++ b/drivers/clk/sunxi/clk_a23.c
@@ -17,6 +17,7 @@ static struct ccu_clk_gate a23_gates[] = {
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
+ [CLK_BUS_NAND] = GATE(0x060, BIT(13)),
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
[CLK_BUS_OTG] = GATE(0x060, BIT(24)),
@@ -34,6 +35,7 @@ static struct ccu_clk_gate a23_gates[] = {
[CLK_BUS_UART3] = GATE(0x06c, BIT(19)),
[CLK_BUS_UART4] = GATE(0x06c, BIT(20)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
@@ -52,6 +54,7 @@ static struct ccu_reset a23_resets[] = {
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
+ [RST_BUS_NAND] = RESET(0x2c0, BIT(13)),
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
[RST_BUS_OTG] = RESET(0x2c0, BIT(24)),
diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
index 360658912dd..6ca800050ed 100644
--- a/drivers/clk/sunxi/clk_a31.c
+++ b/drivers/clk/sunxi/clk_a31.c
@@ -18,6 +18,8 @@ static struct ccu_clk_gate a31_gates[] = {
[CLK_AHB1_MMC1] = GATE(0x060, BIT(9)),
[CLK_AHB1_MMC2] = GATE(0x060, BIT(10)),
[CLK_AHB1_MMC3] = GATE(0x060, BIT(11)),
+ [CLK_AHB1_NAND1] = GATE(0x060, BIT(12)),
+ [CLK_AHB1_NAND0] = GATE(0x060, BIT(13)),
[CLK_AHB1_EMAC] = GATE(0x060, BIT(17)),
[CLK_AHB1_SPI0] = GATE(0x060, BIT(20)),
[CLK_AHB1_SPI1] = GATE(0x060, BIT(21)),
@@ -43,6 +45,8 @@ static struct ccu_clk_gate a31_gates[] = {
[CLK_APB2_UART4] = GATE(0x06c, BIT(20)),
[CLK_APB2_UART5] = GATE(0x06c, BIT(21)),
+ [CLK_NAND0] = GATE(0x080, BIT(31)),
+ [CLK_NAND1] = GATE(0x084, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
[CLK_SPI2] = GATE(0x0a8, BIT(31)),
@@ -65,6 +69,8 @@ static struct ccu_reset a31_resets[] = {
[RST_AHB1_MMC1] = RESET(0x2c0, BIT(9)),
[RST_AHB1_MMC2] = RESET(0x2c0, BIT(10)),
[RST_AHB1_MMC3] = RESET(0x2c0, BIT(11)),
+ [RST_AHB1_NAND1] = RESET(0x2c0, BIT(12)),
+ [RST_AHB1_NAND0] = RESET(0x2c0, BIT(13)),
[RST_AHB1_EMAC] = RESET(0x2c0, BIT(17)),
[RST_AHB1_SPI0] = RESET(0x2c0, BIT(20)),
[RST_AHB1_SPI1] = RESET(0x2c0, BIT(21)),
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 136ba89293d..fd26cd4f5d6 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -20,6 +20,7 @@ static const struct ccu_clk_gate a64_gates[] = {
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
+ [CLK_BUS_NAND] = GATE(0x060, BIT(13)),
[CLK_BUS_EMAC] = GATE(0x060, BIT(17)),
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
@@ -45,6 +46,7 @@ static const struct ccu_clk_gate a64_gates[] = {
[CLK_BUS_UART3] = GATE(0x06c, BIT(19)),
[CLK_BUS_UART4] = GATE(0x06c, BIT(20)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
@@ -74,6 +76,7 @@ static const struct ccu_reset a64_resets[] = {
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
+ [RST_BUS_NAND] = RESET(0x2c0, BIT(13)),
[RST_BUS_EMAC] = RESET(0x2c0, BIT(17)),
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c
index 3c9eb143167..c5834f44103 100644
--- a/drivers/clk/sunxi/clk_a80.c
+++ b/drivers/clk/sunxi/clk_a80.c
@@ -14,12 +14,18 @@
#include <linux/bitops.h>
static const struct ccu_clk_gate a80_gates[] = {
+ [CLK_NAND0_0] = GATE(0x400, BIT(31)),
+ [CLK_NAND0_1] = GATE(0x404, BIT(31)),
+ [CLK_NAND1_0] = GATE(0x408, BIT(31)),
+ [CLK_NAND1_1] = GATE(0x40c, BIT(31)),
[CLK_SPI0] = GATE(0x430, BIT(31)),
[CLK_SPI1] = GATE(0x434, BIT(31)),
[CLK_SPI2] = GATE(0x438, BIT(31)),
[CLK_SPI3] = GATE(0x43c, BIT(31)),
[CLK_BUS_MMC] = GATE(0x580, BIT(8)),
+ [CLK_BUS_NAND0] = GATE(0x580, BIT(13)),
+ [CLK_BUS_NAND1] = GATE(0x580, BIT(12)),
[CLK_BUS_SPI0] = GATE(0x580, BIT(20)),
[CLK_BUS_SPI1] = GATE(0x580, BIT(21)),
[CLK_BUS_SPI2] = GATE(0x580, BIT(22)),
@@ -42,6 +48,8 @@ static const struct ccu_clk_gate a80_gates[] = {
static const struct ccu_reset a80_resets[] = {
[RST_BUS_MMC] = RESET(0x5a0, BIT(8)),
+ [RST_BUS_NAND0] = RESET(0x5a0, BIT(13)),
+ [RST_BUS_NAND1] = RESET(0x5a0, BIT(12)),
[RST_BUS_SPI0] = RESET(0x5a0, BIT(20)),
[RST_BUS_SPI1] = RESET(0x5a0, BIT(21)),
[RST_BUS_SPI2] = RESET(0x5a0, BIT(22)),
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
index d5af37b3d78..760d98cd620 100644
--- a/drivers/clk/sunxi/clk_a83t.c
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -18,6 +18,7 @@ static struct ccu_clk_gate a83t_gates[] = {
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
+ [CLK_BUS_NAND] = GATE(0x060, BIT(13)),
[CLK_BUS_EMAC] = GATE(0x060, BIT(17)),
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
@@ -42,6 +43,7 @@ static struct ccu_clk_gate a83t_gates[] = {
[CLK_BUS_UART3] = GATE(0x06c, BIT(19)),
[CLK_BUS_UART4] = GATE(0x06c, BIT(20)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
@@ -70,6 +72,7 @@ static struct ccu_reset a83t_resets[] = {
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
+ [RST_BUS_NAND] = RESET(0x2c0, BIT(13)),
[RST_BUS_EMAC] = RESET(0x2c0, BIT(17)),
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
index 213ab510ed5..32bc95fccca 100644
--- a/drivers/clk/sunxi/clk_h3.c
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -19,6 +19,7 @@ static struct ccu_clk_gate h3_gates[] = {
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
+ [CLK_BUS_NAND] = GATE(0x060, BIT(13)),
[CLK_BUS_EMAC] = GATE(0x060, BIT(17)),
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
@@ -49,6 +50,7 @@ static struct ccu_clk_gate h3_gates[] = {
[CLK_BUS_EPHY] = GATE(0x070, BIT(0)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
@@ -77,6 +79,7 @@ static struct ccu_reset h3_resets[] = {
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
+ [RST_BUS_NAND] = RESET(0x2c0, BIT(13)),
[RST_BUS_EMAC] = RESET(0x2c0, BIT(17)),
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
index 24eb9725dbc..071fd581003 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -21,6 +21,10 @@ static struct ccu_clk_gate h6_gates[] = {
[CLK_DE] = GATE(0x600, BIT(31)),
[CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+ [CLK_NAND0] = GATE(0x810, BIT(31)),
+ [CLK_NAND1] = GATE(0x814, BIT(31)),
+ [CLK_BUS_NAND] = GATE(0x82c, BIT(0)),
+
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
@@ -72,6 +76,7 @@ static struct ccu_clk_gate h6_gates[] = {
static struct ccu_reset h6_resets[] = {
[RST_BUS_DE] = RESET(0x60c, BIT(16)),
+ [RST_BUS_NAND] = RESET(0x82c, BIT(16)),
[RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
[RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c
index 88d6bf3420d..113dcff2851 100644
--- a/drivers/clk/sunxi/clk_h616.c
+++ b/drivers/clk/sunxi/clk_h616.c
@@ -20,6 +20,10 @@ static struct ccu_clk_gate h616_gates[] = {
[CLK_DE] = GATE(0x600, BIT(31)),
[CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+ [CLK_NAND0] = GATE(0x810, BIT(31)),
+ [CLK_NAND1] = GATE(0x814, BIT(31)),
+ [CLK_BUS_NAND] = GATE(0x82c, BIT(0)),
+
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
@@ -81,6 +85,7 @@ static struct ccu_clk_gate h616_gates[] = {
static struct ccu_reset h616_resets[] = {
[RST_BUS_DE] = RESET(0x60c, BIT(16)),
+ [RST_BUS_NAND] = RESET(0x82c, BIT(16)),
[RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
[RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
index 630e80d2b4e..0fef6f3566d 100644
--- a/drivers/clk/sunxi/clk_r40.c
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -19,6 +19,7 @@ static struct ccu_clk_gate r40_gates[] = {
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
[CLK_BUS_MMC3] = GATE(0x060, BIT(11)),
+ [CLK_BUS_NAND] = GATE(0x060, BIT(13)),
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
[CLK_BUS_SPI2] = GATE(0x060, BIT(22)),
@@ -57,6 +58,7 @@ static struct ccu_clk_gate r40_gates[] = {
[CLK_BUS_UART6] = GATE(0x06c, BIT(22)),
[CLK_BUS_UART7] = GATE(0x06c, BIT(23)),
+ [CLK_NAND] = GATE(0x080, BIT(31)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_SPI1] = GATE(0x0a4, BIT(31)),
[CLK_SPI2] = GATE(0x0a8, BIT(31)),
@@ -91,6 +93,7 @@ static struct ccu_reset r40_resets[] = {
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
[RST_BUS_MMC3] = RESET(0x2c0, BIT(11)),
+ [RST_BUS_NAND] = RESET(0x2c0, BIT(13)),
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
[RST_BUS_SPI2] = RESET(0x2c0, BIT(22)),
diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c
index 91bcd1a2c21..b9b0c28852f 100644
--- a/drivers/core/fdtaddr.c
+++ b/drivers/core/fdtaddr.c
@@ -12,6 +12,7 @@
#include <dm.h>
#include <fdt_support.h>
#include <log.h>
+#include <mapmem.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <dm/device-internal.h>
@@ -97,7 +98,10 @@ void *devfdt_get_addr_index_ptr(const struct udevice *dev, int index)
{
fdt_addr_t addr = devfdt_get_addr_index(dev, index);
- return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)(uintptr_t)addr;
+ if (addr == FDT_ADDR_T_NONE)
+ return NULL;
+
+ return map_sysmem(addr, 0);
}
fdt_addr_t devfdt_get_addr_size_index(const struct udevice *dev, int index,
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 85f7da5a499..81a307992c0 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -33,7 +33,7 @@
DECLARE_GLOBAL_DATA_PTR;
/* list of struct alias_prop aliases */
-LIST_HEAD(aliases_lookup);
+static LIST_HEAD(aliases_lookup);
/* "/aliaes" node */
static struct device_node *of_aliases;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 1762a0796db..e46d5717aa6 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -411,18 +411,14 @@ done:
}
#if CONFIG_IS_ENABLED(OF_REAL)
-int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
- const char *name, struct udevice **devp)
+static int uclass_find_device_by_phandle_id(enum uclass_id id,
+ uint find_phandle,
+ struct udevice **devp)
{
struct udevice *dev;
struct uclass *uc;
- int find_phandle;
int ret;
- *devp = NULL;
- find_phandle = dev_read_u32_default(parent, name, -1);
- if (find_phandle <= 0)
- return -ENOENT;
ret = uclass_get(id, &uc);
if (ret)
return ret;
@@ -440,6 +436,19 @@ int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
return -ENODEV;
}
+
+int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
+ const char *name, struct udevice **devp)
+{
+ int find_phandle;
+
+ *devp = NULL;
+ find_phandle = dev_read_u32_default(parent, name, -1);
+ if (find_phandle <= 0)
+ return -ENOENT;
+
+ return uclass_find_device_by_phandle_id(id, find_phandle, devp);
+}
#endif
int uclass_get_device_by_driver(enum uclass_id id,
@@ -535,31 +544,22 @@ int uclass_get_device_by_ofnode(enum uclass_id id, ofnode node,
return uclass_get_device_tail(dev, ret, devp);
}
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_REAL)
+int uclass_get_device_by_of_path(enum uclass_id id, const char *path,
+ struct udevice **devp)
+{
+ return uclass_get_device_by_ofnode(id, ofnode_path(path), devp);
+}
+
int uclass_get_device_by_phandle_id(enum uclass_id id, uint phandle_id,
struct udevice **devp)
{
struct udevice *dev;
- struct uclass *uc;
int ret;
*devp = NULL;
- ret = uclass_get(id, &uc);
- if (ret)
- return ret;
-
- uclass_foreach_dev(dev, uc) {
- uint phandle;
-
- phandle = dev_read_phandle(dev);
-
- if (phandle == phandle_id) {
- *devp = dev;
- return uclass_get_device_tail(dev, ret, devp);
- }
- }
-
- return -ENODEV;
+ ret = uclass_find_device_by_phandle_id(id, phandle_id, &dev);
+ return uclass_get_device_tail(dev, ret, devp);
}
int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
index 6e7949ac72c..8ec9fb0874e 100644
--- a/drivers/ddr/marvell/a38x/mv_ddr_plat.c
+++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
@@ -1363,13 +1363,6 @@ int mv_ddr_pre_training_soc_config(const char *ddr_type)
DRAM_RESET_MASK_MASKED << DRAM_RESET_MASK_OFFS);
}
- /* Check if DRAM is already initialized */
- if (reg_read(REG_BOOTROM_ROUTINE_ADDR) &
- (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) {
- printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type);
- return MV_OK;
- }
-
/* Fix read ready phases for all SOC in reg 0x15c8 */
reg_val = reg_read(TRAINING_DBG_3_REG);
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
new file mode 100644
index 00000000000..fbb73354aa3
--- /dev/null
+++ b/drivers/extcon/Kconfig
@@ -0,0 +1,31 @@
+menu "Extcon Support"
+
+config EXTCON
+ bool "External Connector Class (extcon) support"
+ depends on DM
+ help
+ Say Y here to enable external connector class (extcon) support.
+ This allows monitoring external connectors and supports external
+ connectors with multiple states; i.e., an extcon that may have
+ multiple cables attached. For example, an external connector
+ of a device may be used to connect an HDMI cable and a AC adaptor,
+ and to host USB ports. Many of 30-pin connectors including PDMI
+ are also good examples.
+
+config EXTCON_SANDBOX
+ bool "Sandbox extcon"
+ depends on EXTCON
+ help
+ Enable extcon support for sandbox. This is an emulation of a real
+ extcon. Currectly all configuration is done in the probe.
+
+config EXTCON_MAX14526
+ bool "Maxim MAX14526 EXTCON Support"
+ depends on DM_I2C
+ depends on EXTCON
+ help
+ If you say yes here you get support for the MUIC device of
+ Maxim MAX14526. The MAX14526 MUIC is a USB port accessory
+ detector and switch.
+
+endmenu
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
new file mode 100644
index 00000000000..3309f2aac2e
--- /dev/null
+++ b/drivers/extcon/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2023 Svyatoslav Ryhel <[email protected]>
+
+obj-$(CONFIG_EXTCON) += extcon-uclass.o
+obj-$(CONFIG_EXTCON_SANDBOX) += extcon-sandbox.o
+obj-$(CONFIG_EXTCON_MAX14526) += extcon-max14526.o
diff --git a/drivers/extcon/extcon-max14526.c b/drivers/extcon/extcon-max14526.c
new file mode 100644
index 00000000000..a33b5ef919c
--- /dev/null
+++ b/drivers/extcon/extcon-max14526.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <log.h>
+#include <extcon.h>
+#include <asm/gpio.h>
+
+#define CONTROL_1 0x01
+#define SW_CONTROL 0x03
+
+#define ID_200 0x10
+#define ADC_EN 0x02
+#define CP_EN 0x01
+
+#define DP_USB 0x00
+#define DP_UART 0x08
+#define DP_AUDIO 0x10
+#define DP_OPEN 0x38
+
+#define DM_USB 0x00
+#define DM_UART 0x01
+#define DM_AUDIO 0x02
+#define DM_OPEN 0x07
+
+#define AP_USB BIT(0)
+#define CP_USB BIT(1)
+#define CP_UART BIT(2)
+
+struct max14526_priv {
+ struct gpio_desc usif_gpio;
+ struct gpio_desc dp2t_gpio;
+ struct gpio_desc ifx_usb_vbus_gpio;
+};
+
+static void max14526_set_mode(struct udevice *dev, int mode)
+{
+ struct max14526_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if ((mode & AP_USB) || (mode & CP_USB)) {
+ /* Connect CP UART signals to AP */
+ ret = dm_gpio_set_value(&priv->usif_gpio, 0);
+ if (ret)
+ log_debug("cp-uart > ap failed (%d)\n", ret);
+ }
+
+ if (mode & CP_UART) {
+ /* Connect CP UART signals to DP2T */
+ ret = dm_gpio_set_value(&priv->usif_gpio, 1);
+ if (ret)
+ log_debug("cp-uart > dp2t failed (%d)\n", ret);
+ }
+
+ if (mode & CP_USB) {
+ /* Connect CP USB to MUIC UART */
+ ret = dm_gpio_set_value(&priv->ifx_usb_vbus_gpio, 1);
+ if (ret)
+ log_debug("usb-vbus-gpio enable failed (%d)\n", ret);
+
+ ret = dm_gpio_set_value(&priv->dp2t_gpio, 1);
+ if (ret)
+ log_debug("cp-usb > muic-uart failed (%d)\n", ret);
+ }
+
+ if ((mode & AP_USB) || (mode & CP_UART)) {
+ /* Connect CP UART to MUIC UART */
+ ret = dm_gpio_set_value(&priv->dp2t_gpio, 0);
+ if (ret)
+ log_debug("cp-uart > muic-uart failed (%d)\n", ret);
+ }
+
+ if (mode & AP_USB) {
+ /* Enables USB Path */
+ ret = dm_i2c_reg_write(dev, SW_CONTROL, DP_USB | DM_USB);
+ if (ret)
+ log_debug("USB path set failed: %d\n", ret);
+ }
+
+ if ((mode & CP_USB) || (mode & CP_UART)) {
+ /* Enables UART Path */
+ ret = dm_i2c_reg_write(dev, SW_CONTROL, DP_UART | DM_UART);
+ if (ret)
+ log_debug("UART path set failed: %d\n", ret);
+ }
+
+ /* Enables 200K, Charger Pump, and ADC */
+ ret = dm_i2c_reg_write(dev, CONTROL_1, ID_200 | ADC_EN | CP_EN);
+ if (ret)
+ log_debug("200K, Charger Pump, and ADC set failed: %d\n", ret);
+}
+
+static int max14526_probe(struct udevice *dev)
+{
+ struct max14526_priv *priv = dev_get_priv(dev);
+ int ret, mode = 0;
+
+ ret = gpio_request_by_name(dev, "usif-gpios", 0,
+ &priv->usif_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode usif-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "dp2t-gpios", 0,
+ &priv->dp2t_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode dp2t-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ if (dev_read_bool(dev, "maxim,ap-usb"))
+ mode |= AP_USB;
+
+ if (dev_read_bool(dev, "maxim,cp-usb")) {
+ mode |= CP_USB;
+
+ ret = gpio_request_by_name(dev, "usb-vbus-gpios", 0,
+ &priv->ifx_usb_vbus_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode usb-vbus-gpios (%d)\n", ret);
+ return ret;
+ }
+ }
+
+ if (dev_read_bool(dev, "maxim,cp-uart"))
+ mode |= CP_UART;
+
+ max14526_set_mode(dev, mode);
+
+ return 0;
+}
+
+static const struct udevice_id max14526_ids[] = {
+ { .compatible = "maxim,max14526-muic" },
+ { }
+};
+
+U_BOOT_DRIVER(extcon_max14526) = {
+ .name = "extcon_max14526",
+ .id = UCLASS_EXTCON,
+ .of_match = max14526_ids,
+ .probe = max14526_probe,
+ .priv_auto = sizeof(struct max14526_priv),
+};
diff --git a/drivers/extcon/extcon-sandbox.c b/drivers/extcon/extcon-sandbox.c
new file mode 100644
index 00000000000..ab6a6c1cfdc
--- /dev/null
+++ b/drivers/extcon/extcon-sandbox.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <dm.h>
+
+static const struct udevice_id sandbox_extcon_ids[] = {
+ { .compatible = "sandbox,extcon" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(extcon_sandbox) = {
+ .name = "extcon_sandbox",
+ .id = UCLASS_EXTCON,
+ .of_match = sandbox_extcon_ids,
+};
diff --git a/drivers/extcon/extcon-uclass.c b/drivers/extcon/extcon-uclass.c
new file mode 100644
index 00000000000..9dd22b57626
--- /dev/null
+++ b/drivers/extcon/extcon-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Svyatoslav Ryhel <[email protected]>
+ */
+
+#define LOG_CATEGORY UCLASS_EXTCON
+
+#include <common.h>
+#include <extcon.h>
+#include <dm.h>
+
+UCLASS_DRIVER(extcon) = {
+ .id = UCLASS_EXTCON,
+ .name = "extcon",
+ .per_device_plat_auto = sizeof(struct extcon_uc_plat),
+};
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index eefa34779c4..a3df9aa3d0f 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -4,6 +4,13 @@ config FASTBOOT
bool
imply ANDROID_BOOT_IMAGE
imply CMD_FASTBOOT
+ help
+ Fastboot is a protocol used in Android devices for
+ communicating between the device and a computer during
+ the bootloader stage. It allows the user to flash the
+ device firmware and unlock the bootloader.
+ More information about the protocol and usecases:
+ https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/
config USB_FUNCTION_FASTBOOT
bool "Enable USB fastboot gadget"
@@ -28,6 +35,13 @@ config UDP_FUNCTION_FASTBOOT_PORT
help
The fastboot protocol requires a UDP port number.
+config TCP_FUNCTION_FASTBOOT
+ depends on NET
+ select FASTBOOT
+ bool "Enable fastboot protocol over TCP"
+ help
+ This enables the fastboot protocol over TCP.
+
if FASTBOOT
config FASTBOOT_BUF_ADDR
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index 57b6182c46a..621146bc6b0 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -15,7 +15,7 @@
#include <command.h>
#include <env.h>
#include <fastboot.h>
-#include <net/fastboot.h>
+#include <net.h>
/**
* fastboot_buf_addr - base address of the fastboot download buffer
@@ -157,6 +157,37 @@ void fastboot_boot(void)
}
/**
+ * fastboot_handle_boot() - Shared implementation of system reaction to
+ * fastboot commands
+ *
+ * Making desceisions about device boot state (stay in fastboot, reboot
+ * to bootloader, reboot to OS, etc).
+ */
+void fastboot_handle_boot(int command, bool success)
+{
+ if (!success)
+ return;
+
+ switch (command) {
+ case FASTBOOT_COMMAND_BOOT:
+ fastboot_boot();
+ net_set_state(NETLOOP_SUCCESS);
+ break;
+
+ case FASTBOOT_COMMAND_CONTINUE:
+ net_set_state(NETLOOP_SUCCESS);
+ break;
+
+ case FASTBOOT_COMMAND_REBOOT:
+ case FASTBOOT_COMMAND_REBOOT_BOOTLOADER:
+ case FASTBOOT_COMMAND_REBOOT_FASTBOOTD:
+ case FASTBOOT_COMMAND_REBOOT_RECOVERY:
+ do_reset(NULL, 0, 0, NULL);
+ break;
+ }
+}
+
+/**
* fastboot_set_progress_callback() - set progress callback
*
* @progress: Pointer to progress callback
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index a06c590234f..9d25c402028 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -287,7 +287,7 @@ static void fb_mmc_boot_ops(struct blk_desc *dev_desc, void *buffer,
*/
static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
struct disk_partition *info,
- struct andr_img_hdr *hdr,
+ struct andr_boot_img_hdr_v0 *hdr,
char *response)
{
ulong sector_size; /* boot partition sector size */
@@ -296,7 +296,7 @@ static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
/* Calculate boot image sectors count */
sector_size = info->blksz;
- hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size);
+ hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_boot_img_hdr_v0), sector_size);
if (hdr_sectors == 0) {
pr_err("invalid number of boot sectors: 0\n");
fastboot_fail("invalid number of boot sectors: 0", response);
@@ -313,8 +313,7 @@ static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
}
/* Check boot header magic string */
- res = android_image_check_header(hdr);
- if (res != 0) {
+ if (!is_android_boot_image_header(hdr)) {
pr_err("bad boot image magic\n");
fastboot_fail("boot partition not initialized", response);
return 0;
@@ -338,7 +337,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
char *response)
{
uintptr_t hdr_addr; /* boot image header address */
- struct andr_img_hdr *hdr; /* boot image header */
+ struct andr_boot_img_hdr_v0 *hdr; /* boot image header */
lbaint_t hdr_sectors; /* boot image header sectors */
u8 *ramdisk_buffer;
u32 ramdisk_sector_start;
@@ -361,7 +360,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
/* Put boot image header in fastboot buffer after downloaded zImage */
hdr_addr = (uintptr_t)download_buffer + ALIGN(download_bytes, PAGE_SIZE);
- hdr = (struct andr_img_hdr *)hdr_addr;
+ hdr = (struct andr_boot_img_hdr_v0 *)hdr_addr;
/* Read boot image header */
hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr, response);
@@ -371,6 +370,14 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
return -1;
}
+ /* Check if boot image header version is 2 or less */
+ if (hdr->header_version > 2) {
+ pr_err("zImage flashing supported only for boot images v2 and less\n");
+ fastboot_fail("zImage flashing supported only for boot images v2 and less",
+ response);
+ return -EOPNOTSUPP;
+ }
+
/* Check if boot image has second stage in it (we don't support it) */
if (hdr->second_size > 0) {
pr_err("moving second stage is not supported yet\n");
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index ef3e9836461..c6b9efab41c 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -319,4 +319,5 @@ U_BOOT_DRIVER(psci) = {
#ifdef CONFIG_ARM_SMCCC_FEATURES
.plat_auto = sizeof(struct psci_plat_data),
#endif
+ .flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 9a32678617d..54d563d929b 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -75,7 +75,7 @@ static int scmi_bind_protocols(struct udevice *dev)
name = ofnode_get_name(node);
switch (protocol_id) {
case SCMI_PROTOCOL_ID_CLOCK:
- if (IS_ENABLED(CONFIG_CLK_SCMI))
+ if (CONFIG_IS_ENABLED(CLK_SCMI))
drv = DM_DRIVER_GET(scmi_clock);
break;
case SCMI_PROTOCOL_ID_RESET_DOMAIN:
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 7d5ddbdee0c..9bf6e428ded 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -547,6 +547,24 @@ config MPC8XXX_GPIO
value setting, the open-drain feature, which can configure individual
GPIOs to work as open-drain outputs, is supported.
+config QE_GPIO
+ bool "Freescale QUICC ENGINE GPIO driver"
+ depends on DM_GPIO
+ depends on QE
+ help
+ This driver supports the QUICC Engine GPIOs of MPC83XX CPUs.
+ Each GPIO bank is identified by its own entry in the device tree,
+ i.e.
+
+ qe_pio_a: gpio-controller@1400 {
+ compatible = "fsl,mpc8323-qe-pario-bank";
+ reg = <0x1400 0x18>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ Each bank has 32 GPIOs.
+
config MPC8XX_GPIO
bool "Freescale MPC8XX GPIO driver"
depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 1e81e369629..64a36c472eb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TEGRA186_GPIO) += tegra186_gpio.o
obj-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o
obj-$(CONFIG_ALTERA_PIO) += altera_pio.o
obj-$(CONFIG_MPC8XXX_GPIO) += mpc8xxx_gpio.o
+obj-$(CONFIG_QE_GPIO) += qe_gpio.o
obj-$(CONFIG_MPC8XX_GPIO) += mpc8xx_gpio.o
obj-$(CONFIG_MPC83XX_SPISEL_BOOT) += mpc83xx_spisel_boot.o
obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
index 35585dc8ac9..49672193ffc 100644
--- a/drivers/gpio/axp_gpio.c
+++ b/drivers/gpio/axp_gpio.c
@@ -36,18 +36,11 @@ static int axp_gpio_direction_input(struct udevice *dev, unsigned pin)
{
u8 reg;
- switch (pin) {
-#ifndef CONFIG_AXP152_POWER /* NA on axp152 */
- case SUNXI_GPIO_AXP0_VBUS_DETECT:
- return 0;
-#endif
- default:
- reg = axp_get_gpio_ctrl_reg(pin);
- if (reg == 0)
- return -EINVAL;
+ reg = axp_get_gpio_ctrl_reg(pin);
+ if (reg == 0)
+ return -EINVAL;
- return pmic_bus_write(reg, AXP_GPIO_CTRL_INPUT);
- }
+ return pmic_bus_write(reg, AXP_GPIO_CTRL_INPUT);
}
static int axp_gpio_direction_output(struct udevice *dev, unsigned pin,
@@ -83,12 +76,6 @@ static int axp_gpio_get_value(struct udevice *dev, unsigned pin)
int ret;
switch (pin) {
-#ifndef CONFIG_AXP152_POWER /* NA on axp152 */
- case SUNXI_GPIO_AXP0_VBUS_DETECT:
- ret = pmic_bus_read(AXP_POWER_STATUS, &val);
- mask = AXP_POWER_STATUS_VBUS_PRESENT;
- break;
-#endif
#ifdef AXP_MISC_CTRL_N_VBUSEN_FUNC
/* Only available on later PMICs */
case SUNXI_GPIO_AXP0_VBUS_ENABLE:
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 138801850d3..9ffb4a56258 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -195,6 +195,7 @@ static const struct udevice_id rcar_gpio_ids[] = {
{ .compatible = "renesas,gpio-r8a779a0", .data = RCAR_GPIO_HAS_INEN },
{ .compatible = "renesas,rcar-gen2-gpio" },
{ .compatible = "renesas,rcar-gen3-gpio" },
+ { .compatible = "renesas,rcar-gen4-gpio", .data = RCAR_GPIO_HAS_INEN },
{ /* sentinel */ }
};
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index c8be5a4d668..712119c3415 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -1219,7 +1219,7 @@ int gpio_request_list_by_name_nodev(ofnode node, const char *list_name,
return count;
err:
- gpio_free_list_nodev(desc, count - 1);
+ gpio_free_list_nodev(desc, count);
return ret;
}
diff --git a/drivers/gpio/qe_gpio.c b/drivers/gpio/qe_gpio.c
new file mode 100644
index 00000000000..16e8d1eae6e
--- /dev/null
+++ b/drivers/gpio/qe_gpio.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 CR GROUP France
+ * Christophe Leroy <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <asm/gpio.h>
+#include <asm/immap_83xx.h>
+#include <asm/io.h>
+#include <dm/of_access.h>
+
+#define QE_DIR_NONE 0
+#define QE_DIR_OUT 1
+#define QE_DIR_IN 2
+#define QE_DIR_IN_OUT 3
+
+struct qe_gpio_data {
+ /* The bank's register base in memory */
+ struct gpio_n __iomem *base;
+ /* The address of the registers; used to identify the bank */
+ phys_addr_t addr;
+};
+
+static inline u32 gpio_mask(uint gpio)
+{
+ return 1U << (31 - (gpio));
+}
+
+static inline u32 gpio_mask2(uint gpio)
+{
+ return 1U << (30 - ((gpio & 15) << 1));
+}
+
+static int qe_gpio_direction_input(struct udevice *dev, uint gpio)
+{
+ struct qe_gpio_data *data = dev_get_priv(dev);
+ struct gpio_n __iomem *base = data->base;
+ u32 mask2 = gpio_mask2(gpio);
+
+ if (gpio < 16)
+ clrsetbits_be32(&base->dir1, mask2 * QE_DIR_OUT, mask2 * QE_DIR_IN);
+ else
+ clrsetbits_be32(&base->dir2, mask2 * QE_DIR_OUT, mask2 * QE_DIR_IN);
+
+ return 0;
+}
+
+static int qe_gpio_set_value(struct udevice *dev, uint gpio, int value)
+{
+ struct qe_gpio_data *data = dev_get_priv(dev);
+ struct gpio_n __iomem *base = data->base;
+ u32 mask = gpio_mask(gpio);
+ u32 mask2 = gpio_mask2(gpio);
+
+ if (gpio < 16)
+ clrsetbits_be32(&base->dir1, mask2 * QE_DIR_IN, mask2 * QE_DIR_OUT);
+ else
+ clrsetbits_be32(&base->dir2, mask2 * QE_DIR_IN, mask2 * QE_DIR_OUT);
+
+ if (value)
+ setbits_be32(&base->pdat, mask);
+ else
+ clrbits_be32(&base->pdat, mask);
+
+ return 0;
+}
+
+static int qe_gpio_get_value(struct udevice *dev, uint gpio)
+{
+ struct qe_gpio_data *data = dev_get_priv(dev);
+ struct gpio_n __iomem *base = data->base;
+ u32 mask = gpio_mask(gpio);
+
+ return !!(in_be32(&base->pdat) & mask);
+}
+
+static int qe_gpio_get_function(struct udevice *dev, uint gpio)
+{
+ struct qe_gpio_data *data = dev_get_priv(dev);
+ struct gpio_n __iomem *base = data->base;
+ u32 mask2 = gpio_mask2(gpio);
+ int dir;
+
+ if (gpio < 16)
+ dir = in_be32(&base->dir1);
+ else
+ dir = in_be32(&base->dir2);
+
+ if ((dir & (mask2 * QE_DIR_IN_OUT)) == (mask2 & QE_DIR_IN))
+ return GPIOF_INPUT;
+ else if ((dir & (mask2 * QE_DIR_IN_OUT)) == (mask2 & QE_DIR_OUT))
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_UNKNOWN;
+}
+
+static int qe_gpio_of_to_plat(struct udevice *dev)
+{
+ struct qe_gpio_plat *plat = dev_get_plat(dev);
+
+ plat->addr = dev_read_addr_size_index(dev, 0, (fdt_size_t *)&plat->size);
+
+ return 0;
+}
+
+static int qe_gpio_plat_to_priv(struct udevice *dev)
+{
+ struct qe_gpio_data *priv = dev_get_priv(dev);
+ struct qe_gpio_plat *plat = dev_get_plat(dev);
+ unsigned long size = plat->size;
+
+ if (size == 0)
+ size = sizeof(struct gpio_n);
+
+ priv->addr = plat->addr;
+ priv->base = (void __iomem *)plat->addr;
+
+ if (!priv->base)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int qe_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct qe_gpio_data *data = dev_get_priv(dev);
+ char name[32], *str;
+
+ qe_gpio_plat_to_priv(dev);
+
+ snprintf(name, sizeof(name), "QE@%.8llx",
+ (unsigned long long)data->addr);
+ str = strdup(name);
+
+ if (!str)
+ return -ENOMEM;
+
+ uc_priv->bank_name = str;
+ uc_priv->gpio_count = 32;
+
+ return 0;
+}
+
+static const struct dm_gpio_ops gpio_qe_ops = {
+ .direction_input = qe_gpio_direction_input,
+ .direction_output = qe_gpio_set_value,
+ .get_value = qe_gpio_get_value,
+ .set_value = qe_gpio_set_value,
+ .get_function = qe_gpio_get_function,
+};
+
+static const struct udevice_id qe_gpio_ids[] = {
+ { .compatible = "fsl,mpc8323-qe-pario-bank"},
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(gpio_qe) = {
+ .name = "gpio_qe",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_qe_ops,
+ .of_to_plat = qe_gpio_of_to_plat,
+ .plat_auto = sizeof(struct qe_gpio_plat),
+ .of_match = qe_gpio_ids,
+ .probe = qe_gpio_probe,
+ .priv_auto = sizeof(struct qe_gpio_data),
+};
diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c
index f7ad4d68b45..4a6ae554bf7 100644
--- a/drivers/gpio/rk_gpio.c
+++ b/drivers/gpio/rk_gpio.c
@@ -13,83 +13,118 @@
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
#include <asm/arch-rockchip/gpio.h>
#include <dm/pinctrl.h>
-#include <dt-bindings/clock/rk3288-cru.h>
+#include <dm/read.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+#define SWPORT_DR 0x0000
+#define SWPORT_DDR 0x0004
+#define EXT_PORT 0x0050
+#define SWPORT_DR_L 0x0000
+#define SWPORT_DR_H 0x0004
+#define SWPORT_DDR_L 0x0008
+#define SWPORT_DDR_H 0x000C
+#define EXT_PORT_V2 0x0070
+#define VER_ID_V2 0x0078
enum {
ROCKCHIP_GPIOS_PER_BANK = 32,
};
-#define OFFSET_TO_BIT(bit) (1UL << (bit))
-
struct rockchip_gpio_priv {
- struct rockchip_gpio_regs *regs;
+ void __iomem *regs;
struct udevice *pinctrl;
int bank;
char name[2];
+ u32 version;
};
-static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
+static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
- struct rockchip_gpio_regs *regs = priv->regs;
+ u32 mask = BIT(offset), data;
- clrbits_le32(&regs->swport_ddr, OFFSET_TO_BIT(offset));
+ if (priv->version)
+ data = readl(priv->regs + EXT_PORT_V2);
+ else
+ data = readl(priv->regs + EXT_PORT);
- return 0;
+ return (data & mask) ? 1 : 0;
}
-static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
- int value)
+static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
{
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
- struct rockchip_gpio_regs *regs = priv->regs;
- int mask = OFFSET_TO_BIT(offset);
+ u32 mask = BIT(offset), data = value ? mask : 0;
- clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
- setbits_le32(&regs->swport_ddr, mask);
+ if (priv->version && offset >= 16)
+ rk_clrsetreg(priv->regs + SWPORT_DR_H, mask >> 16, data >> 16);
+ else if (priv->version)
+ rk_clrsetreg(priv->regs + SWPORT_DR_L, mask, data);
+ else
+ clrsetbits_le32(priv->regs + SWPORT_DR, mask, data);
return 0;
}
-static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
+static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
- struct rockchip_gpio_regs *regs = priv->regs;
+ u32 mask = BIT(offset);
+
+ if (priv->version && offset >= 16)
+ rk_clrreg(priv->regs + SWPORT_DDR_H, mask >> 16);
+ else if (priv->version)
+ rk_clrreg(priv->regs + SWPORT_DDR_L, mask);
+ else
+ clrbits_le32(priv->regs + SWPORT_DDR, mask);
- return readl(&regs->ext_port) & OFFSET_TO_BIT(offset) ? 1 : 0;
+ return 0;
}
-static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
- int value)
+static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
{
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
- struct rockchip_gpio_regs *regs = priv->regs;
- int mask = OFFSET_TO_BIT(offset);
+ u32 mask = BIT(offset);
+
+ rockchip_gpio_set_value(dev, offset, value);
- clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
+ if (priv->version && offset >= 16)
+ rk_setreg(priv->regs + SWPORT_DDR_H, mask >> 16);
+ else if (priv->version)
+ rk_setreg(priv->regs + SWPORT_DDR_L, mask);
+ else
+ setbits_le32(priv->regs + SWPORT_DDR, mask);
return 0;
}
static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
{
-#ifdef CONFIG_SPL_BUILD
- return -ENODATA;
-#else
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
- struct rockchip_gpio_regs *regs = priv->regs;
- bool is_output;
+ u32 mask = BIT(offset), data;
int ret;
- ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
- if (ret)
- return ret;
- is_output = readl(&regs->swport_ddr) & OFFSET_TO_BIT(offset);
+ if (CONFIG_IS_ENABLED(PINCTRL)) {
+ ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
+ if (ret < 0)
+ return ret;
+ else if (ret != RK_FUNC_GPIO)
+ return GPIOF_FUNC;
+ }
+
+ if (priv->version && offset >= 16)
+ data = readl(priv->regs + SWPORT_DDR_H) << 16;
+ else if (priv->version)
+ data = readl(priv->regs + SWPORT_DDR_L);
+ else
+ data = readl(priv->regs + SWPORT_DDR);
- return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
-#endif
+ return (data & mask) ? GPIOF_OUTPUT : GPIOF_INPUT;
}
/* Simple SPL interface to GPIOs */
@@ -147,9 +182,12 @@ static int rockchip_gpio_probe(struct udevice *dev)
int ret;
priv->regs = dev_read_addr_ptr(dev);
- ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
- if (ret)
- return ret;
+
+ if (CONFIG_IS_ENABLED(PINCTRL)) {
+ ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
+ if (ret)
+ return ret;
+ }
/*
* If "gpio-ranges" is present in the devicetree use it to parse
@@ -160,7 +198,7 @@ static int rockchip_gpio_probe(struct udevice *dev)
0, &args);
if (!ret || ret != -ENOENT) {
uc_priv->gpio_count = args.args[2];
- priv->bank = args.args[1] / args.args[2];
+ priv->bank = args.args[1] / ROCKCHIP_GPIOS_PER_BANK;
} else {
uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK;
end = strrchr(dev->name, '@');
@@ -170,6 +208,8 @@ static int rockchip_gpio_probe(struct udevice *dev)
priv->name[0] = 'A' + priv->bank;
uc_priv->bank_name = priv->name;
+ priv->version = readl(priv->regs + VER_ID_V2);
+
return 0;
}
diff --git a/drivers/gpio/sh_pfc.c b/drivers/gpio/sh_pfc.c
index 92522b63bbe..2495d6c1c15 100644
--- a/drivers/gpio/sh_pfc.c
+++ b/drivers/gpio/sh_pfc.c
@@ -569,7 +569,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -1;
- if (IS_ENABLED(CONFIG_RCAR_GEN3) &&
+ if (IS_ENABLED(CONFIG_RCAR_64) &&
((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_INPUT))
offset += 4;
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 1e85db179a6..f0b42e4fdb7 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -117,11 +117,7 @@ int sunxi_name_to_gpio(const char *name)
#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
char lookup[8];
- if (strcasecmp(name, "AXP0-VBUS-DETECT") == 0) {
- sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
- SUNXI_GPIO_AXP0_VBUS_DETECT);
- name = lookup;
- } else if (strcasecmp(name, "AXP0-VBUS-ENABLE") == 0) {
+ if (strcasecmp(name, "AXP0-VBUS-ENABLE") == 0) {
sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
SUNXI_GPIO_AXP0_VBUS_ENABLE);
name = lookup;
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 2eae33cd54c..05b14d2451c 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -496,7 +496,7 @@ config SYS_I2C_OMAP24XX
config SYS_I2C_RCAR_I2C
bool "Renesas RCar I2C driver"
- depends on (RCAR_GEN2 || RCAR_GEN3) && DM_I2C
+ depends on (RCAR_GEN2 || RCAR_64) && DM_I2C
help
Support for Renesas RCar I2C controller.
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index 46c2545f214..28495a3f428 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -147,9 +147,7 @@ static int dw_i2c_acpi_fill_ssdt(const struct udevice *dev,
{
struct dw_i2c_speed_config config;
char path[ACPI_PATH_MAX];
- u32 speeds[4];
uint speed;
- int size;
int ret;
/* If no device-tree node, ignore this since we assume it isn't used */
@@ -160,18 +158,6 @@ static int dw_i2c_acpi_fill_ssdt(const struct udevice *dev,
if (ret)
return log_msg_ret("path", ret);
- size = dev_read_size(dev, "i2c,speeds");
- if (size < 0)
- return log_msg_ret("i2c,speeds", -EINVAL);
-
- size /= sizeof(u32);
- if (size > ARRAY_SIZE(speeds))
- return log_msg_ret("array", -E2BIG);
-
- ret = dev_read_u32_array(dev, "i2c,speeds", speeds, size);
- if (ret)
- return log_msg_ret("read", -E2BIG);
-
speed = dev_read_u32_default(dev, "clock-frequency", 100000);
acpigen_write_scope(ctx, path);
ret = dw_i2c_gen_speed_config(dev, speed, &config);
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index d312f35f044..d9d8ee81d2e 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -278,7 +278,8 @@ static void __i2c_init(const struct fsl_i2c_base *base, int speed, int
set_i2c_bus_speed(base, i2c_clk, speed);
writeb(slaveadd << 1, &base->adr);/* write slave address */
writeb(0x0, &base->sr); /* clear status register */
- writeb(I2C_CR_MEN, &base->cr); /* start I2C controller */
+ /* start I2C controller */
+ writeb(I2C_CR_MEN | I2C_CR_MIEN, &base->cr);
timeval = get_ticks();
while (readb(&base->sr) & I2C_SR_MBB) {
@@ -346,7 +347,7 @@ static int i2c_wait(const struct fsl_i2c_base *base, int write)
static int i2c_write_addr(const struct fsl_i2c_base *base, u8 dev,
u8 dir, int rsta)
{
- writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX
+ writeb(I2C_CR_MEN | I2C_CR_MIEN | I2C_CR_MSTA | I2C_CR_MTX
| (rsta ? I2C_CR_RSTA : 0),
&base->cr);
@@ -378,7 +379,8 @@ static int __i2c_read_data(const struct fsl_i2c_base *base, u8 *data,
{
int i;
- writeb(I2C_CR_MEN | I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0),
+ writeb(I2C_CR_MEN | I2C_CR_MIEN |
+ I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0),
&base->cr);
/* dummy read */
@@ -390,13 +392,13 @@ static int __i2c_read_data(const struct fsl_i2c_base *base, u8 *data,
/* Generate ack on last next to last byte */
if (i == length - 2)
- writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_TXAK,
- &base->cr);
+ writeb(I2C_CR_MEN | I2C_CR_MIEN | I2C_CR_MSTA |
+ I2C_CR_TXAK, &base->cr);
/* Do not generate stop on last byte */
if (i == length - 1)
- writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
- &base->cr);
+ writeb(I2C_CR_MEN | I2C_CR_MIEN | I2C_CR_MSTA |
+ I2C_CR_MTX, &base->cr);
data[i] = readb(&base->dr);
}
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 8d9a89ed890..8867a560bd8 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -508,13 +508,13 @@ static void i2c_gpio_set_pin(struct gpio_desc *pin, int bit)
dm_gpio_set_dir_flags(pin, GPIOD_IS_IN);
else
dm_gpio_set_dir_flags(pin, GPIOD_IS_OUT |
- GPIOD_ACTIVE_LOW |
GPIOD_IS_OUT_ACTIVE);
}
static int i2c_gpio_get_pin(struct gpio_desc *pin)
{
- return dm_gpio_get_value(pin);
+ /* DTS need config GPIO_ACTIVE_LOW */
+ return !dm_gpio_get_value(pin);
}
int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin,
diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c
index 92c500327b4..ad9293c92e1 100644
--- a/drivers/i2c/imx_lpi2c.c
+++ b/drivers/i2c/imx_lpi2c.c
@@ -282,7 +282,7 @@ static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
bool mode;
int i;
- if (IS_ENABLED(CONFIG_CLK)) {
+ if (CONFIG_IS_ENABLED(CLK)) {
clock_rate = clk_get_rate(&i2c_bus->per_clk);
if (clock_rate <= 0) {
dev_err(bus, "Failed to get i2c clk: %d\n", clock_rate);
@@ -462,7 +462,7 @@ static int imx_lpi2c_probe(struct udevice *bus)
return ret;
}
- if (IS_ENABLED(CONFIG_CLK)) {
+ if (CONFIG_IS_ENABLED(CLK)) {
ret = clk_get_by_name(bus, "per", &i2c_bus->per_clk);
if (ret) {
dev_err(bus, "Failed to get per clk\n");
diff --git a/drivers/i2c/rcar_i2c.c b/drivers/i2c/rcar_i2c.c
index d9ece5e3a80..ff9a2d80dda 100644
--- a/drivers/i2c/rcar_i2c.c
+++ b/drivers/i2c/rcar_i2c.c
@@ -369,6 +369,7 @@ static const struct dm_i2c_ops rcar_i2c_ops = {
static const struct udevice_id rcar_i2c_ids[] = {
{ .compatible = "renesas,rcar-gen2-i2c", .data = RCAR_I2C_TYPE_GEN2 },
{ .compatible = "renesas,rcar-gen3-i2c", .data = RCAR_I2C_TYPE_GEN3 },
+ { .compatible = "renesas,rcar-gen4-i2c", .data = RCAR_I2C_TYPE_GEN3 },
{ }
};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4e1ae03e9fd..04460f1acb2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -511,6 +511,13 @@ config WINBOND_W83627
legacy UART or other devices in the Winbond Super IO chips
on X86 platforms.
+config QCOM_GENI_SE
+ bool "Qualcomm GENI Serial Engine Driver"
+ depends on ARCH_SNAPDRAGON
+ help
+ The driver manages Generic Interface (GENI) firmware based
+ Qualcomm Technologies, Inc. Universal Peripheral (QUP) Wrapper.
+
config QFW
bool
help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 3b792f2a14c..52aed096021 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
obj-$(CONFIG_P2SB) += p2sb-uclass.o
obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
+obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
ifdef CONFIG_QFW
obj-y += qfw.o
obj-$(CONFIG_QFW_PIO) += qfw_pio.o
diff --git a/drivers/misc/esm_pmic.c b/drivers/misc/esm_pmic.c
index a195dc5eb1d..b971f32f6a1 100644
--- a/drivers/misc/esm_pmic.c
+++ b/drivers/misc/esm_pmic.c
@@ -26,6 +26,9 @@
#define ESM_MCU_EN BIT(6)
#define ESM_MCU_ENDRV BIT(5)
+#define ESM_MCU_MASK_REG 0x59
+#define ESM_MCU_MASK 0x7
+
/**
* pmic_esm_probe: configures and enables PMIC ESM functionality
*
@@ -48,6 +51,12 @@ static int pmic_esm_probe(struct udevice *dev)
return ret;
}
+ ret = pmic_reg_write(dev->parent, ESM_MCU_MASK_REG, ESM_MCU_MASK);
+ if (ret) {
+ dev_err(dev, "clearing ESM masks failed: %d\n", ret);
+ return ret;
+ }
+
ret = pmic_reg_write(dev->parent, ESM_MCU_START_REG, ESM_MCU_START);
if (ret) {
dev_err(dev, "starting ESM failed: %d\n", ret);
diff --git a/drivers/misc/qcom-geni-se.c b/drivers/misc/qcom-geni-se.c
new file mode 100644
index 00000000000..281a5ec819a
--- /dev/null
+++ b/drivers/misc/qcom-geni-se.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm Generic Interface (GENI) Serial Engine (SE) Wrapper
+ *
+ * Copyright (C) 2023 Linaro Ltd. <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <asm/io.h>
+
+static int geni_se_qup_read(struct udevice *dev, int offset,
+ void *buf, int size)
+{
+ fdt_addr_t base = dev_read_addr(dev);
+
+ if (size != sizeof(u32))
+ return -EINVAL;
+
+ *(u32 *)buf = readl(base + offset);
+
+ return size;
+}
+
+static struct misc_ops geni_se_qup_ops = {
+ .read = geni_se_qup_read,
+};
+
+static const struct udevice_id geni_se_qup_ids[] = {
+ { .compatible = "qcom,geni-se-qup" },
+ {}
+};
+
+U_BOOT_DRIVER(geni_se_qup) = {
+ .name = "geni_se_qup",
+ .id = UCLASS_MISC,
+ .of_match = geni_se_qup_ids,
+ .ops = &geni_se_qup_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c
index 60931a51312..2f96b79ea40 100644
--- a/drivers/misc/rockchip-efuse.c
+++ b/drivers/misc/rockchip-efuse.c
@@ -73,7 +73,7 @@ static int dump_efuse(struct cmd_tbl *cmdtp, int flag,
for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
- if (ret < 0)
+ if (ret <= 0)
return 0;
print_buffer(i, data, 1, sizeof(data), sizeof(data));
@@ -238,8 +238,10 @@ static int rockchip_efuse_read(struct udevice *dev, int offset,
offset += data->offset;
- if (data->block_size <= 1)
- return data->read(dev, offset, buf, size);
+ if (data->block_size <= 1) {
+ ret = data->read(dev, offset, buf, size);
+ goto done;
+ }
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
@@ -255,7 +257,9 @@ static int rockchip_efuse_read(struct udevice *dev, int offset,
memcpy(buf, buffer + block_offset, size);
free(buffer);
- return ret;
+
+done:
+ return ret < 0 ? ret : size;
}
static const struct misc_ops rockchip_efuse_ops = {
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c
index c19cd5ce625..4814e0e501c 100644
--- a/drivers/misc/rockchip-otp.c
+++ b/drivers/misc/rockchip-otp.c
@@ -89,7 +89,7 @@ static int dump_otp(struct cmd_tbl *cmdtp, int flag,
for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
- if (ret < 0)
+ if (ret <= 0)
return 0;
print_buffer(i, data, 1, sizeof(data), sizeof(data));
@@ -249,8 +249,10 @@ static int rockchip_otp_read(struct udevice *dev, int offset,
offset += data->offset;
- if (data->block_size <= 1)
- return data->read(dev, offset, buf, size);
+ if (data->block_size <= 1) {
+ ret = data->read(dev, offset, buf, size);
+ goto done;
+ }
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
@@ -266,7 +268,9 @@ static int rockchip_otp_read(struct udevice *dev, int offset,
memcpy(buf, buffer + block_offset, size);
free(buffer);
- return ret;
+
+done:
+ return ret < 0 ? ret : size;
}
static const struct misc_ops rockchip_otp_ops = {
diff --git a/drivers/misc/usb251xb.c b/drivers/misc/usb251xb.c
index a78ad1843ae..92e92ba5e62 100644
--- a/drivers/misc/usb251xb.c
+++ b/drivers/misc/usb251xb.c
@@ -334,7 +334,7 @@ static int usb251xb_probe(struct udevice *dev)
struct usb251xb *hub = dev_get_priv(dev);
int err;
- if (IS_ENABLED(CONFIG_DM_REGULATOR) && hub->vdd) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && hub->vdd) {
err = regulator_set_enable(hub->vdd, true);
if (err)
return err;
@@ -391,7 +391,7 @@ static int usb251xb_of_to_plat(struct udevice *dev)
return err;
}
- if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
err = device_get_supply_regulator(dev, "vdd-supply",
&hub->vdd);
if (err && err != -ENOENT) {
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 80641e13930..de01b9687ba 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -476,6 +476,14 @@ config MMC_SDHCI_SDMA
This enables support for the SDMA (Single Operation DMA) defined
in the SD Host Controller Standard Specification Version 1.00 .
+config SPL_MMC_SDHCI_SDMA
+ bool "Support SDHCI SDMA in SPL"
+ depends on SPL_MMC && MMC_SDHCI
+ default y if MMC_SDHCI_SDMA
+ help
+ This enables support for the SDMA (Single Operation DMA) defined
+ in the SD Host Controller Standard Specification Version 1.00 in SPL.
+
config MMC_SDHCI_ADMA
bool "Support SDHCI ADMA2"
depends on MMC_SDHCI
@@ -621,6 +629,7 @@ config MMC_SDHCI_MV
bool "SDHCI support on Marvell platform"
depends on ARCH_MVEBU
depends on MMC_SDHCI
+ depends on DM_MMC
help
This selects the Secure Digital Host Controller Interface on
Marvell platform.
diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index 2cec5b9ae32..71962cd47e0 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -100,6 +100,8 @@ static const struct udevice_id hi6220_dwmmc_ids[] = {
.data = (ulong)&hi6220_mmc_data },
{ .compatible = "hisilicon,hi3798cv200-dw-mshc",
.data = (ulong)&hi6220_mmc_data },
+ { .compatible = "hisilicon,hi3798mv200-dw-mshc",
+ .data = (ulong)&hi6220_mmc_data },
{ .compatible = "hisilicon,hi3660-dw-mshc",
.data = (ulong)&hi3660_mmc_data },
{ }
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index dde251c87bc..1af6af82e6b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2432,6 +2432,9 @@ static int mmc_startup_v4(struct mmc *mmc)
mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
+ mmc->can_trim =
+ !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
+
return 0;
error:
if (mmc->ext_csd) {
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 5b7aeeb0121..a6f93380dd0 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -15,7 +15,7 @@
#include <linux/math64.h>
#include "mmc_private.h"
-static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
+static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt, u32 args)
{
struct mmc_cmd cmd;
ulong end;
@@ -52,7 +52,7 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
goto err_out;
cmd.cmdidx = MMC_CMD_ERASE;
- cmd.cmdarg = MMC_ERASE_ARG;
+ cmd.cmdarg = args ? args : MMC_ERASE_ARG;
cmd.resp_type = MMC_RSP_R1b;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -77,7 +77,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
#endif
int dev_num = block_dev->devnum;
int err = 0;
- u32 start_rem, blkcnt_rem;
+ u32 start_rem, blkcnt_rem, erase_args = 0;
struct mmc *mmc = find_mmc_device(dev_num);
lbaint_t blk = 0, blk_r = 0;
int timeout_ms = 1000;
@@ -97,13 +97,25 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
*/
err = div_u64_rem(start, mmc->erase_grp_size, &start_rem);
err = div_u64_rem(blkcnt, mmc->erase_grp_size, &blkcnt_rem);
- if (start_rem || blkcnt_rem)
- printf("\n\nCaution! Your devices Erase group is 0x%x\n"
- "The erase range would be change to "
- "0x" LBAF "~0x" LBAF "\n\n",
- mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
- ((start + blkcnt + mmc->erase_grp_size - 1)
- & ~(mmc->erase_grp_size - 1)) - 1);
+ if (start_rem || blkcnt_rem) {
+ if (mmc->can_trim) {
+ /* Trim function applies the erase operation to write
+ * blocks instead of erase groups.
+ */
+ erase_args = MMC_TRIM_ARG;
+ } else {
+ /* The card ignores all LSB's below the erase group
+ * size, rounding down the addess to a erase group
+ * boundary.
+ */
+ printf("\n\nCaution! Your devices Erase group is 0x%x\n"
+ "The erase range would be change to "
+ "0x" LBAF "~0x" LBAF "\n\n",
+ mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
+ ((start + blkcnt + mmc->erase_grp_size - 1)
+ & ~(mmc->erase_grp_size - 1)) - 1);
+ }
+ }
while (blk < blkcnt) {
if (IS_SD(mmc) && mmc->ssr.au) {
@@ -113,7 +125,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
mmc->erase_grp_size : (blkcnt - blk);
}
- err = mmc_erase_t(mmc, start + blk, blk_r);
+ err = mmc_erase_t(mmc, start + blk, blk_r, erase_args);
if (err)
break;
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index 336ebf14102..dbdd671c88b 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -15,6 +15,13 @@
#define SDHCI_WINDOW_CTRL(win) (0x4080 + ((win) << 4))
#define SDHCI_WINDOW_BASE(win) (0x4084 + ((win) << 4))
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mv_sdhci_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
static void sdhci_mvebu_mbus_config(void __iomem *base)
{
const struct mbus_dram_target_info *dram;
@@ -40,47 +47,6 @@ static void sdhci_mvebu_mbus_config(void __iomem *base)
}
}
-#ifndef CONFIG_DM_MMC
-
-#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-static struct sdhci_ops mv_ops;
-#endif /* CONFIG_MMC_SDHCI_IO_ACCESSORS */
-
-int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks)
-{
- struct sdhci_host *host = NULL;
- host = calloc(1, sizeof(*host));
- if (!host) {
- printf("sdh_host malloc fail!\n");
- return -ENOMEM;
- }
-
- host->name = MVSDH_NAME;
- host->ioaddr = (void *)regbase;
- host->quirks = quirks;
- host->max_clk = max_clk;
-#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
- memset(&mv_ops, 0, sizeof(struct sdhci_ops));
- host->ops = &mv_ops;
-#endif
-
- if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
- /* Configure SDHCI MBUS mbus bridge windows */
- sdhci_mvebu_mbus_config((void __iomem *)regbase);
- }
-
- return add_sdhci(host, 0, min_clk);
-}
-
-#else
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct mv_sdhci_plat {
- struct mmc_config cfg;
- struct mmc mmc;
-};
-
static int mv_sdhci_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
@@ -103,10 +69,8 @@ static int mv_sdhci_probe(struct udevice *dev)
if (ret)
return ret;
- if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
- /* Configure SDHCI MBUS mbus bridge windows */
- sdhci_mvebu_mbus_config(host->ioaddr);
- }
+ /* Configure SDHCI MBUS mbus bridge windows */
+ sdhci_mvebu_mbus_config(host->ioaddr);
upriv->mmc = host->mmc;
@@ -135,4 +99,3 @@ U_BOOT_DRIVER(mv_sdhci_drv) = {
.priv_auto = sizeof(struct sdhci_host),
.plat_auto = sizeof(struct mv_sdhci_plat),
};
-#endif /* CONFIG_DM_MMC */
diff --git a/drivers/mmc/npcm_sdhci.c b/drivers/mmc/npcm_sdhci.c
index 7eb17cce0b3..d63521d6855 100644
--- a/drivers/mmc/npcm_sdhci.c
+++ b/drivers/mmc/npcm_sdhci.c
@@ -36,7 +36,7 @@ static int npcm_sdhci_probe(struct udevice *dev)
return ret;
}
- if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_supply);
vqmmc_uv = dev_read_u32_default(dev, "vqmmc-microvolt", 0);
/* Set IO voltage */
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 34119f949aa..280d96dbc2d 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -843,6 +843,7 @@ static const struct udevice_id renesas_sdhi_match[] = {
{ .compatible = "renesas,sdhi-r8a77970", .data = RENESAS_GEN3_QUIRKS },
{ .compatible = "renesas,sdhi-r8a77990", .data = RENESAS_GEN3_QUIRKS },
{ .compatible = "renesas,sdhi-r8a77995", .data = RENESAS_GEN3_QUIRKS },
+ { .compatible = "renesas,rcar-gen4-sdhi", .data = RENESAS_GEN3_QUIRKS },
{ /* sentinel */ }
};
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index e1409dd2c74..4f110976f4e 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -47,51 +47,51 @@
#define ARASAN_VENDOR_REGISTER 0x78
#define ARASAN_VENDOR_ENHANCED_STROBE BIT(0)
-/* DWC IP vendor area 1 pointer */
-#define DWCMSHC_P_VENDOR_AREA1 0xe8
-#define DWCMSHC_AREA1_MASK GENMASK(11, 0)
-/* Offset inside the vendor area 1 */
-#define DWCMSHC_EMMC_CONTROL 0x2c
+/* Rockchip specific Registers */
+#define DWCMSHC_EMMC_EMMC_CTRL 0x52c
#define DWCMSHC_CARD_IS_EMMC BIT(0)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
-
-/* Rockchip specific Registers */
#define DWCMSHC_EMMC_DLL_CTRL 0x800
#define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1)
#define DWCMSHC_EMMC_DLL_RXCLK 0x804
#define DWCMSHC_EMMC_DLL_TXCLK 0x808
#define DWCMSHC_EMMC_DLL_STRBIN 0x80c
-#define DECMSHC_EMMC_DLL_CMDOUT 0x810
+#define DWCMSHC_EMMC_DLL_CMDOUT 0x810
#define DWCMSHC_EMMC_DLL_STATUS0 0x840
#define DWCMSHC_EMMC_DLL_STATUS1 0x844
#define DWCMSHC_EMMC_DLL_START BIT(0)
-#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
+#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
+#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
#define DWCMSHC_EMMC_DLL_START_POINT 16
#define DWCMSHC_EMMC_DLL_START_DEFAULT 5
#define DWCMSHC_EMMC_DLL_INC_VALUE 2
#define DWCMSHC_EMMC_DLL_INC 8
#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
-#define DLL_TXCLK_TAPNUM_DEFAULT 0xA
-
-#define DLL_STRBIN_TAPNUM_DEFAULT 0x8
+#define DLL_RXCLK_NO_INVERTER BIT(29)
+#define DLL_RXCLK_ORI_GATE BIT(31)
+#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
+#define DLL_TXCLK_TAPNUM_90_DEGREES 0x9
+#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
+#define DLL_TXCLK_NO_INVERTER BIT(29)
+#define DLL_STRBIN_TAPNUM_DEFAULT 0x4
#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
#define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
#define DLL_STRBIN_DELAY_NUM_OFFSET 16
-#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16
+#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x10
+#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
+#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
+#define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
+#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
+#define DLL_CMDOUT_BOTH_CLK_EDGE BIT(30)
-#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
-#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
-#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
-#define DLL_RXCLK_NO_INVERTER 1
-#define DLL_RXCLK_INVERTER 0
-#define DLL_RXCLK_ORI_GATE BIT(31)
-#define DWCMSHC_ENHANCED_STROBE BIT(8)
#define DLL_LOCK_WO_TMOUT(x) \
((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
#define ROCKCHIP_MAX_CLKS 3
+#define FLAG_INVERTER_FLAG_IN_RXCLK BIT(0)
+
struct rockchip_sdhc_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -112,7 +112,6 @@ struct rockchip_sdhc {
};
struct sdhci_data {
- int (*emmc_phy_init)(struct udevice *dev);
int (*get_phy)(struct udevice *dev);
/**
@@ -140,6 +139,9 @@ struct sdhci_data {
*/
int (*set_ios_post)(struct sdhci_host *host);
+ void (*set_clock)(struct sdhci_host *host, u32 div);
+ int (*config_dll)(struct sdhci_host *host, u32 clock, bool enable);
+
/**
* set_enhanced_strobe() - Set HS400 Enhanced Strobe config
*
@@ -152,12 +154,11 @@ struct sdhci_data {
* Return: 0 if successful, -ve on error
*/
int (*set_enhanced_strobe)(struct sdhci_host *host);
-};
-static int rk3399_emmc_phy_init(struct udevice *dev)
-{
- return 0;
-}
+ u32 flags;
+ u8 hs200_txclk_tapnum;
+ u8 hs400_txclk_tapnum;
+};
static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
{
@@ -294,30 +295,27 @@ static int rk3399_sdhci_set_ios_post(struct sdhci_host *host)
return 0;
}
-static int rk3568_emmc_phy_init(struct udevice *dev)
+static void rk3568_sdhci_set_clock(struct sdhci_host *host, u32 div)
{
- struct rockchip_sdhc *prv = dev_get_priv(dev);
- struct sdhci_host *host = &prv->host;
- u32 extra;
-
- extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
- sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct mmc *mmc = host->mmc;
+ ulong rate;
- return 0;
+ rate = clk_set_rate(&priv->emmc_clk, mmc->clock);
+ if (IS_ERR_VALUE(rate))
+ printf("%s: Set clock rate failed: %ld\n", __func__, (long)rate);
}
-static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
+static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+ struct mmc *mmc = host->mmc;
int val, ret;
- u32 extra;
-
- if (clock > host->max_clk)
- clock = host->max_clk;
- if (clock)
- clk_set_rate(&priv->emmc_clk, clock);
+ u32 extra, txclk_tapnum;
- sdhci_set_clock(host->mmc, clock);
+ if (!enable)
+ return 0;
if (clock >= 100 * MHz) {
/* reset DLL */
@@ -337,13 +335,28 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
if (ret)
return ret;
- extra = DWCMSHC_EMMC_DLL_DLYENA |
- DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+ extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
+ if (data->flags & FLAG_INVERTER_FLAG_IN_RXCLK)
+ extra |= DLL_RXCLK_NO_INVERTER;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+ txclk_tapnum = data->hs200_txclk_tapnum;
+ if (mmc->selected_mode == MMC_HS_400 ||
+ mmc->selected_mode == MMC_HS_400_ES) {
+ txclk_tapnum = data->hs400_txclk_tapnum;
+
+ extra = DLL_CMDOUT_SRC_CLK_NEG |
+ DLL_CMDOUT_BOTH_CLK_EDGE |
+ DWCMSHC_EMMC_DLL_DLYENA |
+ DLL_CMDOUT_TAPNUM_90_DEGREES |
+ DLL_CMDOUT_TAPNUM_FROM_SW;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CMDOUT);
+ }
+
extra = DWCMSHC_EMMC_DLL_DLYENA |
- DLL_TXCLK_TAPNUM_DEFAULT |
- DLL_TXCLK_TAPNUM_FROM_SW;
+ DLL_TXCLK_TAPNUM_FROM_SW |
+ DLL_TXCLK_NO_INVERTER |
+ txclk_tapnum;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
extra = DWCMSHC_EMMC_DLL_DLYENA |
@@ -355,11 +368,11 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
* Disable DLL and reset both of sample and drive clock.
* The bypass bit and start bit need to be set if DLL is not locked.
*/
- sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START,
- DWCMSHC_EMMC_DLL_CTRL);
+ extra = DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
- sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CMDOUT);
/*
* Before switching to hs400es mode, the driver will enable
* enhanced strobe first. PHY needs to configure the parameters
@@ -374,56 +387,54 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
return 0;
}
-static int rk3568_emmc_get_phy(struct udevice *dev)
-{
- return 0;
-}
-
-static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
{
struct mmc *mmc = host->mmc;
- u32 vendor;
- int reg;
-
- reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
- + DWCMSHC_EMMC_CONTROL;
+ u32 reg;
- vendor = sdhci_readl(host, reg);
- if (mmc->selected_mode == MMC_HS_400_ES)
- vendor |= DWCMSHC_ENHANCED_STROBE;
- else
- vendor &= ~DWCMSHC_ENHANCED_STROBE;
- sdhci_writel(host, vendor, reg);
+ reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ reg &= ~SDHCI_CTRL_UHS_MASK;
- return 0;
-}
+ switch (mmc->selected_mode) {
+ case UHS_SDR25:
+ case MMC_HS:
+ case MMC_HS_52:
+ reg |= SDHCI_CTRL_UHS_SDR25;
+ break;
+ case UHS_SDR50:
+ reg |= SDHCI_CTRL_UHS_SDR50;
+ break;
+ case UHS_DDR50:
+ case MMC_DDR_52:
+ reg |= SDHCI_CTRL_UHS_DDR50;
+ break;
+ case UHS_SDR104:
+ case MMC_HS_200:
+ reg |= SDHCI_CTRL_UHS_SDR104;
+ break;
+ case MMC_HS_400:
+ case MMC_HS_400_ES:
+ reg |= DWCMSHC_CTRL_HS400;
+ break;
+ default:
+ reg |= SDHCI_CTRL_UHS_SDR12;
+ }
-static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
-{
- struct mmc *mmc = host->mmc;
- uint clock = mmc->tran_speed;
- u32 reg, vendor_reg;
+ sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
- if (!clock)
- clock = mmc->clock;
+ reg = sdhci_readw(host, DWCMSHC_EMMC_EMMC_CTRL);
- rk3568_sdhci_emmc_set_clock(host, clock);
+ if (IS_MMC(mmc))
+ reg |= DWCMSHC_CARD_IS_EMMC;
+ else
+ reg &= ~DWCMSHC_CARD_IS_EMMC;
- if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
- reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- reg &= ~SDHCI_CTRL_UHS_MASK;
- reg |= DWCMSHC_CTRL_HS400;
- sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+ if (mmc->selected_mode == MMC_HS_400_ES)
+ reg |= DWCMSHC_ENHANCED_STROBE;
+ else
+ reg &= ~DWCMSHC_ENHANCED_STROBE;
- vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
- + DWCMSHC_EMMC_CONTROL;
- /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
- reg = sdhci_readw(host, vendor_reg);
- reg |= DWCMSHC_CARD_IS_EMMC;
- sdhci_writew(host, reg, vendor_reg);
- } else {
- sdhci_set_uhs_timing(host);
- }
+ sdhci_writew(host, reg, DWCMSHC_EMMC_EMMC_CTRL);
return 0;
}
@@ -448,23 +459,32 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
return 0;
}
+static void rockchip_sdhci_set_clock(struct sdhci_host *host, u32 div)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+ if (data->set_clock)
+ data->set_clock(host, div);
+}
+
static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
{
- struct sdhci_host *host = dev_get_priv(mmc->dev);
+ struct rockchip_sdhc *priv = dev_get_priv(mmc->dev);
+ struct sdhci_host *host = &priv->host;
char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
struct mmc_cmd cmd;
u32 ctrl, blk_size;
- int ret = 0;
+ int ret;
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl |= SDHCI_CTRL_EXEC_TUNING;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
- sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 64);
- if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && host->mmc->bus_width == 8)
+ if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && mmc->bus_width == 8)
blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 128);
sdhci_writew(host, blk_size, SDHCI_BLOCK_SIZE);
sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
@@ -474,40 +494,39 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
cmd.cmdarg = 0;
do {
- if (tuning_loop_counter-- == 0)
- break;
-
- mmc_send_cmd(mmc, &cmd, NULL);
-
- if (opcode == MMC_CMD_SEND_TUNING_BLOCK)
- /*
- * For tuning command, do not do busy loop. As tuning
- * is happening (CLK-DATA latching for setup/hold time
- * requirements), give time to complete
- */
- udelay(1);
-
+ ret = mmc_send_cmd(mmc, &cmd, NULL);
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ if (ret || tuning_loop_counter-- == 0)
+ break;
} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
- if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
- printf("%s:Tuning failed\n", __func__);
- ret = -EIO;
- }
+ if (ret || tuning_loop_counter < 0 || !(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+ if (!ret)
+ ret = -EIO;
+ printf("%s: Tuning failed: %d\n", __func__, ret);
- if (tuning_loop_counter < 0) {
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
- sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
+ ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
}
/* Enable only interrupts served by the SD controller */
sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_INT_ENABLE);
- /* Mask all sdhci interrupt sources */
- sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
return ret;
}
+static int rockchip_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+ if (data->config_dll)
+ return data->config_dll(host, clock, enable);
+
+ return 0;
+}
+
static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
@@ -516,13 +535,15 @@ static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
if (data->set_enhanced_strobe)
return data->set_enhanced_strobe(host);
- return -ENOTSUPP;
+ return 0;
}
static struct sdhci_ops rockchip_sdhci_ops = {
- .set_ios_post = rockchip_sdhci_set_ios_post,
- .platform_execute_tuning = &rockchip_sdhci_execute_tuning,
.set_control_reg = rockchip_sdhci_set_control_reg,
+ .set_ios_post = rockchip_sdhci_set_ios_post,
+ .set_clock = rockchip_sdhci_set_clock,
+ .platform_execute_tuning = rockchip_sdhci_execute_tuning,
+ .config_dll = rockchip_sdhci_config_dll,
.set_enhanced_strobe = rockchip_sdhci_set_enhanced_strobe,
};
@@ -531,9 +552,9 @@ static int rockchip_sdhci_probe(struct udevice *dev)
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
- struct rockchip_sdhc *prv = dev_get_priv(dev);
+ struct rockchip_sdhc *priv = dev_get_priv(dev);
struct mmc_config *cfg = &plat->cfg;
- struct sdhci_host *host = &prv->host;
+ struct sdhci_host *host = &priv->host;
struct clk clk;
int ret;
@@ -547,8 +568,8 @@ static int rockchip_sdhci_probe(struct udevice *dev)
printf("%s fail to get clk\n", __func__);
}
- prv->emmc_clk = clk;
- prv->dev = dev;
+ priv->emmc_clk = clk;
+ priv->dev = dev;
if (data->get_phy) {
ret = data->get_phy(dev);
@@ -556,17 +577,11 @@ static int rockchip_sdhci_probe(struct udevice *dev)
return ret;
}
- if (data->emmc_phy_init) {
- ret = data->emmc_phy_init(dev);
- if (ret)
- return ret;
- }
-
host->ops = &rockchip_sdhci_ops;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
host->mmc = &plat->mmc;
- host->mmc->priv = &prv->host;
+ host->mmc->priv = &priv->host;
host->mmc->dev = dev;
upriv->mmc = host->mmc;
@@ -574,14 +589,23 @@ static int rockchip_sdhci_probe(struct udevice *dev)
if (ret)
return ret;
+ /*
+ * Reading more than 4 blocks with a single CMD18 command in PIO mode
+ * triggers Data End Bit Error on RK3568 and RK3588. Limit to reading
+ * max 4 blocks in one command when using PIO mode.
+ */
+ if (!(host->flags & USE_DMA))
+ cfg->b_max = 4;
+
return sdhci_probe(dev);
}
static int rockchip_sdhci_of_to_plat(struct udevice *dev)
{
struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
- struct sdhci_host *host = dev_get_priv(dev);
+ struct rockchip_sdhc *priv = dev_get_priv(dev);
struct mmc_config *cfg = &plat->cfg;
+ struct sdhci_host *host = &priv->host;
int ret;
host->name = dev->name;
@@ -603,17 +627,26 @@ static int rockchip_sdhci_bind(struct udevice *dev)
static const struct sdhci_data rk3399_data = {
.get_phy = rk3399_emmc_get_phy,
- .emmc_phy_init = rk3399_emmc_phy_init,
.set_control_reg = rk3399_sdhci_set_control_reg,
.set_ios_post = rk3399_sdhci_set_ios_post,
.set_enhanced_strobe = rk3399_sdhci_set_enhanced_strobe,
};
static const struct sdhci_data rk3568_data = {
- .get_phy = rk3568_emmc_get_phy,
- .emmc_phy_init = rk3568_emmc_phy_init,
.set_ios_post = rk3568_sdhci_set_ios_post,
- .set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe,
+ .set_clock = rk3568_sdhci_set_clock,
+ .config_dll = rk3568_sdhci_config_dll,
+ .flags = FLAG_INVERTER_FLAG_IN_RXCLK,
+ .hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
+ .hs400_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
+};
+
+static const struct sdhci_data rk3588_data = {
+ .set_ios_post = rk3568_sdhci_set_ios_post,
+ .set_clock = rk3568_sdhci_set_clock,
+ .config_dll = rk3568_sdhci_config_dll,
+ .hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
+ .hs400_txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES,
};
static const struct udevice_id sdhci_ids[] = {
@@ -625,6 +658,10 @@ static const struct udevice_id sdhci_ids[] = {
.compatible = "rockchip,rk3568-dwcmshc",
.data = (ulong)&rk3568_data,
},
+ {
+ .compatible = "rockchip,rk3588-dwcmshc",
+ .data = (ulong)&rk3588_data,
+ },
{ }
};
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c6b250b9a1b..9cbe126106c 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -70,7 +70,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data)
}
}
-#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
+#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
int *is_aligned, int trans_bytes)
{
@@ -177,7 +177,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data)
}
} while (!(stat & SDHCI_INT_DATA_END));
-#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
+#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
mmc_get_dma_dir(data));
#endif
@@ -518,6 +518,10 @@ void sdhci_set_uhs_timing(struct sdhci_host *host)
reg &= ~SDHCI_CTRL_UHS_MASK;
switch (mmc->selected_mode) {
+ case UHS_SDR25:
+ case MMC_HS:
+ reg |= SDHCI_CTRL_UHS_SDR25;
+ break;
case UHS_SDR50:
case MMC_HS_52:
reg |= SDHCI_CTRL_UHS_SDR50;
@@ -682,6 +686,7 @@ static int sdhci_set_ios(struct mmc *mmc)
if (!no_hispd_bit) {
if (mmc->selected_mode == MMC_HS ||
mmc->selected_mode == SD_HS ||
+ mmc->selected_mode == MMC_HS_52 ||
mmc->selected_mode == MMC_DDR_52 ||
mmc->selected_mode == MMC_HS_200 ||
mmc->selected_mode == MMC_HS_400 ||
@@ -872,7 +877,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
#endif
debug("%s, caps: 0x%x\n", __func__, caps);
-#ifdef CONFIG_MMC_SDHCI_SDMA
+#if CONFIG_IS_ENABLED(MMC_SDHCI_SDMA)
if ((caps & SDHCI_CAN_DO_SDMA)) {
host->flags |= USE_SDMA;
} else {
@@ -882,7 +887,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
#endif
#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
if (!(caps & SDHCI_CAN_DO_ADMA2)) {
- printf("%s: Your controller doesn't support SDMA!!\n",
+ printf("%s: Your controller doesn't support ADMA!!\n",
__func__);
return -EINVAL;
}
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index e9c7d3a2e00..d1e26815996 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -369,22 +369,23 @@ static bool tmio_sd_addr_is_dmaable(struct mmc_data *data)
if (!IS_ALIGNED(addr, TMIO_SD_DMA_MINALIGN))
return false;
-#if defined(CONFIG_RCAR_GEN3)
- if (!(data->flags & MMC_DATA_READ) && !IS_ALIGNED(addr, 128))
- return false;
- /* Gen3 DMA has 32bit limit */
- if (addr >> 32)
- return false;
-#endif
+ if (IS_ENABLED(CONFIG_RCAR_64)) {
+ if (!(data->flags & MMC_DATA_READ) && !IS_ALIGNED(addr, 128))
+ return false;
+ /* Gen3 DMA has 32bit limit */
+ if (sizeof(addr) > 4 && addr >> 32)
+ return false;
+ }
-#if defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARM64) && \
- defined(CONFIG_SPL_BUILD)
- /*
- * For UniPhier ARMv7 SoCs, the stack is allocated in the locked ways
- * of L2, which is unreachable from the DMA engine.
- */
- if (addr < CONFIG_SPL_STACK)
- return false;
+#ifdef CONFIG_SPL_BUILD
+ if (IS_ENABLED(CONFIG_ARCH_UNIPHIER) && !IS_ENABLED(CONFIG_ARM64)) {
+ /*
+ * For UniPhier ARMv7 SoCs, the stack is allocated in locked
+ * ways of L2, which is unreachable from the DMA engine.
+ */
+ if (addr < CONFIG_SPL_STACK)
+ return false;
+ }
#endif
return true;
@@ -622,25 +623,22 @@ static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, struct mmc *mmc)
static void tmio_sd_set_pins(struct udevice *dev)
{
__maybe_unused struct mmc *mmc = mmc_get_mmc_dev(dev);
-
-#ifdef CONFIG_DM_REGULATOR
struct tmio_sd_priv *priv = dev_get_priv(dev);
- if (priv->vqmmc_dev) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vqmmc_dev) {
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
regulator_set_value(priv->vqmmc_dev, 1800000);
else
regulator_set_value(priv->vqmmc_dev, 3300000);
regulator_set_enable(priv->vqmmc_dev, true);
}
-#endif
-#ifdef CONFIG_PINCTRL
- if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
- pinctrl_select_state(dev, "state_uhs");
- else
- pinctrl_select_state(dev, "default");
-#endif
+ if (CONFIG_IS_ENABLED(PINCTRL)) {
+ if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+ pinctrl_select_state(dev, "state_uhs");
+ else
+ pinctrl_select_state(dev, "default");
+ }
}
int tmio_sd_set_ios(struct udevice *dev)
@@ -734,11 +732,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
if (!priv->regbase)
return -ENOMEM;
-#ifdef CONFIG_DM_REGULATOR
- device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev);
- if (priv->vqmmc_dev)
- regulator_set_value(priv->vqmmc_dev, 3300000);
-#endif
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+ device_get_supply_regulator(dev, "vqmmc-supply",
+ &priv->vqmmc_dev);
+ if (priv->vqmmc_dev)
+ regulator_set_value(priv->vqmmc_dev, 3300000);
+ }
ret = mmc_of_parse(dev, &plat->cfg);
if (ret < 0) {
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 4d717d85dec..f489fb70766 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -133,9 +133,7 @@ struct tmio_sd_priv {
#define TMIO_SD_CAP_RCAR_UHS BIT(7) /* Renesas RCar UHS/SDR modes */
#define TMIO_SD_CAP_RCAR \
(TMIO_SD_CAP_RCAR_GEN2 | TMIO_SD_CAP_RCAR_GEN3)
-#ifdef CONFIG_DM_REGULATOR
struct udevice *vqmmc_dev;
-#endif
#if CONFIG_IS_ENABLED(CLK)
struct clk clk;
struct clk clkh;
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index af45ef00dae..5fa88dae5f3 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -270,4 +270,6 @@ source "drivers/mtd/spi/Kconfig"
source "drivers/mtd/ubi/Kconfig"
+source "drivers/mtd/nvmxip/Kconfig"
+
endmenu
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 3a78590aaaa..c638980ea2b 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -25,6 +25,7 @@ obj-y += nand/
obj-y += onenand/
obj-y += spi/
obj-$(CONFIG_MTD_UBI) += ubi/
+obj-$(CONFIG_NVMXIP) += nvmxip/
#SPL/TPL build
else
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5c7b0d9dcc1..d115fcf841f 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -156,6 +156,13 @@ config NAND_BRCMNAND_63158
help
Enable support for broadcom nand driver on bcm63158.
+config NAND_BRCMNAND_IPROC
+ bool "Support Broadcom NAND controller on the iproc family"
+ depends on NAND_BRCMNAND
+ help
+ Enable support for broadcom nand driver on the Broadcom
+ iproc family such as Northstar (BCM5301x, BCM4708...)
+
config NAND_DAVINCI
bool "Support TI Davinci NAND controller"
select SYS_NAND_SELF_INIT if TARGET_DA850EVM
diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile
index f46a7edae32..0c6325aaa61 100644
--- a/drivers/mtd/nand/raw/brcmnand/Makefile
+++ b/drivers/mtd/nand/raw/brcmnand/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6753_nand.o
obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o
obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o
obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o
+obj-$(CONFIG_NAND_BRCMNAND_IPROC) += iproc_nand.o
obj-$(CONFIG_NAND_BRCMNAND) += brcmnand.o
obj-$(CONFIG_NAND_BRCMNAND) += brcmnand_compat.o
diff --git a/drivers/mtd/nand/raw/brcmnand/iproc_nand.c b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
new file mode 100644
index 00000000000..69711d98ce1
--- /dev/null
+++ b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Code borrowed from the Linux driver
+ * Copyright (C) 2015 Broadcom Corporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <memalign.h>
+#include <nand.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <dm.h>
+
+#include "brcmnand.h"
+
+struct iproc_nand_soc {
+ struct brcmnand_soc soc;
+ void __iomem *idm_base;
+ void __iomem *ext_base;
+};
+
+#define IPROC_NAND_CTLR_READY_OFFSET 0x10
+#define IPROC_NAND_CTLR_READY BIT(0)
+
+#define IPROC_NAND_IO_CTRL_OFFSET 0x00
+#define IPROC_NAND_APB_LE_MODE BIT(24)
+#define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6)
+
+static bool iproc_nand_intc_ack(struct brcmnand_soc *soc)
+{
+ struct iproc_nand_soc *priv =
+ container_of(soc, struct iproc_nand_soc, soc);
+ void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET;
+ u32 val = brcmnand_readl(mmio);
+
+ if (val & IPROC_NAND_CTLR_READY) {
+ brcmnand_writel(IPROC_NAND_CTLR_READY, mmio);
+ return true;
+ }
+
+ return false;
+}
+
+static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+ struct iproc_nand_soc *priv =
+ container_of(soc, struct iproc_nand_soc, soc);
+ void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
+ u32 val = brcmnand_readl(mmio);
+
+ if (en)
+ val |= IPROC_NAND_INT_CTRL_READ_ENABLE;
+ else
+ val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE;
+
+ brcmnand_writel(val, mmio);
+}
+
+static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare,
+ bool is_param)
+{
+ struct iproc_nand_soc *priv =
+ container_of(soc, struct iproc_nand_soc, soc);
+ void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
+ u32 val;
+
+ val = brcmnand_readl(mmio);
+
+ /*
+ * In the case of BE or when dealing with NAND data, always configure
+ * the APB bus to LE mode before accessing the FIFO and back to BE mode
+ * after the access is done
+ */
+ if (IS_ENABLED(CONFIG_SYS_BIG_ENDIAN) || !is_param) {
+ if (prepare)
+ val |= IPROC_NAND_APB_LE_MODE;
+ else
+ val &= ~IPROC_NAND_APB_LE_MODE;
+ } else { /* when in LE accessing the parameter page, keep APB in BE */
+ val &= ~IPROC_NAND_APB_LE_MODE;
+ }
+
+ brcmnand_writel(val, mmio);
+}
+
+static int iproc_nand_probe(struct udevice *dev)
+{
+ struct udevice *pdev = dev;
+ struct iproc_nand_soc *priv = dev_get_priv(dev);
+ struct brcmnand_soc *soc;
+ struct resource res;
+ int ret;
+
+ soc = &priv->soc;
+
+ ret = dev_read_resource_byname(pdev, "iproc-idm", &res);
+ if (ret)
+ return ret;
+
+ priv->idm_base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (IS_ERR(priv->idm_base))
+ return PTR_ERR(priv->idm_base);
+
+ ret = dev_read_resource_byname(pdev, "iproc-ext", &res);
+ if (ret)
+ return ret;
+
+ priv->ext_base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (IS_ERR(priv->ext_base))
+ return PTR_ERR(priv->ext_base);
+
+ soc->ctlrdy_ack = iproc_nand_intc_ack;
+ soc->ctlrdy_set_enabled = iproc_nand_intc_set;
+ soc->prepare_data_bus = iproc_nand_apb_access;
+
+ return brcmnand_probe(pdev, soc);
+}
+
+static const struct udevice_id iproc_nand_dt_ids[] = {
+ {
+ .compatible = "brcm,nand-iproc",
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(iproc_nand) = {
+ .name = "iproc-nand",
+ .id = UCLASS_MTD,
+ .of_match = iproc_nand_dt_ids,
+ .probe = iproc_nand_probe,
+ .priv_auto = sizeof(struct iproc_nand_soc),
+};
+
+void board_nand_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_MTD,
+ DM_DRIVER_GET(iproc_nand), &dev);
+ if (ret && ret != -ENODEV)
+ pr_err("Failed to initialize %s. (error %d)\n", dev->name,
+ ret);
+}
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 9eba360d55f..6b4adcf6bdc 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4487,6 +4487,7 @@ EXPORT_SYMBOL(nand_detect);
static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode node)
{
int ret, ecc_mode = -1, ecc_strength, ecc_step;
+ int ecc_algo = NAND_ECC_UNKNOWN;
const char *str;
ret = ofnode_read_s32_default(node, "nand-bus-width", -1);
@@ -4512,10 +4513,22 @@ static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode nod
ecc_mode = NAND_ECC_SOFT_BCH;
}
- if (ecc_mode == NAND_ECC_SOFT) {
- str = ofnode_read_string(node, "nand-ecc-algo");
- if (str && !strcmp(str, "bch"))
- ecc_mode = NAND_ECC_SOFT_BCH;
+ str = ofnode_read_string(node, "nand-ecc-algo");
+ if (str) {
+ /*
+ * If we are in NAND_ECC_SOFT mode, just alter the
+ * soft mode to BCH here. No change of algorithm.
+ */
+ if (ecc_mode == NAND_ECC_SOFT) {
+ if (!strcmp(str, "bch"))
+ ecc_mode = NAND_ECC_SOFT_BCH;
+ } else {
+ if (!strcmp(str, "bch")) {
+ ecc_algo = NAND_ECC_BCH;
+ } else if (!strcmp(str, "hamming")) {
+ ecc_algo = NAND_ECC_HAMMING;
+ }
+ }
}
ecc_strength = ofnode_read_s32_default(node,
@@ -4529,6 +4542,14 @@ static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode nod
return -EINVAL;
}
+ /*
+ * Chip drivers may have assigned default algorithms here,
+ * onlt override it if we have found something explicitly
+ * specified in the device tree.
+ */
+ if (ecc_algo != NAND_ECC_UNKNOWN)
+ chip->ecc.algo = ecc_algo;
+
if (ecc_mode >= 0)
chip->ecc.mode = ecc_mode;
diff --git a/drivers/mtd/nand/raw/octeontx_bch.c b/drivers/mtd/nand/raw/octeontx_bch.c
index fc16b77416b..056a6857822 100644
--- a/drivers/mtd/nand/raw/octeontx_bch.c
+++ b/drivers/mtd/nand/raw/octeontx_bch.c
@@ -27,7 +27,7 @@
#include <asm/arch/clock.h>
#include "octeontx_bch.h"
-LIST_HEAD(octeontx_bch_devices);
+static LIST_HEAD(octeontx_bch_devices);
static unsigned int num_vfs = BCH_NR_VF;
static void *bch_pf;
static void *bch_vf;
diff --git a/drivers/mtd/nand/raw/octeontx_nand.c b/drivers/mtd/nand/raw/octeontx_nand.c
index 1ffadad9cae..65a03d22c1d 100644
--- a/drivers/mtd/nand/raw/octeontx_nand.c
+++ b/drivers/mtd/nand/raw/octeontx_nand.c
@@ -354,7 +354,7 @@ struct octeontx_probe_device {
static struct bch_vf *bch_vf;
/** Deferred devices due to BCH not being ready */
-LIST_HEAD(octeontx_pci_nand_deferred_devices);
+static LIST_HEAD(octeontx_pci_nand_deferred_devices);
/** default parameters used for probing chips */
#define MAX_ONFI_MODE 5
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index fb3279b405e..69dbb629e93 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -735,6 +735,9 @@ static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
if (IS_ERR(sdrt))
return PTR_ERR(sdrt);
+ if (sdrt->tRC_min < 30000)
+ return -EOPNOTSUPP;
+
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
return 0;
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index c378f08f680..c0fa1e310c6 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -24,12 +24,13 @@
* GNU General Public License for more details.
*/
+#include <clk.h>
#include <common.h>
-#include <fdtdec.h>
+#include <dm.h>
#include <malloc.h>
#include <memalign.h>
#include <nand.h>
-#include <asm/global_data.h>
+#include <reset.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <linux/bitops.h>
@@ -45,8 +46,6 @@
#include <asm/gpio.h>
#include <asm/arch/clock.h>
-DECLARE_GLOBAL_DATA_PTR;
-
#define NFC_REG_CTL 0x0000
#define NFC_REG_ST 0x0004
#define NFC_REG_INT 0x0008
@@ -263,7 +262,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
* NAND Controller structure: stores sunxi NAND controller information
*
* @controller: base controller structure
- * @dev: parent device (used to print error messages)
+ * @dev: DM device (used to print error messages)
* @regs: NAND controller registers
* @ahb_clk: NAND Controller AHB clock
* @mod_clk: NAND Controller mod clock
@@ -276,7 +275,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
*/
struct sunxi_nfc {
struct nand_hw_control controller;
- struct device *dev;
+ struct udevice *dev;
void __iomem *regs;
struct clk *ahb_clk;
struct clk *mod_clk;
@@ -1605,24 +1604,24 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
return 0;
}
-static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
+static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc,
+ ofnode np, int devnum)
{
const struct nand_sdr_timings *timings;
- const void *blob = gd->fdt_blob;
struct sunxi_nand_chip *chip;
struct mtd_info *mtd;
struct nand_chip *nand;
int nsels;
int ret;
int i;
- u32 cs[8], rb[8];
+ u32 tmp;
- if (!fdt_getprop(blob, node, "reg", &nsels))
+ if (!ofnode_get_property(np, "reg", &nsels))
return -EINVAL;
nsels /= sizeof(u32);
if (!nsels || nsels > 8) {
- dev_err(nfc->dev, "invalid reg property size\n");
+ dev_err(dev, "invalid reg property size\n");
return -EINVAL;
}
@@ -1630,7 +1629,7 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
(nsels * sizeof(struct sunxi_nand_chip_sel)),
GFP_KERNEL);
if (!chip) {
- dev_err(nfc->dev, "could not allocate chip\n");
+ dev_err(dev, "could not allocate chip\n");
return -ENOMEM;
}
@@ -1638,48 +1637,34 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
chip->selected = -1;
for (i = 0; i < nsels; i++) {
- cs[i] = -1;
- rb[i] = -1;
- }
-
- ret = fdtdec_get_int_array(gd->fdt_blob, node, "reg", cs, nsels);
- if (ret) {
- dev_err(nfc->dev, "could not retrieve reg property: %d\n", ret);
- return ret;
- }
-
- ret = fdtdec_get_int_array(gd->fdt_blob, node, "allwinner,rb", rb,
- nsels);
- if (ret) {
- dev_err(nfc->dev, "could not retrieve reg property: %d\n", ret);
- return ret;
- }
-
- for (i = 0; i < nsels; i++) {
- int tmp = cs[i];
+ ret = ofnode_read_u32_index(np, "reg", i, &tmp);
+ if (ret) {
+ dev_err(dev, "could not retrieve reg property: %d\n",
+ ret);
+ return ret;
+ }
if (tmp > NFC_MAX_CS) {
- dev_err(nfc->dev,
+ dev_err(dev,
"invalid reg value: %u (max CS = 7)\n", tmp);
return -EINVAL;
}
if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
- dev_err(nfc->dev, "CS %d already assigned\n", tmp);
+ dev_err(dev, "CS %d already assigned\n", tmp);
return -EINVAL;
}
chip->sels[i].cs = tmp;
- tmp = rb[i];
- if (tmp >= 0 && tmp < 2) {
+ if (!ofnode_read_u32_index(np, "allwinner,rb", i, &tmp) &&
+ tmp < 2) {
chip->sels[i].rb.type = RB_NATIVE;
chip->sels[i].rb.info.nativeid = tmp;
} else {
- ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
- "rb-gpios", i,
- &chip->sels[i].rb.info.gpio,
- GPIOD_IS_IN);
+ ret = gpio_request_by_name(dev, "rb-gpios", i,
+ &chip->sels[i].rb.info.gpio,
+ GPIOD_IS_IN);
if (ret)
chip->sels[i].rb.type = RB_GPIO;
else
@@ -1690,7 +1675,7 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
timings = onfi_async_timing_mode_to_sdr_timings(0);
if (IS_ERR(timings)) {
ret = PTR_ERR(timings);
- dev_err(nfc->dev,
+ dev_err(dev,
"could not retrieve timings for ONFI mode 0: %d\n",
ret);
return ret;
@@ -1698,7 +1683,7 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
ret = sunxi_nand_chip_set_timings(nfc, chip, timings);
if (ret) {
- dev_err(nfc->dev, "could not configure chip timings: %d\n", ret);
+ dev_err(dev, "could not configure chip timings: %d\n", ret);
return ret;
}
@@ -1711,7 +1696,7 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
* in the DT.
*/
nand->ecc.mode = NAND_ECC_HW;
- nand->flash_node = offset_to_ofnode(node);
+ nand->flash_node = np;
nand->select_chip = sunxi_nfc_select_chip;
nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
nand->read_buf = sunxi_nfc_read_buf;
@@ -1733,25 +1718,25 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
ret = sunxi_nand_chip_init_timings(nfc, chip);
if (ret) {
- dev_err(nfc->dev, "could not configure chip timings: %d\n", ret);
+ dev_err(dev, "could not configure chip timings: %d\n", ret);
return ret;
}
ret = sunxi_nand_ecc_init(mtd, &nand->ecc);
if (ret) {
- dev_err(nfc->dev, "ECC init failed: %d\n", ret);
+ dev_err(dev, "ECC init failed: %d\n", ret);
return ret;
}
ret = nand_scan_tail(mtd);
if (ret) {
- dev_err(nfc->dev, "nand_scan_tail failed: %d\n", ret);
+ dev_err(dev, "nand_scan_tail failed: %d\n", ret);
return ret;
}
ret = nand_register(devnum, mtd);
if (ret) {
- dev_err(nfc->dev, "failed to register mtd device: %d\n", ret);
+ dev_err(dev, "failed to register mtd device: %d\n", ret);
return ret;
}
@@ -1760,25 +1745,13 @@ static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
return 0;
}
-static int sunxi_nand_chips_init(int node, struct sunxi_nfc *nfc)
+static int sunxi_nand_chips_init(struct udevice *dev, struct sunxi_nfc *nfc)
{
- const void *blob = gd->fdt_blob;
- int nand_node;
+ ofnode nand_np;
int ret, i = 0;
- for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
- nand_node = fdt_next_subnode(blob, nand_node))
- i++;
-
- if (i > 8) {
- dev_err(nfc->dev, "too many NAND chips: %d (max = 8)\n", i);
- return -EINVAL;
- }
-
- i = 0;
- for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
- nand_node = fdt_next_subnode(blob, nand_node)) {
- ret = sunxi_nand_chip_init(nand_node, nfc, i++);
+ dev_for_each_subnode(nand_np, dev) {
+ ret = sunxi_nand_chip_init(dev, nfc, nand_np, i++);
if (ret)
return ret;
}
@@ -1802,55 +1775,67 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
}
#endif /* __UBOOT__ */
-void sunxi_nand_init(void)
+static int sunxi_nand_probe(struct udevice *dev)
{
- const void *blob = gd->fdt_blob;
- struct sunxi_nfc *nfc;
- fdt_addr_t regs;
- int node;
+ struct sunxi_nfc *nfc = dev_get_priv(dev);
+ struct reset_ctl_bulk rst_bulk;
+ struct clk_bulk clk_bulk;
int ret;
- nfc = kzalloc(sizeof(*nfc), GFP_KERNEL);
- if (!nfc)
- return;
-
+ nfc->dev = dev;
spin_lock_init(&nfc->controller.lock);
init_waitqueue_head(&nfc->controller.wq);
INIT_LIST_HEAD(&nfc->chips);
- node = fdtdec_next_compatible(blob, 0, COMPAT_SUNXI_NAND);
- if (node < 0) {
- pr_err("unable to find nfc node in device tree\n");
- goto err;
- }
+ nfc->regs = dev_read_addr_ptr(dev);
+ if (!nfc->regs)
+ return -EINVAL;
- if (!fdtdec_get_is_enabled(blob, node)) {
- pr_err("nfc disabled in device tree\n");
- goto err;
- }
+ ret = reset_get_bulk(dev, &rst_bulk);
+ if (!ret)
+ reset_deassert_bulk(&rst_bulk);
- regs = fdtdec_get_addr(blob, node, "reg");
- if (regs == FDT_ADDR_T_NONE) {
- pr_err("unable to find nfc address in device tree\n");
- goto err;
- }
-
- nfc->regs = (void *)regs;
+ ret = clk_get_bulk(dev, &clk_bulk);
+ if (!ret)
+ clk_enable_bulk(&clk_bulk);
ret = sunxi_nfc_rst(nfc);
if (ret)
- goto err;
+ return ret;
- ret = sunxi_nand_chips_init(node, nfc);
+ ret = sunxi_nand_chips_init(dev, nfc);
if (ret) {
- dev_err(nfc->dev, "failed to init nand chips\n");
- goto err;
+ dev_err(dev, "failed to init nand chips\n");
+ return ret;
}
- return;
+ return 0;
+}
-err:
- kfree(nfc);
+static const struct udevice_id sunxi_nand_ids[] = {
+ {
+ .compatible = "allwinner,sun4i-a10-nand",
+ },
+ { }
+};
+
+U_BOOT_DRIVER(sunxi_nand) = {
+ .name = "sunxi_nand",
+ .id = UCLASS_MTD,
+ .of_match = sunxi_nand_ids,
+ .probe = sunxi_nand_probe,
+ .priv_auto = sizeof(struct sunxi_nfc),
+};
+
+void board_nand_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_MTD,
+ DM_DRIVER_GET(sunxi_nand), &dev);
+ if (ret && ret != -ENODEV)
+ pr_err("Failed to initialize sunxi NAND controller: %d\n", ret);
}
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/nvmxip/Kconfig b/drivers/mtd/nvmxip/Kconfig
new file mode 100644
index 00000000000..3ef71050264
--- /dev/null
+++ b/drivers/mtd/nvmxip/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2023 Arm Limited and/or its affiliates <[email protected]>
+# Authors:
+# Abdellatif El Khlifi <[email protected]>
+
+config NVMXIP
+ bool "NVM XIP devices support"
+ select BLK
+ help
+ This option allows the emulation of a block storage device
+ on top of a direct access non volatile memory XIP flash devices.
+ This support provides the read operation.
+
+config NVMXIP_QSPI
+ bool "QSPI XIP support"
+ select NVMXIP
+ help
+ This option allows the emulation of a block storage device on top of a QSPI XIP flash
diff --git a/drivers/mtd/nvmxip/Makefile b/drivers/mtd/nvmxip/Makefile
new file mode 100644
index 00000000000..54eacc102e6
--- /dev/null
+++ b/drivers/mtd/nvmxip/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2023 Arm Limited and/or its affiliates <[email protected]>
+# Authors:
+# Abdellatif El Khlifi <[email protected]>
+
+obj-y += nvmxip-uclass.o nvmxip.o
+obj-$(CONFIG_NVMXIP_QSPI) += nvmxip_qspi.o
diff --git a/drivers/mtd/nvmxip/nvmxip-uclass.c b/drivers/mtd/nvmxip/nvmxip-uclass.c
new file mode 100644
index 00000000000..6d8eb177b50
--- /dev/null
+++ b/drivers/mtd/nvmxip/nvmxip-uclass.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 Arm Limited and/or its affiliates <[email protected]>
+ *
+ * Authors:
+ * Abdellatif El Khlifi <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#if CONFIG_IS_ENABLED(SANDBOX64)
+#include <asm/test.h>
+#endif
+#include <linux/bitops.h>
+#include "nvmxip.h"
+
+/* LBA Macros */
+
+#define DEFAULT_LBA_SHIFT 10 /* 1024 bytes per block */
+#define DEFAULT_LBA_COUNT 1024 /* block count */
+
+#define DEFAULT_LBA_SZ BIT(DEFAULT_LBA_SHIFT)
+
+/**
+ * nvmxip_post_bind() - post binding treatments
+ * @dev: the NVMXIP device
+ *
+ * Create and probe a child block device.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int nvmxip_post_bind(struct udevice *udev)
+{
+ int ret;
+ struct udevice *bdev = NULL;
+ char bdev_name[NVMXIP_BLKDEV_NAME_SZ + 1];
+ int devnum;
+
+#if CONFIG_IS_ENABLED(SANDBOX64)
+ sandbox_set_enable_memio(true);
+#endif
+
+ devnum = uclass_id_count(UCLASS_NVMXIP);
+ snprintf(bdev_name, NVMXIP_BLKDEV_NAME_SZ, "blk#%d", devnum);
+
+ ret = blk_create_devicef(udev, NVMXIP_BLKDRV_NAME, bdev_name, UCLASS_NVMXIP,
+ devnum, DEFAULT_LBA_SZ,
+ DEFAULT_LBA_COUNT, &bdev);
+ if (ret) {
+ log_err("[%s]: failure during creation of the block device %s, error %d\n",
+ udev->name, bdev_name, ret);
+ return ret;
+ }
+
+ ret = blk_probe_or_unbind(bdev);
+ if (ret) {
+ log_err("[%s]: failure during probing the block device %s, error %d\n",
+ udev->name, bdev_name, ret);
+ return ret;
+ }
+
+ log_info("[%s]: the block device %s ready for use\n", udev->name, bdev_name);
+
+ return 0;
+}
+
+UCLASS_DRIVER(nvmxip) = {
+ .name = "nvmxip",
+ .id = UCLASS_NVMXIP,
+ .post_bind = nvmxip_post_bind,
+};
diff --git a/drivers/mtd/nvmxip/nvmxip.c b/drivers/mtd/nvmxip/nvmxip.c
new file mode 100644
index 00000000000..a359e3b4822
--- /dev/null
+++ b/drivers/mtd/nvmxip/nvmxip.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 Arm Limited and/or its affiliates <[email protected]>
+ *
+ * Authors:
+ * Abdellatif El Khlifi <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <mapmem.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include "nvmxip.h"
+
+/**
+ * nvmxip_mmio_rawread() - read from the XIP flash
+ * @address: address of the data
+ * @value: pointer to where storing the value read
+ *
+ * Read raw data from the XIP flash.
+ *
+ * Return:
+ *
+ * Always return 0.
+ */
+static int nvmxip_mmio_rawread(const phys_addr_t address, u64 *value)
+{
+ *value = readq(address);
+ return 0;
+}
+
+/**
+ * nvmxip_blk_read() - block device read operation
+ * @dev: the block device
+ * @blknr: first block number to read from
+ * @blkcnt: number of blocks to read
+ * @buffer: destination buffer
+ *
+ * Read data from the block storage device.
+ *
+ * Return:
+ *
+ * number of blocks read on success. Otherwise, failure
+ */
+static ulong nvmxip_blk_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct nvmxip_plat *plat = dev_get_plat(dev->parent);
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
+ /* number of the u64 words to read */
+ u32 qwords = (blkcnt * desc->blksz) / sizeof(u64);
+ /* physical address of the first block to read */
+ phys_addr_t blkaddr = plat->phys_base + blknr * desc->blksz;
+ u64 *virt_blkaddr;
+ u64 *pdst = buffer;
+ uint qdata_idx;
+
+ if (!pdst)
+ return -EINVAL;
+
+ log_debug("[%s]: reading from blknr: %lu , blkcnt: %lu\n", dev->name, blknr, blkcnt);
+
+ virt_blkaddr = map_sysmem(blkaddr, 0);
+
+ /* assumption: the data is virtually contiguous */
+
+ for (qdata_idx = 0 ; qdata_idx < qwords ; qdata_idx++)
+ nvmxip_mmio_rawread((phys_addr_t)(virt_blkaddr + qdata_idx), pdst++);
+
+ log_debug("[%s]: src[0]: 0x%llx , dst[0]: 0x%llx , src[-1]: 0x%llx , dst[-1]: 0x%llx\n",
+ dev->name,
+ *virt_blkaddr,
+ *(u64 *)buffer,
+ *(u64 *)((u8 *)virt_blkaddr + desc->blksz * blkcnt - sizeof(u64)),
+ *(u64 *)((u8 *)buffer + desc->blksz * blkcnt - sizeof(u64)));
+
+ unmap_sysmem(virt_blkaddr);
+
+ return blkcnt;
+}
+
+/**
+ * nvmxip_blk_probe() - block storage device probe
+ * @dev: the block storage device
+ *
+ * Initialize the block storage descriptor.
+ *
+ * Return:
+ *
+ * Always return 0.
+ */
+static int nvmxip_blk_probe(struct udevice *dev)
+{
+ struct nvmxip_plat *plat = dev_get_plat(dev->parent);
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
+
+ desc->lba = plat->lba;
+ desc->log2blksz = plat->lba_shift;
+ desc->blksz = BIT(plat->lba_shift);
+ desc->bdev = dev;
+
+ log_debug("[%s]: block storage layout\n lbas: %lu , log2blksz: %d, blksz: %lu\n",
+ dev->name, desc->lba, desc->log2blksz, desc->blksz);
+
+ return 0;
+}
+
+static const struct blk_ops nvmxip_blk_ops = {
+ .read = nvmxip_blk_read,
+};
+
+U_BOOT_DRIVER(nvmxip_blk) = {
+ .name = NVMXIP_BLKDRV_NAME,
+ .id = UCLASS_BLK,
+ .probe = nvmxip_blk_probe,
+ .ops = &nvmxip_blk_ops,
+};
diff --git a/drivers/mtd/nvmxip/nvmxip.h b/drivers/mtd/nvmxip/nvmxip.h
new file mode 100644
index 00000000000..f4ef37725d2
--- /dev/null
+++ b/drivers/mtd/nvmxip/nvmxip.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2023 Arm Limited and/or its affiliates <[email protected]>
+ *
+ * Authors:
+ * Abdellatif El Khlifi <[email protected]>
+ */
+
+#ifndef __DRIVER_NVMXIP_H__
+#define __DRIVER_NVMXIP_H__
+
+#include <blk.h>
+
+#define NVMXIP_BLKDRV_NAME "nvmxip-blk"
+#define NVMXIP_BLKDEV_NAME_SZ 20
+
+/**
+ * struct nvmxip_plat - the NVMXIP driver plat
+ *
+ * @phys_base: NVM XIP device base address
+ * @lba_shift: block size shift count
+ * @lba: number of blocks
+ *
+ * The NVMXIP information read from the DT.
+ */
+struct nvmxip_plat {
+ phys_addr_t phys_base;
+ u32 lba_shift;
+ lbaint_t lba;
+};
+
+#endif /* __DRIVER_NVMXIP_H__ */
diff --git a/drivers/mtd/nvmxip/nvmxip_qspi.c b/drivers/mtd/nvmxip/nvmxip_qspi.c
new file mode 100644
index 00000000000..7221fd1cb46
--- /dev/null
+++ b/drivers/mtd/nvmxip/nvmxip_qspi.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 Arm Limited and/or its affiliates <[email protected]>
+ *
+ * Authors:
+ * Abdellatif El Khlifi <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <linux/errno.h>
+#include "nvmxip.h"
+
+#include <asm/global_data.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NVMXIP_QSPI_DRV_NAME "nvmxip_qspi"
+
+/**
+ * nvmxip_qspi_of_to_plat() -read from DT
+ * @dev: the NVMXIP device
+ *
+ * Read from the DT the NVMXIP information.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int nvmxip_qspi_of_to_plat(struct udevice *dev)
+{
+ struct nvmxip_plat *plat = dev_get_plat(dev);
+ int ret;
+
+ plat->phys_base = (phys_addr_t)dev_read_addr(dev);
+ if (plat->phys_base == FDT_ADDR_T_NONE) {
+ log_err("[%s]: can not get base address from device tree\n", dev->name);
+ return -EINVAL;
+ }
+
+ ret = dev_read_u32(dev, "lba_shift", &plat->lba_shift);
+ if (ret) {
+ log_err("[%s]: can not get lba_shift from device tree\n", dev->name);
+ return -EINVAL;
+ }
+
+ ret = dev_read_u32(dev, "lba", (u32 *)&plat->lba);
+ if (ret) {
+ log_err("[%s]: can not get lba from device tree\n", dev->name);
+ return -EINVAL;
+ }
+
+ log_debug("[%s]: XIP device base addr: 0x%llx , lba_shift: %d , lbas: %lu\n",
+ dev->name, plat->phys_base, plat->lba_shift, plat->lba);
+
+ return 0;
+}
+
+static const struct udevice_id nvmxip_qspi_ids[] = {
+ { .compatible = "nvmxip,qspi" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(nvmxip_qspi) = {
+ .name = NVMXIP_QSPI_DRV_NAME,
+ .id = UCLASS_NVMXIP,
+ .of_match = nvmxip_qspi_ids,
+ .of_to_plat = nvmxip_qspi_of_to_plat,
+ .plat_auto = sizeof(struct nvmxip_plat),
+};
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 3c01e3b41c8..4fe547171a5 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -248,6 +248,7 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
break;
case SPINOR_OP_READ_FAST:
sbsf->pad_addr_bytes = 1;
+ fallthrough;
case SPINOR_OP_READ:
case SPINOR_OP_PP:
sbsf->state = SF_ADDR;
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 2c3116ee530..6093277f171 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -669,6 +669,7 @@ static int set_4byte(struct spi_nor *nor, const struct flash_info *info,
case SNOR_MFR_MICRON:
/* Some Micron need WREN command; all will accept it */
need_wren = true;
+ fallthrough;
case SNOR_MFR_ISSI:
case SNOR_MFR_MACRONIX:
case SNOR_MFR_WINBOND:
@@ -903,6 +904,30 @@ static int read_bar(struct spi_nor *nor, const struct flash_info *info)
}
#endif
+/**
+ * spi_nor_erase_chip() - Erase the entire flash memory.
+ * @nor: pointer to 'struct spi_nor'.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_erase_chip(struct spi_nor *nor)
+{
+ struct spi_mem_op op =
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
+ SPI_MEM_OP_NO_ADDR,
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_NO_DATA);
+ int ret;
+
+ spi_nor_setup_op(nor, &op, nor->write_proto);
+
+ ret = spi_mem_exec_op(nor->spi, &op);
+ if (ret)
+ return ret;
+
+ return nor->mtd.size;
+}
+
/*
* Initiate the erasure of a single sector. Returns the number of bytes erased
* on success, a negative error code on error.
@@ -974,7 +999,12 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
if (ret < 0)
goto erase_err;
- ret = spi_nor_erase_sector(nor, addr);
+ if (len == mtd->size &&
+ !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+ ret = spi_nor_erase_chip(nor);
+ } else {
+ ret = spi_nor_erase_sector(nor, addr);
+ }
if (ret < 0)
goto erase_err;
@@ -3199,6 +3229,87 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
/* Use ID byte 4 to distinguish S25FS256T and S25Hx-T */
#define S25FS256T_ID4 (0x08)
+/* Number of dummy cycle for Read Any Register (RDAR) op. */
+#define S25FS_S_RDAR_DUMMY 8
+
+static int s25fs_s_quad_enable(struct spi_nor *nor)
+{
+ return spansion_quad_enable_volatile(nor, 0, S25FS_S_RDAR_DUMMY);
+}
+
+static int s25fs_s_erase_non_uniform(struct spi_nor *nor, loff_t addr)
+{
+ /* Support 8 x 4KB sectors at bottom */
+ return spansion_erase_non_uniform(nor, addr, SPINOR_OP_BE_4K_4B, 0, SZ_32K);
+}
+
+static int s25fs_s_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params)
+{
+ int ret;
+ u8 cfr3v;
+
+ /* Bank Address Register is not supported */
+ if (CONFIG_IS_ENABLED(SPI_FLASH_BAR))
+ return -EOPNOTSUPP;
+
+ /*
+ * Read CR3V to check if uniform sector is selected. If not, assign an
+ * erase hook that supports non-uniform erase.
+ */
+ ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V,
+ S25FS_S_RDAR_DUMMY, &cfr3v);
+ if (ret)
+ return ret;
+ if (!(cfr3v & CFR3V_UNHYSA))
+ nor->erase = s25fs_s_erase_non_uniform;
+
+ return spi_nor_default_setup(nor, info, params);
+}
+
+static void s25fs_s_default_init(struct spi_nor *nor)
+{
+ nor->setup = s25fs_s_setup;
+}
+
+static int s25fs_s_post_bfpt_fixup(struct spi_nor *nor,
+ const struct sfdp_parameter_header *header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
+{
+ /* The erase size is set to 4K from BFPT, but it's wrong. Fix it. */
+ nor->erase_opcode = SPINOR_OP_SE;
+ nor->mtd.erasesize = nor->info->sector_size;
+
+ /* The S25FS-S chip family reports 512-byte pages in BFPT but
+ * in reality the write buffer still wraps at the safe default
+ * of 256 bytes. Overwrite the page size advertised by BFPT
+ * to get the writes working.
+ */
+ params->page_size = 256;
+
+ return 0;
+}
+
+static void s25fs_s_post_sfdp_fixup(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
+{
+ /* READ_1_1_2 is not supported */
+ params->hwcaps.mask &= ~SNOR_HWCAPS_READ_1_1_2;
+ /* READ_1_1_4 is not supported */
+ params->hwcaps.mask &= ~SNOR_HWCAPS_READ_1_1_4;
+ /* PP_1_1_4 is not supported */
+ params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4;
+ /* Use volatile register to enable quad */
+ params->quad_enable = s25fs_s_quad_enable;
+}
+
+static struct spi_nor_fixups s25fs_s_fixups = {
+ .default_init = s25fs_s_default_init,
+ .post_bfpt = s25fs_s_post_bfpt_fixup,
+ .post_sfdp = s25fs_s_post_sfdp_fixup,
+};
+
static int s25_mdp_ready(struct spi_nor *nor)
{
u32 addr;
@@ -3897,6 +4008,10 @@ void spi_nor_set_fixups(struct spi_nor *nor)
if (CONFIG_IS_ENABLED(SPI_FLASH_BAR) &&
!strcmp(nor->info->name, "s25fl256l"))
nor->fixups = &s25fl256l_fixups;
+
+ /* For FS-S (family ID = 0x81) */
+ if (JEDEC_MFR(nor->info) == SNOR_MFR_SPANSION && nor->info->id[5] == 0x81)
+ nor->fixups = &s25fs_s_fixups;
#endif
#ifdef CONFIG_SPI_FLASH_MT35XU
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ceadee98a1e..09039a283eb 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -752,9 +752,17 @@ config GMAC_ROCKCHIP
This driver provides Rockchip SoCs network support based on the
Synopsys Designware driver.
+config RENESAS_ETHER_SWITCH
+ bool "Renesas Ethernet Switch support"
+ depends on DM_ETH && R8A779F0
+ select PHYLIB
+ help
+ This driver implements support for the Renesas Ethernet Switch
+ which is available on R-Car S4 SoC (r8a779f0).
+
config RENESAS_RAVB
bool "Renesas Ethernet AVB MAC"
- depends on RCAR_GEN3
+ depends on RCAR_64
select PHYLIB
help
This driver implements support for the Ethernet AVB block in
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 75daa5e694c..46a40e2ed9f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_OCTEONTX_SMI) += octeontx/smi.o
obj-$(CONFIG_PCH_GBE) += pch_gbe.o
obj-$(CONFIG_PCNET) += pcnet.o
obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
+obj-$(CONFIG_RENESAS_ETHER_SWITCH) += rswitch.o
obj-$(CONFIG_RENESAS_RAVB) += ravb.o
obj-$(CONFIG_RTL8139) += rtl8139.o
obj-$(CONFIG_RTL8169) += rtl8169.o
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index ec58697b311..9bbba6eed07 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -794,9 +794,21 @@ static int eqos_start(struct udevice *dev)
*/
if (!eqos->phy) {
int addr = -1;
- addr = eqos_get_phy_addr(eqos, dev);
- eqos->phy = phy_connect(eqos->mii, addr, dev,
- eqos->config->interface(dev));
+ ofnode fixed_node;
+
+ if (IS_ENABLED(CONFIG_PHY_FIXED)) {
+ fixed_node = ofnode_find_subnode(dev_ofnode(dev),
+ "fixed-link");
+ if (ofnode_valid(fixed_node))
+ eqos->phy = fixed_phy_create(dev_ofnode(dev));
+ }
+
+ if (!eqos->phy) {
+ addr = eqos_get_phy_addr(eqos, dev);
+ eqos->phy = phy_connect(eqos->mii, addr, dev,
+ eqos->config->interface(dev));
+ }
+
if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 4f84403d956..78a40f285aa 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -29,6 +29,7 @@
#include <fsl-mc/fsl_dpsparser.h>
#include <fsl-mc/fsl_qbman_portal.h>
#include <fsl-mc/ldpaa_wriop.h>
+#include <net/ldpaa_eth.h>
#define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024)
#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1))
@@ -383,37 +384,31 @@ static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id,
static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
{
- int i, err = 0, ret = 0;
-#define ETH_NAME_LEN 20
struct udevice *eth_dev;
- char ethname[ETH_NAME_LEN];
+ int err = 0, ret = 0;
+ struct uclass *uc;
+ uint32_t dpmac_id;
- for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
- /* port not enabled */
- if (wriop_is_enabled_dpmac(i) != 1)
- continue;
-
- snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i,
- phy_interface_strings[wriop_get_enet_if(i)]);
-
- eth_dev = eth_get_dev_by_name(ethname);
- if (eth_dev == NULL)
+ uclass_get(UCLASS_ETH, &uc);
+ uclass_foreach_dev(eth_dev, uc) {
+ if (!eth_dev->driver || !eth_dev->driver->name ||
+ strcmp(eth_dev->driver->name, LDPAA_ETH_DRIVER_NAME))
continue;
+ dpmac_id = ldpaa_eth_get_dpmac_id(eth_dev);
switch (type) {
case MC_FIXUP_DPL:
- err = mc_fixup_dpl_mac_addr(blob, i, eth_dev);
+ err = mc_fixup_dpl_mac_addr(blob, dpmac_id, eth_dev);
break;
case MC_FIXUP_DPC:
- err = mc_fixup_dpc_mac_addr(blob, i, eth_dev);
+ err = mc_fixup_dpc_mac_addr(blob, dpmac_id, eth_dev);
break;
default:
break;
}
if (err)
- printf("fsl-mc: ERROR fixing mac address for %s\n",
- ethname);
+ printf("fsl-mc: ERROR fixing mac address for %s\n", eth_dev->name);
ret |= err;
}
diff --git a/drivers/net/ksz9477.c b/drivers/net/ksz9477.c
index fb5c76c600b..6b59b5fcd26 100644
--- a/drivers/net/ksz9477.c
+++ b/drivers/net/ksz9477.c
@@ -337,11 +337,21 @@ static int ksz_port_setup(struct udevice *dev, int port,
return 0;
}
+static int ksz_port_probe(struct udevice *dev, int port, struct phy_device *phy)
+{
+ int supported = PHY_GBIT_FEATURES;
+
+ /* configure phy */
+ phy->supported &= supported;
+ phy->advertising &= supported;
+
+ return phy_config(phy);
+}
+
static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy)
{
struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
struct ksz_dsa_priv *priv = dev_get_priv(dev);
- int supported = PHY_GBIT_FEATURES;
u8 data8;
int ret;
@@ -365,23 +375,12 @@ static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy
if (port == pdata->cpu_port)
return 0;
- /* configure phy */
- phy->supported &= supported;
- phy->advertising &= supported;
- ret = phy_config(phy);
- if (ret)
- return ret;
-
- ret = phy_startup(phy);
- if (ret)
- return ret;
-
/* start switch */
ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
data8 |= SW_START;
ksz_write8(priv->dev, REG_SW_OPERATION, data8);
- return 0;
+ return phy_startup(phy);
}
static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *phy)
@@ -410,6 +409,7 @@ static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *p
}
static const struct dsa_ops ksz_dsa_ops = {
+ .port_probe = ksz_port_probe,
.port_enable = ksz_port_enable,
.port_disable = ksz_port_disable,
};
@@ -443,15 +443,10 @@ static int ksz_i2c_probe(struct udevice *dev)
{
struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
struct ksz_dsa_priv *priv = dev_get_priv(dev);
- struct udevice *master = dsa_get_master(dev);
int i, ret;
u8 data8;
u32 id;
- if (!master)
- return -ENODEV;
-
- dev_dbg(dev, "%s %s master:%s\n", __func__, dev->name, master->name);
dev_set_parent_priv(dev, priv);
ret = i2c_set_chip_offset_len(dev, 2);
@@ -501,8 +496,6 @@ static int ksz_i2c_probe(struct udevice *dev)
ksz_pwrite8(priv->dev, i, REG_PORT_MSTP_STATE, data8);
}
- dsa_set_tagging(dev, 0, 0);
-
return 0;
};
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
index 24850777949..2cb6e9b7d70 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.c
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2014-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017, 2023 NXP
*/
#include <common.h>
@@ -21,6 +21,7 @@
#include <linux/compat.h>
#include <linux/delay.h>
#include <asm/global_data.h>
+#include <net/ldpaa_eth.h>
#include "ldpaa_eth.h"
#ifdef CONFIG_PHYLIB
@@ -995,7 +996,7 @@ static int ldpaa_eth_probe(struct udevice *dev)
return 0;
}
-static uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
+uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
{
int port_node = dev_of_offset(dev);
@@ -1049,7 +1050,7 @@ static const struct udevice_id ldpaa_eth_of_ids[] = {
};
U_BOOT_DRIVER(ldpaa_eth) = {
- .name = "ldpaa_eth",
+ .name = LDPAA_ETH_DRIVER_NAME,
.id = UCLASS_ETH,
.of_match = ldpaa_eth_of_ids,
.of_to_plat = ldpaa_eth_of_to_plat,
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 1bad50d344c..f407d8f6a81 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -2871,7 +2871,6 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port)
switch (port->phy_interface) {
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
val |= MVPP2_GMAC_INBAND_AN_MASK;
break;
case PHY_INTERFACE_MODE_1000BASEX:
@@ -2939,7 +2938,6 @@ static void mvpp2_port_loopback_set(struct mvpp2_port *port)
val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
if (port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_SGMII_2500 ||
port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
port->phy_interface == PHY_INTERFACE_MODE_2500BASEX)
val |= MVPP2_GMAC_PCS_LB_EN_MASK;
@@ -3027,48 +3025,6 @@ static int gop_bypass_clk_cfg(struct mvpp2_port *port, int en)
return 0;
}
-static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port)
-{
- u32 val, thresh;
-
- /*
- * Configure minimal level of the Tx FIFO before the lower part
- * starts to read a packet
- */
- thresh = MVPP2_SGMII2_5_TX_FIFO_MIN_TH;
- val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
- val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
- val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
- writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
-
- /* Disable bypass of sync module */
- val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
- val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
- /* configure DP clock select according to mode */
- val |= MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
- /* configure QSGMII bypass according to mode */
- val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
- writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
-
- val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
- /*
- * Configure GIG MAC to SGMII mode connected to a fiber
- * transceiver
- */
- val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
- writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
-
- /* configure AN 0x9268 */
- val = MVPP2_GMAC_EN_PCS_AN |
- MVPP2_GMAC_AN_BYPASS_EN |
- MVPP2_GMAC_CONFIG_MII_SPEED |
- MVPP2_GMAC_CONFIG_GMII_SPEED |
- MVPP2_GMAC_FC_ADV_EN |
- MVPP2_GMAC_CONFIG_FULL_DUPLEX |
- MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
-}
-
static void gop_gmac_sgmii_cfg(struct mvpp2_port *port)
{
u32 val, thresh;
@@ -3239,9 +3195,6 @@ static int gop_gmac_mode_cfg(struct mvpp2_port *port)
case PHY_INTERFACE_MODE_SGMII:
gop_gmac_sgmii_cfg(port);
break;
- case PHY_INTERFACE_MODE_SGMII_2500:
- gop_gmac_sgmii2_5_cfg(port);
- break;
case PHY_INTERFACE_MODE_1000BASEX:
gop_gmac_1000basex_cfg(port);
break;
@@ -3422,7 +3375,6 @@ static int gop_port_init(struct mvpp2_port *port)
break;
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
/* configure PCS */
@@ -3439,7 +3391,9 @@ static int gop_port_init(struct mvpp2_port *port)
gop_gmac_reset(port, 0);
break;
- case PHY_INTERFACE_MODE_SFI:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_XAUI:
num_of_act_lanes = 2;
mac_num = 0;
/* configure PCS */
@@ -3482,7 +3436,6 @@ static void gop_port_enable(struct mvpp2_port *port, int enable)
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
if (enable)
@@ -3491,7 +3444,9 @@ static void gop_port_enable(struct mvpp2_port *port, int enable)
mvpp2_port_disable(port);
break;
- case PHY_INTERFACE_MODE_SFI:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_XAUI:
gop_xlg_mac_port_enable(port, enable);
break;
@@ -3519,7 +3474,6 @@ static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
if (gop_id == 2) {
if (phy_type == PHY_INTERFACE_MODE_SGMII ||
- phy_type == PHY_INTERFACE_MODE_SGMII_2500 ||
phy_type == PHY_INTERFACE_MODE_1000BASEX ||
phy_type == PHY_INTERFACE_MODE_2500BASEX)
val |= MV_NETC_GE_MAC2_SGMII;
@@ -3530,7 +3484,6 @@ static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
if (gop_id == 3) {
if (phy_type == PHY_INTERFACE_MODE_SGMII ||
- phy_type == PHY_INTERFACE_MODE_SGMII_2500 ||
phy_type == PHY_INTERFACE_MODE_1000BASEX ||
phy_type == PHY_INTERFACE_MODE_2500BASEX)
val |= MV_NETC_GE_MAC3_SGMII;
@@ -4529,7 +4482,6 @@ static void mvpp2_start_dev(struct mvpp2_port *port)
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
mvpp2_gmac_max_rx_size_set(port);
@@ -5263,7 +5215,6 @@ static int mvpp2_start(struct udevice *dev)
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
mvpp2_port_power_up(port);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6806e3c0903..24158776f52 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -174,6 +174,11 @@ config PHY_LXT
config PHY_MARVELL
bool "Marvell Ethernet PHYs support"
+config PHY_MARVELL_10G
+ bool "Marvell Alaska 10Gbit PHYs"
+ help
+ Support for the Marvell Alaska MV88X3310 and compatible PHYs.
+
config PHY_MESON_GXL
bool "Amlogic Meson GXL Internal PHY support"
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index d38e99e7171..85d17f109cd 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PHY_DAVICOM) += davicom.o
obj-$(CONFIG_PHY_ET1011C) += et1011c.o
obj-$(CONFIG_PHY_LXT) += lxt.o
obj-$(CONFIG_PHY_MARVELL) += marvell.o
+obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o
obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
@@ -29,7 +30,7 @@ obj-$(CONFIG_PHY_NXP_TJA11XX) += nxp-tja11xx.o
obj-$(CONFIG_PHY_REALTEK) += realtek.o
obj-$(CONFIG_PHY_SMSC) += smsc.o
obj-$(CONFIG_PHY_TERANETICS) += teranetics.o
-obj-$(CONFIG_PHY_TI) += ti_phy_init.o
+obj-$(CONFIG_PHY_TI_GENERIC) += ti_phy_init.o
obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o
obj-$(CONFIG_PHY_TI_DP83869) += dp83869.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index a5bfd960d9c..fb9f1e4c70d 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -252,7 +252,7 @@ static int adin1300_config(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver ADIN1300_driver = {
+U_BOOT_PHY_DRIVER(ADIN1300) = {
.name = "ADIN1300",
.uid = PHY_ID_ADIN1300,
.mask = 0xffffffff,
@@ -261,10 +261,3 @@ static struct phy_driver ADIN1300_driver = {
.startup = genphy_startup,
.shutdown = genphy_shutdown,
};
-
-int phy_adin_init(void)
-{
- phy_register(&ADIN1300_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 8eb6024829d..a958e88d44f 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -598,7 +598,7 @@ int aquantia_startup(struct phy_device *phydev)
return 0;
}
-struct phy_driver aq1202_driver = {
+U_BOOT_PHY_DRIVER(aq1202) = {
.name = "Aquantia AQ1202",
.uid = 0x3a1b445,
.mask = 0xfffffff0,
@@ -611,7 +611,7 @@ struct phy_driver aq1202_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver aq2104_driver = {
+U_BOOT_PHY_DRIVER(aq2104) = {
.name = "Aquantia AQ2104",
.uid = 0x3a1b460,
.mask = 0xfffffff0,
@@ -624,7 +624,7 @@ struct phy_driver aq2104_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver aqr105_driver = {
+U_BOOT_PHY_DRIVER(aqr105) = {
.name = "Aquantia AQR105",
.uid = 0x3a1b4a2,
.mask = 0xfffffff0,
@@ -638,7 +638,7 @@ struct phy_driver aqr105_driver = {
.data = AQUANTIA_GEN1,
};
-struct phy_driver aqr106_driver = {
+U_BOOT_PHY_DRIVER(aqr106) = {
.name = "Aquantia AQR106",
.uid = 0x3a1b4d0,
.mask = 0xfffffff0,
@@ -651,7 +651,7 @@ struct phy_driver aqr106_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver aqr107_driver = {
+U_BOOT_PHY_DRIVER(aqr107) = {
.name = "Aquantia AQR107",
.uid = 0x3a1b4e0,
.mask = 0xfffffff0,
@@ -665,7 +665,7 @@ struct phy_driver aqr107_driver = {
.data = AQUANTIA_GEN2,
};
-struct phy_driver aqr112_driver = {
+U_BOOT_PHY_DRIVER(aqr112) = {
.name = "Aquantia AQR112",
.uid = 0x3a1b660,
.mask = 0xfffffff0,
@@ -679,7 +679,7 @@ struct phy_driver aqr112_driver = {
.data = AQUANTIA_GEN3,
};
-struct phy_driver aqr113c_driver = {
+U_BOOT_PHY_DRIVER(aqr113c) = {
.name = "Aquantia AQR113C",
.uid = 0x31c31c12,
.mask = 0xfffffff0,
@@ -693,7 +693,7 @@ struct phy_driver aqr113c_driver = {
.data = AQUANTIA_GEN3,
};
-struct phy_driver aqr405_driver = {
+U_BOOT_PHY_DRIVER(aqr405) = {
.name = "Aquantia AQR405",
.uid = 0x3a1b4b2,
.mask = 0xfffffff0,
@@ -707,7 +707,7 @@ struct phy_driver aqr405_driver = {
.data = AQUANTIA_GEN1,
};
-struct phy_driver aqr412_driver = {
+U_BOOT_PHY_DRIVER(aqr412) = {
.name = "Aquantia AQR412",
.uid = 0x3a1b710,
.mask = 0xfffffff0,
@@ -720,18 +720,3 @@ struct phy_driver aqr412_driver = {
.shutdown = &gen10g_shutdown,
.data = AQUANTIA_GEN3,
};
-
-int phy_aquantia_init(void)
-{
- phy_register(&aq1202_driver);
- phy_register(&aq2104_driver);
- phy_register(&aqr105_driver);
- phy_register(&aqr106_driver);
- phy_register(&aqr107_driver);
- phy_register(&aqr112_driver);
- phy_register(&aqr113c_driver);
- phy_register(&aqr405_driver);
- phy_register(&aqr412_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index c6f9f916459..abb7bdf537c 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -333,7 +333,7 @@ static int ar803x_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver AR8021_driver = {
+U_BOOT_PHY_DRIVER(AR8021) = {
.name = "AR8021",
.uid = AR8021_PHY_ID,
.mask = 0xfffffff0,
@@ -343,7 +343,7 @@ static struct phy_driver AR8021_driver = {
.shutdown = genphy_shutdown,
};
-static struct phy_driver AR8031_driver = {
+U_BOOT_PHY_DRIVER(AR8031) = {
.name = "AR8031/AR8033",
.uid = AR8031_PHY_ID,
.mask = 0xffffffef,
@@ -353,7 +353,7 @@ static struct phy_driver AR8031_driver = {
.shutdown = genphy_shutdown,
};
-static struct phy_driver AR8035_driver = {
+U_BOOT_PHY_DRIVER(AR8035) = {
.name = "AR8035",
.uid = AR8035_PHY_ID,
.mask = 0xffffffef,
@@ -362,12 +362,3 @@ static struct phy_driver AR8035_driver = {
.startup = genphy_startup,
.shutdown = genphy_shutdown,
};
-
-int phy_atheros_init(void)
-{
- phy_register(&AR8021_driver);
- phy_register(&AR8031_driver);
- phy_register(&AR8035_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/b53.c b/drivers/net/phy/b53.c
index c706e2b9bde..26e8e2fe64f 100644
--- a/drivers/net/phy/b53.c
+++ b/drivers/net/phy/b53.c
@@ -612,7 +612,7 @@ static int b53_phy_startup(struct phy_device *phydev)
return 0;
}
-static struct phy_driver b53_driver = {
+U_BOOT_PHY_DRIVER(b53) = {
.name = "Broadcom BCM53125",
.uid = 0x03625c00,
.mask = 0xfffffc00,
@@ -623,13 +623,6 @@ static struct phy_driver b53_driver = {
.shutdown = &genphy_shutdown,
};
-int phy_b53_init(void)
-{
- phy_register(&b53_driver);
-
- return 0;
-}
-
int do_b53_reg_read(const char *name, int argc, char *const argv[])
{
u8 page, offset, width;
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 566fcb8de73..36c70da181a 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -162,18 +162,6 @@ static int bcm5482_config(struct phy_device *phydev)
return 0;
}
-static int bcm_cygnus_startup(struct phy_device *phydev)
-{
- int ret;
-
- /* Read the Status (2x to make sure link is right) */
- ret = genphy_update_link(phydev);
- if (ret)
- return ret;
-
- return genphy_parse_link(phydev);
-}
-
static void bcm_cygnus_afe(struct phy_device *phydev)
{
/* ensures smdspclk is enabled */
@@ -323,7 +311,7 @@ static int bcm5482_startup(struct phy_device *phydev)
return bcm54xx_parse_status(phydev);
}
-static struct phy_driver BCM5461S_driver = {
+U_BOOT_PHY_DRIVER(bcm5461s) = {
.name = "Broadcom BCM5461S",
.uid = 0x2060c0,
.mask = 0xfffff0,
@@ -333,7 +321,7 @@ static struct phy_driver BCM5461S_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver BCM5464S_driver = {
+U_BOOT_PHY_DRIVER(bcm5464s) = {
.name = "Broadcom BCM5464S",
.uid = 0x2060b0,
.mask = 0xfffff0,
@@ -343,7 +331,7 @@ static struct phy_driver BCM5464S_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver BCM5482S_driver = {
+U_BOOT_PHY_DRIVER(bcm5482s) = {
.name = "Broadcom BCM5482S",
.uid = 0x143bcb0,
.mask = 0xffffff0,
@@ -353,22 +341,12 @@ static struct phy_driver BCM5482S_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver BCM_CYGNUS_driver = {
+U_BOOT_PHY_DRIVER(bcm_cygnus) = {
.name = "Broadcom CYGNUS GPHY",
.uid = 0xae025200,
.mask = 0xfffff0,
.features = PHY_GBIT_FEATURES,
.config = &bcm_cygnus_config,
- .startup = &bcm_cygnus_startup,
+ .startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_broadcom_init(void)
-{
- phy_register(&BCM5482S_driver);
- phy_register(&BCM5464S_driver);
- phy_register(&BCM5461S_driver);
- phy_register(&BCM_CYGNUS_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/ca_phy.c b/drivers/net/phy/ca_phy.c
index 16851a6820f..edef21867b0 100644
--- a/drivers/net/phy/ca_phy.c
+++ b/drivers/net/phy/ca_phy.c
@@ -104,7 +104,7 @@ static int rtl8211_probe(struct phy_device *phydev)
}
/* Support for RTL8211 External PHY */
-struct phy_driver rtl8211_external_driver = {
+U_BOOT_PHY_DRIVER(rtl8211_external) = {
.name = "Cortina RTL8211 External",
.uid = PHY_ID_RTL8211_EXT,
.mask = PHY_ID_MASK,
@@ -115,7 +115,7 @@ struct phy_driver rtl8211_external_driver = {
};
/* Support for RTL8211 Internal PHY */
-struct phy_driver rtl8211_internal_driver = {
+U_BOOT_PHY_DRIVER(rtl8211_internal) = {
.name = "Cortina RTL8211 Inrernal",
.uid = PHY_ID_RTL8211_INT,
.mask = PHY_ID_MASK,
@@ -124,10 +124,3 @@ struct phy_driver rtl8211_internal_driver = {
.probe = &rtl8211_probe,
.startup = &genphy_startup,
};
-
-int phy_cortina_access_init(void)
-{
- phy_register(&rtl8211_external_driver);
- phy_register(&rtl8211_internal_driver);
- return 0;
-}
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index 778d93e609c..1cf8b28f582 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -382,7 +382,7 @@ int cs4223_startup(struct phy_device *phydev)
return 0;
}
-struct phy_driver cs4340_driver = {
+U_BOOT_PHY_DRIVER(cs4340) = {
.name = "Cortina CS4315/CS4340",
.uid = PHY_UID_CS4340,
.mask = 0xfffffff0,
@@ -396,7 +396,7 @@ struct phy_driver cs4340_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver cs4223_driver = {
+U_BOOT_PHY_DRIVER(cs4223) = {
.name = "Cortina CS4223",
.uid = PHY_UID_CS4223,
.mask = 0x0ffff00f,
@@ -409,13 +409,6 @@ struct phy_driver cs4223_driver = {
.shutdown = &gen10g_shutdown,
};
-int phy_cortina_init(void)
-{
- phy_register(&cs4340_driver);
- phy_register(&cs4223_driver);
- return 0;
-}
-
int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
{
int phy_reg;
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 4666497d44f..31ffa1ac7a9 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -69,7 +69,7 @@ static int dm9161_startup(struct phy_device *phydev)
return dm9161_parse_status(phydev);
}
-static struct phy_driver DM9161_driver = {
+U_BOOT_PHY_DRIVER(dm9161) = {
.name = "Davicom DM9161E",
.uid = 0x181b880,
.mask = 0xffffff0,
@@ -78,10 +78,3 @@ static struct phy_driver DM9161_driver = {
.startup = &dm9161_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_davicom_init(void)
-{
- phy_register(&DM9161_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index a45152bddc9..7111e36aa0d 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -330,7 +330,7 @@ static int dp83867_config(struct phy_device *phydev)
DP83867_RGMIIDCTL, delay);
}
- if (phy_interface_is_sgmii(phydev)) {
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
if (dp83867->sgmii_ref_clk_en)
phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL,
DP83867_SGMII_TYPE);
@@ -409,7 +409,7 @@ static int dp83867_probe(struct phy_device *phydev)
return 0;
}
-static struct phy_driver DP83867_driver = {
+U_BOOT_PHY_DRIVER(dp83867) = {
.name = "TI DP83867",
.uid = 0x2000a231,
.mask = 0xfffffff0,
@@ -419,9 +419,3 @@ static struct phy_driver DP83867_driver = {
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_dp83867_init(void)
-{
- phy_register(&DP83867_driver);
- return 0;
-}
diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
index 23dbf42b68c..8d32d73b07f 100644
--- a/drivers/net/phy/dp83869.c
+++ b/drivers/net/phy/dp83869.c
@@ -473,7 +473,7 @@ static int dp83869_probe(struct phy_device *phydev)
return 0;
}
-static struct phy_driver DP83869_driver = {
+U_BOOT_PHY_DRIVER(dp83869) = {
.name = "TI DP83869",
.uid = 0x2000a0f1,
.mask = 0xfffffff0,
@@ -485,9 +485,3 @@ static struct phy_driver DP83869_driver = {
.readext = dp83869_readext,
.writeext = dp83869_writeext
};
-
-int phy_dp83869_init(void)
-{
- phy_register(&DP83869_driver);
- return 0;
-}
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index 7eff5ec7cac..fa4831427d5 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -87,7 +87,7 @@ static int et1011c_startup(struct phy_device *phydev)
return et1011c_parse_status(phydev);
}
-static struct phy_driver et1011c_driver = {
+U_BOOT_PHY_DRIVER(et1011c) = {
.name = "ET1011C",
.uid = 0x0282f014,
.mask = 0xfffffff0,
@@ -95,10 +95,3 @@ static struct phy_driver et1011c_driver = {
.config = &et1011c_config,
.startup = &et1011c_startup,
};
-
-int phy_et1011c_init(void)
-{
- phy_register(&et1011c_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c
index 8864f99bb32..a715e83db98 100644
--- a/drivers/net/phy/ethernet_id.c
+++ b/drivers/net/phy/ethernet_id.c
@@ -39,7 +39,7 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
if (!IS_ENABLED(CONFIG_DM_ETH_PHY)) {
ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
- GPIOD_ACTIVE_LOW);
+ GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
if (!ret) {
assert = ofnode_read_u32_default(node,
"reset-assert-us", 0);
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 1192915ee52..2f0823b8365 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -93,7 +93,7 @@ static int fixedphy_shutdown(struct phy_device *phydev)
return 0;
}
-static struct phy_driver fixedphy_driver = {
+U_BOOT_PHY_DRIVER(fixedphy) = {
.uid = PHY_FIXED_ID,
.mask = 0xffffffff,
.name = "Fixed PHY",
@@ -103,9 +103,3 @@ static struct phy_driver fixedphy_driver = {
.startup = fixedphy_startup,
.shutdown = fixedphy_shutdown,
};
-
-int phy_fixed_init(void)
-{
- phy_register(&fixedphy_driver);
- return 0;
-}
diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c
index b4384e1f781..34ac51ea070 100644
--- a/drivers/net/phy/generic_10g.c
+++ b/drivers/net/phy/generic_10g.c
@@ -80,7 +80,7 @@ int gen10g_config(struct phy_device *phydev)
return gen10g_discover_mmds(phydev);
}
-struct phy_driver gen10g_driver = {
+U_BOOT_PHY_DRIVER(gen10g) = {
.uid = 0xffffffff,
.mask = 0xffffffff,
.name = "Generic 10G PHY",
diff --git a/drivers/net/phy/intel_xway.c b/drivers/net/phy/intel_xway.c
index dfce3f8332e..9d1b97d349f 100644
--- a/drivers/net/phy/intel_xway.c
+++ b/drivers/net/phy/intel_xway.c
@@ -30,7 +30,7 @@ static int xway_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver XWAY_driver = {
+U_BOOT_PHY_DRIVER(xway) = {
.name = "XWAY",
.uid = 0xD565A400,
.mask = 0xffffff00,
@@ -39,10 +39,3 @@ static struct phy_driver XWAY_driver = {
.startup = genphy_startup,
.shutdown = genphy_shutdown,
};
-
-int phy_xway_init(void)
-{
- phy_register(&XWAY_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 2618deb0096..20940033a38 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -58,7 +58,7 @@ static int lxt971_startup(struct phy_device *phydev)
return lxt971_parse_status(phydev);
}
-static struct phy_driver LXT971_driver = {
+U_BOOT_PHY_DRIVER(lxt971) = {
.name = "LXT971",
.uid = 0x1378e0,
.mask = 0xfffff0,
@@ -67,10 +67,3 @@ static struct phy_driver LXT971_driver = {
.startup = &lxt971_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_lxt_init(void)
-{
- phy_register(&LXT971_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 1a25775eee6..0a90f710dfe 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
#include <errno.h>
+#include <marvell_phy.h>
#include <phy.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -693,90 +694,90 @@ static int m88e1680_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver M88E1011S_driver = {
+U_BOOT_PHY_DRIVER(m88e1011s) = {
.name = "Marvell 88E1011S",
- .uid = 0x1410c60,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1101,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1011s_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1111S_driver = {
+U_BOOT_PHY_DRIVER(m88e1111s) = {
.name = "Marvell 88E1111S",
- .uid = 0x1410cc0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1111,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1111s_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1118_driver = {
+U_BOOT_PHY_DRIVER(m88e1118) = {
.name = "Marvell 88E1118",
- .uid = 0x1410e10,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1118,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1118_config,
.startup = &m88e1118_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1118R_driver = {
+U_BOOT_PHY_DRIVER(m88e1118r) = {
.name = "Marvell 88E1118R",
- .uid = 0x1410e40,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1116R,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1118_config,
.startup = &m88e1118_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1121R_driver = {
+U_BOOT_PHY_DRIVER(m88e1121r) = {
.name = "Marvell 88E1121R",
- .uid = 0x1410cb0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1121R,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1121_config,
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1145_driver = {
+U_BOOT_PHY_DRIVER(m88e1145) = {
.name = "Marvell 88E1145",
- .uid = 0x1410cd0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1145,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1145_config,
.startup = &m88e1145_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1149S_driver = {
+U_BOOT_PHY_DRIVER(m88e1149s) = {
.name = "Marvell 88E1149S",
- .uid = 0x1410ca0,
- .mask = 0xffffff0,
+ .uid = 0x01410ca0,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1149_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1240_driver = {
+U_BOOT_PHY_DRIVER(m88e1240) = {
.name = "Marvell 88E1240",
- .uid = 0x1410e30,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1240,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1240_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E151x_driver = {
+U_BOOT_PHY_DRIVER(m88e151x) = {
.name = "Marvell 88E151x",
- .uid = 0x1410dd0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1510,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e151x_config,
.startup = &m88e1011s_startup,
@@ -785,39 +786,22 @@ static struct phy_driver M88E151x_driver = {
.writeext = &m88e1xxx_phy_extwrite,
};
-static struct phy_driver M88E1310_driver = {
+U_BOOT_PHY_DRIVER(m88e1310) = {
.name = "Marvell 88E1310",
- .uid = 0x01410e90,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1318S,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1310_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
-static struct phy_driver M88E1680_driver = {
+U_BOOT_PHY_DRIVER(m88e1680) = {
.name = "Marvell 88E1680",
- .uid = 0x1410ed0,
- .mask = 0xffffff0,
+ .uid = 0x01410ed0,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1680_config,
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_marvell_init(void)
-{
- phy_register(&M88E1310_driver);
- phy_register(&M88E1149S_driver);
- phy_register(&M88E1145_driver);
- phy_register(&M88E1121R_driver);
- phy_register(&M88E1118_driver);
- phy_register(&M88E1118R_driver);
- phy_register(&M88E1111S_driver);
- phy_register(&M88E1011S_driver);
- phy_register(&M88E1240_driver);
- phy_register(&M88E151x_driver);
- phy_register(&M88E1680_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
new file mode 100644
index 00000000000..9e64672f5ca
--- /dev/null
+++ b/drivers/net/phy/marvell10g.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Marvell 10G 88x3310 PHY driver
+ *
+ * Based upon the ID registers, this PHY appears to be a mixture of IPs
+ * from two different companies.
+ *
+ * There appears to be several different data paths through the PHY which
+ * are automatically managed by the PHY. The following has been determined
+ * via observation and experimentation for a setup using single-lane Serdes:
+ *
+ * SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
+ * 10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
+ * 10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
+ *
+ * With XAUI, observation shows:
+ *
+ * XAUI PHYXS -- <appropriate PCS as above>
+ *
+ * and no switching of the host interface mode occurs.
+ *
+ * If both the fiber and copper ports are connected, the first to gain
+ * link takes priority and the other port is completely locked out.
+ */
+#include <common.h>
+#include <console.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <errno.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <marvell_phy.h>
+#include <phy.h>
+
+#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
+#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
+
+#define MV_VERSION(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+enum {
+ MV_PMA_FW_VER0 = 0xc011,
+ MV_PMA_FW_VER1 = 0xc012,
+ MV_PMA_21X0_PORT_CTRL = 0xc04a,
+ MV_PMA_21X0_PORT_CTRL_SWRST = BIT(15),
+ MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK = 0x7,
+ MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII = 0x0,
+ MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII = 0x1,
+ MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII = 0x2,
+ MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER = 0x4,
+ MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN = 0x5,
+ MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
+ MV_PMA_BOOT = 0xc050,
+ MV_PMA_BOOT_FATAL = BIT(0),
+
+ MV_PCS_BASE_T = 0x0000,
+ MV_PCS_BASE_R = 0x1000,
+ MV_PCS_1000BASEX = 0x2000,
+
+ MV_PCS_CSCR1 = 0x8000,
+ MV_PCS_CSCR1_ED_MASK = 0x0300,
+ MV_PCS_CSCR1_ED_OFF = 0x0000,
+ MV_PCS_CSCR1_ED_RX = 0x0200,
+ MV_PCS_CSCR1_ED_NLP = 0x0300,
+ MV_PCS_CSCR1_MDIX_MASK = 0x0060,
+ MV_PCS_CSCR1_MDIX_MDI = 0x0000,
+ MV_PCS_CSCR1_MDIX_MDIX = 0x0020,
+ MV_PCS_CSCR1_MDIX_AUTO = 0x0060,
+
+ MV_PCS_DSC1 = 0x8003,
+ MV_PCS_DSC1_ENABLE = BIT(9),
+ MV_PCS_DSC1_10GBT = 0x01c0,
+ MV_PCS_DSC1_1GBR = 0x0038,
+ MV_PCS_DSC1_100BTX = 0x0007,
+ MV_PCS_DSC2 = 0x8004,
+ MV_PCS_DSC2_2P5G = 0xf000,
+ MV_PCS_DSC2_5G = 0x0f00,
+
+ MV_PCS_CSSR1 = 0x8008,
+ MV_PCS_CSSR1_SPD1_MASK = 0xc000,
+ MV_PCS_CSSR1_SPD1_SPD2 = 0xc000,
+ MV_PCS_CSSR1_SPD1_1000 = 0x8000,
+ MV_PCS_CSSR1_SPD1_100 = 0x4000,
+ MV_PCS_CSSR1_SPD1_10 = 0x0000,
+ MV_PCS_CSSR1_DUPLEX_FULL = BIT(13),
+ MV_PCS_CSSR1_RESOLVED = BIT(11),
+ MV_PCS_CSSR1_MDIX = BIT(6),
+ MV_PCS_CSSR1_SPD2_MASK = 0x000c,
+ MV_PCS_CSSR1_SPD2_5000 = 0x0008,
+ MV_PCS_CSSR1_SPD2_2500 = 0x0004,
+ MV_PCS_CSSR1_SPD2_10000 = 0x0000,
+
+ /* Temperature read register (88E2110 only) */
+ MV_PCS_TEMP = 0x8042,
+
+ /* Number of ports on the device */
+ MV_PCS_PORT_INFO = 0xd00d,
+ MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380,
+ MV_PCS_PORT_INFO_NPORTS_SHIFT = 7,
+
+ /* SerDes reinitialization 88E21X0 */
+ MV_AN_21X0_SERDES_CTRL2 = 0x800f,
+ MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13),
+ MV_AN_21X0_SERDES_CTRL2_RUN_INIT = BIT(15),
+
+ /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
+ * registers appear to set themselves to the 0x800X when AN is
+ * restarted, but status registers appear readable from either.
+ */
+ MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */
+ MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
+
+ /* Vendor2 MMD registers */
+ MV_V2_PORT_CTRL = 0xf001,
+ MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
+ MV_V2_33X0_PORT_CTRL_SWRST = BIT(15),
+ MV_V2_33X0_PORT_CTRL_MACTYPE_MASK = 0x7,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI = 0x0,
+ MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH = 0x1,
+ MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN = 0x1,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH = 0x2,
+ MV_V2_3310_PORT_CTRL_MACTYPE_XAUI = 0x3,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER = 0x4,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7,
+ MV_V2_PORT_INTR_STS = 0xf040,
+ MV_V2_PORT_INTR_MASK = 0xf043,
+ MV_V2_PORT_INTR_STS_WOL_EN = BIT(8),
+ MV_V2_MAGIC_PKT_WORD0 = 0xf06b,
+ MV_V2_MAGIC_PKT_WORD1 = 0xf06c,
+ MV_V2_MAGIC_PKT_WORD2 = 0xf06d,
+ /* Wake on LAN registers */
+ MV_V2_WOL_CTRL = 0xf06e,
+ MV_V2_WOL_CTRL_CLEAR_STS = BIT(15),
+ MV_V2_WOL_CTRL_MAGIC_PKT_EN = BIT(0),
+ /* Temperature control/read registers (88X3310 only) */
+ MV_V2_TEMP_CTRL = 0xf08a,
+ MV_V2_TEMP_CTRL_MASK = 0xc000,
+ MV_V2_TEMP_CTRL_SAMPLE = 0x0000,
+ MV_V2_TEMP_CTRL_DISABLE = 0xc000,
+ MV_V2_TEMP = 0xf08c,
+ MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */
+};
+
+struct mv3310_chip {
+ bool (*has_downshift)(struct phy_device *phydev);
+ int (*test_supported_interfaces)(struct phy_device *phydev);
+ int (*get_mactype)(struct phy_device *phydev);
+ int (*set_mactype)(struct phy_device *phydev, int mactype);
+ int (*select_mactype)(struct phy_device *phydev);
+ int (*init_interface)(struct phy_device *phydev, int mactype);
+};
+
+struct mv3310_priv {
+ DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
+
+ u32 firmware_ver;
+ bool has_downshift;
+ bool rate_match;
+};
+
+static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
+{
+ return (const struct mv3310_chip *)phydev->drv->data;
+}
+
+static int mv3310_power_down(struct phy_device *phydev)
+{
+ return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+ MV_V2_PORT_CTRL_PWRDOWN);
+}
+
+static int mv3310_power_up(struct phy_device *phydev)
+{
+ struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+ int ret;
+
+ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+ MV_V2_PORT_CTRL_PWRDOWN);
+
+ if (phydev->drv->uid != MARVELL_PHY_ID_88X3310 ||
+ priv->firmware_ver < 0x00030000)
+ return ret;
+
+ return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+ MV_V2_33X0_PORT_CTRL_SWRST);
+}
+
+static int mv3310_reset(struct phy_device *phydev, u32 unit)
+{
+ int val, err;
+
+ err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
+ MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
+ if (err < 0)
+ return err;
+
+ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
+ unit + MDIO_CTRL1, val,
+ !(val & MDIO_CTRL1_RESET),
+ 5000, 100000, true);
+}
+
+static int mv3310_set_downshift(struct phy_device *phydev)
+{
+ struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+ const u8 ds = 1;
+ u16 val;
+ int err;
+
+ if (!priv->has_downshift)
+ return -EOPNOTSUPP;
+
+ val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);
+ val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);
+ err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,
+ MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);
+ if (err < 0)
+ return err;
+
+ val = MV_PCS_DSC1_ENABLE;
+ val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);
+ val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);
+ val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);
+
+ return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
+ MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |
+ MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);
+}
+
+static int mv3310_set_edpd(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
+ MV_PCS_CSCR1_ED_MASK,
+ MV_PCS_CSCR1_ED_NLP);
+ if (err > 0)
+ err = mv3310_reset(phydev, MV_PCS_BASE_T);
+
+ return err;
+}
+
+static int mv3310_probe(struct phy_device *phydev)
+{
+ const struct mv3310_chip *chip = to_mv3310_chip(phydev);
+ struct mv3310_priv *priv;
+ u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+ int ret;
+
+ if (!phydev->is_c45 ||
+ (phydev->mmds & mmd_mask) != mmd_mask)
+ return -ENODEV;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
+ if (ret < 0)
+ return ret;
+
+ if (ret & MV_PMA_BOOT_FATAL) {
+ dev_warn(phydev->dev,
+ "PHY failed to boot firmware, status=%04x\n", ret);
+ return -ENODEV;
+ }
+
+ priv = devm_kzalloc(phydev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ phydev->priv = priv;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
+ if (ret < 0)
+ return ret;
+
+ priv->firmware_ver = ret << 16;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
+ if (ret < 0)
+ return ret;
+
+ priv->firmware_ver |= ret;
+
+ dev_info(phydev->dev, "Firmware version %u.%u.%u.%u\n",
+ priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
+ (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
+
+ if (chip->has_downshift)
+ priv->has_downshift = chip->has_downshift(phydev);
+
+ /* Powering down the port when not in use saves about 600mW */
+ ret = mv3310_power_down(phydev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mv2110_get_mactype(struct phy_device *phydev)
+{
+ int mactype;
+
+ mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
+ if (mactype < 0)
+ return mactype;
+
+ return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
+}
+
+static int mv2110_set_mactype(struct phy_device *phydev, int mactype)
+{
+ int err, val;
+
+ mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
+ err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL,
+ MV_PMA_21X0_PORT_CTRL_SWRST |
+ MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK,
+ MV_PMA_21X0_PORT_CTRL_SWRST | mactype);
+ if (err)
+ return err;
+
+ err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
+ MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS |
+ MV_AN_21X0_SERDES_CTRL2_RUN_INIT);
+ if (err)
+ return err;
+
+ err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN,
+ MV_AN_21X0_SERDES_CTRL2, val,
+ !(val &
+ MV_AN_21X0_SERDES_CTRL2_RUN_INIT),
+ 5000, 100000, true);
+ if (err)
+ return err;
+
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
+ MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS);
+}
+
+static int mv2110_select_mactype(struct phy_device *phydev)
+{
+ if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
+ return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII;
+ else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+ !(phydev->interface == PHY_INTERFACE_MODE_10GBASER))
+ return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER;
+ else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+ return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
+ else
+ return -1;
+}
+
+static int mv3310_get_mactype(struct phy_device *phydev)
+{
+ int mactype;
+
+ mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
+ if (mactype < 0)
+ return mactype;
+
+ return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
+}
+
+static int mv3310_set_mactype(struct phy_device *phydev, int mactype)
+{
+ int ret;
+
+ mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+ MV_V2_33X0_PORT_CTRL_MACTYPE_MASK,
+ mactype);
+ if (ret <= 0)
+ return ret;
+
+ return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+ MV_V2_33X0_PORT_CTRL_SWRST);
+}
+
+static int mv3310_select_mactype(struct phy_device *phydev)
+{
+ if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
+ return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII;
+ else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+ return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
+ else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface == PHY_INTERFACE_MODE_RXAUI)
+ return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI;
+ else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface == PHY_INTERFACE_MODE_XAUI)
+ return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI;
+ else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+ return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
+ else if (phydev->interface == PHY_INTERFACE_MODE_RXAUI)
+ return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH;
+ else if (phydev->interface == PHY_INTERFACE_MODE_XAUI)
+ return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH;
+ else if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
+ return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
+ else
+ return -1;
+}
+
+static int mv2110_init_interface(struct phy_device *phydev, int mactype)
+{
+ struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+ priv->rate_match = false;
+
+ if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
+ priv->rate_match = true;
+
+ return 0;
+}
+
+static int mv3310_init_interface(struct phy_device *phydev, int mactype)
+{
+ struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+ priv->rate_match = false;
+
+ if (mactype != MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
+ return 0;
+
+ if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
+ mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
+ mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
+ priv->rate_match = true;
+
+ return 0;
+}
+
+static int mv3310_config_init(struct phy_device *phydev)
+{
+ const struct mv3310_chip *chip = to_mv3310_chip(phydev);
+ int err, mactype;
+
+ /* Check that the PHY interface type is compatible */
+ err = chip->test_supported_interfaces(phydev);
+ if (err)
+ return err;
+
+ /* Power up so reset works */
+ err = mv3310_power_up(phydev);
+ if (err)
+ return err;
+
+ /* If host provided host supported interface modes, try to select the
+ * best one
+ */
+ mactype = chip->select_mactype(phydev);
+ if (mactype >= 0) {
+ dev_info(phydev->dev, "Changing MACTYPE to %i\n",
+ mactype);
+ err = chip->set_mactype(phydev, mactype);
+ if (err)
+ return err;
+ }
+
+ mactype = chip->get_mactype(phydev);
+ if (mactype < 0)
+ return mactype;
+
+ err = chip->init_interface(phydev, mactype);
+ if (err) {
+ dev_err(phydev->dev, "MACTYPE configuration invalid\n");
+ return err;
+ }
+
+ /* Enable EDPD mode - saving 600mW */
+ err = mv3310_set_edpd(phydev);
+ if (err)
+ return err;
+
+ /* Allow downshift */
+ err = mv3310_set_downshift(phydev);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ return 0;
+}
+
+static int mv3310_config(struct phy_device *phydev)
+{
+ int err;
+
+ err = mv3310_probe(phydev);
+ if (!err)
+ err = mv3310_config_init(phydev);
+
+ return err;
+}
+
+static int mv3310_get_number_of_ports(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
+ if (ret < 0)
+ return ret;
+
+ ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
+ ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;
+
+ return ret + 1;
+}
+
+static int mv3310_match_phy_device(struct phy_device *phydev)
+{
+ if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
+ return 0;
+
+ return mv3310_get_number_of_ports(phydev) == 1;
+}
+
+static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
+{
+ int val;
+
+ if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
+ return 0;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
+ if (val < 0)
+ return val;
+
+ return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
+}
+
+static int mv2110_match_phy_device(struct phy_device *phydev)
+{
+ return mv211x_match_phy_device(phydev, true);
+}
+
+static bool mv3310_has_downshift(struct phy_device *phydev)
+{
+ struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+ /* Fails to downshift with firmware older than v0.3.5.0 */
+ return priv->firmware_ver >= MV_VERSION(0, 3, 5, 0);
+}
+
+#define mv_test_bit(iface, phydev) \
+ ({ if ((phydev)->interface & (iface)) return 0; })
+
+static int mv3310_mv3340_test_supported_interfaces(struct phy_device *phydev)
+{
+ mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
+ if (mv3310_match_phy_device(phydev))
+ mv_test_bit(PHY_INTERFACE_MODE_XAUI, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_RXAUI, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
+ return -ENODEV;
+}
+
+static int mv2110_mv2111_test_supported_interfaces(struct phy_device *phydev)
+{
+ mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
+ if (mv2110_match_phy_device(phydev))
+ mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
+ mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
+ return -ENODEV;
+}
+
+static const struct mv3310_chip mv3310_mv3340_type = {
+ .has_downshift = mv3310_has_downshift,
+ .test_supported_interfaces = mv3310_mv3340_test_supported_interfaces,
+ .get_mactype = mv3310_get_mactype,
+ .set_mactype = mv3310_set_mactype,
+ .select_mactype = mv3310_select_mactype,
+ .init_interface = mv3310_init_interface,
+};
+
+static const struct mv3310_chip mv2110_mv2111_type = {
+ .test_supported_interfaces = mv2110_mv2111_test_supported_interfaces,
+ .get_mactype = mv2110_get_mactype,
+ .set_mactype = mv2110_set_mactype,
+ .select_mactype = mv2110_select_mactype,
+ .init_interface = mv2110_init_interface,
+};
+
+U_BOOT_PHY_DRIVER(mv88e3310_mv88e3340) = {
+ .name = "mv88x3310",
+ .uid = MARVELL_PHY_ID_88X3310,
+ .mask = MARVELL_PHY_ID_MASK,
+ .features = PHY_10G_FEATURES,
+ .data = (ulong)&mv3310_mv3340_type,
+ .config = mv3310_config,
+};
+
+U_BOOT_PHY_DRIVER(mv88e2110_mv88e2111) = {
+ .name = "mv88e2110",
+ .uid = MARVELL_PHY_ID_88E2110,
+ .mask = MARVELL_PHY_ID_MASK,
+ .features = PHY_10G_FEATURES,
+ .data = (ulong)&mv2110_mv2111_type,
+ .config = mv3310_config,
+};
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 753ca727686..b49c9b5f495 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -124,7 +124,7 @@ static int meson_gxl_phy_config(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver meson_gxl_phy_driver = {
+U_BOOT_PHY_DRIVER(meson_gxl_phy) = {
.name = "Meson GXL Internal PHY",
.uid = 0x01814400,
.mask = 0xfffffff0,
@@ -133,10 +133,3 @@ static struct phy_driver meson_gxl_phy_driver = {
.startup = &meson_gxl_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_meson_gxl_init(void)
-{
- phy_register(&meson_gxl_phy_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c
index 60d42fe9840..b0f3abcb037 100644
--- a/drivers/net/phy/micrel_ksz8xxx.c
+++ b/drivers/net/phy/micrel_ksz8xxx.c
@@ -14,7 +14,7 @@
#include <phy.h>
#include <linux/bitops.h>
-static struct phy_driver KSZ804_driver = {
+U_BOOT_PHY_DRIVER(ksz804) = {
.name = "Micrel KSZ804",
.uid = 0x221510,
.mask = 0xfffff0,
@@ -44,7 +44,7 @@ static int ksz_genconfig_bcastoff(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver KSZ8031_driver = {
+U_BOOT_PHY_DRIVER(ksz8031) = {
.name = "Micrel KSZ8021/KSZ8031",
.uid = 0x221550,
.mask = 0xfffff0,
@@ -72,7 +72,7 @@ static int ksz8051_config(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver KSZ8051_driver = {
+U_BOOT_PHY_DRIVER(ksz8051) = {
.name = "Micrel KSZ8051",
.uid = 0x221550,
.mask = 0xfffff0,
@@ -87,7 +87,7 @@ static int ksz8061_config(struct phy_device *phydev)
return phy_write(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A);
}
-static struct phy_driver KSZ8061_driver = {
+U_BOOT_PHY_DRIVER(ksz8061) = {
.name = "Micrel KSZ8061",
.uid = 0x00221570,
.mask = 0xfffff0,
@@ -115,7 +115,7 @@ static int ksz8081_config(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver KSZ8081_driver = {
+U_BOOT_PHY_DRIVER(ksz8081) = {
.name = "Micrel KSZ8081",
.uid = 0x221560,
.mask = 0xfffff0,
@@ -172,7 +172,7 @@ static int ksz8895_startup(struct phy_device *phydev)
return 0;
}
-static struct phy_driver ksz8895_driver = {
+U_BOOT_PHY_DRIVER(ksz8895) = {
.name = "Micrel KSZ8895/KSZ8864",
.uid = 0x221450,
.mask = 0xffffe1,
@@ -185,7 +185,7 @@ static struct phy_driver ksz8895_driver = {
/* Micrel used the exact same model number for the KSZ9021,
* so the revision number is used to distinguish them.
*/
-static struct phy_driver KS8721_driver = {
+U_BOOT_PHY_DRIVER(ks8721) = {
.name = "Micrel KS8721BL",
.uid = 0x221618,
.mask = 0xfffffc,
@@ -210,7 +210,7 @@ static int ksz886x_startup(struct phy_device *phydev)
return 0;
}
-static struct phy_driver ksz886x_driver = {
+U_BOOT_PHY_DRIVER(ksz886x) = {
.name = "Micrel KSZ886x Switch",
.uid = 0x00221430,
.mask = 0xfffff0,
@@ -219,16 +219,3 @@ static struct phy_driver ksz886x_driver = {
.startup = &ksz886x_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_micrel_ksz8xxx_init(void)
-{
- phy_register(&KSZ804_driver);
- phy_register(&KSZ8031_driver);
- phy_register(&KSZ8051_driver);
- phy_register(&KSZ8061_driver);
- phy_register(&KSZ8081_driver);
- phy_register(&KS8721_driver);
- phy_register(&ksz8895_driver);
- phy_register(&ksz886x_driver);
- return 0;
-}
diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index 79ebdb5e82a..ffc3c987eaa 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -270,7 +270,7 @@ static int ksz9021_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver ksz9021_driver = {
+U_BOOT_PHY_DRIVER(ksz9021) = {
.name = "Micrel ksz9021",
.uid = 0x221610,
.mask = 0xfffffe,
@@ -368,7 +368,7 @@ static int ksz9031_config(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver ksz9031_driver = {
+U_BOOT_PHY_DRIVER(ksz9031) = {
.name = "Micrel ksz9031",
.uid = PHY_ID_KSZ9031,
.mask = MII_KSZ9x31_SILICON_REV_MASK,
@@ -477,7 +477,7 @@ static int ksz9131_config(struct phy_device *phydev)
return genphy_config(phydev);
}
-static struct phy_driver ksz9131_driver = {
+U_BOOT_PHY_DRIVER(ksz9131) = {
.name = "Micrel ksz9131",
.uid = PHY_ID_KSZ9131,
.mask = MII_KSZ9x31_SILICON_REV_MASK,
@@ -497,11 +497,3 @@ int ksz9xx1_phy_get_id(struct phy_device *phydev)
return phyid;
}
-
-int phy_micrel_ksz90x1_init(void)
-{
- phy_register(&ksz9021_driver);
- phy_register(&ksz9031_driver);
- phy_register(&ksz9131_driver);
- return 0;
-}
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index f9482b21a01..ef1761a8bda 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -1558,7 +1558,7 @@ static int vsc8502_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver VSC8530_driver = {
+U_BOOT_PHY_DRIVER(vsc8530) = {
.name = "Microsemi VSC8530",
.uid = PHY_ID_VSC8530,
.mask = 0x000ffff0,
@@ -1568,7 +1568,7 @@ static struct phy_driver VSC8530_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8531_driver = {
+U_BOOT_PHY_DRIVER(vsc8531) = {
.name = "Microsemi VSC8531",
.uid = PHY_ID_VSC8531,
.mask = 0x000ffff0,
@@ -1578,7 +1578,7 @@ static struct phy_driver VSC8531_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8502_driver = {
+U_BOOT_PHY_DRIVER(vsc8502) = {
.name = "Microsemi VSC8502",
.uid = PHY_ID_VSC8502,
.mask = 0x000ffff0,
@@ -1588,7 +1588,7 @@ static struct phy_driver VSC8502_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8540_driver = {
+U_BOOT_PHY_DRIVER(vsc8540) = {
.name = "Microsemi VSC8540",
.uid = PHY_ID_VSC8540,
.mask = 0x000ffff0,
@@ -1598,7 +1598,7 @@ static struct phy_driver VSC8540_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8541_driver = {
+U_BOOT_PHY_DRIVER(vsc8541) = {
.name = "Microsemi VSC8541",
.uid = PHY_ID_VSC8541,
.mask = 0x000ffff0,
@@ -1608,7 +1608,7 @@ static struct phy_driver VSC8541_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8574_driver = {
+U_BOOT_PHY_DRIVER(vsc8574) = {
.name = "Microsemi VSC8574",
.uid = PHY_ID_VSC8574,
.mask = 0x000ffff0,
@@ -1618,7 +1618,7 @@ static struct phy_driver VSC8574_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8584_driver = {
+U_BOOT_PHY_DRIVER(vsc8584) = {
.name = "Microsemi VSC8584",
.uid = PHY_ID_VSC8584,
.mask = 0x000ffff0,
@@ -1627,16 +1627,3 @@ static struct phy_driver VSC8584_driver = {
.startup = &mscc_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_mscc_init(void)
-{
- phy_register(&VSC8530_driver);
- phy_register(&VSC8531_driver);
- phy_register(&VSC8502_driver);
- phy_register(&VSC8540_driver);
- phy_register(&VSC8541_driver);
- phy_register(&VSC8574_driver);
- phy_register(&VSC8584_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 7ab60164c77..85778106edd 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -1127,7 +1127,7 @@ static int mv88e61xx_phy_startup(struct phy_device *phydev)
return 0;
}
-static struct phy_driver mv88e61xx_driver = {
+U_BOOT_PHY_DRIVER(mv88e61xx) = {
.name = "Marvell MV88E61xx",
.uid = 0x01410eb1,
.mask = 0xfffffff0,
@@ -1138,7 +1138,7 @@ static struct phy_driver mv88e61xx_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver mv88e609x_driver = {
+U_BOOT_PHY_DRIVER(mv88e609x) = {
.name = "Marvell MV88E609x",
.uid = 0x1410c89,
.mask = 0xfffffff0,
@@ -1149,7 +1149,7 @@ static struct phy_driver mv88e609x_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver mv88e6071_driver = {
+U_BOOT_PHY_DRIVER(mv88e6071) = {
.name = "Marvell MV88E6071",
.uid = 0x1410db0,
.mask = 0xfffffff0,
@@ -1160,15 +1160,6 @@ static struct phy_driver mv88e6071_driver = {
.shutdown = &genphy_shutdown,
};
-int phy_mv88e61xx_init(void)
-{
- phy_register(&mv88e61xx_driver);
- phy_register(&mv88e609x_driver);
- phy_register(&mv88e6071_driver);
-
- return 0;
-}
-
/*
* Overload weak get_phy_id definition since we need non-standard functions
* to read PHY registers
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
index efde4574deb..6b9e99ea115 100644
--- a/drivers/net/phy/natsemi.c
+++ b/drivers/net/phy/natsemi.c
@@ -33,7 +33,7 @@ static int dp83630_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver DP83630_driver = {
+U_BOOT_PHY_DRIVER(dp83630) = {
.name = "NatSemi DP83630",
.uid = 0x20005ce1,
.mask = 0xfffffff0,
@@ -103,7 +103,7 @@ static int dp83865_startup(struct phy_device *phydev)
}
-static struct phy_driver DP83865_driver = {
+U_BOOT_PHY_DRIVER(dp83865) = {
.name = "NatSemi DP83865",
.uid = 0x20005c70,
.mask = 0xfffffff0,
@@ -146,7 +146,7 @@ static int dp83848_startup(struct phy_device *phydev)
return dp83848_parse_status(phydev);
}
-static struct phy_driver DP83848_driver = {
+U_BOOT_PHY_DRIVER(dp83848) = {
.name = "NatSemi DP83848",
.uid = 0x20005c90,
.mask = 0x2000ff90,
@@ -155,12 +155,3 @@ static struct phy_driver DP83848_driver = {
.startup = &dp83848_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_natsemi_init(void)
-{
- phy_register(&DP83630_driver);
- phy_register(&DP83865_driver);
- phy_register(&DP83848_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/ncsi.c b/drivers/net/phy/ncsi.c
index bb7ecebed38..eb3fd65bb47 100644
--- a/drivers/net/phy/ncsi.c
+++ b/drivers/net/phy/ncsi.c
@@ -881,7 +881,7 @@ int ncsi_shutdown(struct phy_device *phydev)
return 0;
}
-static struct phy_driver ncsi_driver = {
+U_BOOT_PHY_DRIVER(ncsi) = {
.uid = PHY_NCSI_ID,
.mask = 0xffffffff,
.name = "NC-SI",
@@ -891,9 +891,3 @@ static struct phy_driver ncsi_driver = {
.startup = ncsi_startup,
.shutdown = ncsi_shutdown,
};
-
-int phy_ncsi_init(void)
-{
- phy_register(&ncsi_driver);
- return 0;
-}
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index a0f41fab698..f701790194c 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -330,7 +330,7 @@ static int nxp_c45_probe(struct phy_device *phydev)
return 0;
}
-static struct phy_driver nxp_c45_tja11xx = {
+U_BOOT_PHY_DRIVER(nxp_c45_tja11xx) = {
.name = "NXP C45 TJA1103",
.uid = PHY_ID_TJA_1103,
.mask = 0xfffff0,
@@ -340,9 +340,3 @@ static struct phy_driver nxp_c45_tja11xx = {
.startup = &nxp_c45_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_nxp_c45_tja11xx_init(void)
-{
- phy_register(&nxp_c45_tja11xx);
- return 0;
-}
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
index 30dec5e605b..471b0e322b5 100644
--- a/drivers/net/phy/nxp-tja11xx.c
+++ b/drivers/net/phy/nxp-tja11xx.c
@@ -248,7 +248,7 @@ static int tja11xx_startup(struct phy_device *phydev)
return 0;
}
-static struct phy_driver TJA1100_driver = {
+U_BOOT_PHY_DRIVER(tja1100) = {
.name = "NXP TJA1100",
.uid = PHY_ID_TJA1100,
.mask = PHY_ID_MASK,
@@ -258,7 +258,7 @@ static struct phy_driver TJA1100_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver TJA1101_driver = {
+U_BOOT_PHY_DRIVER(tja1101) = {
.name = "NXP TJA1101",
.uid = PHY_ID_TJA1101,
.mask = PHY_ID_MASK,
@@ -267,11 +267,3 @@ static struct phy_driver TJA1101_driver = {
.startup = &tja11xx_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_nxp_tja11xx_init(void)
-{
- phy_register(&TJA1100_driver);
- phy_register(&TJA1101_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 80230b907c1..0eeb0cb3a85 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -451,7 +451,7 @@ int genphy_shutdown(struct phy_device *phydev)
return 0;
}
-static struct phy_driver genphy_driver = {
+U_BOOT_PHY_DRIVER(genphy) = {
.uid = 0xffffffff,
.mask = 0xffffffff,
.name = "Generic PHY",
@@ -463,144 +463,36 @@ static struct phy_driver genphy_driver = {
.shutdown = genphy_shutdown,
};
-static int genphy_init(void)
-{
- return phy_register(&genphy_driver);
-}
-
-static LIST_HEAD(phy_drivers);
-
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
int phy_init(void)
{
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
- /*
- * The pointers inside phy_drivers also needs to be updated incase of
- * manual reloc, without which these points to some invalid
- * pre reloc address and leads to invalid accesses, hangs.
- */
- struct list_head *head = &phy_drivers;
+ const int ll_n_ents = ll_entry_count(struct phy_driver, phy_driver);
+ struct phy_driver *drv, *ll_entry;
- head->next = (void *)head->next + gd->reloc_off;
- head->prev = (void *)head->prev + gd->reloc_off;
-#endif
-
-#ifdef CONFIG_B53_SWITCH
- phy_b53_init();
-#endif
-#ifdef CONFIG_MV88E61XX_SWITCH
- phy_mv88e61xx_init();
-#endif
-#ifdef CONFIG_PHY_ADIN
- phy_adin_init();
-#endif
-#ifdef CONFIG_PHY_AQUANTIA
- phy_aquantia_init();
-#endif
-#ifdef CONFIG_PHY_ATHEROS
- phy_atheros_init();
-#endif
-#ifdef CONFIG_PHY_BROADCOM
- phy_broadcom_init();
-#endif
-#ifdef CONFIG_PHY_CORTINA
- phy_cortina_init();
-#endif
-#ifdef CONFIG_PHY_CORTINA_ACCESS
- phy_cortina_access_init();
-#endif
-#ifdef CONFIG_PHY_DAVICOM
- phy_davicom_init();
-#endif
-#ifdef CONFIG_PHY_ET1011C
- phy_et1011c_init();
-#endif
-#ifdef CONFIG_PHY_LXT
- phy_lxt_init();
-#endif
-#ifdef CONFIG_PHY_MARVELL
- phy_marvell_init();
-#endif
-#ifdef CONFIG_PHY_MICREL_KSZ8XXX
- phy_micrel_ksz8xxx_init();
-#endif
-#ifdef CONFIG_PHY_MICREL_KSZ90X1
- phy_micrel_ksz90x1_init();
-#endif
-#ifdef CONFIG_PHY_MESON_GXL
- phy_meson_gxl_init();
-#endif
-#ifdef CONFIG_PHY_NATSEMI
- phy_natsemi_init();
-#endif
-#ifdef CONFIG_NXP_C45_TJA11XX_PHY
- phy_nxp_c45_tja11xx_init();
-#endif
-#ifdef CONFIG_PHY_NXP_TJA11XX
- phy_nxp_tja11xx_init();
-#endif
-#ifdef CONFIG_PHY_REALTEK
- phy_realtek_init();
-#endif
-#ifdef CONFIG_PHY_SMSC
- phy_smsc_init();
-#endif
-#ifdef CONFIG_PHY_TERANETICS
- phy_teranetics_init();
-#endif
-#ifdef CONFIG_PHY_TI
- phy_ti_init();
-#endif
-#ifdef CONFIG_PHY_VITESSE
- phy_vitesse_init();
-#endif
-#ifdef CONFIG_PHY_XILINX
- phy_xilinx_init();
-#endif
-#ifdef CONFIG_PHY_XWAY
- phy_xway_init();
-#endif
-#ifdef CONFIG_PHY_MSCC
- phy_mscc_init();
-#endif
-#ifdef CONFIG_PHY_FIXED
- phy_fixed_init();
-#endif
-#ifdef CONFIG_PHY_NCSI
- phy_ncsi_init();
-#endif
-#ifdef CONFIG_PHY_XILINX_GMII2RGMII
- phy_xilinx_gmii2rgmii_init();
-#endif
- genphy_init();
+ /* Perform manual relocation on linker list based PHY drivers */
+ ll_entry = ll_entry_start(struct phy_driver, phy_driver);
+ for (drv = ll_entry; drv != ll_entry + ll_n_ents; drv++) {
+ if (drv->probe)
+ drv->probe += gd->reloc_off;
+ if (drv->config)
+ drv->config += gd->reloc_off;
+ if (drv->startup)
+ drv->startup += gd->reloc_off;
+ if (drv->shutdown)
+ drv->shutdown += gd->reloc_off;
+ if (drv->readext)
+ drv->readext += gd->reloc_off;
+ if (drv->writeext)
+ drv->writeext += gd->reloc_off;
+ if (drv->read_mmd)
+ drv->read_mmd += gd->reloc_off;
+ if (drv->write_mmd)
+ drv->write_mmd += gd->reloc_off;
+ }
return 0;
}
-
-int phy_register(struct phy_driver *drv)
-{
- INIT_LIST_HEAD(&drv->list);
- list_add_tail(&drv->list, &phy_drivers);
-
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
- if (drv->probe)
- drv->probe += gd->reloc_off;
- if (drv->config)
- drv->config += gd->reloc_off;
- if (drv->startup)
- drv->startup += gd->reloc_off;
- if (drv->shutdown)
- drv->shutdown += gd->reloc_off;
- if (drv->readext)
- drv->readext += gd->reloc_off;
- if (drv->writeext)
- drv->writeext += gd->reloc_off;
- if (drv->read_mmd)
- drv->read_mmd += gd->reloc_off;
- if (drv->write_mmd)
- drv->write_mmd += gd->reloc_off;
#endif
- return 0;
-}
int phy_set_supported(struct phy_device *phydev, u32 max_speed)
{
@@ -645,23 +537,23 @@ static struct phy_driver *generic_for_phy(struct phy_device *phydev)
{
#ifdef CONFIG_PHYLIB_10G
if (phydev->is_c45)
- return &gen10g_driver;
+ return ll_entry_get(struct phy_driver, gen10g, phy_driver);
#endif
- return &genphy_driver;
+ return ll_entry_get(struct phy_driver, genphy, phy_driver);
}
static struct phy_driver *get_phy_driver(struct phy_device *phydev)
{
- struct list_head *entry;
+ const int ll_n_ents = ll_entry_count(struct phy_driver, phy_driver);
int phy_id = phydev->phy_id;
- struct phy_driver *drv = NULL;
+ struct phy_driver *ll_entry;
+ struct phy_driver *drv;
- list_for_each(entry, &phy_drivers) {
- drv = list_entry(entry, struct phy_driver, list);
+ ll_entry = ll_entry_start(struct phy_driver, phy_driver);
+ for (drv = ll_entry; drv != ll_entry + ll_n_ents; drv++)
if ((drv->uid & drv->mask) == (phy_id & drv->mask))
return drv;
- }
/* If we made it here, there's no driver for this PHY */
return generic_for_phy(phydev);
@@ -1266,9 +1158,67 @@ int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val
return 0;
}
+/**
+ * phy_modify_mmd_changed - Function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int new, ret;
+
+ ret = phy_read_mmd(phydev, devad, regnum);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~mask) | set;
+ if (new == ret)
+ return 0;
+
+ ret = phy_write_mmd(phydev, devad, regnum, new);
+
+ return ret < 0 ? ret : 1;
+}
+
+/**
+ * phy_modify_mmd - Convenience function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
+
+ return ret < 0 ? ret : 0;
+}
+
bool phy_interface_is_ncsi(void)
{
+#ifdef CONFIG_PHY_NCSI
struct eth_pdata *pdata = dev_get_plat(eth_get_dev());
return pdata->phy_interface == PHY_INTERFACE_MODE_NCSI;
+#else
+ return 0;
+#endif
}
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 24c3ea59bbb..396cac76d63 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -384,17 +384,6 @@ static int rtl8211x_startup(struct phy_device *phydev)
return rtl8211x_parse_status(phydev);
}
-static int rtl8211e_startup(struct phy_device *phydev)
-{
- int ret;
-
- ret = genphy_update_link(phydev);
- if (ret)
- return ret;
-
- return genphy_parse_link(phydev);
-}
-
static int rtl8211f_startup(struct phy_device *phydev)
{
int ret;
@@ -409,7 +398,7 @@ static int rtl8211f_startup(struct phy_device *phydev)
}
/* Support for RTL8211B PHY */
-static struct phy_driver RTL8211B_driver = {
+U_BOOT_PHY_DRIVER(rtl8211b) = {
.name = "RealTek RTL8211B",
.uid = 0x1cc912,
.mask = 0xffffff,
@@ -421,19 +410,19 @@ static struct phy_driver RTL8211B_driver = {
};
/* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
-static struct phy_driver RTL8211E_driver = {
+U_BOOT_PHY_DRIVER(rtl8211e) = {
.name = "RealTek RTL8211E",
.uid = 0x1cc915,
.mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
.probe = &rtl8211e_probe,
.config = &rtl8211e_config,
- .startup = &rtl8211e_startup,
+ .startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
/* Support for RTL8211DN PHY */
-static struct phy_driver RTL8211DN_driver = {
+U_BOOT_PHY_DRIVER(rtl8211dn) = {
.name = "RealTek RTL8211DN",
.uid = 0x1cc914,
.mask = 0xffffff,
@@ -444,7 +433,7 @@ static struct phy_driver RTL8211DN_driver = {
};
/* Support for RTL8211F PHY */
-static struct phy_driver RTL8211F_driver = {
+U_BOOT_PHY_DRIVER(rtl8211f) = {
.name = "RealTek RTL8211F",
.uid = 0x1cc916,
.mask = 0xffffff,
@@ -458,24 +447,13 @@ static struct phy_driver RTL8211F_driver = {
};
/* Support for RTL8201F PHY */
-static struct phy_driver RTL8201F_driver = {
+U_BOOT_PHY_DRIVER(rtl8201f) = {
.name = "RealTek RTL8201F 10/100Mbps Ethernet",
.uid = 0x1cc816,
.mask = 0xffffff,
.features = PHY_BASIC_FEATURES,
.probe = &rtl8210f_probe,
.config = &rtl8201f_config,
- .startup = &rtl8211e_startup,
+ .startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_realtek_init(void)
-{
- phy_register(&RTL8211B_driver);
- phy_register(&RTL8211E_driver);
- phy_register(&RTL8211F_driver);
- phy_register(&RTL8211DN_driver);
- phy_register(&RTL8201F_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 7740a2510d2..056b607e0b8 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -43,7 +43,7 @@ static int smsc_startup(struct phy_device *phydev)
return smsc_parse_status(phydev);
}
-static struct phy_driver lan8700_driver = {
+U_BOOT_PHY_DRIVER(lan8700) = {
.name = "SMSC LAN8700",
.uid = 0x0007c0c0,
.mask = 0xffff0,
@@ -53,7 +53,7 @@ static struct phy_driver lan8700_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver lan911x_driver = {
+U_BOOT_PHY_DRIVER(lan911x) = {
.name = "SMSC LAN911x Internal PHY",
.uid = 0x0007c0d0,
.mask = 0xffff0,
@@ -63,7 +63,7 @@ static struct phy_driver lan911x_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver lan8710_driver = {
+U_BOOT_PHY_DRIVER(lan8710) = {
.name = "SMSC LAN8710/LAN8720",
.uid = 0x0007c0f0,
.mask = 0xffff0,
@@ -73,7 +73,7 @@ static struct phy_driver lan8710_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver lan8740_driver = {
+U_BOOT_PHY_DRIVER(lan8740) = {
.name = "SMSC LAN8740",
.uid = 0x0007c110,
.mask = 0xffff0,
@@ -83,7 +83,7 @@ static struct phy_driver lan8740_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver lan8741_driver = {
+U_BOOT_PHY_DRIVER(lan8741) = {
.name = "SMSC LAN8741",
.uid = 0x0007c120,
.mask = 0xffff0,
@@ -93,7 +93,7 @@ static struct phy_driver lan8741_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver lan8742_driver = {
+U_BOOT_PHY_DRIVER(lan8742) = {
.name = "SMSC LAN8742",
.uid = 0x0007c130,
.mask = 0xffff0,
@@ -102,15 +102,3 @@ static struct phy_driver lan8742_driver = {
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_smsc_init(void)
-{
- phy_register(&lan8710_driver);
- phy_register(&lan911x_driver);
- phy_register(&lan8700_driver);
- phy_register(&lan8740_driver);
- phy_register(&lan8741_driver);
- phy_register(&lan8742_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index 60049c2074f..15f2c12ed83 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -90,7 +90,7 @@ int tn2020_startup(struct phy_device *phydev)
return 0;
}
-struct phy_driver tn2020_driver = {
+U_BOOT_PHY_DRIVER(tn2020) = {
.name = "Teranetics TN2020",
.uid = PHY_UID_TN2020,
.mask = 0xfffffff0,
@@ -102,10 +102,3 @@ struct phy_driver tn2020_driver = {
.startup = &tn2020_startup,
.shutdown = &gen10g_shutdown,
};
-
-int phy_teranetics_init(void)
-{
- phy_register(&tn2020_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c
index 075b19a39f0..a0878193ac0 100644
--- a/drivers/net/phy/ti_phy_init.c
+++ b/drivers/net/phy/ti_phy_init.c
@@ -10,8 +10,7 @@
#include <phy.h>
#include "ti_phy_init.h"
-#ifdef CONFIG_PHY_TI_GENERIC
-static struct phy_driver dp83822_driver = {
+U_BOOT_PHY_DRIVER(dp83822) = {
.name = "TI DP83822",
.uid = 0x2000a240,
.mask = 0xfffffff0,
@@ -21,7 +20,7 @@ static struct phy_driver dp83822_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver dp83826nc_driver = {
+U_BOOT_PHY_DRIVER(dp83826nc) = {
.name = "TI DP83826NC",
.uid = 0x2000a110,
.mask = 0xfffffff0,
@@ -31,7 +30,7 @@ static struct phy_driver dp83826nc_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver dp83826c_driver = {
+U_BOOT_PHY_DRIVER(dp83826c) = {
.name = "TI DP83826C",
.uid = 0x2000a130,
.mask = 0xfffffff0,
@@ -41,7 +40,7 @@ static struct phy_driver dp83826c_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver dp83825s_driver = {
+U_BOOT_PHY_DRIVER(dp83825s) = {
.name = "TI DP83825S",
.uid = 0x2000a140,
.mask = 0xfffffff0,
@@ -51,7 +50,7 @@ static struct phy_driver dp83825s_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver dp83825i_driver = {
+U_BOOT_PHY_DRIVER(dp83825i) = {
.name = "TI DP83825I",
.uid = 0x2000a150,
.mask = 0xfffffff0,
@@ -61,7 +60,7 @@ static struct phy_driver dp83825i_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver dp83825m_driver = {
+U_BOOT_PHY_DRIVER(dp83825m) = {
.name = "TI DP83825M",
.uid = 0x2000a160,
.mask = 0xfffffff0,
@@ -71,7 +70,7 @@ static struct phy_driver dp83825m_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver dp83825cs_driver = {
+U_BOOT_PHY_DRIVER(dp83825cs) = {
.name = "TI DP83825CS",
.uid = 0x2000a170,
.mask = 0xfffffff0,
@@ -80,26 +79,3 @@ static struct phy_driver dp83825cs_driver = {
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
-#endif /* CONFIG_PHY_TI_GENERIC */
-
-int phy_ti_init(void)
-{
-#ifdef CONFIG_PHY_TI_DP83867
- phy_dp83867_init();
-#endif
-
-#ifdef CONFIG_PHY_TI_DP83869
- phy_dp83869_init();
-#endif
-
-#ifdef CONFIG_PHY_TI_GENERIC
- phy_register(&dp83822_driver);
- phy_register(&dp83825s_driver);
- phy_register(&dp83825i_driver);
- phy_register(&dp83825m_driver);
- phy_register(&dp83825cs_driver);
- phy_register(&dp83826c_driver);
- phy_register(&dp83826nc_driver);
-#endif
- return 0;
-}
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index eca26c98938..c5cf0d7dfbd 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -293,7 +293,7 @@ static int vsc8664_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver VSC8211_driver = {
+U_BOOT_PHY_DRIVER(vsc8211) = {
.name = "Vitesse VSC8211",
.uid = 0xfc4b0,
.mask = 0xffff0,
@@ -303,7 +303,7 @@ static struct phy_driver VSC8211_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8221_driver = {
+U_BOOT_PHY_DRIVER(vsc8221) = {
.name = "Vitesse VSC8221",
.uid = 0xfc550,
.mask = 0xffff0,
@@ -313,7 +313,7 @@ static struct phy_driver VSC8221_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8244_driver = {
+U_BOOT_PHY_DRIVER(vsc8244) = {
.name = "Vitesse VSC8244",
.uid = 0xfc6c0,
.mask = 0xffff0,
@@ -323,7 +323,7 @@ static struct phy_driver VSC8244_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8234_driver = {
+U_BOOT_PHY_DRIVER(vsc8234) = {
.name = "Vitesse VSC8234",
.uid = 0xfc620,
.mask = 0xffff0,
@@ -333,7 +333,7 @@ static struct phy_driver VSC8234_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8574_driver = {
+U_BOOT_PHY_DRIVER(vsc8574) = {
.name = "Vitesse VSC8574",
.uid = 0x704a0,
.mask = 0xffff0,
@@ -343,7 +343,7 @@ static struct phy_driver VSC8574_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8514_driver = {
+U_BOOT_PHY_DRIVER(vsc8514) = {
.name = "Vitesse VSC8514",
.uid = 0x70670,
.mask = 0xffff0,
@@ -353,7 +353,7 @@ static struct phy_driver VSC8514_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8584_driver = {
+U_BOOT_PHY_DRIVER(vsc8584) = {
.name = "Vitesse VSC8584",
.uid = 0x707c0,
.mask = 0xffff0,
@@ -363,7 +363,7 @@ static struct phy_driver VSC8584_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8601_driver = {
+U_BOOT_PHY_DRIVER(vsc8601) = {
.name = "Vitesse VSC8601",
.uid = 0x70420,
.mask = 0xffff0,
@@ -373,7 +373,7 @@ static struct phy_driver VSC8601_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8641_driver = {
+U_BOOT_PHY_DRIVER(vsc8641) = {
.name = "Vitesse VSC8641",
.uid = 0x70430,
.mask = 0xffff0,
@@ -383,7 +383,7 @@ static struct phy_driver VSC8641_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8662_driver = {
+U_BOOT_PHY_DRIVER(vsc8662) = {
.name = "Vitesse VSC8662",
.uid = 0x70660,
.mask = 0xffff0,
@@ -393,7 +393,7 @@ static struct phy_driver VSC8662_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver VSC8664_driver = {
+U_BOOT_PHY_DRIVER(vsc8664) = {
.name = "Vitesse VSC8664",
.uid = 0x70660,
.mask = 0xffff0,
@@ -404,7 +404,7 @@ static struct phy_driver VSC8664_driver = {
};
/* Vitesse bought Cicada, so we'll put these here */
-static struct phy_driver cis8201_driver = {
+U_BOOT_PHY_DRIVER(cis8201) = {
.name = "CIS8201",
.uid = 0xfc410,
.mask = 0xffff0,
@@ -414,7 +414,7 @@ static struct phy_driver cis8201_driver = {
.shutdown = &genphy_shutdown,
};
-static struct phy_driver cis8204_driver = {
+U_BOOT_PHY_DRIVER(cis8204) = {
.name = "Cicada Cis8204",
.uid = 0xfc440,
.mask = 0xffff0,
@@ -423,22 +423,3 @@ static struct phy_driver cis8204_driver = {
.startup = &vitesse_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_vitesse_init(void)
-{
- phy_register(&VSC8641_driver);
- phy_register(&VSC8601_driver);
- phy_register(&VSC8234_driver);
- phy_register(&VSC8244_driver);
- phy_register(&VSC8211_driver);
- phy_register(&VSC8221_driver);
- phy_register(&VSC8574_driver);
- phy_register(&VSC8584_driver);
- phy_register(&VSC8514_driver);
- phy_register(&VSC8662_driver);
- phy_register(&VSC8664_driver);
- phy_register(&cis8201_driver);
- phy_register(&cis8204_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
index 73762839565..e2969bc4842 100644
--- a/drivers/net/phy/xilinx_gmii2rgmii.c
+++ b/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -48,7 +48,14 @@ static int xilinxgmiitorgmii_config(struct phy_device *phydev)
return -EINVAL;
}
- ext_phydev->interface = PHY_INTERFACE_MODE_RGMII;
+ ext_phydev->interface = ofnode_read_phy_mode(node);
+ if (ext_phydev->interface == PHY_INTERFACE_MODE_NA) {
+ ext_phydev->interface = PHY_INTERFACE_MODE_RGMII;
+ } else if (!phy_interface_is_rgmii(ext_phydev)) {
+ printf("Incorrect external interface type\n");
+ return -EINVAL;
+ }
+
ext_phydev->node = phandle.node;
phydev->priv = ext_phydev;
@@ -124,7 +131,7 @@ static int xilinxgmiitorgmii_probe(struct phy_device *phydev)
return 0;
}
-static struct phy_driver gmii2rgmii_driver = {
+U_BOOT_PHY_DRIVER(gmii2rgmii) = {
.name = "XILINX GMII2RGMII",
.uid = PHY_GMII2RGMII_ID,
.mask = 0xffffffff,
@@ -135,10 +142,3 @@ static struct phy_driver gmii2rgmii_driver = {
.writeext = xilinxgmiitorgmii_extwrite,
.readext = xilinxgmiitorgmii_extread,
};
-
-int phy_xilinx_gmii2rgmii_init(void)
-{
- phy_register(&gmii2rgmii_driver);
-
- return 0;
-}
diff --git a/drivers/net/phy/xilinx_phy.c b/drivers/net/phy/xilinx_phy.c
index 39dbfdb7da8..1df639d6f44 100644
--- a/drivers/net/phy/xilinx_phy.c
+++ b/drivers/net/phy/xilinx_phy.c
@@ -127,7 +127,7 @@ static int xilinxphy_config(struct phy_device *phydev)
return 0;
}
-static struct phy_driver xilinxphy_driver = {
+U_BOOT_PHY_DRIVER(xilinxphy) = {
.uid = XILINX_PHY_ID,
.mask = XILINX_PHY_ID_MASK,
.name = "Xilinx PCS/PMA PHY",
@@ -136,11 +136,3 @@ static struct phy_driver xilinxphy_driver = {
.startup = &xilinxphy_startup,
.shutdown = &genphy_shutdown,
};
-
-int phy_xilinx_init(void)
-{
- debug("%s\n", __func__);
- phy_register(&xilinxphy_driver);
-
- return 0;
-}
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index 0bc50dc7335..c74c8a81f94 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -692,6 +692,7 @@ int ravb_of_to_plat(struct udevice *dev)
static const struct udevice_id ravb_ids[] = {
{ .compatible = "renesas,etheravb-rcar-gen3" },
+ { .compatible = "renesas,etheravb-rcar-gen4" },
{ }
};
diff --git a/drivers/net/rswitch.c b/drivers/net/rswitch.c
new file mode 100644
index 00000000000..5a69ca1a0f9
--- /dev/null
+++ b/drivers/net/rswitch.c
@@ -0,0 +1,1139 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Renesas Ethernet RSwitch2 (Ethernet-TSN).
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ *
+ * Based on the Renesas Ethernet AVB driver.
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/mii.h>
+#include <eth_phy.h>
+#include <log.h>
+#include <malloc.h>
+#include <miiphy.h>
+
+#define RSWITCH_SLEEP_US 1000
+#define RSWITCH_TIMEOUT_US 1000000
+
+#define RSWITCH_NUM_HW 5
+
+#define ETHA_TO_GWCA(i) ((i) % 2)
+#define GWCA_TO_HW_INDEX(i) ((i) + 3)
+#define HW_INDEX_TO_GWCA(i) ((i) - 3)
+
+#define RSWITCH_MAX_CTAG_PCP 7
+
+/* Registers */
+#define RSWITCH_COMA_OFFSET 0x00009000
+#define RSWITCH_ETHA_OFFSET 0x0000a000 /* with RMAC */
+#define RSWITCH_ETHA_SIZE 0x00002000 /* with RMAC */
+#define RSWITCH_GWCA_OFFSET 0x00010000
+#define RSWITCH_GWCA_SIZE 0x00002000
+
+#define FWRO 0
+#define CARO RSWITCH_COMA_OFFSET
+#define GWRO 0
+#define TARO 0
+#define RMRO 0x1000
+
+enum rswitch_reg {
+ EAMC = TARO + 0x0000,
+ EAMS = TARO + 0x0004,
+ EATDQDC = TARO + 0x0060,
+ EATTFC = TARO + 0x0138,
+ EATASRIRM = TARO + 0x03E4,
+
+ GWMC = GWRO + 0x0000,
+ GWMS = GWRO + 0x0004,
+ GWMTIRM = GWRO + 0x0100,
+ GWVCC = GWRO + 0x0130,
+ GWTTFC = GWRO + 0x0138,
+ GWDCBAC0 = GWRO + 0x0194,
+ GWDCBAC1 = GWRO + 0x0198,
+ GWTRC = GWRO + 0x0200,
+ GWARIRM = GWRO + 0x0380,
+ GWDCC = GWRO + 0x0400,
+
+ RRC = CARO + 0x0004,
+ RCEC = CARO + 0x0008,
+ RCDC = CARO + 0x000C,
+ CABPIRM = CARO + 0x0140,
+
+ FWPC0 = FWRO + 0x0100,
+ FWPBFC = FWRO + 0x4A00,
+ FWPBFCSDC = FWRO + 0x4A04,
+
+ MPSM = RMRO + 0x0000,
+ MPIC = RMRO + 0x0004,
+ MRMAC0 = RMRO + 0x0084,
+ MRMAC1 = RMRO + 0x0088,
+ MRAFC = RMRO + 0x008C,
+ MRSCE = RMRO + 0x0090,
+ MRSCP = RMRO + 0x0094,
+ MLVC = RMRO + 0x0180,
+ MLBC = RMRO + 0x0188,
+ MXGMIIC = RMRO + 0x0190,
+ MPCH = RMRO + 0x0194,
+ MANM = RMRO + 0x019C,
+ MMIS0 = RMRO + 0x0210,
+ MMIS1 = RMRO + 0x0220,
+};
+
+/* COMA */
+#define RRC_RR BIT(0)
+#define RCEC_RCE BIT(16)
+
+#define CABPIRM_BPIOG BIT(0)
+#define CABPIRM_BPR BIT(1)
+
+/* MFWD */
+#define FWPC0(i) (FWPC0 + (i) * 0x10)
+#define FWPC0_LTHTA BIT(0)
+#define FWPC0_IP4UE BIT(3)
+#define FWPC0_IP4TE BIT(4)
+#define FWPC0_IP4OE BIT(5)
+#define FWPC0_L2SE BIT(9)
+#define FWPC0_IP4EA BIT(10)
+#define FWPC0_IPDSA BIT(12)
+#define FWPC0_IPHLA BIT(18)
+#define FWPC0_MACSDA BIT(20)
+#define FWPC0_MACHLA BIT(26)
+#define FWPC0_MACHMA BIT(27)
+#define FWPC0_VLANSA BIT(28)
+
+#define FWPC0_DEFAULT (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | \
+ FWPC0_IP4OE | FWPC0_L2SE | FWPC0_IP4EA | \
+ FWPC0_IPDSA | FWPC0_IPHLA | FWPC0_MACSDA | \
+ FWPC0_MACHLA | FWPC0_MACHMA | FWPC0_VLANSA)
+
+#define FWPBFC(i) (FWPBFC + (i) * 0x10)
+#define FWPBFCSDC(j, i) (FWPBFCSDC + (i) * 0x10 + (j) * 0x04)
+
+/* ETHA */
+#define EATASRIRM_TASRIOG BIT(0)
+#define EATASRIRM_TASRR BIT(1)
+#define EATDQDC(q) (EATDQDC + (q) * 0x04)
+#define EATDQDC_DQD (0xff)
+
+/* RMAC */
+#define MPIC_PIS_GMII 0x02
+#define MPIC_LSC_MASK (0x07 << 3)
+#define MPIC_LSC_100 (0x01 << 3)
+#define MPIC_LSC_1000 (0x02 << 3)
+#define MPIC_LSC_2500 (0x03 << 3)
+#define MLVC_PLV BIT(16)
+#define MLVC_LVT 0x09
+#define MMIS0_LVSS 0x02
+
+#define MPIC_PSMCS_MASK (0x7f << 16)
+#define MPIC_PSMHT_MASK (0x06 << 24)
+#define MPIC_MDC_CLK_SET (0x06050000)
+
+#define MPSM_MFF_C45 BIT(2)
+#define MPSM_MFF_C22 0x0
+#define MPSM_PSME BIT(0)
+
+#define MDIO_READ_C45 0x03
+#define MDIO_WRITE_C45 0x01
+#define MDIO_ADDR_C45 0x00
+
+#define MDIO_READ_C22 0x02
+#define MDIO_WRITE_C22 0x01
+
+#define MPSM_POP_MASK (0x03 << 13)
+#define MPSM_PRA_MASK (0x1f << 8)
+#define MPSM_PDA_MASK (0x1f << 3)
+#define MPSM_PRD_MASK (0xffff << 16)
+
+/* Completion flags */
+#define MMIS1_PAACS BIT(2) /* Address */
+#define MMIS1_PWACS BIT(1) /* Write */
+#define MMIS1_PRACS BIT(0) /* Read */
+#define MMIS1_CLEAR_FLAGS 0xf
+
+/* ETHA */
+enum rswitch_etha_mode {
+ EAMC_OPC_RESET,
+ EAMC_OPC_DISABLE,
+ EAMC_OPC_CONFIG,
+ EAMC_OPC_OPERATION,
+};
+
+#define EAMS_OPS_MASK EAMC_OPC_OPERATION
+
+/* GWCA */
+enum rswitch_gwca_mode {
+ GWMC_OPC_RESET,
+ GWMC_OPC_DISABLE,
+ GWMC_OPC_CONFIG,
+ GWMC_OPC_OPERATION,
+};
+
+#define GWMS_OPS_MASK GWMC_OPC_OPERATION
+
+#define GWMTIRM_MTIOG BIT(0)
+#define GWMTIRM_MTR BIT(1)
+#define GWARIRM_ARIOG BIT(0)
+#define GWARIRM_ARR BIT(1)
+#define GWVCC_VEM_SC_TAG (0x3 << 16)
+#define GWDCBAC0_DCBAUP (0xff)
+#define GWTRC(i) (GWTRC + (i) * 0x04)
+#define GWDCC(i) (GWDCC + (i) * 0x04)
+#define GWDCC_DQT BIT(11)
+#define GWDCC_BALR BIT(24)
+
+struct rswitch_etha {
+ int index;
+ void __iomem *addr;
+ struct phy_device *phydev;
+ struct mii_dev *bus;
+ unsigned char *enetaddr;
+};
+
+struct rswitch_gwca {
+ int index;
+ void __iomem *addr;
+ int num_chain;
+};
+
+/* Setting value */
+#define LINK_SPEED_100 100
+#define LINK_SPEED_1000 1000
+#define LINK_SPEED_2500 2500
+
+/* Decriptor */
+#define RSWITCH_NUM_BASE_DESC 2
+#define RSWITCH_TX_CHAIN_INDEX 0
+#define RSWITCH_RX_CHAIN_INDEX 1
+#define RSWITCH_NUM_TX_DESC 8
+#define RSWITCH_NUM_RX_DESC 8
+
+enum RX_DS_CC_BIT {
+ RX_DS = 0x0fff, /* Data size */
+ RX_TR = 0x1000, /* Truncation indication */
+ RX_EI = 0x2000, /* Error indication */
+ RX_PS = 0xc000, /* Padding selection */
+};
+
+enum DIE_DT {
+ /* Frame data */
+ DT_FSINGLE = 0x80,
+ DT_FSTART = 0x90,
+ DT_FMID = 0xa0,
+ DT_FEND = 0xb8,
+
+ /* Chain control */
+ DT_LEMPTY = 0xc0,
+ DT_EEMPTY = 0xd0,
+ DT_LINKFIX = 0x00,
+ DT_LINK = 0xe0,
+ DT_EOS = 0xf0,
+ /* HW/SW arbitration */
+ DT_FEMPTY = 0x40,
+ DT_FEMPTY_IS = 0x10,
+ DT_FEMPTY_IC = 0x20,
+ DT_FEMPTY_ND = 0x38,
+ DT_FEMPTY_START = 0x50,
+ DT_FEMPTY_MID = 0x60,
+ DT_FEMPTY_END = 0x70,
+
+ DT_MASK = 0xf0,
+ DIE = 0x08, /* Descriptor Interrupt Enable */
+};
+
+struct rswitch_desc {
+ __le16 info_ds; /* Descriptor size */
+ u8 die_dt; /* Descriptor interrupt enable and type */
+ __u8 dptrh; /* Descriptor pointer MSB */
+ __le32 dptrl; /* Descriptor pointer LSW */
+} __packed;
+
+struct rswitch_rxdesc {
+ struct rswitch_desc data;
+ struct rswitch_desc link;
+ u8 __pad[48];
+ u8 packet[PKTSIZE_ALIGN];
+} __packed;
+
+struct rswitch_port_priv {
+ void __iomem *addr;
+ struct phy serdes;
+ struct rswitch_etha etha;
+ struct rswitch_gwca gwca;
+ struct rswitch_desc bat_desc[RSWITCH_NUM_BASE_DESC];
+ struct rswitch_desc tx_desc[RSWITCH_NUM_TX_DESC];
+ struct rswitch_rxdesc rx_desc[RSWITCH_NUM_RX_DESC];
+ u32 rx_desc_index;
+ u32 tx_desc_index;
+};
+
+struct rswitch_priv {
+ void __iomem *addr;
+ struct clk *rsw_clk;
+};
+
+static inline void rswitch_flush_dcache(u32 addr, u32 len)
+{
+ flush_dcache_range(addr, addr + len);
+}
+
+static inline void rswitch_invalidate_dcache(u32 addr, u32 len)
+{
+ u32 start = addr & ~((uintptr_t)ARCH_DMA_MINALIGN - 1);
+ u32 end = roundup(addr + len, ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rswitch_agent_clock_ctrl(struct rswitch_port_priv *priv, int port, int enable)
+{
+ u32 val;
+
+ if (enable) {
+ val = readl(priv->addr + RCEC);
+ if ((val & (RCEC_RCE | BIT(port))) != (RCEC_RCE | BIT(port)))
+ writel(val | RCEC_RCE | BIT(port), priv->addr + RCEC);
+ } else {
+ setbits_le32(priv->addr + RCDC, BIT(port));
+ }
+}
+
+static int rswitch_etha_change_mode(struct rswitch_port_priv *priv,
+ enum rswitch_etha_mode mode)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ u32 pval;
+ int ret;
+
+ /* Enable clock */
+ rswitch_agent_clock_ctrl(priv, etha->index, 1);
+
+ writel(mode, etha->addr + EAMC);
+
+ ret = readl_poll_sleep_timeout(etha->addr + EAMS, pval,
+ (pval & EAMS_OPS_MASK) == mode,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+
+ /* Disable clock */
+ if (mode == EAMC_OPC_DISABLE)
+ rswitch_agent_clock_ctrl(priv, etha->index, 0);
+
+ return ret;
+}
+
+static int rswitch_gwca_change_mode(struct rswitch_port_priv *priv,
+ enum rswitch_gwca_mode mode)
+{
+ struct rswitch_gwca *gwca = &priv->gwca;
+ u32 pval;
+ int ret;
+
+ /* Enable clock */
+ rswitch_agent_clock_ctrl(priv, gwca->index, 1);
+
+ writel(mode, gwca->addr + GWMC);
+
+ ret = readl_poll_sleep_timeout(gwca->addr + GWMS, pval,
+ (pval & GWMS_OPS_MASK) == mode,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+
+ /* Disable clock */
+ if (mode == GWMC_OPC_DISABLE)
+ rswitch_agent_clock_ctrl(priv, gwca->index, 0);
+
+ return ret;
+}
+
+static int rswitch_mii_access_c45(struct rswitch_etha *etha, bool read,
+ int phyad, int devad, int regad, int data)
+{
+ u32 pval, val;
+ int ret;
+
+ /* No match device */
+ if (devad == 0xffffffff)
+ return 0;
+
+ /* Clear completion flags */
+ writel(MMIS1_CLEAR_FLAGS, etha->addr + MMIS1);
+
+ /* Submit address to PHY (MDIO_ADDR_C45 << 13) */
+ val = MPSM_PSME | MPSM_MFF_C45 | (devad << 8) | (phyad << 3);
+ writel((regad << 16) | val, etha->addr + MPSM);
+
+ ret = readl_poll_sleep_timeout(etha->addr + MMIS1, pval,
+ pval & MMIS1_PAACS,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Clear address completion flag */
+ setbits_le32(etha->addr + MMIS1, MMIS1_PAACS);
+
+ /* Read/Write PHY register */
+ if (read) {
+ val |= MDIO_READ_C45 << 13;
+ writel(val, etha->addr + MPSM);
+
+ ret = readl_poll_sleep_timeout(etha->addr + MMIS1, pval,
+ pval & MMIS1_PRACS,
+ RSWITCH_SLEEP_US,
+ RSWITCH_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Read data */
+ ret = (readl(etha->addr + MPSM) & MPSM_PRD_MASK) >> 16;
+
+ /* Clear read completion flag */
+ setbits_le32(etha->addr + MMIS1, MMIS1_PRACS);
+ } else {
+ val |= MDIO_WRITE_C45 << 13;
+ val |= data << 16;
+ writel(val, etha->addr + MPSM);
+
+ ret = readl_poll_sleep_timeout(etha->addr + MMIS1, pval,
+ pval & MMIS1_PWACS,
+ RSWITCH_SLEEP_US,
+ RSWITCH_TIMEOUT_US);
+ }
+
+ return ret;
+}
+
+static int rswitch_mii_read_c45(struct mii_dev *miidev, int phyad, int devad, int regad)
+{
+ struct rswitch_port_priv *priv = miidev->priv;
+ struct rswitch_etha *etha = &priv->etha;
+ int val;
+ int reg;
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ /* Change to config mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_CONFIG);
+
+ /* Enable Station Management clock */
+ reg = readl(etha->addr + MPIC);
+ reg &= ~MPIC_PSMCS_MASK & ~MPIC_PSMHT_MASK;
+ writel(reg | MPIC_MDC_CLK_SET, etha->addr + MPIC);
+
+ /* Set Station Management Mode : Clause 45 */
+ setbits_le32(etha->addr + MPSM, MPSM_MFF_C45);
+
+ /* Access PHY register */
+ val = rswitch_mii_access_c45(etha, true, phyad, devad, regad, 0);
+
+ /* Disable Station Management Clock */
+ clrbits_le32(etha->addr + MPIC, MPIC_PSMCS_MASK);
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ return val;
+}
+
+int rswitch_mii_write_c45(struct mii_dev *miidev, int phyad, int devad, int regad, u16 data)
+{
+ struct rswitch_port_priv *priv = miidev->priv;
+ struct rswitch_etha *etha = &priv->etha;
+ int reg;
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ /* Change to config mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_CONFIG);
+
+ /* Enable Station Management clock */
+ reg = readl(etha->addr + MPIC);
+ reg &= ~MPIC_PSMCS_MASK & ~MPIC_PSMHT_MASK;
+ writel(reg | MPIC_MDC_CLK_SET, etha->addr + MPIC);
+
+ /* Set Station Management Mode : Clause 45 */
+ setbits_le32(etha->addr + MPSM, MPSM_MFF_C45);
+
+ /* Access PHY register */
+ rswitch_mii_access_c45(etha, false, phyad, devad, regad, data);
+
+ /* Disable Station Management Clock */
+ clrbits_le32(etha->addr + MPIC, MPIC_PSMCS_MASK);
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ return 0;
+}
+
+static int rswitch_check_link(struct rswitch_etha *etha)
+{
+ u32 pval;
+ int ret;
+
+ /* Request Link Verification */
+ writel(MLVC_PLV, etha->addr + MLVC);
+
+ /* Complete Link Verification */
+ ret = readl_poll_sleep_timeout(etha->addr + MLVC, pval,
+ !(pval & MLVC_PLV),
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+ if (ret) {
+ debug("\n%s: Link verification timeout!", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rswitch_reset(struct rswitch_port_priv *priv)
+{
+ int ret;
+
+ setbits_le32(priv->addr + RRC, RRC_RR);
+ clrbits_le32(priv->addr + RRC, RRC_RR);
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void rswitch_bat_desc_init(struct rswitch_port_priv *priv)
+{
+ const u32 desc_size = RSWITCH_NUM_BASE_DESC * sizeof(struct rswitch_desc);
+ int i;
+
+ /* Initialize all descriptors */
+ memset(priv->bat_desc, 0x0, desc_size);
+
+ for (i = 0; i < RSWITCH_NUM_BASE_DESC; i++)
+ priv->bat_desc[i].die_dt = DT_EOS;
+
+ rswitch_flush_dcache((uintptr_t)priv->bat_desc, desc_size);
+}
+
+static void rswitch_tx_desc_init(struct rswitch_port_priv *priv)
+{
+ const u32 desc_size = RSWITCH_NUM_TX_DESC * sizeof(struct rswitch_desc);
+ u64 tx_desc_addr;
+ int i;
+
+ /* Initialize all descriptor */
+ memset(priv->tx_desc, 0x0, desc_size);
+ priv->tx_desc_index = 0;
+
+ for (i = 0; i < RSWITCH_NUM_TX_DESC; i++)
+ priv->tx_desc[i].die_dt = DT_EEMPTY;
+
+ /* Mark the end of the descriptors */
+ priv->tx_desc[RSWITCH_NUM_TX_DESC - 1].die_dt = DT_LINKFIX;
+ tx_desc_addr = (uintptr_t)priv->tx_desc;
+ priv->tx_desc[RSWITCH_NUM_TX_DESC - 1].dptrl = lower_32_bits(tx_desc_addr);
+ priv->tx_desc[RSWITCH_NUM_TX_DESC - 1].dptrh = upper_32_bits(tx_desc_addr);
+ rswitch_flush_dcache(tx_desc_addr, desc_size);
+
+ /* Point the controller to the TX descriptor list */
+ priv->bat_desc[RSWITCH_TX_CHAIN_INDEX].die_dt = DT_LINKFIX;
+ priv->bat_desc[RSWITCH_TX_CHAIN_INDEX].dptrl = lower_32_bits(tx_desc_addr);
+ priv->bat_desc[RSWITCH_TX_CHAIN_INDEX].dptrh = upper_32_bits(tx_desc_addr);
+ rswitch_flush_dcache((uintptr_t)&priv->bat_desc[RSWITCH_TX_CHAIN_INDEX],
+ sizeof(struct rswitch_desc));
+}
+
+static void rswitch_rx_desc_init(struct rswitch_port_priv *priv)
+{
+ const u32 desc_size = RSWITCH_NUM_RX_DESC * sizeof(struct rswitch_rxdesc);
+ int i;
+ u64 packet_addr;
+ u64 next_rx_desc_addr;
+ u64 rx_desc_addr;
+
+ /* Initialize all descriptor */
+ memset(priv->rx_desc, 0x0, desc_size);
+ priv->rx_desc_index = 0;
+
+ for (i = 0; i < RSWITCH_NUM_RX_DESC; i++) {
+ priv->rx_desc[i].data.die_dt = DT_EEMPTY;
+ priv->rx_desc[i].data.info_ds = PKTSIZE_ALIGN;
+ packet_addr = (uintptr_t)priv->rx_desc[i].packet;
+ priv->rx_desc[i].data.dptrl = lower_32_bits(packet_addr);
+ priv->rx_desc[i].data.dptrh = upper_32_bits(packet_addr);
+
+ priv->rx_desc[i].link.die_dt = DT_LINKFIX;
+ next_rx_desc_addr = (uintptr_t)&priv->rx_desc[i + 1];
+ priv->rx_desc[i].link.dptrl = lower_32_bits(next_rx_desc_addr);
+ priv->rx_desc[i].link.dptrh = upper_32_bits(next_rx_desc_addr);
+ }
+
+ /* Mark the end of the descriptors */
+ priv->rx_desc[RSWITCH_NUM_RX_DESC - 1].link.die_dt = DT_LINKFIX;
+ rx_desc_addr = (uintptr_t)priv->rx_desc;
+ priv->rx_desc[RSWITCH_NUM_RX_DESC - 1].link.dptrl = lower_32_bits(rx_desc_addr);
+ priv->rx_desc[RSWITCH_NUM_RX_DESC - 1].link.dptrh = upper_32_bits(rx_desc_addr);
+ rswitch_flush_dcache(rx_desc_addr, desc_size);
+
+ /* Point the controller to the rx descriptor list */
+ priv->bat_desc[RSWITCH_RX_CHAIN_INDEX].die_dt = DT_LINKFIX;
+ priv->bat_desc[RSWITCH_RX_CHAIN_INDEX].dptrl = lower_32_bits(rx_desc_addr);
+ priv->bat_desc[RSWITCH_RX_CHAIN_INDEX].dptrh = upper_32_bits(rx_desc_addr);
+ rswitch_flush_dcache((uintptr_t)&priv->bat_desc[RSWITCH_RX_CHAIN_INDEX],
+ sizeof(struct rswitch_desc));
+}
+
+static void rswitch_clock_enable(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ struct rswitch_gwca *gwca = &priv->gwca;
+
+ setbits_le32(priv->addr + RCEC, BIT(etha->index) | BIT(gwca->index) | RCEC_RCE);
+}
+
+static int rswitch_bpool_init(struct rswitch_port_priv *priv)
+{
+ u32 pval;
+
+ writel(CABPIRM_BPIOG, priv->addr + CABPIRM);
+
+ return readl_poll_sleep_timeout(priv->addr + CABPIRM, pval,
+ pval & CABPIRM_BPR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static void rswitch_mfwd_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ struct rswitch_gwca *gwca = &priv->gwca;
+
+ writel(FWPC0_DEFAULT, priv->addr + FWPC0(etha->index));
+ writel(FWPC0_DEFAULT, priv->addr + FWPC0(gwca->index));
+
+ writel(RSWITCH_RX_CHAIN_INDEX,
+ priv->addr + FWPBFCSDC(HW_INDEX_TO_GWCA(gwca->index), etha->index));
+
+ writel(BIT(gwca->index),
+ priv->addr + FWPBFC(etha->index));
+
+ writel(BIT(etha->index),
+ priv->addr + FWPBFC(gwca->index));
+}
+
+static void rswitch_rmac_init(struct rswitch_etha *etha)
+{
+ unsigned char *mac = etha->enetaddr;
+
+ /* Set MAC address */
+ writel((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
+ etha->addr + MRMAC1);
+
+ writel((mac[0] << 8) | mac[1], etha->addr + MRMAC0);
+
+ /* Set MIIx */
+ writel(MPIC_PIS_GMII | MPIC_LSC_1000, etha->addr + MPIC);
+
+ writel(0x07E707E7, etha->addr + MRAFC);
+}
+
+static int rswitch_gwca_mcast_table_reset(struct rswitch_gwca *gwca)
+{
+ u32 pval;
+
+ writel(GWMTIRM_MTIOG, gwca->addr + GWMTIRM);
+
+ return readl_poll_sleep_timeout(gwca->addr + GWMTIRM, pval,
+ pval & GWMTIRM_MTR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static int rswitch_gwca_axi_ram_reset(struct rswitch_gwca *gwca)
+{
+ u32 pval;
+
+ writel(GWARIRM_ARIOG, gwca->addr + GWARIRM);
+
+ return readl_poll_sleep_timeout(gwca->addr + GWARIRM, pval,
+ pval & GWARIRM_ARR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static int rswitch_gwca_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_gwca *gwca = &priv->gwca;
+ int ret;
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_CONFIG);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_mcast_table_reset(gwca);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_axi_ram_reset(gwca);
+ if (ret)
+ return ret;
+
+ /* Setting flow */
+ writel(GWVCC_VEM_SC_TAG, gwca->addr + GWVCC);
+ writel(0, gwca->addr + GWTTFC);
+ writel(upper_32_bits((uintptr_t)priv->bat_desc) & GWDCBAC0_DCBAUP, gwca->addr + GWDCBAC0);
+ writel(lower_32_bits((uintptr_t)priv->bat_desc), gwca->addr + GWDCBAC1);
+ writel(GWDCC_DQT | GWDCC_BALR, gwca->addr + GWDCC(RSWITCH_TX_CHAIN_INDEX));
+ writel(GWDCC_BALR, gwca->addr + GWDCC(RSWITCH_RX_CHAIN_INDEX));
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_OPERATION);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rswitch_etha_tas_ram_reset(struct rswitch_etha *etha)
+{
+ u32 pval;
+
+ writel(EATASRIRM_TASRIOG, etha->addr + EATASRIRM);
+
+ return readl_poll_sleep_timeout(etha->addr + EATASRIRM, pval,
+ pval & EATASRIRM_TASRR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static int rswitch_etha_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ int ret;
+ u32 prio;
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_CONFIG);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_tas_ram_reset(etha);
+ if (ret)
+ return ret;
+
+ /* Setting flow */
+ writel(0, etha->addr + EATTFC);
+
+ for (prio = 0; prio < RSWITCH_MAX_CTAG_PCP; prio++)
+ writel(EATDQDC_DQD, etha->addr + EATDQDC(prio));
+
+ rswitch_rmac_init(etha);
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_OPERATION);
+ if (ret)
+ return ret;
+
+ /* Link Verification */
+ ret = rswitch_check_link(etha);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rswitch_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ int ret;
+
+ ret = rswitch_reset(priv);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_set_mode(&priv->serdes, PHY_MODE_ETHERNET,
+ etha->phydev->interface);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_set_speed(&priv->serdes, etha->phydev->speed);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_init(&priv->serdes);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_power_on(&priv->serdes);
+ if (ret)
+ return ret;
+
+ ret = phy_startup(etha->phydev);
+ if (ret)
+ return ret;
+
+ rswitch_bat_desc_init(priv);
+ rswitch_tx_desc_init(priv);
+ rswitch_rx_desc_init(priv);
+
+ rswitch_clock_enable(priv);
+
+ ret = rswitch_bpool_init(priv);
+ if (ret)
+ return ret;
+
+ rswitch_mfwd_init(priv);
+
+ ret = rswitch_gwca_init(priv);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_init(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rswitch_start(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = rswitch_init(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#define RSWITCH_TX_TIMEOUT_MS 1000
+static int rswitch_send(struct udevice *dev, void *packet, int len)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_desc *desc = &priv->tx_desc[priv->tx_desc_index];
+ struct rswitch_gwca *gwca = &priv->gwca;
+ u32 gwtrc_index, start;
+
+ /* Update TX descriptor */
+ rswitch_flush_dcache((uintptr_t)packet, len);
+ memset(desc, 0x0, sizeof(*desc));
+ desc->die_dt = DT_FSINGLE;
+ desc->info_ds = len;
+ desc->dptrl = lower_32_bits((uintptr_t)packet);
+ desc->dptrh = upper_32_bits((uintptr_t)packet);
+ rswitch_flush_dcache((uintptr_t)desc, sizeof(*desc));
+
+ /* Start transmission */
+ gwtrc_index = RSWITCH_TX_CHAIN_INDEX / 32;
+ setbits_le32(gwca->addr + GWTRC(gwtrc_index), BIT(RSWITCH_TX_CHAIN_INDEX));
+
+ /* Wait until packet is transmitted */
+ start = get_timer(0);
+ while (get_timer(start) < RSWITCH_TX_TIMEOUT_MS) {
+ rswitch_invalidate_dcache((uintptr_t)desc, sizeof(*desc));
+ if ((desc->die_dt & DT_MASK) != DT_FSINGLE)
+ break;
+ udelay(10);
+ }
+
+ if (get_timer(start) >= RSWITCH_TX_TIMEOUT_MS) {
+ dev_dbg(dev, "\n%s: Timeout", __func__);
+ return -ETIMEDOUT;
+ }
+
+ priv->tx_desc_index = (priv->tx_desc_index + 1) % (RSWITCH_NUM_TX_DESC - 1);
+
+ return 0;
+}
+
+static int rswitch_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_rxdesc *desc = &priv->rx_desc[priv->rx_desc_index];
+ u8 *packet;
+ int len;
+
+ /* Check if the rx descriptor is ready */
+ rswitch_invalidate_dcache((uintptr_t)desc, sizeof(*desc));
+ if ((desc->data.die_dt & DT_MASK) == DT_FEMPTY)
+ return -EAGAIN;
+
+ len = desc->data.info_ds & RX_DS;
+ packet = (u8 *)(((uintptr_t)(desc->data.dptrh) << 32) | (uintptr_t)desc->data.dptrl);
+ rswitch_invalidate_dcache((uintptr_t)packet, len);
+
+ *packetp = packet;
+
+ return len;
+}
+
+static int rswitch_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_rxdesc *desc = &priv->rx_desc[priv->rx_desc_index];
+
+ /* Make current descritor available again */
+ desc->data.die_dt = DT_FEMPTY;
+ desc->data.info_ds = PKTSIZE_ALIGN;
+ rswitch_flush_dcache((uintptr_t)desc, sizeof(*desc));
+
+ /* Point to the next descriptor */
+ priv->rx_desc_index = (priv->rx_desc_index + 1) % RSWITCH_NUM_RX_DESC;
+ desc = &priv->rx_desc[priv->rx_desc_index];
+ rswitch_invalidate_dcache((uintptr_t)desc, sizeof(*desc));
+
+ return 0;
+}
+
+static void rswitch_stop(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+
+ phy_shutdown(priv->etha.phydev);
+
+ generic_phy_power_off(&priv->serdes);
+}
+
+static int rswitch_write_hwaddr(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_etha *etha = &priv->etha;
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ unsigned char *mac = pdata->enetaddr;
+
+ writel((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
+ etha->addr + MRMAC1);
+
+ writel((mac[0] << 8) | mac[1], etha->addr + MRMAC0);
+
+ return 0;
+}
+
+static int rswitch_phy_config(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_etha *etha = &priv->etha;
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct phy_device *phydev;
+ int phy_addr;
+
+ phy_addr = eth_phy_get_addr(dev);
+ if (phy_addr < 0)
+ return phy_addr;
+
+ phydev = phy_connect(etha->bus, phy_addr, dev, pdata->phy_interface);
+ if (!phydev)
+ return -ENODEV;
+
+ etha->phydev = phydev;
+ phydev->speed = SPEED_1000;
+
+ phy_config(phydev);
+
+ return 0;
+}
+
+static int rswitch_port_probe(struct udevice *dev)
+{
+ struct rswitch_priv *rpriv =
+ (struct rswitch_priv *)dev_get_driver_data(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_etha *etha = &priv->etha;
+ struct rswitch_gwca *gwca = &priv->gwca;
+ struct mii_dev *mdiodev;
+ int ret;
+
+ priv->addr = rpriv->addr;
+
+ etha->enetaddr = pdata->enetaddr;
+
+ etha->index = dev_read_u32_default(dev, "reg", 0);
+ etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + etha->index * RSWITCH_ETHA_SIZE;
+
+ gwca->index = 1;
+ gwca->addr = priv->addr + RSWITCH_GWCA_OFFSET + gwca->index * RSWITCH_GWCA_SIZE;
+ gwca->index = GWCA_TO_HW_INDEX(gwca->index);
+
+ ret = generic_phy_get_by_index(dev, 0, &priv->serdes);
+ if (ret)
+ return ret;
+
+ /* Toggle the reset so we can access the PHYs */
+ ret = rswitch_reset(priv);
+ if (ret)
+ return ret;
+
+ mdiodev = mdio_alloc();
+ if (!mdiodev)
+ return -ENOMEM;
+
+ mdiodev->priv = priv;
+ mdiodev->read = rswitch_mii_read_c45;
+ mdiodev->write = rswitch_mii_write_c45;
+ snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name);
+
+ ret = mdio_register(mdiodev);
+ if (ret)
+ goto err_mdio_register;
+
+ priv->etha.bus = miiphy_get_dev_by_name(dev->name);
+
+ ret = rswitch_phy_config(dev);
+ if (ret)
+ goto err_mdio_register;
+
+ return 0;
+
+err_mdio_register:
+ mdio_free(mdiodev);
+ return ret;
+}
+
+static int rswitch_port_remove(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+
+ mdio_unregister(priv->etha.bus);
+ free(priv->etha.phydev);
+
+ return 0;
+}
+
+int rswitch_ofdata_to_platdata(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+
+ pdata->phy_interface = dev_read_phy_mode(dev);
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
+ return -EINVAL;
+
+ pdata->max_speed = dev_read_u32_default(dev, "max-speed", 1000);
+
+ return 0;
+}
+
+static const struct eth_ops rswitch_port_ops = {
+ .start = rswitch_start,
+ .send = rswitch_send,
+ .recv = rswitch_recv,
+ .free_pkt = rswitch_free_pkt,
+ .stop = rswitch_stop,
+ .write_hwaddr = rswitch_write_hwaddr,
+};
+
+U_BOOT_DRIVER(rswitch_port) = {
+ .name = "rswitch-port",
+ .id = UCLASS_ETH,
+ .of_to_plat = rswitch_ofdata_to_platdata,
+ .probe = rswitch_port_probe,
+ .remove = rswitch_port_remove,
+ .ops = &rswitch_port_ops,
+ .priv_auto = sizeof(struct rswitch_port_priv),
+ .plat_auto = sizeof(struct eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE,
+};
+
+static int rswitch_probe(struct udevice *dev)
+{
+ struct rswitch_priv *priv = dev_get_plat(dev);
+ fdt_addr_t secure_base;
+ fdt_size_t size;
+ int ret;
+
+ secure_base = dev_read_addr_size_name(dev, "secure_base", &size);
+ if (!secure_base)
+ return -EINVAL;
+
+ priv->addr = map_physmem(secure_base, size, MAP_NOCACHE);
+ if (!priv->addr)
+ return -EINVAL;
+
+ priv->rsw_clk = devm_clk_get(dev, NULL);
+ if (ret)
+ goto err_map;
+
+ ret = clk_prepare_enable(priv->rsw_clk);
+ if (ret)
+ goto err_map;
+
+ return 0;
+
+err_map:
+ unmap_physmem(priv->addr, MAP_NOCACHE);
+ return ret;
+}
+
+static int rswitch_remove(struct udevice *dev)
+{
+ struct rswitch_priv *priv = dev_get_plat(dev);
+
+ clk_disable_unprepare(priv->rsw_clk);
+ unmap_physmem(priv->addr, MAP_NOCACHE);
+
+ return 0;
+}
+
+static int rswitch_bind(struct udevice *parent)
+{
+ struct rswitch_port_priv *priv = dev_get_plat(parent);
+ ofnode ports_np, node;
+ struct udevice *dev;
+ struct driver *drv;
+ int ret;
+
+ drv = lists_driver_lookup_name("rswitch-port");
+ if (!drv)
+ return -ENOENT;
+
+ ports_np = dev_read_subnode(parent, "ethernet-ports");
+ if (!ofnode_valid(ports_np))
+ return -ENOENT;
+
+ ofnode_for_each_subnode(node, ports_np) {
+ ret = device_bind_with_driver_data(parent, drv,
+ ofnode_get_name(node),
+ (ulong)priv, node, &dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id rswitch_ids[] = {
+ { .compatible = "renesas,r8a779f0-ether-switch" },
+ { }
+};
+
+U_BOOT_DRIVER(rswitch) = {
+ .name = "rswitch",
+ .id = UCLASS_NOP,
+ .of_match = rswitch_ids,
+ .bind = rswitch_bind,
+ .probe = rswitch_probe,
+ .remove = rswitch_remove,
+ .plat_auto = sizeof(struct rswitch_priv),
+};
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index c9c07a5a8ff..2276a465e78 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -118,9 +118,9 @@ enum RTL8169_registers {
FLASH = 0x30,
ERSR = 0x36,
ChipCmd = 0x37,
- TxPoll = 0x38,
- IntrMask = 0x3C,
- IntrStatus = 0x3E,
+ TxPoll_8169 = 0x38,
+ IntrMask_8169 = 0x3C,
+ IntrStatus_8169 = 0x3E,
TxConfig = 0x40,
RxConfig = 0x44,
RxMissed = 0x4C,
@@ -148,6 +148,12 @@ enum RTL8169_registers {
FuncForceEvent = 0xFC,
};
+enum RTL8125_registers {
+ IntrMask_8125 = 0x38,
+ IntrStatus_8125 = 0x3C,
+ TxPoll_8125 = 0x90,
+};
+
enum RTL8169_register_content {
/*InterruptStatusBits */
SYSErr = 0x8000,
@@ -263,6 +269,7 @@ static struct {
{"RTL-8101e", 0x34, 0xff7e1880,},
{"RTL-8100e", 0x32, 0xff7e1880,},
{"RTL-8168h/8111h", 0x54, 0xff7e1880,},
+ {"RTL-8125B", 0x64, 0xff7e1880,},
};
enum _DescStatusBit {
@@ -347,6 +354,7 @@ static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125) },
{}
};
@@ -517,6 +525,7 @@ static int rtl_recv_common(struct udevice *dev, unsigned long dev_iobase,
/* return true if there's an ethernet packet ready to read */
/* nic->packet should contain data on return */
/* nic->packetlen should contain length of data */
+ struct pci_child_plat *pplat = dev_get_parent_plat(dev);
int cur_rx;
int length = 0;
@@ -558,6 +567,10 @@ static int rtl_recv_common(struct udevice *dev, unsigned long dev_iobase,
return length;
} else {
+ u32 IntrStatus = IntrStatus_8169;
+
+ if (pplat->device == 0x8125)
+ IntrStatus = IntrStatus_8125;
ushort sts = RTL_R8(IntrStatus);
RTL_W8(IntrStatus, sts & ~(TxErr | RxErr | SYSErr));
udelay(100); /* wait */
@@ -582,6 +595,7 @@ static int rtl_send_common(struct udevice *dev, unsigned long dev_iobase,
{
/* send the packet to destination */
+ struct pci_child_plat *pplat = dev_get_parent_plat(dev);
u32 to;
u8 *ptxb;
int entry = tpc->cur_tx % NUM_TX_DESC;
@@ -618,7 +632,10 @@ static int rtl_send_common(struct udevice *dev, unsigned long dev_iobase,
((len > ETH_ZLEN) ? len : ETH_ZLEN));
}
rtl_flush_tx_desc(&tpc->TxDescArray[entry]);
- RTL_W8(TxPoll, 0x40); /* set polling bit */
+ if (pplat->device == 0x8125)
+ RTL_W8(TxPoll_8125, 0x1); /* set polling bit */
+ else
+ RTL_W8(TxPoll_8169, 0x40); /* set polling bit */
tpc->cur_tx++;
to = currticks() + TX_TIMEOUT;
@@ -824,21 +841,26 @@ static int rtl8169_eth_start(struct udevice *dev)
return 0;
}
-static void rtl_halt_common(unsigned long dev_iobase)
+static void rtl_halt_common(struct udevice *dev)
{
+ struct rtl8169_private *priv = dev_get_priv(dev);
+ struct pci_child_plat *pplat = dev_get_parent_plat(dev);
int i;
#ifdef DEBUG_RTL8169
printf ("%s\n", __FUNCTION__);
#endif
- ioaddr = dev_iobase;
+ ioaddr = priv->iobase;
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8(ChipCmd, 0x00);
/* Disable interrupts by clearing the interrupt mask. */
- RTL_W16(IntrMask, 0x0000);
+ if (pplat->device == 0x8125)
+ RTL_W16(IntrMask_8125, 0x0000);
+ else
+ RTL_W16(IntrMask_8169, 0x0000);
RTL_W32(RxMissed, 0);
@@ -849,9 +871,7 @@ static void rtl_halt_common(unsigned long dev_iobase)
void rtl8169_eth_stop(struct udevice *dev)
{
- struct rtl8169_private *priv = dev_get_priv(dev);
-
- rtl_halt_common(priv->iobase);
+ rtl_halt_common(dev);
}
static int rtl8169_write_hwaddr(struct udevice *dev)
@@ -1025,23 +1045,25 @@ static int rtl8169_eth_probe(struct udevice *dev)
struct pci_child_plat *pplat = dev_get_parent_plat(dev);
struct rtl8169_private *priv = dev_get_priv(dev);
struct eth_pdata *plat = dev_get_plat(dev);
- u32 iobase;
int region;
int ret;
- debug("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);
switch (pplat->device) {
case 0x8168:
+ case 0x8125:
region = 2;
break;
default:
region = 1;
break;
}
- dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0 + region * 4, &iobase);
- iobase &= ~0xf;
- priv->iobase = (int)dm_pci_mem_to_phys(dev, iobase);
+ priv->iobase = (ulong)dm_pci_map_bar(dev,
+ PCI_BASE_ADDRESS_0 + region * 4,
+ 0, 0,
+ PCI_REGION_TYPE, PCI_REGION_MEM);
+
+ debug("rtl8169: REALTEK RTL8169 @0x%lx\n", priv->iobase);
ret = rtl_init(priv->iobase, dev->name, plat->enetaddr);
if (ret < 0) {
printf(pr_fmt("failed to initialize card: %d\n"), ret);
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index e800a326b81..04c3274fbe1 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -127,12 +127,10 @@
DECLARE_GLOBAL_DATA_PTR;
-enum emac_variant {
- A83T_EMAC = 1,
- H3_EMAC,
- A64_EMAC,
- R40_GMAC,
- H6_EMAC,
+struct emac_variant {
+ uint syscon_offset;
+ bool soc_has_internal_phy;
+ bool support_rmii;
};
struct emac_dma_desc {
@@ -160,9 +158,9 @@ struct emac_eth_dev {
u32 tx_slot;
bool use_internal_phy;
- enum emac_variant variant;
+ const struct emac_variant *variant;
void *mac_reg;
- phys_addr_t sysctl_reg;
+ void *sysctl_reg;
struct phy_device *phydev;
struct mii_dev *bus;
struct clk tx_clk;
@@ -317,25 +315,12 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
{
u32 reg;
- if (priv->variant == R40_GMAC) {
- /* Select RGMII for R40 */
- reg = readl(priv->sysctl_reg + 0x164);
- reg |= SC_ETCS_INT_GMII |
- SC_EPIT |
- (CONFIG_GMAC_TX_DELAY << SC_ETXDC_OFFSET);
-
- writel(reg, priv->sysctl_reg + 0x164);
- return 0;
- }
-
- reg = readl(priv->sysctl_reg + 0x30);
+ reg = readl(priv->sysctl_reg);
reg = sun8i_emac_set_syscon_ephy(priv, reg);
reg &= ~(SC_ETCS_MASK | SC_EPIT);
- if (priv->variant == H3_EMAC ||
- priv->variant == A64_EMAC ||
- priv->variant == H6_EMAC)
+ if (priv->variant->support_rmii)
reg &= ~SC_RMII_EN;
switch (priv->interface) {
@@ -349,13 +334,10 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
reg |= SC_EPIT | SC_ETCS_INT_GMII;
break;
case PHY_INTERFACE_MODE_RMII:
- if (priv->variant == H3_EMAC ||
- priv->variant == A64_EMAC ||
- priv->variant == H6_EMAC) {
+ if (priv->variant->support_rmii) {
reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
- break;
+ break;
}
- /* RMII not supported on A83T */
default:
debug("%s: Invalid PHY interface\n", __func__);
return -EINVAL;
@@ -369,7 +351,7 @@ static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
& SC_ERXDC_MASK;
- writel(reg, priv->sysctl_reg + 0x30);
+ writel(reg, priv->sysctl_reg);
return 0;
}
@@ -792,6 +774,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
struct emac_eth_dev *priv = dev_get_priv(dev);
+ phys_addr_t syscon_base;
const fdt32_t *reg;
int node = dev_of_offset(dev);
int offset = 0;
@@ -806,7 +789,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
return -EINVAL;
}
- priv->variant = dev_get_driver_data(dev);
+ priv->variant = (const void *)dev_get_driver_data(dev);
if (!priv->variant) {
printf("%s: Missing variant\n", __func__);
@@ -837,13 +820,15 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
__func__);
return -EINVAL;
}
- priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob,
- offset, reg);
- if (priv->sysctl_reg == FDT_ADDR_T_NONE) {
+
+ syscon_base = fdt_translate_address((void *)gd->fdt_blob, offset, reg);
+ if (syscon_base == FDT_ADDR_T_NONE) {
debug("%s: Cannot find syscon base address\n", __func__);
return -EINVAL;
}
+ priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
+
pdata->phy_interface = -1;
priv->phyaddr = -1;
priv->use_internal_phy = false;
@@ -860,7 +845,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
return -EINVAL;
- if (priv->variant == H3_EMAC) {
+ if (priv->variant->soc_has_internal_phy) {
ret = sun8i_handle_internal_phy(dev, priv);
if (ret)
return ret;
@@ -900,16 +885,41 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
return 0;
}
+static const struct emac_variant emac_variant_a83t = {
+ .syscon_offset = 0x30,
+};
+
+static const struct emac_variant emac_variant_h3 = {
+ .syscon_offset = 0x30,
+ .soc_has_internal_phy = true,
+ .support_rmii = true,
+};
+
+static const struct emac_variant emac_variant_r40 = {
+ .syscon_offset = 0x164,
+};
+
+static const struct emac_variant emac_variant_a64 = {
+ .syscon_offset = 0x30,
+ .support_rmii = true,
+};
+
+static const struct emac_variant emac_variant_h6 = {
+ .syscon_offset = 0x30,
+ .support_rmii = true,
+};
+
static const struct udevice_id sun8i_emac_eth_ids[] = {
- {.compatible = "allwinner,sun8i-h3-emac", .data = (uintptr_t)H3_EMAC },
- {.compatible = "allwinner,sun50i-a64-emac",
- .data = (uintptr_t)A64_EMAC },
- {.compatible = "allwinner,sun8i-a83t-emac",
- .data = (uintptr_t)A83T_EMAC },
- {.compatible = "allwinner,sun8i-r40-gmac",
- .data = (uintptr_t)R40_GMAC },
- {.compatible = "allwinner,sun50i-h6-emac",
- .data = (uintptr_t)H6_EMAC },
+ { .compatible = "allwinner,sun8i-a83t-emac",
+ .data = (ulong)&emac_variant_a83t },
+ { .compatible = "allwinner,sun8i-h3-emac",
+ .data = (ulong)&emac_variant_h3 },
+ { .compatible = "allwinner,sun8i-r40-gmac",
+ .data = (ulong)&emac_variant_r40 },
+ { .compatible = "allwinner,sun50i-a64-emac",
+ .data = (ulong)&emac_variant_a64 },
+ { .compatible = "allwinner,sun50i-h6-emac",
+ .data = (ulong)&emac_variant_h6 },
{ }
};
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 14fd3bbf679..01230360bad 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -580,10 +580,6 @@ int dm_pciauto_config_device(struct udevice *dev)
break;
#endif
- case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
- debug("PCI AutoConfig: Found PowerPC device\n");
- /* fall through */
-
default:
dm_pciauto_setup_device(dev, pci_mem, pci_prefetch, pci_io);
break;
diff --git a/drivers/pci/pci_mpc85xx.c b/drivers/pci/pci_mpc85xx.c
index 8a81a74067e..249cfe66466 100644
--- a/drivers/pci/pci_mpc85xx.c
+++ b/drivers/pci/pci_mpc85xx.c
@@ -22,10 +22,33 @@ static int mpc85xx_pci_dm_read_config(const struct udevice *dev, pci_dev_t bdf,
struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
u32 addr;
- addr = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset);
+ if (offset > 0xff) {
+ *value = pci_get_ff(size);
+ return 0;
+ }
+
+ /* Skip mpc85xx PCI controller's ATMU inbound registers */
+ if (PCI_BUS(bdf) == 0 && PCI_DEV(bdf) == 0 && PCI_FUNC(bdf) == 0 &&
+ (offset & ~3) >= PCI_BASE_ADDRESS_0 && (offset & ~3) <= PCI_BASE_ADDRESS_5) {
+ *value = 0;
+ return 0;
+ }
+
+ addr = PCI_CONF1_ADDRESS(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset);
out_be32(priv->cfg_addr, addr);
sync();
- *value = pci_conv_32_to_size(in_le32(priv->cfg_data), offset, size);
+
+ switch (size) {
+ case PCI_SIZE_8:
+ *value = in_8(priv->cfg_data + (offset & 3));
+ break;
+ case PCI_SIZE_16:
+ *value = in_le16(priv->cfg_data + (offset & 2));
+ break;
+ case PCI_SIZE_32:
+ *value = in_le32(priv->cfg_data);
+ break;
+ }
return 0;
}
@@ -37,10 +60,30 @@ static int mpc85xx_pci_dm_write_config(struct udevice *dev, pci_dev_t bdf,
struct mpc85xx_pci_priv *priv = dev_get_priv(dev);
u32 addr;
- addr = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset);
+ if (offset > 0xff)
+ return 0;
+
+ /* Skip mpc85xx PCI controller's ATMU inbound registers */
+ if (PCI_BUS(bdf) == 0 && PCI_DEV(bdf) == 0 && PCI_FUNC(bdf) == 0 &&
+ (offset & ~3) >= PCI_BASE_ADDRESS_0 && (offset & ~3) <= PCI_BASE_ADDRESS_5)
+ return 0;
+
+ addr = PCI_CONF1_ADDRESS(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset);
out_be32(priv->cfg_addr, addr);
sync();
- out_le32(priv->cfg_data, pci_conv_size_to_32(0, value, offset, size));
+
+ switch (size) {
+ case PCI_SIZE_8:
+ out_8(priv->cfg_data + (offset & 3), value);
+ break;
+ case PCI_SIZE_16:
+ out_le16(priv->cfg_data + (offset & 2), value);
+ break;
+ case PCI_SIZE_32:
+ out_le32(priv->cfg_data, value);
+ break;
+ }
+ sync();
return 0;
}
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c
index 4600652f2b1..8d89a1e5919 100644
--- a/drivers/pci/pcie_fsl.c
+++ b/drivers/pci/pcie_fsl.c
@@ -58,6 +58,14 @@ static int fsl_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
return 0;
}
+ /* Skip Freescale PCIe controller's PEXCSRBAR register */
+ if (PCI_BUS(bdf) - dev_seq(bus) == 0 &&
+ PCI_DEV(bdf) == 0 && PCI_FUNC(bdf) == 0 &&
+ (offset & ~3) == PCI_BASE_ADDRESS_0) {
+ *valuep = 0;
+ return 0;
+ }
+
val = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf) - dev_seq(bus),
PCI_DEV(bdf), PCI_FUNC(bdf),
offset);
@@ -95,6 +103,12 @@ static int fsl_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
if (fsl_pcie_addr_valid(pcie, bdf))
return 0;
+ /* Skip Freescale PCIe controller's PEXCSRBAR register */
+ if (PCI_BUS(bdf) - dev_seq(bus) == 0 &&
+ PCI_DEV(bdf) == 0 && PCI_FUNC(bdf) == 0 &&
+ (offset & ~3) == PCI_BASE_ADDRESS_0)
+ return 0;
+
val = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf) - dev_seq(bus),
PCI_DEV(bdf), PCI_FUNC(bdf),
offset);
diff --git a/drivers/pci/pcie_layerscape_rc.c b/drivers/pci/pcie_layerscape_rc.c
index 17969e2f236..6a5bf88da23 100644
--- a/drivers/pci/pcie_layerscape_rc.c
+++ b/drivers/pci/pcie_layerscape_rc.c
@@ -403,6 +403,7 @@ static const struct ls_pcie_drvdata ls1028a_drvdata = {
static const struct udevice_id ls_pcie_ids[] = {
{ .compatible = "fsl,ls-pcie" },
{ .compatible = "fsl,ls1028a-pcie", .data = (ulong)&ls1028a_drvdata },
+ { .compatible = "fsl,ls1088a-pcie", .data = (ulong)&ls1028a_drvdata },
{ }
};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index cf4d5908d73..7a2d54f71d2 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -285,5 +285,6 @@ source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/cadence/Kconfig"
source "drivers/phy/ti/Kconfig"
source "drivers/phy/qcom/Kconfig"
+source "drivers/phy/renesas/Kconfig"
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a3b9f3c5b18..aca365d219c 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o
obj-y += cadence/
obj-y += ti/
obj-y += qcom/
+obj-y += renesas/
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 2e969ab91e3..6428163c188 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -224,6 +224,12 @@ static int sun4i_usb_phy_power_on(struct phy *phy)
initial_usb_scan_delay = 0;
}
+ /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
+ if (phy->id == 0 && sun4i_usb_phy_vbus_detect(phy)) {
+ dev_warn(phy->dev, "External vbus detected, not enabling our own vbus\n");
+ return 0;
+ }
+
if (dm_gpio_is_valid(&usb_phy->gpio_vbus))
dm_gpio_set_value(&usb_phy->gpio_vbus, 1);
diff --git a/drivers/phy/phy-ti-am654.c b/drivers/phy/phy-ti-am654.c
index 27a312227bc..70a746d2c92 100644
--- a/drivers/phy/phy-ti-am654.c
+++ b/drivers/phy/phy-ti-am654.c
@@ -16,7 +16,6 @@
#include <dt-bindings/phy/phy.h>
#include <generic-phy.h>
#include <asm/io.h>
-#include <asm/arch/sys_proto.h>
#include <power-domain.h>
#include <regmap.h>
#include <syscon.h>
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 3fef5135a9c..83e4b63079d 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -351,6 +351,28 @@ int generic_phy_configure(struct phy *phy, void *params)
return ops->configure ? ops->configure(phy, params) : 0;
}
+int generic_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct phy_ops const *ops;
+
+ if (!generic_phy_valid(phy))
+ return 0;
+ ops = phy_dev_ops(phy->dev);
+
+ return ops->set_mode ? ops->set_mode(phy, mode, submode) : 0;
+}
+
+int generic_phy_set_speed(struct phy *phy, int speed)
+{
+ struct phy_ops const *ops;
+
+ if (!generic_phy_valid(phy))
+ return 0;
+ ops = phy_dev_ops(phy->dev);
+
+ return ops->set_speed ? ops->set_speed(phy, speed) : 0;
+}
+
int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk)
{
int i, ret, count;
diff --git a/drivers/phy/renesas/Kconfig b/drivers/phy/renesas/Kconfig
new file mode 100644
index 00000000000..0efb0f8f337
--- /dev/null
+++ b/drivers/phy/renesas/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Phy drivers for Renesas platforms
+
+config PHY_R8A779F0_ETHERNET_SERDES
+ tristate "Renesas R-Car S4-8 Ethernet SERDES driver"
+ depends on RCAR_64 && PHY
+ help
+ Support for Ethernet SERDES found on Renesas R-Car S4-8 SoCs.
diff --git a/drivers/phy/renesas/Makefile b/drivers/phy/renesas/Makefile
new file mode 100644
index 00000000000..fd6b8d964e5
--- /dev/null
+++ b/drivers/phy/renesas/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PHY_R8A779F0_ETHERNET_SERDES) += r8a779f0-ether-serdes.o
diff --git a/drivers/phy/renesas/r8a779f0-ether-serdes.c b/drivers/phy/renesas/r8a779f0-ether-serdes.c
new file mode 100644
index 00000000000..bd1fdd3a667
--- /dev/null
+++ b/drivers/phy/renesas/r8a779f0-ether-serdes.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Renesas Ethernet SERDES device driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+
+#include <asm/io.h>
+#include <clk-uclass.h>
+#include <clk.h>
+#include <common.h>
+#include <div64.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <dm/of_access.h>
+#include <generic-phy.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <log.h>
+#include <reset.h>
+#include <syscon.h>
+
+#define R8A779F0_ETH_SERDES_NUM 3
+#define R8A779F0_ETH_SERDES_OFFSET 0x0400
+#define R8A779F0_ETH_SERDES_BANK_SELECT 0x03fc
+#define R8A779F0_ETH_SERDES_TIMEOUT_US 100000
+#define R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP 3
+
+struct r8a779f0_eth_serdes_drv_data;
+struct r8a779f0_eth_serdes_channel {
+ struct r8a779f0_eth_serdes_drv_data *dd;
+ struct phy *phy;
+ void __iomem *addr;
+ phy_interface_t phy_interface;
+ int speed;
+ int index;
+};
+
+struct r8a779f0_eth_serdes_drv_data {
+ void __iomem *addr;
+ struct reset_ctl *reset;
+ struct r8a779f0_eth_serdes_channel channel[R8A779F0_ETH_SERDES_NUM];
+ bool initialized;
+};
+
+/*
+ * The datasheet describes initialization procedure without any information
+ * about registers' name/bits. So, this is all black magic to initialize
+ * the hardware.
+ */
+static void r8a779f0_eth_serdes_write32(void __iomem *addr, u32 offs, u32 bank, u32 data)
+{
+ writel(bank, addr + R8A779F0_ETH_SERDES_BANK_SELECT);
+ writel(data, addr + offs);
+}
+
+static int
+r8a779f0_eth_serdes_reg_wait(struct r8a779f0_eth_serdes_channel *channel,
+ u32 offs, u32 bank, u32 mask, u32 expected)
+{
+ u32 val = 0;
+ int ret;
+
+ writel(bank, channel->addr + R8A779F0_ETH_SERDES_BANK_SELECT);
+
+ ret = readl_poll_timeout(channel->addr + offs, val,
+ (val & mask) == expected,
+ R8A779F0_ETH_SERDES_TIMEOUT_US);
+ if (ret)
+ dev_dbg(channel->phy->dev,
+ "%s: index %d, offs %x, bank %x, mask %x, expected %x\n",
+ __func__, channel->index, offs, bank, mask, expected);
+
+ return ret;
+}
+
+static int
+r8a779f0_eth_serdes_common_init_ram(struct r8a779f0_eth_serdes_drv_data *dd)
+{
+ struct r8a779f0_eth_serdes_channel *channel;
+ int i, ret;
+
+ for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
+ channel = &dd->channel[i];
+ ret = r8a779f0_eth_serdes_reg_wait(channel, 0x026c, 0x180, BIT(0), 0x01);
+ if (ret)
+ return ret;
+ }
+
+ r8a779f0_eth_serdes_write32(dd->addr, 0x026c, 0x180, 0x03);
+
+ return ret;
+}
+
+static int
+r8a779f0_eth_serdes_common_setting(struct r8a779f0_eth_serdes_channel *channel)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = channel->dd;
+
+ switch (channel->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ r8a779f0_eth_serdes_write32(dd->addr, 0x0244, 0x180, 0x0097);
+ r8a779f0_eth_serdes_write32(dd->addr, 0x01d0, 0x180, 0x0060);
+ r8a779f0_eth_serdes_write32(dd->addr, 0x01d8, 0x180, 0x2200);
+ r8a779f0_eth_serdes_write32(dd->addr, 0x01d4, 0x180, 0x0000);
+ r8a779f0_eth_serdes_write32(dd->addr, 0x01e0, 0x180, 0x003d);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel)
+{
+ int ret;
+
+ switch (channel->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2000);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x01c0, 0x180, 0x0011);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0248, 0x180, 0x0540);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0258, 0x180, 0x0015);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0100);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x01a0, 0x180, 0x0000);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00d0, 0x180, 0x0002);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0150, 0x180, 0x0003);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0100);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0100);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0174, 0x180, 0x0000);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0160, 0x180, 0x0007);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x01ac, 0x180, 0x0000);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x0310);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0101);
+ ret = r8a779f0_eth_serdes_reg_wait(channel, 0x00c8, 0x0180, BIT(0), 0);
+ if (ret)
+ return ret;
+
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0101);
+ ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0148, 0x0180, BIT(0), 0);
+ if (ret)
+ return ret;
+
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x1310);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00d8, 0x180, 0x1800);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x00dc, 0x180, 0x0000);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x001c, 0x300, 0x0001);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2100);
+ ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0000, 0x0380, BIT(8), 0);
+ if (ret)
+ return ret;
+
+ if (channel->speed == 1000)
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x0140);
+ else if (channel->speed == 100)
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x2100);
+
+ /* For AN_ON */
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0004, 0x1f80, 0x0005);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0028, 0x1f80, 0x07a1);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f80, 0x0208);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int
+r8a779f0_eth_serdes_chan_speed(struct r8a779f0_eth_serdes_channel *channel)
+{
+ int ret;
+
+ switch (channel->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ /* For AN_ON */
+ if (channel->speed == 1000)
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x1140);
+ else if (channel->speed == 100)
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x3100);
+ ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0008, 0x1f80, BIT(0), 1);
+ if (ret)
+ return ret;
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0008, 0x1f80, 0x0000);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int r8a779f0_eth_serdes_monitor_linkup(struct r8a779f0_eth_serdes_channel *channel)
+{
+ int i, ret;
+
+ for (i = 0; i < R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP; i++) {
+ ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0004, 0x300,
+ BIT(2), BIT(2));
+ if (!ret)
+ break;
+
+ /* restart */
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0100);
+ udelay(1);
+ r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0000);
+ }
+
+ return ret;
+}
+
+static int r8a779f0_eth_serdes_hw_init(struct r8a779f0_eth_serdes_channel *channel)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = channel->dd;
+ int i, ret;
+
+ if (dd->initialized)
+ return 0;
+
+ ret = r8a779f0_eth_serdes_common_init_ram(dd);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
+ ret = r8a779f0_eth_serdes_reg_wait(&dd->channel[i], 0x0000,
+ 0x300, BIT(15), 0);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++)
+ r8a779f0_eth_serdes_write32(dd->channel[i].addr, 0x03d4, 0x380, 0x0443);
+
+ ret = r8a779f0_eth_serdes_common_setting(channel);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++)
+ r8a779f0_eth_serdes_write32(dd->channel[i].addr, 0x03d0, 0x380, 0x0001);
+
+ r8a779f0_eth_serdes_write32(dd->addr, 0x0000, 0x380, 0x8000);
+
+ ret = r8a779f0_eth_serdes_common_init_ram(dd);
+ if (ret)
+ return ret;
+
+ return r8a779f0_eth_serdes_reg_wait(&dd->channel[0], 0x0000, 0x380, BIT(15), 0);
+}
+
+static int r8a779f0_eth_serdes_init(struct phy *p)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
+ struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
+ int ret;
+
+ ret = r8a779f0_eth_serdes_hw_init(channel);
+ if (!ret)
+ channel->dd->initialized = true;
+
+ return ret;
+}
+
+static int r8a779f0_eth_serdes_hw_init_late(struct r8a779f0_eth_serdes_channel *channel)
+{
+ int ret;
+
+ ret = r8a779f0_eth_serdes_chan_setting(channel);
+ if (ret)
+ return ret;
+
+ ret = r8a779f0_eth_serdes_chan_speed(channel);
+ if (ret)
+ return ret;
+
+ r8a779f0_eth_serdes_write32(channel->addr, 0x03c0, 0x380, 0x0000);
+
+ r8a779f0_eth_serdes_write32(channel->addr, 0x03d0, 0x380, 0x0000);
+
+ return r8a779f0_eth_serdes_monitor_linkup(channel);
+}
+
+static int r8a779f0_eth_serdes_power_on(struct phy *p)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
+ struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
+
+ return r8a779f0_eth_serdes_hw_init_late(channel);
+}
+
+static int r8a779f0_eth_serdes_set_mode(struct phy *p, enum phy_mode mode,
+ int submode)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
+ struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
+
+ if (mode != PHY_MODE_ETHERNET)
+ return -EOPNOTSUPP;
+
+ switch (submode) {
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_USXGMII:
+ channel->phy_interface = submode;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int r8a779f0_eth_serdes_set_speed(struct phy *p, int speed)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
+ struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
+
+ channel->speed = speed;
+
+ return 0;
+}
+
+static int r8a779f0_eth_serdes_of_xlate(struct phy *phy,
+ struct ofnode_phandle_args *args)
+{
+ if (args->args_count < 1)
+ return -ENODEV;
+
+ if (args->args[0] >= R8A779F0_ETH_SERDES_NUM)
+ return -ENODEV;
+
+ phy->id = args->args[0];
+
+ return 0;
+}
+
+static const struct phy_ops r8a779f0_eth_serdes_ops = {
+ .init = r8a779f0_eth_serdes_init,
+ .power_on = r8a779f0_eth_serdes_power_on,
+ .set_mode = r8a779f0_eth_serdes_set_mode,
+ .set_speed = r8a779f0_eth_serdes_set_speed,
+ .of_xlate = r8a779f0_eth_serdes_of_xlate,
+};
+
+static const struct udevice_id r8a779f0_eth_serdes_of_table[] = {
+ { .compatible = "renesas,r8a779f0-ether-serdes", },
+ { }
+};
+
+static int r8a779f0_eth_serdes_probe(struct udevice *dev)
+{
+ struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(dev);
+ int i;
+
+ dd->addr = dev_read_addr_ptr(dev);
+ if (!dd->addr)
+ return -EINVAL;
+
+ dd->reset = devm_reset_control_get(dev, NULL);
+ if (IS_ERR(dd->reset))
+ return PTR_ERR(dd->reset);
+
+ reset_assert(dd->reset);
+ reset_deassert(dd->reset);
+
+ for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
+ struct r8a779f0_eth_serdes_channel *channel = &dd->channel[i];
+
+ channel->addr = dd->addr + R8A779F0_ETH_SERDES_OFFSET * i;
+ channel->dd = dd;
+ channel->index = i;
+ }
+
+ return 0;
+}
+
+U_BOOT_DRIVER(r8a779f0_eth_serdes_driver_platform) = {
+ .name = "r8a779f0_eth_serdes",
+ .id = UCLASS_PHY,
+ .of_match = r8a779f0_eth_serdes_of_table,
+ .probe = r8a779f0_eth_serdes_probe,
+ .ops = &r8a779f0_eth_serdes_ops,
+ .priv_auto = sizeof(struct r8a779f0_eth_serdes_drv_data),
+};
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 13057639403..f87ca8c3106 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -4,6 +4,14 @@
menu "Rockchip PHY driver"
+config PHY_ROCKCHIP_INNO_DSIDPHY
+ bool "Rockchip INNO DSIDPHY Driver"
+ depends on ARCH_ROCKCHIP
+ select PHY
+ select MIPI_DPHY_HELPERS
+ help
+ Support for Rockchip MIPI DPHY with Innosilicon IP block.
+
config PHY_ROCKCHIP_INNO_USB2
bool "Rockchip INNO USB2PHY Driver"
depends on ARCH_ROCKCHIP
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index a236877234b..25a803a8a86 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY) += phy-rockchip-naneng-combphy.o
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
new file mode 100644
index 00000000000..9ed7af0d6ef
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
@@ -0,0 +1,680 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
+ *
+ * Author: Wyon Bi <[email protected]>
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <div64.h>
+#include <generic-phy.h>
+#include <linux/kernel.h>
+#include <linux/iopoll.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <phy-mipi-dphy.h>
+#include <reset.h>
+
+#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
+
+/*
+ * The offset address[7:0] is distributed two parts, one from the bit7 to bit5
+ * is the first address, the other from the bit4 to bit0 is the second address.
+ * when you configure the registers, you must set both of them. The Clock Lane
+ * and Data Lane use the same registers with the same second address, but the
+ * first address is different.
+ */
+#define FIRST_ADDRESS(x) (((x) & 0x7) << 5)
+#define SECOND_ADDRESS(x) (((x) & 0x1f) << 0)
+#define PHY_REG(first, second) (FIRST_ADDRESS(first) | \
+ SECOND_ADDRESS(second))
+
+/* Analog Register Part: reg00 */
+#define BANDGAP_POWER_MASK BIT(7)
+#define BANDGAP_POWER_DOWN BIT(7)
+#define BANDGAP_POWER_ON 0
+#define LANE_EN_MASK GENMASK(6, 2)
+#define LANE_EN_CK BIT(6)
+#define LANE_EN_3 BIT(5)
+#define LANE_EN_2 BIT(4)
+#define LANE_EN_1 BIT(3)
+#define LANE_EN_0 BIT(2)
+#define POWER_WORK_MASK GENMASK(1, 0)
+#define POWER_WORK_ENABLE UPDATE(1, 1, 0)
+#define POWER_WORK_DISABLE UPDATE(2, 1, 0)
+/* Analog Register Part: reg01 */
+#define REG_SYNCRST_MASK BIT(2)
+#define REG_SYNCRST_RESET BIT(2)
+#define REG_SYNCRST_NORMAL 0
+#define REG_LDOPD_MASK BIT(1)
+#define REG_LDOPD_POWER_DOWN BIT(1)
+#define REG_LDOPD_POWER_ON 0
+#define REG_PLLPD_MASK BIT(0)
+#define REG_PLLPD_POWER_DOWN BIT(0)
+#define REG_PLLPD_POWER_ON 0
+/* Analog Register Part: reg03 */
+#define REG_FBDIV_HI_MASK BIT(5)
+#define REG_FBDIV_HI(x) UPDATE((x >> 8), 5, 5)
+#define REG_PREDIV_MASK GENMASK(4, 0)
+#define REG_PREDIV(x) UPDATE(x, 4, 0)
+/* Analog Register Part: reg04 */
+#define REG_FBDIV_LO_MASK GENMASK(7, 0)
+#define REG_FBDIV_LO(x) UPDATE(x, 7, 0)
+/* Analog Register Part: reg05 */
+#define SAMPLE_CLOCK_PHASE_MASK GENMASK(6, 4)
+#define SAMPLE_CLOCK_PHASE(x) UPDATE(x, 6, 4)
+#define CLOCK_LANE_SKEW_PHASE_MASK GENMASK(2, 0)
+#define CLOCK_LANE_SKEW_PHASE(x) UPDATE(x, 2, 0)
+/* Analog Register Part: reg06 */
+#define DATA_LANE_3_SKEW_PHASE_MASK GENMASK(6, 4)
+#define DATA_LANE_3_SKEW_PHASE(x) UPDATE(x, 6, 4)
+#define DATA_LANE_2_SKEW_PHASE_MASK GENMASK(2, 0)
+#define DATA_LANE_2_SKEW_PHASE(x) UPDATE(x, 2, 0)
+/* Analog Register Part: reg07 */
+#define DATA_LANE_1_SKEW_PHASE_MASK GENMASK(6, 4)
+#define DATA_LANE_1_SKEW_PHASE(x) UPDATE(x, 6, 4)
+#define DATA_LANE_0_SKEW_PHASE_MASK GENMASK(2, 0)
+#define DATA_LANE_0_SKEW_PHASE(x) UPDATE(x, 2, 0)
+/* Analog Register Part: reg08 */
+#define PLL_POST_DIV_ENABLE_MASK BIT(5)
+#define PLL_POST_DIV_ENABLE BIT(5)
+#define SAMPLE_CLOCK_DIRECTION_MASK BIT(4)
+#define SAMPLE_CLOCK_DIRECTION_REVERSE BIT(4)
+#define SAMPLE_CLOCK_DIRECTION_FORWARD 0
+#define LOWFRE_EN_MASK BIT(5)
+#define PLL_OUTPUT_FREQUENCY_DIV_BY_1 0
+#define PLL_OUTPUT_FREQUENCY_DIV_BY_2 1
+/* Analog Register Part: reg0b */
+#define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
+#define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
+#define VOD_MIN_RANGE 0x1
+#define VOD_MID_RANGE 0x3
+#define VOD_BIG_RANGE 0x7
+#define VOD_MAX_RANGE 0xf
+/* Analog Register Part: reg1E */
+#define PLL_MODE_SEL_MASK GENMASK(6, 5)
+#define PLL_MODE_SEL_LVDS_MODE 0
+#define PLL_MODE_SEL_MIPI_MODE BIT(5)
+/* Digital Register Part: reg00 */
+#define REG_DIG_RSTN_MASK BIT(0)
+#define REG_DIG_RSTN_NORMAL BIT(0)
+#define REG_DIG_RSTN_RESET 0
+/* Digital Register Part: reg01 */
+#define INVERT_TXCLKESC_MASK BIT(1)
+#define INVERT_TXCLKESC_ENABLE BIT(1)
+#define INVERT_TXCLKESC_DISABLE 0
+#define INVERT_TXBYTECLKHS_MASK BIT(0)
+#define INVERT_TXBYTECLKHS_ENABLE BIT(0)
+#define INVERT_TXBYTECLKHS_DISABLE 0
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg05 */
+#define T_LPX_CNT_MASK GENMASK(5, 0)
+#define T_LPX_CNT(x) UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */
+#define T_HS_ZERO_CNT_HI_MASK BIT(7)
+#define T_HS_ZERO_CNT_HI(x) UPDATE(x, 7, 7)
+#define T_HS_PREPARE_CNT_MASK GENMASK(6, 0)
+#define T_HS_PREPARE_CNT(x) UPDATE(x, 6, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */
+#define T_HS_ZERO_CNT_LO_MASK GENMASK(5, 0)
+#define T_HS_ZERO_CNT_LO(x) UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */
+#define T_HS_TRAIL_CNT_MASK GENMASK(6, 0)
+#define T_HS_TRAIL_CNT(x) UPDATE(x, 6, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */
+#define T_HS_EXIT_CNT_LO_MASK GENMASK(4, 0)
+#define T_HS_EXIT_CNT_LO(x) UPDATE(x, 4, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */
+#define T_CLK_POST_CNT_LO_MASK GENMASK(3, 0)
+#define T_CLK_POST_CNT_LO(x) UPDATE(x, 3, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */
+#define LPDT_TX_PPI_SYNC_MASK BIT(2)
+#define LPDT_TX_PPI_SYNC_ENABLE BIT(2)
+#define LPDT_TX_PPI_SYNC_DISABLE 0
+#define T_WAKEUP_CNT_HI_MASK GENMASK(1, 0)
+#define T_WAKEUP_CNT_HI(x) UPDATE(x, 1, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0d */
+#define T_WAKEUP_CNT_LO_MASK GENMASK(7, 0)
+#define T_WAKEUP_CNT_LO(x) UPDATE(x, 7, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0e */
+#define T_CLK_PRE_CNT_MASK GENMASK(3, 0)
+#define T_CLK_PRE_CNT(x) UPDATE(x, 3, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */
+#define T_CLK_POST_CNT_HI_MASK GENMASK(7, 6)
+#define T_CLK_POST_CNT_HI(x) UPDATE(x, 7, 6)
+#define T_TA_GO_CNT_MASK GENMASK(5, 0)
+#define T_TA_GO_CNT(x) UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */
+#define T_HS_EXIT_CNT_HI_MASK BIT(6)
+#define T_HS_EXIT_CNT_HI(x) UPDATE(x, 6, 6)
+#define T_TA_SURE_CNT_MASK GENMASK(5, 0)
+#define T_TA_SURE_CNT(x) UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */
+#define T_TA_WAIT_CNT_MASK GENMASK(5, 0)
+#define T_TA_WAIT_CNT(x) UPDATE(x, 5, 0)
+/* LVDS Register Part: reg00 */
+#define LVDS_DIGITAL_INTERNAL_RESET_MASK BIT(2)
+#define LVDS_DIGITAL_INTERNAL_RESET_DISABLE BIT(2)
+#define LVDS_DIGITAL_INTERNAL_RESET_ENABLE 0
+/* LVDS Register Part: reg01 */
+#define LVDS_DIGITAL_INTERNAL_ENABLE_MASK BIT(7)
+#define LVDS_DIGITAL_INTERNAL_ENABLE BIT(7)
+#define LVDS_DIGITAL_INTERNAL_DISABLE 0
+/* LVDS Register Part: reg03 */
+#define MODE_ENABLE_MASK GENMASK(2, 0)
+#define TTL_MODE_ENABLE BIT(2)
+#define LVDS_MODE_ENABLE BIT(1)
+#define MIPI_MODE_ENABLE BIT(0)
+/* LVDS Register Part: reg0b */
+#define LVDS_LANE_EN_MASK GENMASK(7, 3)
+#define LVDS_DATA_LANE0_EN BIT(7)
+#define LVDS_DATA_LANE1_EN BIT(6)
+#define LVDS_DATA_LANE2_EN BIT(5)
+#define LVDS_DATA_LANE3_EN BIT(4)
+#define LVDS_CLK_LANE_EN BIT(3)
+#define LVDS_PLL_POWER_MASK BIT(2)
+#define LVDS_PLL_POWER_OFF BIT(2)
+#define LVDS_PLL_POWER_ON 0
+#define LVDS_BANDGAP_POWER_MASK BIT(0)
+#define LVDS_BANDGAP_POWER_DOWN BIT(0)
+#define LVDS_BANDGAP_POWER_ON 0
+
+#define DSI_PHY_RSTZ 0xa0
+#define PHY_ENABLECLK BIT(2)
+#define DSI_PHY_STATUS 0xb0
+#define PHY_LOCK BIT(0)
+
+#define PSEC_PER_SEC 1000000000000LL
+
+#define msleep(a) udelay(a * 1000)
+
+enum phy_max_rate {
+ MAX_1GHZ,
+ MAX_2_5GHZ,
+};
+
+struct clk_hw {
+ struct clk_core *core;
+ struct clk *clk;
+ const struct clk_init_data *init;
+};
+
+struct inno_video_phy_plat_data {
+ const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table;
+ const unsigned int num_timings;
+ enum phy_max_rate max_rate;
+};
+
+struct inno_dsidphy {
+ struct udevice *dev;
+ struct clk *ref_clk;
+ struct clk *pclk_phy;
+ struct clk *pclk_host;
+ const struct inno_video_phy_plat_data *pdata;
+ void __iomem *phy_base;
+ void __iomem *host_base;
+ struct reset_ctl *rst;
+ struct phy_configure_opts_mipi_dphy dphy_cfg;
+
+ struct clk *pll_clk;
+ struct {
+ struct clk_hw hw;
+ u8 prediv;
+ u16 fbdiv;
+ unsigned long rate;
+ } pll;
+};
+
+enum {
+ REGISTER_PART_ANALOG,
+ REGISTER_PART_DIGITAL,
+ REGISTER_PART_CLOCK_LANE,
+ REGISTER_PART_DATA0_LANE,
+ REGISTER_PART_DATA1_LANE,
+ REGISTER_PART_DATA2_LANE,
+ REGISTER_PART_DATA3_LANE,
+ REGISTER_PART_LVDS,
+};
+
+struct inno_mipi_dphy_timing {
+ unsigned long rate;
+ u8 lpx;
+ u8 hs_prepare;
+ u8 clk_lane_hs_zero;
+ u8 data_lane_hs_zero;
+ u8 hs_trail;
+};
+
+static const
+struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = {
+ { 110000000, 0x0, 0x20, 0x16, 0x02, 0x22},
+ { 150000000, 0x0, 0x06, 0x16, 0x03, 0x45},
+ { 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b},
+ { 250000000, 0x0, 0x05, 0x17, 0x05, 0x16},
+ { 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c},
+ { 400000000, 0x0, 0x64, 0x19, 0x07, 0x33},
+ { 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e},
+ { 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a},
+ { 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a},
+ { 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29},
+ {1000000000, 0x0, 0x09, 0x20, 0x09, 0x27},
+};
+
+static const
+struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = {
+ { 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02},
+ { 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02},
+ { 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02},
+ { 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04},
+ { 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04},
+ { 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04},
+ { 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08},
+ { 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10},
+ { 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30},
+ { 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30},
+ {1000000000, 0x05, 0x08, 0x20, 0x09, 0x30},
+ {1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f},
+ {1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f},
+ {1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f},
+ {1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f},
+ {2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b},
+ {2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b},
+ {2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a},
+ {2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a},
+};
+
+static void phy_update_bits(struct inno_dsidphy *inno,
+ u8 first, u8 second, u8 mask, u8 val)
+{
+ u32 reg = PHY_REG(first, second) << 2;
+ unsigned int tmp, orig;
+
+ orig = readl(inno->phy_base + reg);
+ tmp = orig & ~mask;
+ tmp |= val & mask;
+ writel(tmp, inno->phy_base + reg);
+}
+
+static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno,
+ unsigned long rate)
+{
+ unsigned long prate;
+ unsigned long best_freq = 0;
+ unsigned long fref, fout;
+ u8 min_prediv, max_prediv;
+ u8 _prediv, best_prediv = 1;
+ u16 _fbdiv, best_fbdiv = 1;
+ u32 min_delta = UINT_MAX;
+
+ /*
+ * Upstream Linux tries to read the ref_clk, while the BSP
+ * U-Boot hard-codes this as 24MHz. Try the first, and if that
+ * fails do the second.
+ */
+ prate = clk_get_rate(inno->ref_clk);
+ if (IS_ERR_VALUE(prate))
+ prate = 24000000;
+
+ /*
+ * The PLL output frequency can be calculated using a simple formula:
+ * PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2
+ * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2
+ */
+ fref = prate / 2;
+ if (rate > 1000000000UL)
+ fout = 1000000000UL;
+ else
+ fout = rate;
+
+ /* 5Mhz < Fref / prediv < 40MHz */
+ min_prediv = DIV_ROUND_UP(fref, 40000000);
+ max_prediv = fref / 5000000;
+
+ for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
+ u64 tmp;
+ u32 delta;
+
+ tmp = (u64)fout * _prediv;
+ do_div(tmp, fref);
+ _fbdiv = tmp;
+
+ /*
+ * The possible settings of feedback divider are
+ * 12, 13, 14, 16, ~ 511
+ */
+ if (_fbdiv == 15)
+ continue;
+
+ if (_fbdiv < 12 || _fbdiv > 511)
+ continue;
+
+ tmp = (u64)_fbdiv * fref;
+ do_div(tmp, _prediv);
+
+ delta = abs(fout - tmp);
+ if (!delta) {
+ best_prediv = _prediv;
+ best_fbdiv = _fbdiv;
+ best_freq = tmp;
+ break;
+ } else if (delta < min_delta) {
+ best_prediv = _prediv;
+ best_fbdiv = _fbdiv;
+ best_freq = tmp;
+ min_delta = delta;
+ }
+ }
+
+ if (best_freq) {
+ inno->pll.prediv = best_prediv;
+ inno->pll.fbdiv = best_fbdiv;
+ inno->pll.rate = best_freq;
+ }
+
+ return best_freq;
+}
+
+static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
+{
+ struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg;
+ const struct inno_mipi_dphy_timing *timings;
+ u32 t_txbyteclkhs, t_txclkesc;
+ u32 txbyteclkhs, txclkesc, esc_clk_div;
+ u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait;
+ u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero;
+ unsigned int i;
+
+ timings = inno->pdata->inno_mipi_dphy_timing_table;
+
+ inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate);
+
+ /* Select MIPI mode */
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,
+ MODE_ENABLE_MASK, MIPI_MODE_ENABLE);
+ /* Configure PLL */
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,
+ REG_PREDIV_MASK, REG_PREDIV(inno->pll.prediv));
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,
+ REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv));
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,
+ REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv));
+ if (inno->pdata->max_rate == MAX_2_5GHZ) {
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,
+ PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b,
+ CLOCK_LANE_VOD_RANGE_SET_MASK,
+ CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
+ }
+ /* Enable PLL and LDO */
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+ REG_LDOPD_MASK | REG_PLLPD_MASK,
+ REG_LDOPD_POWER_ON | REG_PLLPD_POWER_ON);
+ /* Reset analog */
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+ REG_SYNCRST_MASK, REG_SYNCRST_RESET);
+ udelay(1);
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+ REG_SYNCRST_MASK, REG_SYNCRST_NORMAL);
+ /* Reset digital */
+ phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,
+ REG_DIG_RSTN_MASK, REG_DIG_RSTN_RESET);
+ udelay(1);
+ phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,
+ REG_DIG_RSTN_MASK, REG_DIG_RSTN_NORMAL);
+
+ txbyteclkhs = inno->pll.rate / 8;
+ t_txbyteclkhs = div_u64(PSEC_PER_SEC, txbyteclkhs);
+
+ esc_clk_div = DIV_ROUND_UP(txbyteclkhs, 20000000);
+ txclkesc = txbyteclkhs / esc_clk_div;
+ t_txclkesc = div_u64(PSEC_PER_SEC, txclkesc);
+
+ /*
+ * The value of counter for HS Ths-exit
+ * Ths-exit = Tpin_txbyteclkhs * value
+ */
+ hs_exit = DIV_ROUND_UP(cfg->hs_exit, t_txbyteclkhs);
+ /*
+ * The value of counter for HS Tclk-post
+ * Tclk-post = Tpin_txbyteclkhs * value
+ */
+ clk_post = DIV_ROUND_UP(cfg->clk_post, t_txbyteclkhs);
+ /*
+ * The value of counter for HS Tclk-pre
+ * Tclk-pre = Tpin_txbyteclkhs * value
+ */
+ clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE);
+
+ /*
+ * The value of counter for HS Tta-go
+ * Tta-go for turnaround
+ * Tta-go = Ttxclkesc * value
+ */
+ ta_go = DIV_ROUND_UP(cfg->ta_go, t_txclkesc);
+ /*
+ * The value of counter for HS Tta-sure
+ * Tta-sure for turnaround
+ * Tta-sure = Ttxclkesc * value
+ */
+ ta_sure = DIV_ROUND_UP(cfg->ta_sure, t_txclkesc);
+ /*
+ * The value of counter for HS Tta-wait
+ * Tta-wait for turnaround
+ * Tta-wait = Ttxclkesc * value
+ */
+ ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc);
+
+ for (i = 0; i < inno->pdata->num_timings; i++)
+ if (inno->pll.rate <= timings[i].rate)
+ break;
+
+ if (i == inno->pdata->num_timings)
+ --i;
+
+ /*
+ * The value of counter for HS Tlpx Time
+ * Tlpx = Tpin_txbyteclkhs * (2 + value)
+ */
+ if (inno->pdata->max_rate == MAX_1GHZ) {
+ lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);
+ if (lpx >= 2)
+ lpx -= 2;
+ } else {
+ lpx = timings[i].lpx;
+ }
+
+ hs_prepare = timings[i].hs_prepare;
+ hs_trail = timings[i].hs_trail;
+ clk_lane_hs_zero = timings[i].clk_lane_hs_zero;
+ data_lane_hs_zero = timings[i].data_lane_hs_zero;
+ wakeup = 0x3ff;
+
+ for (i = REGISTER_PART_CLOCK_LANE; i <= REGISTER_PART_DATA3_LANE; i++) {
+ if (i == REGISTER_PART_CLOCK_LANE)
+ hs_zero = clk_lane_hs_zero;
+ else
+ hs_zero = data_lane_hs_zero;
+
+ phy_update_bits(inno, i, 0x05, T_LPX_CNT_MASK,
+ T_LPX_CNT(lpx));
+ phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK,
+ T_HS_PREPARE_CNT(hs_prepare));
+ if (inno->pdata->max_rate == MAX_2_5GHZ)
+ phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK,
+ T_HS_ZERO_CNT_HI(hs_zero >> 6));
+ phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK,
+ T_HS_ZERO_CNT_LO(hs_zero));
+ phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK,
+ T_HS_TRAIL_CNT(hs_trail));
+ if (inno->pdata->max_rate == MAX_2_5GHZ)
+ phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK,
+ T_HS_EXIT_CNT_HI(hs_exit >> 5));
+ phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK,
+ T_HS_EXIT_CNT_LO(hs_exit));
+ if (inno->pdata->max_rate == MAX_2_5GHZ)
+ phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK,
+ T_CLK_POST_CNT_HI(clk_post >> 4));
+ phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK,
+ T_CLK_POST_CNT_LO(clk_post));
+ phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK,
+ T_CLK_PRE_CNT(clk_pre));
+ phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK,
+ T_WAKEUP_CNT_HI(wakeup >> 8));
+ phy_update_bits(inno, i, 0x0d, T_WAKEUP_CNT_LO_MASK,
+ T_WAKEUP_CNT_LO(wakeup));
+ phy_update_bits(inno, i, 0x10, T_TA_GO_CNT_MASK,
+ T_TA_GO_CNT(ta_go));
+ phy_update_bits(inno, i, 0x11, T_TA_SURE_CNT_MASK,
+ T_TA_SURE_CNT(ta_sure));
+ phy_update_bits(inno, i, 0x12, T_TA_WAIT_CNT_MASK,
+ T_TA_WAIT_CNT(ta_wait));
+ }
+
+ /* Enable all lanes on analog part */
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+ LANE_EN_MASK, LANE_EN_CK | LANE_EN_3 | LANE_EN_2 |
+ LANE_EN_1 | LANE_EN_0);
+}
+
+static int inno_dsidphy_power_on(struct phy *phy)
+{
+ struct inno_dsidphy *inno = dev_get_priv(phy->dev);
+
+ clk_prepare_enable(inno->pclk_phy);
+ clk_prepare_enable(inno->ref_clk);
+
+ /* Bandgap power on */
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+ BANDGAP_POWER_MASK, BANDGAP_POWER_ON);
+ /* Enable power work */
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+ POWER_WORK_MASK, POWER_WORK_ENABLE);
+
+ inno_dsidphy_mipi_mode_enable(inno);
+
+ return 0;
+}
+
+static int inno_dsidphy_power_off(struct phy *phy)
+{
+ struct inno_dsidphy *inno = dev_get_priv(phy->dev);
+
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00, LANE_EN_MASK, 0);
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+ REG_LDOPD_MASK | REG_PLLPD_MASK,
+ REG_LDOPD_POWER_DOWN | REG_PLLPD_POWER_DOWN);
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+ POWER_WORK_MASK, POWER_WORK_DISABLE);
+ phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+ BANDGAP_POWER_MASK, BANDGAP_POWER_DOWN);
+
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b, LVDS_LANE_EN_MASK, 0);
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,
+ LVDS_DIGITAL_INTERNAL_ENABLE_MASK,
+ LVDS_DIGITAL_INTERNAL_DISABLE);
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,
+ LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,
+ LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN);
+
+ clk_disable_unprepare(inno->ref_clk);
+ clk_disable_unprepare(inno->pclk_phy);
+
+ return 0;
+}
+
+static int inno_dsidphy_configure(struct phy *phy, void *params)
+{
+ struct inno_dsidphy *inno = dev_get_priv(phy->dev);
+ struct phy_configure_opts_mipi_dphy *config = params;
+ int ret;
+
+ ret = phy_mipi_dphy_config_validate(config);
+ if (ret)
+ return ret;
+
+ memcpy(&inno->dphy_cfg, config, sizeof(inno->dphy_cfg));
+
+ return 0;
+}
+
+static const struct phy_ops inno_dsidphy_ops = {
+ .configure = inno_dsidphy_configure,
+ .power_on = inno_dsidphy_power_on,
+ .power_off = inno_dsidphy_power_off,
+};
+
+static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = {
+ .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz,
+ .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz),
+ .max_rate = MAX_1GHZ,
+};
+
+static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = {
+ .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz,
+ .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz),
+ .max_rate = MAX_2_5GHZ,
+};
+
+static int inno_dsidphy_probe(struct udevice *dev)
+{
+ struct inno_dsidphy *inno = dev_get_priv(dev);
+ int ret;
+
+ inno->dev = dev;
+ inno->pdata = (const struct inno_video_phy_plat_data *)dev_get_driver_data(dev);
+
+ inno->phy_base = dev_read_addr_ptr(dev);
+ if (IS_ERR(inno->phy_base))
+ return PTR_ERR(inno->phy_base);
+
+ inno->ref_clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(inno->ref_clk)) {
+ ret = PTR_ERR(inno->ref_clk);
+ dev_err(dev, "failed to get ref clock: %d\n", ret);
+ return ret;
+ }
+
+ inno->pclk_phy = devm_clk_get(dev, "pclk");
+ if (IS_ERR(inno->pclk_phy)) {
+ ret = PTR_ERR(inno->pclk_phy);
+ dev_err(dev, "failed to get phy pclk: %d\n", ret);
+ return ret;
+ }
+
+ inno->rst = devm_reset_control_get(dev, "apb");
+ if (IS_ERR(inno->rst)) {
+ ret = PTR_ERR(inno->rst);
+ dev_err(dev, "failed to get system reset control: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id inno_dsidphy_of_match[] = {
+ {
+ .compatible = "rockchip,px30-dsi-dphy",
+ .data = (long)&max_1ghz_video_phy_plat_data,
+ }, {
+ .compatible = "rockchip,rk3128-dsi-dphy",
+ .data = (long)&max_1ghz_video_phy_plat_data,
+ }, {
+ .compatible = "rockchip,rk3368-dsi-dphy",
+ .data = (long)&max_1ghz_video_phy_plat_data,
+ }, {
+ .compatible = "rockchip,rk3568-dsi-dphy",
+ .data = (long)&max_2_5ghz_video_phy_plat_data,
+ },
+ {}
+};
+
+U_BOOT_DRIVER(rockchip_inno_dsidphy) = {
+ .name = "rockchip-inno-dsidphy",
+ .id = UCLASS_PHY,
+ .of_match = inno_dsidphy_of_match,
+ .probe = inno_dsidphy_probe,
+ .ops = &inno_dsidphy_ops,
+ .priv_auto = sizeof(struct inno_dsidphy),
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index b6ef2acced2..75b3ff47a2e 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -359,5 +359,6 @@ source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/rockchip/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
+source "drivers/pinctrl/starfive/Kconfig"
endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 3b167d099fc..852adee4b4f 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
obj-$(CONFIG_$(SPL_)PINCTRL_STMFX) += pinctrl-stmfx.o
obj-y += broadcom/
obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o
+obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 47e2d67426f..5a4d58b3272 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -349,10 +349,10 @@ int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, bool disable,
{
int err;
- /* try pupd_r1_r0 if pullen_pullsel return error */
+ /* set pupd_r1_r0 if pullen_pullsel succeeded */
err = mtk_pinconf_bias_set_pullen_pullsel(dev, pin, disable, pullup,
val);
- if (err)
+ if (!err)
return mtk_pinconf_bias_set_pupd_r1_r0(dev, pin, disable,
pullup, val);
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index b755fa42b4f..b06da50b2cd 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -61,6 +61,13 @@ static const char * const pinmux_otype[] = {
[STM32_GPIO_OTYPE_OD] = "open-drain",
};
+static const char * const pinmux_speed[] = {
+ [STM32_GPIO_SPEED_2M] = "Low speed",
+ [STM32_GPIO_SPEED_25M] = "Medium speed",
+ [STM32_GPIO_SPEED_50M] = "High speed",
+ [STM32_GPIO_SPEED_100M] = "Very-high speed",
+};
+
static int stm32_pinctrl_get_af(struct udevice *dev, unsigned int offset)
{
struct stm32_gpio_priv *priv = dev_get_priv(dev);
@@ -201,6 +208,7 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
int af_num;
unsigned int gpio_idx;
u32 pupd, otype;
+ u8 speed;
/* look up for the bank which owns the requested pin */
gpio_dev = stm32_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
@@ -214,6 +222,7 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
priv = dev_get_priv(gpio_dev);
pupd = (readl(&priv->regs->pupdr) >> (gpio_idx * 2)) & PUPD_MASK;
otype = (readl(&priv->regs->otyper) >> gpio_idx) & OTYPE_MSK;
+ speed = (readl(&priv->regs->ospeedr) >> gpio_idx * 2) & OSPEED_MASK;
switch (mode) {
case GPIOF_UNKNOWN:
@@ -222,13 +231,15 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
break;
case GPIOF_FUNC:
af_num = stm32_pinctrl_get_af(gpio_dev, gpio_idx);
- snprintf(buf, size, "%s %d %s %s", pinmux_mode[mode], af_num,
- pinmux_otype[otype], pinmux_bias[pupd]);
+ snprintf(buf, size, "%s %d %s %s %s", pinmux_mode[mode], af_num,
+ pinmux_otype[otype], pinmux_bias[pupd],
+ pinmux_speed[speed]);
break;
case GPIOF_OUTPUT:
- snprintf(buf, size, "%s %s %s %s",
+ snprintf(buf, size, "%s %s %s %s %s",
pinmux_mode[mode], pinmux_otype[otype],
- pinmux_bias[pupd], label ? label : "");
+ pinmux_bias[pupd], label ? label : "",
+ pinmux_speed[speed]);
break;
case GPIOF_INPUT:
snprintf(buf, size, "%s %s %s", pinmux_mode[mode],
diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig
index 8f994d8d769..509cdd3fb25 100644
--- a/drivers/pinctrl/renesas/Kconfig
+++ b/drivers/pinctrl/renesas/Kconfig
@@ -119,6 +119,18 @@ config PINCTRL_PFC_R8A779A0
help
Support pin multiplexing control on Renesas RCar Gen3 R8A779A0 SoCs.
+config PINCTRL_PFC_R8A779F0
+ bool "Renesas RCar Gen4 R8A779F0 pin control driver"
+ depends on PINCTRL_PFC
+ help
+ Support pin multiplexing control on Renesas RCar Gen4 R8A779F0 SoCs.
+
+config PINCTRL_PFC_R8A779G0
+ bool "Renesas RCar Gen4 R8A779G0 pin control driver"
+ depends on PINCTRL_PFC
+ help
+ Support pin multiplexing control on Renesas RCar Gen4 R8A779G0 SoCs.
+
config PINCTRL_PFC_R7S72100
bool "Renesas RZ/A1 R7S72100 pin control driver"
depends on CPU_RZA1
diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile
index 1198c868557..5cea1423cad 100644
--- a/drivers/pinctrl/renesas/Makefile
+++ b/drivers/pinctrl/renesas/Makefile
@@ -17,4 +17,6 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77980) += pfc-r8a77980.o
obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o
obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o
obj-$(CONFIG_PINCTRL_PFC_R8A779A0) += pfc-r8a779a0.o
+obj-$(CONFIG_PINCTRL_PFC_R8A779F0) += pfc-r8a779f0.o
+obj-$(CONFIG_PINCTRL_PFC_R8A779G0) += pfc-r8a779g0.o
obj-$(CONFIG_PINCTRL_PFC_R7S72100) += pfc-r7s72100.o
diff --git a/drivers/pinctrl/renesas/pfc-r8a779f0.c b/drivers/pinctrl/renesas/pfc-r8a779f0.c
new file mode 100644
index 00000000000..e2ac9d1efde
--- /dev/null
+++ b/drivers/pinctrl/renesas/pfc-r8a779f0.c
@@ -0,0 +1,2106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R8A779F0 processor support - PFC hardware block.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * This file is based on the drivers/pinctrl/renesas/pfc-r8a779a0.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+
+#include "sh_pfc.h"
+
+#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
+#define CPU_ALL_GP(fn, sfx) \
+ PORT_GP_CFG_21(0, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \
+ PORT_GP_CFG_25(1, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \
+ PORT_GP_CFG_17(2, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_19(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(PRESETOUT0_N, "PRESETOUT0#", fn, SH_PFC_PIN_CFG_PULL_DOWN), \
+ PIN_NOGP_CFG(EXTALR, "EXTALR", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
+/*
+ * F_() : just information
+ * FM() : macro for FN_xxx / xxx_MARK
+ */
+
+/* GPSR0 */
+#define GPSR0_20 F_(IRQ3, IP2SR0_19_16)
+#define GPSR0_19 F_(IRQ2, IP2SR0_15_12)
+#define GPSR0_18 F_(IRQ1, IP2SR0_11_8)
+#define GPSR0_17 F_(IRQ0, IP2SR0_7_4)
+#define GPSR0_16 F_(MSIOF0_SS2, IP2SR0_3_0)
+#define GPSR0_15 F_(MSIOF0_SS1, IP1SR0_31_28)
+#define GPSR0_14 F_(MSIOF0_SCK, IP1SR0_27_24)
+#define GPSR0_13 F_(MSIOF0_TXD, IP1SR0_23_20)
+#define GPSR0_12 F_(MSIOF0_RXD, IP1SR0_19_16)
+#define GPSR0_11 F_(MSIOF0_SYNC, IP1SR0_15_12)
+#define GPSR0_10 F_(CTS0_N, IP1SR0_11_8)
+#define GPSR0_9 F_(RTS0_N, IP1SR0_7_4)
+#define GPSR0_8 F_(SCK0, IP1SR0_3_0)
+#define GPSR0_7 F_(TX0, IP0SR0_31_28)
+#define GPSR0_6 F_(RX0, IP0SR0_27_24)
+#define GPSR0_5 F_(HRTS0_N, IP0SR0_23_20)
+#define GPSR0_4 F_(HCTS0_N, IP0SR0_19_16)
+#define GPSR0_3 F_(HTX0, IP0SR0_15_12)
+#define GPSR0_2 F_(HRX0, IP0SR0_11_8)
+#define GPSR0_1 F_(HSCK0, IP0SR0_7_4)
+#define GPSR0_0 F_(SCIF_CLK, IP0SR0_3_0)
+
+/* GPSR1 */
+#define GPSR1_24 FM(SD_WP)
+#define GPSR1_23 FM(SD_CD)
+#define GPSR1_22 FM(MMC_SD_CMD)
+#define GPSR1_21 FM(MMC_D7)
+#define GPSR1_20 FM(MMC_DS)
+#define GPSR1_19 FM(MMC_D6)
+#define GPSR1_18 FM(MMC_D4)
+#define GPSR1_17 FM(MMC_D5)
+#define GPSR1_16 FM(MMC_SD_D3)
+#define GPSR1_15 FM(MMC_SD_D2)
+#define GPSR1_14 FM(MMC_SD_D1)
+#define GPSR1_13 FM(MMC_SD_D0)
+#define GPSR1_12 FM(MMC_SD_CLK)
+#define GPSR1_11 FM(GP1_11)
+#define GPSR1_10 FM(GP1_10)
+#define GPSR1_9 FM(GP1_09)
+#define GPSR1_8 FM(GP1_08)
+#define GPSR1_7 F_(GP1_07, IP0SR1_31_28)
+#define GPSR1_6 F_(GP1_06, IP0SR1_27_24)
+#define GPSR1_5 F_(GP1_05, IP0SR1_23_20)
+#define GPSR1_4 F_(GP1_04, IP0SR1_19_16)
+#define GPSR1_3 F_(GP1_03, IP0SR1_15_12)
+#define GPSR1_2 F_(GP1_02, IP0SR1_11_8)
+#define GPSR1_1 F_(GP1_01, IP0SR1_7_4)
+#define GPSR1_0 F_(GP1_00, IP0SR1_3_0)
+
+/* GPSR2 */
+#define GPSR2_16 FM(PCIE1_CLKREQ_N)
+#define GPSR2_15 FM(PCIE0_CLKREQ_N)
+#define GPSR2_14 FM(QSPI0_IO3)
+#define GPSR2_13 FM(QSPI0_SSL)
+#define GPSR2_12 FM(QSPI0_MISO_IO1)
+#define GPSR2_11 FM(QSPI0_IO2)
+#define GPSR2_10 FM(QSPI0_SPCLK)
+#define GPSR2_9 FM(QSPI0_MOSI_IO0)
+#define GPSR2_8 FM(QSPI1_SPCLK)
+#define GPSR2_7 FM(QSPI1_MOSI_IO0)
+#define GPSR2_6 FM(QSPI1_IO2)
+#define GPSR2_5 FM(QSPI1_MISO_IO1)
+#define GPSR2_4 FM(QSPI1_IO3)
+#define GPSR2_3 FM(QSPI1_SSL)
+#define GPSR2_2 FM(RPC_RESET_N)
+#define GPSR2_1 FM(RPC_WP_N)
+#define GPSR2_0 FM(RPC_INT_N)
+
+/* GPSR3 */
+#define GPSR3_18 FM(TSN0_AVTP_CAPTURE_B)
+#define GPSR3_17 FM(TSN0_AVTP_MATCH_B)
+#define GPSR3_16 FM(TSN0_AVTP_PPS)
+#define GPSR3_15 FM(TSN1_AVTP_CAPTURE_B)
+#define GPSR3_14 FM(TSN1_AVTP_MATCH_B)
+#define GPSR3_13 FM(TSN1_AVTP_PPS)
+#define GPSR3_12 FM(TSN0_MAGIC_B)
+#define GPSR3_11 FM(TSN1_PHY_INT_B)
+#define GPSR3_10 FM(TSN0_PHY_INT_B)
+#define GPSR3_9 FM(TSN2_PHY_INT_B)
+#define GPSR3_8 FM(TSN0_LINK_B)
+#define GPSR3_7 FM(TSN2_LINK_B)
+#define GPSR3_6 FM(TSN1_LINK_B)
+#define GPSR3_5 FM(TSN1_MDC_B)
+#define GPSR3_4 FM(TSN0_MDC_B)
+#define GPSR3_3 FM(TSN2_MDC_B)
+#define GPSR3_2 FM(TSN0_MDIO_B)
+#define GPSR3_1 FM(TSN2_MDIO_B)
+#define GPSR3_0 FM(TSN1_MDIO_B)
+
+/* IP0SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 - F */
+#define IP0SR0_3_0 FM(SCIF_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_7_4 FM(HSCK0) FM(SCK3) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) FM(TSN0_AVTP_CAPTURE_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_11_8 FM(HRX0) FM(RX3) FM(MSIOF3_RXD) F_(0, 0) F_(0, 0) FM(TSN0_AVTP_MATCH_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_15_12 FM(HTX0) FM(TX3) FM(MSIOF3_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_19_16 FM(HCTS0_N) FM(CTS3_N) FM(MSIOF3_SS1) F_(0, 0) F_(0, 0) FM(TSN0_MDC_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_23_20 FM(HRTS0_N) FM(RTS3_N) FM(MSIOF3_SS2) F_(0, 0) F_(0, 0) FM(TSN0_MDIO_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_27_24 FM(RX0) FM(HRX1) F_(0, 0) FM(MSIOF1_RXD) F_(0, 0) FM(TSN1_AVTP_MATCH_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_31_28 FM(TX0) FM(HTX1) F_(0, 0) FM(MSIOF1_TXD) F_(0, 0) FM(TSN1_AVTP_CAPTURE_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+/* IP1SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 - F */
+#define IP1SR0_3_0 FM(SCK0) FM(HSCK1) F_(0, 0) FM(MSIOF1_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_7_4 FM(RTS0_N) FM(HRTS1_N) FM(MSIOF3_SYNC) F_(0, 0) F_(0, 0) FM(TSN1_MDIO_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_11_8 FM(CTS0_N) FM(HCTS1_N) F_(0, 0) FM(MSIOF1_SYNC) F_(0, 0) FM(TSN1_MDC_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_15_12 FM(MSIOF0_SYNC) FM(HCTS3_N) FM(CTS1_N) FM(IRQ4) F_(0, 0) FM(TSN0_LINK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_19_16 FM(MSIOF0_RXD) FM(HRX3) FM(RX1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_23_20 FM(MSIOF0_TXD) FM(HTX3) FM(TX1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_27_24 FM(MSIOF0_SCK) FM(HSCK3) FM(SCK1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_31_28 FM(MSIOF0_SS1) FM(HRTS3_N) FM(RTS1_N) FM(IRQ5) F_(0, 0) FM(TSN1_LINK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+/* IP2SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 - F */
+#define IP2SR0_3_0 FM(MSIOF0_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(TSN2_LINK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR0_7_4 FM(IRQ0) F_(0, 0) F_(0, 0) FM(MSIOF1_SS1) F_(0, 0) FM(TSN0_MAGIC_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR0_11_8 FM(IRQ1) F_(0, 0) F_(0, 0) FM(MSIOF1_SS2) F_(0, 0) FM(TSN0_PHY_INT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR0_15_12 FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(TSN1_PHY_INT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR0_19_16 FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(TSN2_PHY_INT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP0SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 - F */
+#define IP0SR1_3_0 FM(GP1_00) FM(TCLK1) FM(HSCK2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_7_4 FM(GP1_01) FM(TCLK4) FM(HRX2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_11_8 FM(GP1_02) F_(0, 0) FM(HTX2) FM(MSIOF2_SS1) F_(0, 0) FM(TSN2_MDC_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_15_12 FM(GP1_03) FM(TCLK2) FM(HCTS2_N) FM(MSIOF2_SS2) FM(CTS4_N) FM(TSN2_MDIO_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_19_16 FM(GP1_04) FM(TCLK3) FM(HRTS2_N) FM(MSIOF2_SYNC) FM(RTS4_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_23_20 FM(GP1_05) FM(MSIOF2_SCK) FM(SCK4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_27_24 FM(GP1_06) FM(MSIOF2_RXD) FM(RX4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_31_28 FM(GP1_07) FM(MSIOF2_TXD) FM(TX4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+#define PINMUX_GPSR \
+ GPSR1_24 \
+ GPSR1_23 \
+ GPSR1_22 \
+ GPSR1_21 \
+GPSR0_20 GPSR1_20 \
+GPSR0_19 GPSR1_19 \
+GPSR0_18 GPSR1_18 GPSR3_18 \
+GPSR0_17 GPSR1_17 GPSR3_17 \
+GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 \
+GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 \
+GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 \
+GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 \
+GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 \
+GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 \
+GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 \
+GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 \
+GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 \
+GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 \
+GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 \
+GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 \
+GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 \
+GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 \
+GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 \
+GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 \
+GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0
+
+#define PINMUX_IPSR \
+\
+FM(IP0SR0_3_0) IP0SR0_3_0 FM(IP1SR0_3_0) IP1SR0_3_0 FM(IP2SR0_3_0) IP2SR0_3_0 \
+FM(IP0SR0_7_4) IP0SR0_7_4 FM(IP1SR0_7_4) IP1SR0_7_4 FM(IP2SR0_7_4) IP2SR0_7_4 \
+FM(IP0SR0_11_8) IP0SR0_11_8 FM(IP1SR0_11_8) IP1SR0_11_8 FM(IP2SR0_11_8) IP2SR0_11_8 \
+FM(IP0SR0_15_12) IP0SR0_15_12 FM(IP1SR0_15_12) IP1SR0_15_12 FM(IP2SR0_15_12) IP2SR0_15_12 \
+FM(IP0SR0_19_16) IP0SR0_19_16 FM(IP1SR0_19_16) IP1SR0_19_16 FM(IP2SR0_19_16) IP2SR0_19_16 \
+FM(IP0SR0_23_20) IP0SR0_23_20 FM(IP1SR0_23_20) IP1SR0_23_20 \
+FM(IP0SR0_27_24) IP0SR0_27_24 FM(IP1SR0_27_24) IP1SR0_27_24 \
+FM(IP0SR0_31_28) IP0SR0_31_28 FM(IP1SR0_31_28) IP1SR0_31_28 \
+\
+FM(IP0SR1_3_0) IP0SR1_3_0 \
+FM(IP0SR1_7_4) IP0SR1_7_4 \
+FM(IP0SR1_11_8) IP0SR1_11_8 \
+FM(IP0SR1_15_12) IP0SR1_15_12 \
+FM(IP0SR1_19_16) IP0SR1_19_16 \
+FM(IP0SR1_23_20) IP0SR1_23_20 \
+FM(IP0SR1_27_24) IP0SR1_27_24 \
+FM(IP0SR1_31_28) IP0SR1_31_28
+
+/* MOD_SEL1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */
+#define MOD_SEL1_11_10 FM(SEL_I2C5_0) F_(0, 0) F_(0, 0) FM(SEL_I2C5_3)
+#define MOD_SEL1_9_8 FM(SEL_I2C4_0) F_(0, 0) F_(0, 0) FM(SEL_I2C4_3)
+#define MOD_SEL1_7_6 FM(SEL_I2C3_0) F_(0, 0) F_(0, 0) FM(SEL_I2C3_3)
+#define MOD_SEL1_5_4 FM(SEL_I2C2_0) F_(0, 0) F_(0, 0) FM(SEL_I2C2_3)
+#define MOD_SEL1_3_2 FM(SEL_I2C1_0) F_(0, 0) F_(0, 0) FM(SEL_I2C1_3)
+#define MOD_SEL1_1_0 FM(SEL_I2C0_0) F_(0, 0) F_(0, 0) FM(SEL_I2C0_3)
+
+#define PINMUX_MOD_SELS \
+\
+MOD_SEL1_11_10 \
+MOD_SEL1_9_8 \
+MOD_SEL1_7_6 \
+MOD_SEL1_5_4 \
+MOD_SEL1_3_2 \
+MOD_SEL1_1_0
+
+#define PINMUX_PHYS \
+ FM(SCL0) FM(SDA0) FM(SCL1) FM(SDA1) FM(SCL2) FM(SDA2) FM(SCL3) FM(SDA3) \
+ FM(SCL4) FM(SDA4) FM(SCL5) FM(SDA5)
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ GP_ALL(DATA),
+ PINMUX_DATA_END,
+
+#define F_(x, y)
+#define FM(x) FN_##x,
+ PINMUX_FUNCTION_BEGIN,
+ GP_ALL(FN),
+ PINMUX_GPSR
+ PINMUX_IPSR
+ PINMUX_MOD_SELS
+ PINMUX_FUNCTION_END,
+#undef F_
+#undef FM
+
+#define F_(x, y)
+#define FM(x) x##_MARK,
+ PINMUX_MARK_BEGIN,
+ PINMUX_GPSR
+ PINMUX_IPSR
+ PINMUX_MOD_SELS
+ PINMUX_PHYS
+ PINMUX_MARK_END,
+#undef F_
+#undef FM
+};
+
+static const u16 pinmux_data[] = {
+/* Using GP_1_[0-9] requires disabling I2C in MOD_SEL1 */
+#define GP_1_0_FN GP_1_0_FN, FN_SEL_I2C0_0
+#define GP_1_1_FN GP_1_1_FN, FN_SEL_I2C0_0
+#define GP_1_2_FN GP_1_2_FN, FN_SEL_I2C1_0
+#define GP_1_3_FN GP_1_3_FN, FN_SEL_I2C1_0
+#define GP_1_4_FN GP_1_4_FN, FN_SEL_I2C2_0
+#define GP_1_5_FN GP_1_5_FN, FN_SEL_I2C2_0
+#define GP_1_6_FN GP_1_6_FN, FN_SEL_I2C3_0
+#define GP_1_7_FN GP_1_7_FN, FN_SEL_I2C3_0
+#define GP_1_8_FN GP_1_8_FN, FN_SEL_I2C4_0
+#define GP_1_9_FN GP_1_9_FN, FN_SEL_I2C4_0
+ PINMUX_DATA_GP_ALL(),
+#undef GP_1_0_FN
+#undef GP_1_1_FN
+#undef GP_1_2_FN
+#undef GP_1_3_FN
+#undef GP_1_4_FN
+#undef GP_1_5_FN
+#undef GP_1_6_FN
+#undef GP_1_7_FN
+#undef GP_1_8_FN
+#undef GP_1_9_FN
+
+ PINMUX_SINGLE(SD_WP),
+ PINMUX_SINGLE(SD_CD),
+ PINMUX_SINGLE(MMC_SD_CMD),
+ PINMUX_SINGLE(MMC_D7),
+ PINMUX_SINGLE(MMC_DS),
+ PINMUX_SINGLE(MMC_D6),
+ PINMUX_SINGLE(MMC_D4),
+ PINMUX_SINGLE(MMC_D5),
+ PINMUX_SINGLE(MMC_SD_D3),
+ PINMUX_SINGLE(MMC_SD_D2),
+ PINMUX_SINGLE(MMC_SD_D1),
+ PINMUX_SINGLE(MMC_SD_D0),
+ PINMUX_SINGLE(MMC_SD_CLK),
+ PINMUX_SINGLE(PCIE1_CLKREQ_N),
+ PINMUX_SINGLE(PCIE0_CLKREQ_N),
+ PINMUX_SINGLE(QSPI0_IO3),
+ PINMUX_SINGLE(QSPI0_SSL),
+ PINMUX_SINGLE(QSPI0_MISO_IO1),
+ PINMUX_SINGLE(QSPI0_IO2),
+ PINMUX_SINGLE(QSPI0_SPCLK),
+ PINMUX_SINGLE(QSPI0_MOSI_IO0),
+ PINMUX_SINGLE(QSPI1_SPCLK),
+ PINMUX_SINGLE(QSPI1_MOSI_IO0),
+ PINMUX_SINGLE(QSPI1_IO2),
+ PINMUX_SINGLE(QSPI1_MISO_IO1),
+ PINMUX_SINGLE(QSPI1_IO3),
+ PINMUX_SINGLE(QSPI1_SSL),
+ PINMUX_SINGLE(RPC_RESET_N),
+ PINMUX_SINGLE(RPC_WP_N),
+ PINMUX_SINGLE(RPC_INT_N),
+
+ PINMUX_SINGLE(TSN0_AVTP_CAPTURE_B),
+ PINMUX_SINGLE(TSN0_AVTP_MATCH_B),
+ PINMUX_SINGLE(TSN0_AVTP_PPS),
+ PINMUX_SINGLE(TSN1_AVTP_CAPTURE_B),
+ PINMUX_SINGLE(TSN1_AVTP_MATCH_B),
+ PINMUX_SINGLE(TSN1_AVTP_PPS),
+ PINMUX_SINGLE(TSN0_MAGIC_B),
+ PINMUX_SINGLE(TSN1_PHY_INT_B),
+ PINMUX_SINGLE(TSN0_PHY_INT_B),
+ PINMUX_SINGLE(TSN2_PHY_INT_B),
+ PINMUX_SINGLE(TSN0_LINK_B),
+ PINMUX_SINGLE(TSN2_LINK_B),
+ PINMUX_SINGLE(TSN1_LINK_B),
+ PINMUX_SINGLE(TSN1_MDC_B),
+ PINMUX_SINGLE(TSN0_MDC_B),
+ PINMUX_SINGLE(TSN2_MDC_B),
+ PINMUX_SINGLE(TSN0_MDIO_B),
+ PINMUX_SINGLE(TSN2_MDIO_B),
+ PINMUX_SINGLE(TSN1_MDIO_B),
+
+ /* IP0SR0 */
+ PINMUX_IPSR_GPSR(IP0SR0_3_0, SCIF_CLK),
+
+ PINMUX_IPSR_GPSR(IP0SR0_7_4, HSCK0),
+ PINMUX_IPSR_GPSR(IP0SR0_7_4, SCK3),
+ PINMUX_IPSR_GPSR(IP0SR0_7_4, MSIOF3_SCK),
+ PINMUX_IPSR_GPSR(IP0SR0_7_4, TSN0_AVTP_CAPTURE_A),
+
+ PINMUX_IPSR_GPSR(IP0SR0_11_8, HRX0),
+ PINMUX_IPSR_GPSR(IP0SR0_11_8, RX3),
+ PINMUX_IPSR_GPSR(IP0SR0_11_8, MSIOF3_RXD),
+ PINMUX_IPSR_GPSR(IP0SR0_11_8, TSN0_AVTP_MATCH_A),
+
+ PINMUX_IPSR_GPSR(IP0SR0_15_12, HTX0),
+ PINMUX_IPSR_GPSR(IP0SR0_15_12, TX3),
+ PINMUX_IPSR_GPSR(IP0SR0_15_12, MSIOF3_TXD),
+
+ PINMUX_IPSR_GPSR(IP0SR0_19_16, HCTS0_N),
+ PINMUX_IPSR_GPSR(IP0SR0_19_16, CTS3_N),
+ PINMUX_IPSR_GPSR(IP0SR0_19_16, MSIOF3_SS1),
+ PINMUX_IPSR_GPSR(IP0SR0_19_16, TSN0_MDC_A),
+
+ PINMUX_IPSR_GPSR(IP0SR0_23_20, HRTS0_N),
+ PINMUX_IPSR_GPSR(IP0SR0_23_20, RTS3_N),
+ PINMUX_IPSR_GPSR(IP0SR0_23_20, MSIOF3_SS2),
+ PINMUX_IPSR_GPSR(IP0SR0_23_20, TSN0_MDIO_A),
+
+ PINMUX_IPSR_GPSR(IP0SR0_27_24, RX0),
+ PINMUX_IPSR_GPSR(IP0SR0_27_24, HRX1),
+ PINMUX_IPSR_GPSR(IP0SR0_27_24, MSIOF1_RXD),
+ PINMUX_IPSR_GPSR(IP0SR0_27_24, TSN1_AVTP_MATCH_A),
+
+ PINMUX_IPSR_GPSR(IP0SR0_31_28, TX0),
+ PINMUX_IPSR_GPSR(IP0SR0_31_28, HTX1),
+ PINMUX_IPSR_GPSR(IP0SR0_31_28, MSIOF1_TXD),
+ PINMUX_IPSR_GPSR(IP0SR0_31_28, TSN1_AVTP_CAPTURE_A),
+
+ /* IP1SR0 */
+ PINMUX_IPSR_GPSR(IP1SR0_3_0, SCK0),
+ PINMUX_IPSR_GPSR(IP1SR0_3_0, HSCK1),
+ PINMUX_IPSR_GPSR(IP1SR0_3_0, MSIOF1_SCK),
+
+ PINMUX_IPSR_GPSR(IP1SR0_7_4, RTS0_N),
+ PINMUX_IPSR_GPSR(IP1SR0_7_4, HRTS1_N),
+ PINMUX_IPSR_GPSR(IP1SR0_7_4, MSIOF3_SYNC),
+ PINMUX_IPSR_GPSR(IP1SR0_7_4, TSN1_MDIO_A),
+
+ PINMUX_IPSR_GPSR(IP1SR0_11_8, CTS0_N),
+ PINMUX_IPSR_GPSR(IP1SR0_11_8, HCTS1_N),
+ PINMUX_IPSR_GPSR(IP1SR0_11_8, MSIOF1_SYNC),
+ PINMUX_IPSR_GPSR(IP1SR0_11_8, TSN1_MDC_A),
+
+ PINMUX_IPSR_GPSR(IP1SR0_15_12, MSIOF0_SYNC),
+ PINMUX_IPSR_GPSR(IP1SR0_15_12, HCTS3_N),
+ PINMUX_IPSR_GPSR(IP1SR0_15_12, CTS1_N),
+ PINMUX_IPSR_GPSR(IP1SR0_15_12, IRQ4),
+ PINMUX_IPSR_GPSR(IP1SR0_15_12, TSN0_LINK_A),
+
+ PINMUX_IPSR_GPSR(IP1SR0_19_16, MSIOF0_RXD),
+ PINMUX_IPSR_GPSR(IP1SR0_19_16, HRX3),
+ PINMUX_IPSR_GPSR(IP1SR0_19_16, RX1),
+
+ PINMUX_IPSR_GPSR(IP1SR0_23_20, MSIOF0_TXD),
+ PINMUX_IPSR_GPSR(IP1SR0_23_20, HTX3),
+ PINMUX_IPSR_GPSR(IP1SR0_23_20, TX1),
+
+ PINMUX_IPSR_GPSR(IP1SR0_27_24, MSIOF0_SCK),
+ PINMUX_IPSR_GPSR(IP1SR0_27_24, HSCK3),
+ PINMUX_IPSR_GPSR(IP1SR0_27_24, SCK1),
+
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, MSIOF0_SS1),
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, HRTS3_N),
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, RTS1_N),
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, IRQ5),
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, TSN1_LINK_A),
+
+ /* IP2SR0 */
+ PINMUX_IPSR_GPSR(IP2SR0_3_0, MSIOF0_SS2),
+ PINMUX_IPSR_GPSR(IP2SR0_3_0, TSN2_LINK_A),
+
+ PINMUX_IPSR_GPSR(IP2SR0_7_4, IRQ0),
+ PINMUX_IPSR_GPSR(IP2SR0_7_4, MSIOF1_SS1),
+ PINMUX_IPSR_GPSR(IP2SR0_7_4, TSN0_MAGIC_A),
+
+ PINMUX_IPSR_GPSR(IP2SR0_11_8, IRQ1),
+ PINMUX_IPSR_GPSR(IP2SR0_11_8, MSIOF1_SS2),
+ PINMUX_IPSR_GPSR(IP2SR0_11_8, TSN0_PHY_INT_A),
+
+ PINMUX_IPSR_GPSR(IP2SR0_15_12, IRQ2),
+ PINMUX_IPSR_GPSR(IP2SR0_15_12, TSN1_PHY_INT_A),
+
+ PINMUX_IPSR_GPSR(IP2SR0_19_16, IRQ3),
+ PINMUX_IPSR_GPSR(IP2SR0_19_16, TSN2_PHY_INT_A),
+
+ /* IP0SR1 */
+ /* GP1_00 = SCL0 */
+ PINMUX_IPSR_MSEL(IP0SR1_3_0, GP1_00, SEL_I2C0_0),
+ PINMUX_IPSR_MSEL(IP0SR1_3_0, TCLK1, SEL_I2C0_0),
+ PINMUX_IPSR_MSEL(IP0SR1_3_0, HSCK2, SEL_I2C0_0),
+ PINMUX_IPSR_PHYS(IP0SR1_3_0, SCL0, SEL_I2C0_3),
+
+ /* GP1_01 = SDA0 */
+ PINMUX_IPSR_MSEL(IP0SR1_7_4, GP1_01, SEL_I2C0_0),
+ PINMUX_IPSR_MSEL(IP0SR1_7_4, TCLK4, SEL_I2C0_0),
+ PINMUX_IPSR_MSEL(IP0SR1_7_4, HRX2, SEL_I2C0_0),
+ PINMUX_IPSR_PHYS(IP0SR1_7_4, SDA0, SEL_I2C0_3),
+
+ /* GP1_02 = SCL1 */
+ PINMUX_IPSR_MSEL(IP0SR1_11_8, GP1_02, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_11_8, HTX2, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_11_8, MSIOF2_SS1, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_11_8, TSN2_MDC_A, SEL_I2C1_0),
+ PINMUX_IPSR_PHYS(IP0SR1_11_8, SCL1, SEL_I2C1_3),
+
+ /* GP1_03 = SDA1 */
+ PINMUX_IPSR_MSEL(IP0SR1_15_12, GP1_03, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_15_12, TCLK2, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_15_12, HCTS2_N, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_15_12, MSIOF2_SS2, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_15_12, CTS4_N, SEL_I2C1_0),
+ PINMUX_IPSR_MSEL(IP0SR1_15_12, TSN2_MDIO_A, SEL_I2C1_0),
+ PINMUX_IPSR_PHYS(IP0SR1_15_12, SDA1, SEL_I2C1_3),
+
+ /* GP1_04 = SCL2 */
+ PINMUX_IPSR_MSEL(IP0SR1_19_16, GP1_04, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP0SR1_19_16, TCLK3, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP0SR1_19_16, HRTS2_N, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP0SR1_19_16, MSIOF2_SYNC, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP0SR1_19_16, RTS4_N, SEL_I2C2_0),
+ PINMUX_IPSR_PHYS(IP0SR1_19_16, SCL2, SEL_I2C2_3),
+
+ /* GP1_05 = SDA2 */
+ PINMUX_IPSR_MSEL(IP0SR1_23_20, GP1_05, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP0SR1_23_20, MSIOF2_SCK, SEL_I2C2_0),
+ PINMUX_IPSR_MSEL(IP0SR1_23_20, SCK4, SEL_I2C2_0),
+ PINMUX_IPSR_PHYS(IP0SR1_23_20, SDA2, SEL_I2C2_3),
+
+ /* GP1_06 = SCL3 */
+ PINMUX_IPSR_MSEL(IP0SR1_27_24, GP1_06, SEL_I2C3_0),
+ PINMUX_IPSR_MSEL(IP0SR1_27_24, MSIOF2_RXD, SEL_I2C3_0),
+ PINMUX_IPSR_MSEL(IP0SR1_27_24, RX4, SEL_I2C3_0),
+ PINMUX_IPSR_PHYS(IP0SR1_27_24, SCL3, SEL_I2C3_3),
+
+ /* GP1_07 = SDA3 */
+ PINMUX_IPSR_MSEL(IP0SR1_31_28, GP1_07, SEL_I2C3_0),
+ PINMUX_IPSR_MSEL(IP0SR1_31_28, MSIOF2_TXD, SEL_I2C3_0),
+ PINMUX_IPSR_MSEL(IP0SR1_31_28, TX4, SEL_I2C3_0),
+ PINMUX_IPSR_PHYS(IP0SR1_31_28, SDA3, SEL_I2C3_3),
+
+ /* GP1_08 = SCL4 */
+ PINMUX_IPSR_NOGM(0, GP1_08, SEL_I2C4_0),
+ PINMUX_IPSR_NOFN(GP1_08, SCL4, SEL_I2C4_3),
+
+ /* GP1_09 = SDA4 */
+ PINMUX_IPSR_NOGM(0, GP1_09, SEL_I2C4_0),
+ PINMUX_IPSR_NOFN(GP1_09, SDA4, SEL_I2C4_3),
+
+ /* GP1_10 = SCL5 */
+ PINMUX_IPSR_NOGM(0, GP1_10, SEL_I2C5_0),
+ PINMUX_IPSR_NOFN(GP1_10, SCL5, SEL_I2C5_3),
+
+ /* GP1_11 = SDA5 */
+ PINMUX_IPSR_NOGM(0, GP1_11, SEL_I2C5_0),
+ PINMUX_IPSR_NOFN(GP1_11, SDA5, SEL_I2C5_3),
+};
+
+/*
+ * Pins not associated with a GPIO port.
+ */
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
+
+static const struct sh_pfc_pin pinmux_pins[] = {
+ PINMUX_GPIO_GP_ALL(),
+};
+
+/* - HSCIF0 ----------------------------------------------------------------- */
+static const unsigned int hscif0_data_pins[] = {
+ /* HRX0, HTX0 */
+ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3),
+};
+static const unsigned int hscif0_data_mux[] = {
+ HRX0_MARK, HTX0_MARK,
+};
+static const unsigned int hscif0_clk_pins[] = {
+ /* HSCK0 */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int hscif0_clk_mux[] = {
+ HSCK0_MARK,
+};
+static const unsigned int hscif0_ctrl_pins[] = {
+ /* HRTS0#, HCTS0# */
+ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4),
+};
+static const unsigned int hscif0_ctrl_mux[] = {
+ HRTS0_N_MARK, HCTS0_N_MARK,
+};
+
+/* - HSCIF1 ----------------------------------------------------------------- */
+static const unsigned int hscif1_data_pins[] = {
+ /* HRX1, HTX1 */
+ RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7),
+};
+static const unsigned int hscif1_data_mux[] = {
+ HRX1_MARK, HTX1_MARK,
+};
+static const unsigned int hscif1_clk_pins[] = {
+ /* HSCK1 */
+ RCAR_GP_PIN(0, 8),
+};
+static const unsigned int hscif1_clk_mux[] = {
+ HSCK1_MARK,
+};
+static const unsigned int hscif1_ctrl_pins[] = {
+ /* HRTS1#, HCTS1# */
+ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10),
+};
+static const unsigned int hscif1_ctrl_mux[] = {
+ HRTS1_N_MARK, HCTS1_N_MARK,
+};
+
+/* - HSCIF2 ----------------------------------------------------------------- */
+static const unsigned int hscif2_data_pins[] = {
+ /* HRX2, HTX2 */
+ RCAR_GP_PIN(1, 1), RCAR_GP_PIN(1, 2),
+};
+static const unsigned int hscif2_data_mux[] = {
+ HRX2_MARK, HTX2_MARK,
+};
+static const unsigned int hscif2_clk_pins[] = {
+ /* HSCK2 */
+ RCAR_GP_PIN(1, 0),
+};
+static const unsigned int hscif2_clk_mux[] = {
+ HSCK2_MARK,
+};
+static const unsigned int hscif2_ctrl_pins[] = {
+ /* HRTS2#, HCTS2# */
+ RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 3),
+};
+static const unsigned int hscif2_ctrl_mux[] = {
+ HRTS2_N_MARK, HCTS2_N_MARK,
+};
+
+/* - HSCIF3 ----------------------------------------------------------------- */
+static const unsigned int hscif3_data_pins[] = {
+ /* HRX3, HTX3 */
+ RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13),
+};
+static const unsigned int hscif3_data_mux[] = {
+ HRX3_MARK, HTX3_MARK,
+};
+static const unsigned int hscif3_clk_pins[] = {
+ /* HSCK3 */
+ RCAR_GP_PIN(0, 14),
+};
+static const unsigned int hscif3_clk_mux[] = {
+ HSCK3_MARK,
+};
+static const unsigned int hscif3_ctrl_pins[] = {
+ /* HRTS3#, HCTS3# */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 11),
+};
+static const unsigned int hscif3_ctrl_mux[] = {
+ HRTS3_N_MARK, HCTS3_N_MARK,
+};
+
+/* - I2C0 ------------------------------------------------------------------- */
+static const unsigned int i2c0_pins[] = {
+ /* SDA0, SCL0 */
+ RCAR_GP_PIN(1, 1), RCAR_GP_PIN(1, 0),
+};
+static const unsigned int i2c0_mux[] = {
+ SDA0_MARK, SCL0_MARK,
+};
+
+/* - I2C1 ------------------------------------------------------------------- */
+static const unsigned int i2c1_pins[] = {
+ /* SDA1, SCL1 */
+ RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 2),
+};
+static const unsigned int i2c1_mux[] = {
+ SDA1_MARK, SCL1_MARK,
+};
+
+/* - I2C2 ------------------------------------------------------------------- */
+static const unsigned int i2c2_pins[] = {
+ /* SDA2, SCL2 */
+ RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 4),
+};
+static const unsigned int i2c2_mux[] = {
+ SDA2_MARK, SCL2_MARK,
+};
+
+/* - I2C3 ------------------------------------------------------------------- */
+static const unsigned int i2c3_pins[] = {
+ /* SDA3, SCL3 */
+ RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int i2c3_mux[] = {
+ SDA3_MARK, SCL3_MARK,
+};
+
+/* - I2C4 ------------------------------------------------------------------- */
+static const unsigned int i2c4_pins[] = {
+ /* SDA4, SCL4 */
+ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8),
+};
+static const unsigned int i2c4_mux[] = {
+ SDA4_MARK, SCL4_MARK,
+};
+
+/* - I2C5 ------------------------------------------------------------------- */
+static const unsigned int i2c5_pins[] = {
+ /* SDA5, SCL5 */
+ RCAR_GP_PIN(1, 11), RCAR_GP_PIN(1, 10),
+};
+static const unsigned int i2c5_mux[] = {
+ SDA5_MARK, SCL5_MARK,
+};
+
+
+/* - INTC-EX ---------------------------------------------------------------- */
+static const unsigned int intc_ex_irq0_pins[] = {
+ /* IRQ0 */
+ RCAR_GP_PIN(0, 17),
+};
+static const unsigned int intc_ex_irq0_mux[] = {
+ IRQ0_MARK,
+};
+static const unsigned int intc_ex_irq1_pins[] = {
+ /* IRQ1 */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int intc_ex_irq1_mux[] = {
+ IRQ1_MARK,
+};
+static const unsigned int intc_ex_irq2_pins[] = {
+ /* IRQ2 */
+ RCAR_GP_PIN(0, 19),
+};
+static const unsigned int intc_ex_irq2_mux[] = {
+ IRQ2_MARK,
+};
+static const unsigned int intc_ex_irq3_pins[] = {
+ /* IRQ3 */
+ RCAR_GP_PIN(0, 20),
+};
+static const unsigned int intc_ex_irq3_mux[] = {
+ IRQ3_MARK,
+};
+static const unsigned int intc_ex_irq4_pins[] = {
+ /* IRQ4 */
+ RCAR_GP_PIN(0, 11),
+};
+static const unsigned int intc_ex_irq4_mux[] = {
+ IRQ4_MARK,
+};
+static const unsigned int intc_ex_irq5_pins[] = {
+ /* IRQ5 */
+ RCAR_GP_PIN(0, 15),
+};
+static const unsigned int intc_ex_irq5_mux[] = {
+ IRQ5_MARK,
+};
+
+/* - MMC -------------------------------------------------------------------- */
+static const unsigned int mmc_data_pins[] = {
+ /* MMC_SD_D[0:3], MMC_D[4:7] */
+ RCAR_GP_PIN(1, 13), RCAR_GP_PIN(1, 14),
+ RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 16),
+ RCAR_GP_PIN(1, 18), RCAR_GP_PIN(1, 17),
+ RCAR_GP_PIN(1, 19), RCAR_GP_PIN(1, 21),
+};
+static const unsigned int mmc_data_mux[] = {
+ MMC_SD_D0_MARK, MMC_SD_D1_MARK,
+ MMC_SD_D2_MARK, MMC_SD_D3_MARK,
+ MMC_D4_MARK, MMC_D5_MARK,
+ MMC_D6_MARK, MMC_D7_MARK,
+};
+static const unsigned int mmc_ctrl_pins[] = {
+ /* MMC_SD_CLK, MMC_SD_CMD */
+ RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 22),
+};
+static const unsigned int mmc_ctrl_mux[] = {
+ MMC_SD_CLK_MARK, MMC_SD_CMD_MARK,
+};
+static const unsigned int mmc_cd_pins[] = {
+ /* SD_CD */
+ RCAR_GP_PIN(1, 23),
+};
+static const unsigned int mmc_cd_mux[] = {
+ SD_CD_MARK,
+};
+static const unsigned int mmc_wp_pins[] = {
+ /* SD_WP */
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int mmc_wp_mux[] = {
+ SD_WP_MARK,
+};
+static const unsigned int mmc_ds_pins[] = {
+ /* MMC_DS */
+ RCAR_GP_PIN(1, 20),
+};
+static const unsigned int mmc_ds_mux[] = {
+ MMC_DS_MARK,
+};
+
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_clk_pins[] = {
+ /* MSIOF0_SCK */
+ RCAR_GP_PIN(0, 14),
+};
+static const unsigned int msiof0_clk_mux[] = {
+ MSIOF0_SCK_MARK,
+};
+static const unsigned int msiof0_sync_pins[] = {
+ /* MSIOF0_SYNC */
+ RCAR_GP_PIN(0, 11),
+};
+static const unsigned int msiof0_sync_mux[] = {
+ MSIOF0_SYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+ /* MSIOF0_SS1 */
+ RCAR_GP_PIN(0, 15),
+};
+static const unsigned int msiof0_ss1_mux[] = {
+ MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+ /* MSIOF0_SS2 */
+ RCAR_GP_PIN(0, 16),
+};
+static const unsigned int msiof0_ss2_mux[] = {
+ MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_txd_pins[] = {
+ /* MSIOF0_TXD */
+ RCAR_GP_PIN(0, 13),
+};
+static const unsigned int msiof0_txd_mux[] = {
+ MSIOF0_TXD_MARK,
+};
+static const unsigned int msiof0_rxd_pins[] = {
+ /* MSIOF0_RXD */
+ RCAR_GP_PIN(0, 12),
+};
+static const unsigned int msiof0_rxd_mux[] = {
+ MSIOF0_RXD_MARK,
+};
+
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_clk_pins[] = {
+ /* MSIOF1_SCK */
+ RCAR_GP_PIN(0, 8),
+};
+static const unsigned int msiof1_clk_mux[] = {
+ MSIOF1_SCK_MARK,
+};
+static const unsigned int msiof1_sync_pins[] = {
+ /* MSIOF1_SYNC */
+ RCAR_GP_PIN(0, 10),
+};
+static const unsigned int msiof1_sync_mux[] = {
+ MSIOF1_SYNC_MARK,
+};
+static const unsigned int msiof1_ss1_pins[] = {
+ /* MSIOF1_SS1 */
+ RCAR_GP_PIN(0, 17),
+};
+static const unsigned int msiof1_ss1_mux[] = {
+ MSIOF1_SS1_MARK,
+};
+static const unsigned int msiof1_ss2_pins[] = {
+ /* MSIOF1_SS2 */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int msiof1_ss2_mux[] = {
+ MSIOF1_SS2_MARK,
+};
+static const unsigned int msiof1_txd_pins[] = {
+ /* MSIOF1_TXD */
+ RCAR_GP_PIN(0, 7),
+};
+static const unsigned int msiof1_txd_mux[] = {
+ MSIOF1_TXD_MARK,
+};
+static const unsigned int msiof1_rxd_pins[] = {
+ /* MSIOF1_RXD */
+ RCAR_GP_PIN(0, 6),
+};
+static const unsigned int msiof1_rxd_mux[] = {
+ MSIOF1_RXD_MARK,
+};
+
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_clk_pins[] = {
+ /* MSIOF2_SCK */
+ RCAR_GP_PIN(1, 5),
+};
+static const unsigned int msiof2_clk_mux[] = {
+ MSIOF2_SCK_MARK,
+};
+static const unsigned int msiof2_sync_pins[] = {
+ /* MSIOF2_SYNC */
+ RCAR_GP_PIN(1, 4),
+};
+static const unsigned int msiof2_sync_mux[] = {
+ MSIOF2_SYNC_MARK,
+};
+static const unsigned int msiof2_ss1_pins[] = {
+ /* MSIOF2_SS1 */
+ RCAR_GP_PIN(1, 2),
+};
+static const unsigned int msiof2_ss1_mux[] = {
+ MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss2_pins[] = {
+ /* MSIOF2_SS2 */
+ RCAR_GP_PIN(1, 3),
+};
+static const unsigned int msiof2_ss2_mux[] = {
+ MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_txd_pins[] = {
+ /* MSIOF2_TXD */
+ RCAR_GP_PIN(1, 7),
+};
+static const unsigned int msiof2_txd_mux[] = {
+ MSIOF2_TXD_MARK,
+};
+static const unsigned int msiof2_rxd_pins[] = {
+ /* MSIOF2_RXD */
+ RCAR_GP_PIN(1, 6),
+};
+static const unsigned int msiof2_rxd_mux[] = {
+ MSIOF2_RXD_MARK,
+};
+
+/* - MSIOF3 ----------------------------------------------------------------- */
+static const unsigned int msiof3_clk_pins[] = {
+ /* MSIOF3_SCK */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int msiof3_clk_mux[] = {
+ MSIOF3_SCK_MARK,
+};
+static const unsigned int msiof3_sync_pins[] = {
+ /* MSIOF3_SYNC */
+ RCAR_GP_PIN(0, 9),
+};
+static const unsigned int msiof3_sync_mux[] = {
+ MSIOF3_SYNC_MARK,
+};
+static const unsigned int msiof3_ss1_pins[] = {
+ /* MSIOF3_SS1 */
+ RCAR_GP_PIN(0, 4),
+};
+static const unsigned int msiof3_ss1_mux[] = {
+ MSIOF3_SS1_MARK,
+};
+static const unsigned int msiof3_ss2_pins[] = {
+ /* MSIOF3_SS2 */
+ RCAR_GP_PIN(0, 5),
+};
+static const unsigned int msiof3_ss2_mux[] = {
+ MSIOF3_SS2_MARK,
+};
+static const unsigned int msiof3_txd_pins[] = {
+ /* MSIOF3_TXD */
+ RCAR_GP_PIN(0, 3),
+};
+static const unsigned int msiof3_txd_mux[] = {
+ MSIOF3_TXD_MARK,
+};
+static const unsigned int msiof3_rxd_pins[] = {
+ /* MSIOF3_RXD */
+ RCAR_GP_PIN(0, 2),
+};
+static const unsigned int msiof3_rxd_mux[] = {
+ MSIOF3_RXD_MARK,
+};
+
+/* - PCIE ------------------------------------------------------------------- */
+static const unsigned int pcie0_clkreq_n_pins[] = {
+ /* PCIE0_CLKREQ# */
+ RCAR_GP_PIN(2, 15),
+};
+
+static const unsigned int pcie0_clkreq_n_mux[] = {
+ PCIE0_CLKREQ_N_MARK,
+};
+
+static const unsigned int pcie1_clkreq_n_pins[] = {
+ /* PCIE1_CLKREQ# */
+ RCAR_GP_PIN(2, 16),
+};
+
+static const unsigned int pcie1_clkreq_n_mux[] = {
+ PCIE1_CLKREQ_N_MARK,
+};
+
+/* - QSPI0 ------------------------------------------------------------------ */
+static const unsigned int qspi0_ctrl_pins[] = {
+ /* SPCLK, SSL */
+ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 13),
+};
+static const unsigned int qspi0_ctrl_mux[] = {
+ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK,
+};
+static const unsigned int qspi0_data_pins[] = {
+ /* MOSI_IO0, MISO_IO1, IO2, IO3 */
+ RCAR_GP_PIN(2, 9), RCAR_GP_PIN(2, 12),
+ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 14),
+};
+static const unsigned int qspi0_data_mux[] = {
+ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+ QSPI0_IO2_MARK, QSPI0_IO3_MARK
+};
+
+/* - QSPI1 ------------------------------------------------------------------ */
+static const unsigned int qspi1_ctrl_pins[] = {
+ /* SPCLK, SSL */
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 3),
+};
+static const unsigned int qspi1_ctrl_mux[] = {
+ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK,
+};
+static const unsigned int qspi1_data_pins[] = {
+ /* MOSI_IO0, MISO_IO1, IO2, IO3 */
+ RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 5),
+ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 4),
+};
+static const unsigned int qspi1_data_mux[] = {
+ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+ QSPI1_IO2_MARK, QSPI1_IO3_MARK
+};
+
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+ /* RX0, TX0 */
+ RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7),
+};
+static const unsigned int scif0_data_mux[] = {
+ RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_clk_pins[] = {
+ /* SCK0 */
+ RCAR_GP_PIN(0, 8),
+};
+static const unsigned int scif0_clk_mux[] = {
+ SCK0_MARK,
+};
+static const unsigned int scif0_ctrl_pins[] = {
+ /* RTS0#, CTS0# */
+ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10),
+};
+static const unsigned int scif0_ctrl_mux[] = {
+ RTS0_N_MARK, CTS0_N_MARK,
+};
+
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_pins[] = {
+ /* RX1, TX1 */
+ RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13),
+};
+static const unsigned int scif1_data_mux[] = {
+ RX1_MARK, TX1_MARK,
+};
+static const unsigned int scif1_clk_pins[] = {
+ /* SCK1 */
+ RCAR_GP_PIN(0, 14),
+};
+static const unsigned int scif1_clk_mux[] = {
+ SCK1_MARK,
+};
+static const unsigned int scif1_ctrl_pins[] = {
+ /* RTS1#, CTS1# */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 11),
+};
+static const unsigned int scif1_ctrl_mux[] = {
+ RTS1_N_MARK, CTS1_N_MARK,
+};
+
+/* - SCIF3 ------------------------------------------------------------------ */
+static const unsigned int scif3_data_pins[] = {
+ /* RX3, TX3 */
+ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3),
+};
+static const unsigned int scif3_data_mux[] = {
+ RX3_MARK, TX3_MARK,
+};
+static const unsigned int scif3_clk_pins[] = {
+ /* SCK3 */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int scif3_clk_mux[] = {
+ SCK3_MARK,
+};
+static const unsigned int scif3_ctrl_pins[] = {
+ /* RTS3#, CTS3# */
+ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4),
+};
+static const unsigned int scif3_ctrl_mux[] = {
+ RTS3_N_MARK, CTS3_N_MARK,
+};
+
+/* - SCIF4 ------------------------------------------------------------------ */
+static const unsigned int scif4_data_pins[] = {
+ /* RX4, TX4 */
+ RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7),
+};
+static const unsigned int scif4_data_mux[] = {
+ RX4_MARK, TX4_MARK,
+};
+static const unsigned int scif4_clk_pins[] = {
+ /* SCK4 */
+ RCAR_GP_PIN(1, 5),
+};
+static const unsigned int scif4_clk_mux[] = {
+ SCK4_MARK,
+};
+static const unsigned int scif4_ctrl_pins[] = {
+ /* RTS4#, CTS4# */
+ RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 3),
+};
+static const unsigned int scif4_ctrl_mux[] = {
+ RTS4_N_MARK, CTS4_N_MARK,
+};
+
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(0, 0),
+};
+static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+};
+
+/* - TSN0 ------------------------------------------------ */
+static const unsigned int tsn0_link_a_pins[] = {
+ /* TSN0_LINK_A */
+ RCAR_GP_PIN(0, 11),
+};
+static const unsigned int tsn0_link_a_mux[] = {
+ TSN0_LINK_A_MARK,
+};
+static const unsigned int tsn0_magic_a_pins[] = {
+ /* TSN0_MAGIC_A */
+ RCAR_GP_PIN(0, 17),
+};
+static const unsigned int tsn0_magic_a_mux[] = {
+ TSN0_MAGIC_A_MARK,
+};
+static const unsigned int tsn0_phy_int_a_pins[] = {
+ /* TSN0_PHY_INT_A */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int tsn0_phy_int_a_mux[] = {
+ TSN0_PHY_INT_A_MARK,
+};
+static const unsigned int tsn0_mdio_a_pins[] = {
+ /* TSN0_MDC_A, TSN0_MDIO_A */
+ RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5),
+};
+static const unsigned int tsn0_mdio_a_mux[] = {
+ TSN0_MDC_A_MARK, TSN0_MDIO_A_MARK,
+};
+static const unsigned int tsn0_link_b_pins[] = {
+ /* TSN0_LINK_B */
+ RCAR_GP_PIN(3, 8),
+};
+static const unsigned int tsn0_link_b_mux[] = {
+ TSN0_LINK_B_MARK,
+};
+static const unsigned int tsn0_magic_b_pins[] = {
+ /* TSN0_MAGIC_B */
+ RCAR_GP_PIN(3, 12),
+};
+static const unsigned int tsn0_magic_b_mux[] = {
+ TSN0_MAGIC_B_MARK,
+};
+static const unsigned int tsn0_phy_int_b_pins[] = {
+ /* TSN0_PHY_INT_B */
+ RCAR_GP_PIN(3, 10),
+};
+static const unsigned int tsn0_phy_int_b_mux[] = {
+ TSN0_PHY_INT_B_MARK,
+};
+static const unsigned int tsn0_mdio_b_pins[] = {
+ /* TSN0_MDC_B, TSN0_MDIO_B */
+ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 2),
+};
+static const unsigned int tsn0_mdio_b_mux[] = {
+ TSN0_MDC_B_MARK, TSN0_MDIO_B_MARK,
+};
+static const unsigned int tsn0_avtp_pps_pins[] = {
+ /* TSN0_AVTP_PPS */
+ RCAR_GP_PIN(3, 16),
+};
+static const unsigned int tsn0_avtp_pps_mux[] = {
+ TSN0_AVTP_PPS_MARK,
+};
+static const unsigned int tsn0_avtp_capture_a_pins[] = {
+ /* TSN0_AVTP_CAPTURE_A */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int tsn0_avtp_capture_a_mux[] = {
+ TSN0_AVTP_CAPTURE_A_MARK,
+};
+static const unsigned int tsn0_avtp_match_a_pins[] = {
+ /* TSN0_AVTP_MATCH_A */
+ RCAR_GP_PIN(0, 2),
+};
+static const unsigned int tsn0_avtp_match_a_mux[] = {
+ TSN0_AVTP_MATCH_A_MARK,
+};
+static const unsigned int tsn0_avtp_capture_b_pins[] = {
+ /* TSN0_AVTP_CAPTURE_B */
+ RCAR_GP_PIN(3, 18),
+};
+static const unsigned int tsn0_avtp_capture_b_mux[] = {
+ TSN0_AVTP_CAPTURE_B_MARK,
+};
+static const unsigned int tsn0_avtp_match_b_pins[] = {
+ /* TSN0_AVTP_MATCH_B */
+ RCAR_GP_PIN(3, 17),
+};
+static const unsigned int tsn0_avtp_match_b_mux[] = {
+ TSN0_AVTP_MATCH_B_MARK,
+};
+
+/* - TSN1 ------------------------------------------------ */
+static const unsigned int tsn1_link_a_pins[] = {
+ /* TSN1_LINK_A */
+ RCAR_GP_PIN(0, 15),
+};
+static const unsigned int tsn1_link_a_mux[] = {
+ TSN1_LINK_A_MARK,
+};
+static const unsigned int tsn1_phy_int_a_pins[] = {
+ /* TSN1_PHY_INT_A */
+ RCAR_GP_PIN(0, 19),
+};
+static const unsigned int tsn1_phy_int_a_mux[] = {
+ TSN1_PHY_INT_A_MARK,
+};
+static const unsigned int tsn1_mdio_a_pins[] = {
+ /* TSN1_MDC_A, TSN1_MDIO_A */
+ RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 9),
+};
+static const unsigned int tsn1_mdio_a_mux[] = {
+ TSN1_MDC_A_MARK, TSN1_MDIO_A_MARK,
+};
+static const unsigned int tsn1_link_b_pins[] = {
+ /* TSN1_LINK_B */
+ RCAR_GP_PIN(3, 6),
+};
+static const unsigned int tsn1_link_b_mux[] = {
+ TSN1_LINK_B_MARK,
+};
+static const unsigned int tsn1_phy_int_b_pins[] = {
+ /* TSN1_PHY_INT_B */
+ RCAR_GP_PIN(3, 11),
+};
+static const unsigned int tsn1_phy_int_b_mux[] = {
+ TSN1_PHY_INT_B_MARK,
+};
+static const unsigned int tsn1_mdio_b_pins[] = {
+ /* TSN1_MDC_B, TSN1_MDIO_B */
+ RCAR_GP_PIN(3, 5), RCAR_GP_PIN(3, 0),
+};
+static const unsigned int tsn1_mdio_b_mux[] = {
+ TSN1_MDC_B_MARK, TSN1_MDIO_B_MARK,
+};
+static const unsigned int tsn1_avtp_pps_pins[] = {
+ /* TSN1_AVTP_PPS */
+ RCAR_GP_PIN(3, 13),
+};
+static const unsigned int tsn1_avtp_pps_mux[] = {
+ TSN0_AVTP_PPS_MARK,
+};
+static const unsigned int tsn1_avtp_capture_a_pins[] = {
+ /* TSN1_AVTP_CAPTURE_A */
+ RCAR_GP_PIN(0, 7),
+};
+static const unsigned int tsn1_avtp_capture_a_mux[] = {
+ TSN1_AVTP_CAPTURE_A_MARK,
+};
+static const unsigned int tsn1_avtp_match_a_pins[] = {
+ /* TSN1_AVTP_MATCH_A */
+ RCAR_GP_PIN(0, 6),
+};
+static const unsigned int tsn1_avtp_match_a_mux[] = {
+ TSN1_AVTP_MATCH_A_MARK,
+};
+static const unsigned int tsn1_avtp_capture_b_pins[] = {
+ /* TSN1_AVTP_CAPTURE_B */
+ RCAR_GP_PIN(3, 15),
+};
+static const unsigned int tsn1_avtp_capture_b_mux[] = {
+ TSN1_AVTP_CAPTURE_B_MARK,
+};
+static const unsigned int tsn1_avtp_match_b_pins[] = {
+ /* TSN1_AVTP_MATCH_B */
+ RCAR_GP_PIN(3, 14),
+};
+static const unsigned int tsn1_avtp_match_b_mux[] = {
+ TSN1_AVTP_MATCH_B_MARK,
+};
+
+/* - TSN2 ------------------------------------------------ */
+static const unsigned int tsn2_link_a_pins[] = {
+ /* TSN2_LINK_A */
+ RCAR_GP_PIN(0, 16),
+};
+static const unsigned int tsn2_link_a_mux[] = {
+ TSN2_LINK_A_MARK,
+};
+static const unsigned int tsn2_phy_int_a_pins[] = {
+ /* TSN2_PHY_INT_A */
+ RCAR_GP_PIN(0, 20),
+};
+static const unsigned int tsn2_phy_int_a_mux[] = {
+ TSN2_PHY_INT_A_MARK,
+};
+static const unsigned int tsn2_mdio_a_pins[] = {
+ /* TSN2_MDC_A, TSN2_MDIO_A */
+ RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 3),
+};
+static const unsigned int tsn2_mdio_a_mux[] = {
+ TSN2_MDC_A_MARK, TSN2_MDIO_A_MARK,
+};
+static const unsigned int tsn2_link_b_pins[] = {
+ /* TSN2_LINK_B */
+ RCAR_GP_PIN(3, 7),
+};
+static const unsigned int tsn2_link_b_mux[] = {
+ TSN2_LINK_B_MARK,
+};
+static const unsigned int tsn2_phy_int_b_pins[] = {
+ /* TSN2_PHY_INT_B */
+ RCAR_GP_PIN(3, 9),
+};
+static const unsigned int tsn2_phy_int_b_mux[] = {
+ TSN2_PHY_INT_B_MARK,
+};
+static const unsigned int tsn2_mdio_b_pins[] = {
+ /* TSN2_MDC_B, TSN2_MDIO_B */
+ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 1),
+};
+static const unsigned int tsn2_mdio_b_mux[] = {
+ TSN2_MDC_B_MARK, TSN2_MDIO_B_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(hscif0_data),
+ SH_PFC_PIN_GROUP(hscif0_clk),
+ SH_PFC_PIN_GROUP(hscif0_ctrl),
+ SH_PFC_PIN_GROUP(hscif1_data),
+ SH_PFC_PIN_GROUP(hscif1_clk),
+ SH_PFC_PIN_GROUP(hscif1_ctrl),
+ SH_PFC_PIN_GROUP(hscif2_data),
+ SH_PFC_PIN_GROUP(hscif2_clk),
+ SH_PFC_PIN_GROUP(hscif2_ctrl),
+ SH_PFC_PIN_GROUP(hscif3_data),
+ SH_PFC_PIN_GROUP(hscif3_clk),
+ SH_PFC_PIN_GROUP(hscif3_ctrl),
+ SH_PFC_PIN_GROUP(i2c0),
+ SH_PFC_PIN_GROUP(i2c1),
+ SH_PFC_PIN_GROUP(i2c2),
+ SH_PFC_PIN_GROUP(i2c3),
+ SH_PFC_PIN_GROUP(i2c4),
+ SH_PFC_PIN_GROUP(i2c5),
+ SH_PFC_PIN_GROUP(intc_ex_irq0),
+ SH_PFC_PIN_GROUP(intc_ex_irq1),
+ SH_PFC_PIN_GROUP(intc_ex_irq2),
+ SH_PFC_PIN_GROUP(intc_ex_irq3),
+ SH_PFC_PIN_GROUP(intc_ex_irq4),
+ SH_PFC_PIN_GROUP(intc_ex_irq5),
+ BUS_DATA_PIN_GROUP(mmc_data, 1),
+ BUS_DATA_PIN_GROUP(mmc_data, 4),
+ BUS_DATA_PIN_GROUP(mmc_data, 8),
+ SH_PFC_PIN_GROUP(mmc_ctrl),
+ SH_PFC_PIN_GROUP(mmc_cd),
+ SH_PFC_PIN_GROUP(mmc_wp),
+ SH_PFC_PIN_GROUP(mmc_ds),
+ SH_PFC_PIN_GROUP(msiof0_clk),
+ SH_PFC_PIN_GROUP(msiof0_sync),
+ SH_PFC_PIN_GROUP(msiof0_ss1),
+ SH_PFC_PIN_GROUP(msiof0_ss2),
+ SH_PFC_PIN_GROUP(msiof0_txd),
+ SH_PFC_PIN_GROUP(msiof0_rxd),
+ SH_PFC_PIN_GROUP(msiof1_clk),
+ SH_PFC_PIN_GROUP(msiof1_sync),
+ SH_PFC_PIN_GROUP(msiof1_ss1),
+ SH_PFC_PIN_GROUP(msiof1_ss2),
+ SH_PFC_PIN_GROUP(msiof1_txd),
+ SH_PFC_PIN_GROUP(msiof1_rxd),
+ SH_PFC_PIN_GROUP(msiof2_clk),
+ SH_PFC_PIN_GROUP(msiof2_sync),
+ SH_PFC_PIN_GROUP(msiof2_ss1),
+ SH_PFC_PIN_GROUP(msiof2_ss2),
+ SH_PFC_PIN_GROUP(msiof2_txd),
+ SH_PFC_PIN_GROUP(msiof2_rxd),
+ SH_PFC_PIN_GROUP(msiof3_clk),
+ SH_PFC_PIN_GROUP(msiof3_sync),
+ SH_PFC_PIN_GROUP(msiof3_ss1),
+ SH_PFC_PIN_GROUP(msiof3_ss2),
+ SH_PFC_PIN_GROUP(msiof3_txd),
+ SH_PFC_PIN_GROUP(msiof3_rxd),
+ SH_PFC_PIN_GROUP(pcie0_clkreq_n),
+ SH_PFC_PIN_GROUP(pcie1_clkreq_n),
+ SH_PFC_PIN_GROUP(qspi0_ctrl),
+ BUS_DATA_PIN_GROUP(qspi0_data, 2),
+ BUS_DATA_PIN_GROUP(qspi0_data, 4),
+ SH_PFC_PIN_GROUP(qspi1_ctrl),
+ BUS_DATA_PIN_GROUP(qspi1_data, 2),
+ BUS_DATA_PIN_GROUP(qspi1_data, 4),
+ SH_PFC_PIN_GROUP(scif0_data),
+ SH_PFC_PIN_GROUP(scif0_clk),
+ SH_PFC_PIN_GROUP(scif0_ctrl),
+ SH_PFC_PIN_GROUP(scif1_data),
+ SH_PFC_PIN_GROUP(scif1_clk),
+ SH_PFC_PIN_GROUP(scif1_ctrl),
+ SH_PFC_PIN_GROUP(scif3_data),
+ SH_PFC_PIN_GROUP(scif3_clk),
+ SH_PFC_PIN_GROUP(scif3_ctrl),
+ SH_PFC_PIN_GROUP(scif4_data),
+ SH_PFC_PIN_GROUP(scif4_clk),
+ SH_PFC_PIN_GROUP(scif4_ctrl),
+ SH_PFC_PIN_GROUP(scif_clk),
+ SH_PFC_PIN_GROUP(tsn0_link_a),
+ SH_PFC_PIN_GROUP(tsn0_magic_a),
+ SH_PFC_PIN_GROUP(tsn0_phy_int_a),
+ SH_PFC_PIN_GROUP(tsn0_mdio_a),
+ SH_PFC_PIN_GROUP(tsn0_link_b),
+ SH_PFC_PIN_GROUP(tsn0_magic_b),
+ SH_PFC_PIN_GROUP(tsn0_phy_int_b),
+ SH_PFC_PIN_GROUP(tsn0_mdio_b),
+ SH_PFC_PIN_GROUP(tsn0_avtp_pps),
+ SH_PFC_PIN_GROUP(tsn0_avtp_capture_a),
+ SH_PFC_PIN_GROUP(tsn0_avtp_match_a),
+ SH_PFC_PIN_GROUP(tsn0_avtp_capture_b),
+ SH_PFC_PIN_GROUP(tsn0_avtp_match_b),
+ SH_PFC_PIN_GROUP(tsn1_link_a),
+ SH_PFC_PIN_GROUP(tsn1_phy_int_a),
+ SH_PFC_PIN_GROUP(tsn1_mdio_a),
+ SH_PFC_PIN_GROUP(tsn1_link_b),
+ SH_PFC_PIN_GROUP(tsn1_phy_int_b),
+ SH_PFC_PIN_GROUP(tsn1_mdio_b),
+ SH_PFC_PIN_GROUP(tsn1_avtp_pps),
+ SH_PFC_PIN_GROUP(tsn1_avtp_capture_a),
+ SH_PFC_PIN_GROUP(tsn1_avtp_match_a),
+ SH_PFC_PIN_GROUP(tsn1_avtp_capture_b),
+ SH_PFC_PIN_GROUP(tsn1_avtp_match_b),
+ SH_PFC_PIN_GROUP(tsn2_link_a),
+ SH_PFC_PIN_GROUP(tsn2_phy_int_a),
+ SH_PFC_PIN_GROUP(tsn2_mdio_a),
+ SH_PFC_PIN_GROUP(tsn2_link_b),
+ SH_PFC_PIN_GROUP(tsn2_phy_int_b),
+ SH_PFC_PIN_GROUP(tsn2_mdio_b),
+};
+
+static const char * const hscif0_groups[] = {
+ "hscif0_data",
+ "hscif0_clk",
+ "hscif0_ctrl",
+};
+
+static const char * const hscif1_groups[] = {
+ "hscif1_data",
+ "hscif1_clk",
+ "hscif1_ctrl",
+};
+
+static const char * const hscif2_groups[] = {
+ "hscif2_data",
+ "hscif2_clk",
+ "hscif2_ctrl",
+};
+
+static const char * const hscif3_groups[] = {
+ "hscif3_data",
+ "hscif3_clk",
+ "hscif3_ctrl",
+};
+
+static const char * const i2c0_groups[] = {
+ "i2c0",
+};
+
+static const char * const i2c1_groups[] = {
+ "i2c1",
+};
+
+static const char * const i2c2_groups[] = {
+ "i2c2",
+};
+
+static const char * const i2c3_groups[] = {
+ "i2c3",
+};
+
+static const char * const i2c4_groups[] = {
+ "i2c4",
+};
+
+static const char * const i2c5_groups[] = {
+ "i2c5",
+};
+
+static const char * const intc_ex_groups[] = {
+ "intc_ex_irq0",
+ "intc_ex_irq1",
+ "intc_ex_irq2",
+ "intc_ex_irq3",
+ "intc_ex_irq4",
+ "intc_ex_irq5",
+};
+
+static const char * const mmc_groups[] = {
+ "mmc_data1",
+ "mmc_data4",
+ "mmc_data8",
+ "mmc_ctrl",
+ "mmc_cd",
+ "mmc_wp",
+ "mmc_ds",
+};
+
+static const char * const msiof0_groups[] = {
+ "msiof0_clk",
+ "msiof0_sync",
+ "msiof0_ss1",
+ "msiof0_ss2",
+ "msiof0_txd",
+ "msiof0_rxd",
+};
+
+static const char * const msiof1_groups[] = {
+ "msiof1_clk",
+ "msiof1_sync",
+ "msiof1_ss1",
+ "msiof1_ss2",
+ "msiof1_txd",
+ "msiof1_rxd",
+};
+
+static const char * const msiof2_groups[] = {
+ "msiof2_clk",
+ "msiof2_sync",
+ "msiof2_ss1",
+ "msiof2_ss2",
+ "msiof2_txd",
+ "msiof2_rxd",
+};
+
+static const char * const msiof3_groups[] = {
+ "msiof3_clk",
+ "msiof3_sync",
+ "msiof3_ss1",
+ "msiof3_ss2",
+ "msiof3_txd",
+ "msiof3_rxd",
+};
+
+static const char * const pcie_groups[] = {
+ "pcie0_clkreq_n",
+ "pcie1_clkreq_n",
+};
+
+static const char * const qspi0_groups[] = {
+ "qspi0_ctrl",
+ "qspi0_data2",
+ "qspi0_data4",
+};
+
+static const char * const qspi1_groups[] = {
+ "qspi1_ctrl",
+ "qspi1_data2",
+ "qspi1_data4",
+};
+
+static const char * const scif0_groups[] = {
+ "scif0_data",
+ "scif0_clk",
+ "scif0_ctrl",
+};
+
+static const char * const scif1_groups[] = {
+ "scif1_data",
+ "scif1_clk",
+ "scif1_ctrl",
+};
+
+static const char * const scif3_groups[] = {
+ "scif3_data",
+ "scif3_clk",
+ "scif3_ctrl",
+};
+
+static const char * const scif4_groups[] = {
+ "scif4_data",
+ "scif4_clk",
+ "scif4_ctrl",
+};
+
+static const char * const scif_clk_groups[] = {
+ "scif_clk",
+};
+
+static const char * const tsn0_groups[] = {
+ "tsn0_link_a",
+ "tsn0_magic_a",
+ "tsn0_phy_int_a",
+ "tsn0_mdio_a",
+ "tsn0_link_b",
+ "tsn0_magic_b",
+ "tsn0_phy_int_b",
+ "tsn0_mdio_b",
+ "tsn0_avtp_pps",
+ "tsn0_avtp_capture_a",
+ "tsn0_avtp_match_a",
+ "tsn0_avtp_capture_b",
+ "tsn0_avtp_match_b",
+};
+
+static const char * const tsn1_groups[] = {
+ "tsn1_link_a",
+ "tsn1_phy_int_a",
+ "tsn1_mdio_a",
+ "tsn1_link_b",
+ "tsn1_phy_int_b",
+ "tsn1_mdio_b",
+ "tsn1_avtp_pps",
+ "tsn1_avtp_capture_a",
+ "tsn1_avtp_match_a",
+ "tsn1_avtp_capture_b",
+ "tsn1_avtp_match_b",
+};
+
+static const char * const tsn2_groups[] = {
+ "tsn2_link_a",
+ "tsn2_phy_int_a",
+ "tsn2_mdio_a",
+ "tsn2_link_b",
+ "tsn2_phy_int_b",
+ "tsn2_mdio_b",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(hscif0),
+ SH_PFC_FUNCTION(hscif1),
+ SH_PFC_FUNCTION(hscif2),
+ SH_PFC_FUNCTION(hscif3),
+ SH_PFC_FUNCTION(i2c0),
+ SH_PFC_FUNCTION(i2c1),
+ SH_PFC_FUNCTION(i2c2),
+ SH_PFC_FUNCTION(i2c3),
+ SH_PFC_FUNCTION(i2c4),
+ SH_PFC_FUNCTION(i2c5),
+ SH_PFC_FUNCTION(intc_ex),
+ SH_PFC_FUNCTION(mmc),
+ SH_PFC_FUNCTION(msiof0),
+ SH_PFC_FUNCTION(msiof1),
+ SH_PFC_FUNCTION(msiof2),
+ SH_PFC_FUNCTION(msiof3),
+ SH_PFC_FUNCTION(pcie),
+ SH_PFC_FUNCTION(qspi0),
+ SH_PFC_FUNCTION(qspi1),
+ SH_PFC_FUNCTION(scif0),
+ SH_PFC_FUNCTION(scif1),
+ SH_PFC_FUNCTION(scif3),
+ SH_PFC_FUNCTION(scif4),
+ SH_PFC_FUNCTION(scif_clk),
+ SH_PFC_FUNCTION(tsn0),
+ SH_PFC_FUNCTION(tsn1),
+ SH_PFC_FUNCTION(tsn2),
+};
+
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
+#define F_(x, y) FN_##y
+#define FM(x) FN_##x
+ { PINMUX_CFG_REG_VAR("GPSR0", 0xe6050040, 32,
+ GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP0_31_21 RESERVED */
+ GP_0_20_FN, GPSR0_20,
+ GP_0_19_FN, GPSR0_19,
+ GP_0_18_FN, GPSR0_18,
+ GP_0_17_FN, GPSR0_17,
+ GP_0_16_FN, GPSR0_16,
+ GP_0_15_FN, GPSR0_15,
+ GP_0_14_FN, GPSR0_14,
+ GP_0_13_FN, GPSR0_13,
+ GP_0_12_FN, GPSR0_12,
+ GP_0_11_FN, GPSR0_11,
+ GP_0_10_FN, GPSR0_10,
+ GP_0_9_FN, GPSR0_9,
+ GP_0_8_FN, GPSR0_8,
+ GP_0_7_FN, GPSR0_7,
+ GP_0_6_FN, GPSR0_6,
+ GP_0_5_FN, GPSR0_5,
+ GP_0_4_FN, GPSR0_4,
+ GP_0_3_FN, GPSR0_3,
+ GP_0_2_FN, GPSR0_2,
+ GP_0_1_FN, GPSR0_1,
+ GP_0_0_FN, GPSR0_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR1", 0xe6050840, 32,
+ GROUP(-7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP1_31_25 RESERVED */
+ GP_1_24_FN, GPSR1_24,
+ GP_1_23_FN, GPSR1_23,
+ GP_1_22_FN, GPSR1_22,
+ GP_1_21_FN, GPSR1_21,
+ GP_1_20_FN, GPSR1_20,
+ GP_1_19_FN, GPSR1_19,
+ GP_1_18_FN, GPSR1_18,
+ GP_1_17_FN, GPSR1_17,
+ GP_1_16_FN, GPSR1_16,
+ GP_1_15_FN, GPSR1_15,
+ GP_1_14_FN, GPSR1_14,
+ GP_1_13_FN, GPSR1_13,
+ GP_1_12_FN, GPSR1_12,
+ GP_1_11_FN, GPSR1_11,
+ GP_1_10_FN, GPSR1_10,
+ GP_1_9_FN, GPSR1_9,
+ GP_1_8_FN, GPSR1_8,
+ GP_1_7_FN, GPSR1_7,
+ GP_1_6_FN, GPSR1_6,
+ GP_1_5_FN, GPSR1_5,
+ GP_1_4_FN, GPSR1_4,
+ GP_1_3_FN, GPSR1_3,
+ GP_1_2_FN, GPSR1_2,
+ GP_1_1_FN, GPSR1_1,
+ GP_1_0_FN, GPSR1_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR2", 0xe6051040, 32,
+ GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP2_31_17 RESERVED */
+ GP_2_16_FN, GPSR2_16,
+ GP_2_15_FN, GPSR2_15,
+ GP_2_14_FN, GPSR2_14,
+ GP_2_13_FN, GPSR2_13,
+ GP_2_12_FN, GPSR2_12,
+ GP_2_11_FN, GPSR2_11,
+ GP_2_10_FN, GPSR2_10,
+ GP_2_9_FN, GPSR2_9,
+ GP_2_8_FN, GPSR2_8,
+ GP_2_7_FN, GPSR2_7,
+ GP_2_6_FN, GPSR2_6,
+ GP_2_5_FN, GPSR2_5,
+ GP_2_4_FN, GPSR2_4,
+ GP_2_3_FN, GPSR2_3,
+ GP_2_2_FN, GPSR2_2,
+ GP_2_1_FN, GPSR2_1,
+ GP_2_0_FN, GPSR2_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR3", 0xe6051840, 32,
+ GROUP(-13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP3_31_19 RESERVED */
+ GP_3_18_FN, GPSR3_18,
+ GP_3_17_FN, GPSR3_17,
+ GP_3_16_FN, GPSR3_16,
+ GP_3_15_FN, GPSR3_15,
+ GP_3_14_FN, GPSR3_14,
+ GP_3_13_FN, GPSR3_13,
+ GP_3_12_FN, GPSR3_12,
+ GP_3_11_FN, GPSR3_11,
+ GP_3_10_FN, GPSR3_10,
+ GP_3_9_FN, GPSR3_9,
+ GP_3_8_FN, GPSR3_8,
+ GP_3_7_FN, GPSR3_7,
+ GP_3_6_FN, GPSR3_6,
+ GP_3_5_FN, GPSR3_5,
+ GP_3_4_FN, GPSR3_4,
+ GP_3_3_FN, GPSR3_3,
+ GP_3_2_FN, GPSR3_2,
+ GP_3_1_FN, GPSR3_1,
+ GP_3_0_FN, GPSR3_0, ))
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG("IP0SR0", 0xe6050060, 32, 4, GROUP(
+ IP0SR0_31_28
+ IP0SR0_27_24
+ IP0SR0_23_20
+ IP0SR0_19_16
+ IP0SR0_15_12
+ IP0SR0_11_8
+ IP0SR0_7_4
+ IP0SR0_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR0", 0xe6050064, 32, 4, GROUP(
+ IP1SR0_31_28
+ IP1SR0_27_24
+ IP1SR0_23_20
+ IP1SR0_19_16
+ IP1SR0_15_12
+ IP1SR0_11_8
+ IP1SR0_7_4
+ IP1SR0_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP2SR0", 0xe6050068, 32,
+ GROUP(-12, 4, 4, 4, 4, 4),
+ GROUP(
+ /* IP2SR0_31_20 RESERVED */
+ IP2SR0_19_16
+ IP2SR0_15_12
+ IP2SR0_11_8
+ IP2SR0_7_4
+ IP2SR0_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR1", 0xe6050860, 32, 4, GROUP(
+ IP0SR1_31_28
+ IP0SR1_27_24
+ IP0SR1_23_20
+ IP0SR1_19_16
+ IP0SR1_15_12
+ IP0SR1_11_8
+ IP0SR1_7_4
+ IP0SR1_3_0))
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6050900, 32,
+ GROUP(-20, 2, 2, 2, 2, 2, 2),
+ GROUP(
+ /* RESERVED 31-12 */
+ MOD_SEL1_11_10
+ MOD_SEL1_9_8
+ MOD_SEL1_7_6
+ MOD_SEL1_5_4
+ MOD_SEL1_3_2
+ MOD_SEL1_1_0))
+ },
+ { /* sentinel */ },
+};
+
+static const struct pinmux_drive_reg pinmux_drive_regs[] = {
+ { PINMUX_DRIVE_REG("DRV0CTRL0", 0xe6050080) {
+ { RCAR_GP_PIN(0, 7), 28, 3 }, /* TX0 */
+ { RCAR_GP_PIN(0, 6), 24, 3 }, /* RX0 */
+ { RCAR_GP_PIN(0, 5), 20, 3 }, /* HRTS0_N */
+ { RCAR_GP_PIN(0, 4), 16, 3 }, /* HCTS0_N */
+ { RCAR_GP_PIN(0, 3), 12, 3 }, /* HTX0 */
+ { RCAR_GP_PIN(0, 2), 8, 3 }, /* HRX0 */
+ { RCAR_GP_PIN(0, 1), 4, 3 }, /* HSCK0 */
+ { RCAR_GP_PIN(0, 0), 0, 3 }, /* SCIF_CLK */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL0", 0xe6050084) {
+ { RCAR_GP_PIN(0, 15), 28, 3 }, /* MSIOF0_SS1 */
+ { RCAR_GP_PIN(0, 14), 24, 3 }, /* MSIOF0_SCK */
+ { RCAR_GP_PIN(0, 13), 20, 3 }, /* MSIOF0_TXD */
+ { RCAR_GP_PIN(0, 12), 16, 3 }, /* MSIOF0_RXD */
+ { RCAR_GP_PIN(0, 11), 12, 3 }, /* MSIOF0_SYNC */
+ { RCAR_GP_PIN(0, 10), 8, 3 }, /* CTS0_N */
+ { RCAR_GP_PIN(0, 9), 4, 3 }, /* RTS0_N */
+ { RCAR_GP_PIN(0, 8), 0, 3 }, /* SCK0 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL0", 0xe6050088) {
+ { RCAR_GP_PIN(0, 20), 16, 3 }, /* IRQ3 */
+ { RCAR_GP_PIN(0, 19), 12, 3 }, /* IRQ2 */
+ { RCAR_GP_PIN(0, 18), 8, 3 }, /* IRQ1 */
+ { RCAR_GP_PIN(0, 17), 4, 3 }, /* IRQ0 */
+ { RCAR_GP_PIN(0, 16), 0, 3 }, /* MSIOF0_SS2 */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL1", 0xe6050880) {
+ { RCAR_GP_PIN(1, 7), 28, 3 }, /* GP1_07 */
+ { RCAR_GP_PIN(1, 6), 24, 3 }, /* GP1_06 */
+ { RCAR_GP_PIN(1, 5), 20, 3 }, /* GP1_05 */
+ { RCAR_GP_PIN(1, 4), 16, 3 }, /* GP1_04 */
+ { RCAR_GP_PIN(1, 3), 12, 3 }, /* GP1_03 */
+ { RCAR_GP_PIN(1, 2), 8, 3 }, /* GP1_02 */
+ { RCAR_GP_PIN(1, 1), 4, 3 }, /* GP1_01 */
+ { RCAR_GP_PIN(1, 0), 0, 3 }, /* GP1_00 */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL1", 0xe6050884) {
+ { RCAR_GP_PIN(1, 15), 28, 3 }, /* MMC_SD_D2 */
+ { RCAR_GP_PIN(1, 14), 24, 3 }, /* MMC_SD_D1 */
+ { RCAR_GP_PIN(1, 13), 20, 3 }, /* MMC_SD_D0 */
+ { RCAR_GP_PIN(1, 12), 16, 3 }, /* MMC_SD_CLK */
+ { RCAR_GP_PIN(1, 11), 12, 3 }, /* GP1_11 */
+ { RCAR_GP_PIN(1, 10), 8, 3 }, /* GP1_10 */
+ { RCAR_GP_PIN(1, 9), 4, 3 }, /* GP1_09 */
+ { RCAR_GP_PIN(1, 8), 0, 3 }, /* GP1_08 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL1", 0xe6050888) {
+ { RCAR_GP_PIN(1, 23), 28, 3 }, /* SD_CD */
+ { RCAR_GP_PIN(1, 22), 24, 3 }, /* MMC_SD_CMD */
+ { RCAR_GP_PIN(1, 21), 20, 3 }, /* MMC_D7 */
+ { RCAR_GP_PIN(1, 20), 16, 3 }, /* MMC_DS */
+ { RCAR_GP_PIN(1, 19), 12, 3 }, /* MMC_D6 */
+ { RCAR_GP_PIN(1, 18), 8, 3 }, /* MMC_D4 */
+ { RCAR_GP_PIN(1, 17), 4, 3 }, /* MMC_D5 */
+ { RCAR_GP_PIN(1, 16), 0, 3 }, /* MMC_SD_D3 */
+ } },
+ { PINMUX_DRIVE_REG("DRV3CTRL1", 0xe605088c) {
+ { RCAR_GP_PIN(1, 24), 0, 3 }, /* SD_WP */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL2", 0xe6051080) {
+ { RCAR_GP_PIN(2, 7), 28, 2 }, /* QSPI1_MOSI_IO0 */
+ { RCAR_GP_PIN(2, 6), 24, 2 }, /* QSPI1_IO2 */
+ { RCAR_GP_PIN(2, 5), 20, 2 }, /* QSPI1_MISO_IO1 */
+ { RCAR_GP_PIN(2, 4), 16, 2 }, /* QSPI1_IO3 */
+ { RCAR_GP_PIN(2, 3), 12, 2 }, /* QSPI1_SSL */
+ { RCAR_GP_PIN(2, 2), 8, 2 }, /* RPC_RESET_N */
+ { RCAR_GP_PIN(2, 1), 4, 2 }, /* RPC_WP_N */
+ { RCAR_GP_PIN(2, 0), 0, 2 }, /* RPC_INT_N */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL2", 0xe6051084) {
+ { RCAR_GP_PIN(2, 15), 28, 3 }, /* PCIE0_CLKREQ_N */
+ { RCAR_GP_PIN(2, 14), 24, 2 }, /* QSPI0_IO3 */
+ { RCAR_GP_PIN(2, 13), 20, 2 }, /* QSPI0_SSL */
+ { RCAR_GP_PIN(2, 12), 16, 2 }, /* QSPI0_MISO_IO1 */
+ { RCAR_GP_PIN(2, 11), 12, 2 }, /* QSPI0_IO2 */
+ { RCAR_GP_PIN(2, 10), 8, 2 }, /* QSPI0_SPCLK */
+ { RCAR_GP_PIN(2, 9), 4, 2 }, /* QSPI0_MOSI_IO0 */
+ { RCAR_GP_PIN(2, 8), 0, 2 }, /* QSPI1_SPCLK */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL2", 0xe6051088) {
+ { RCAR_GP_PIN(2, 16), 0, 3 }, /* PCIE1_CLKREQ_N */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL3", 0xe6051880) {
+ { RCAR_GP_PIN(3, 7), 28, 3 }, /* TSN2_LINK_B */
+ { RCAR_GP_PIN(3, 6), 24, 3 }, /* TSN1_LINK_B */
+ { RCAR_GP_PIN(3, 5), 20, 3 }, /* TSN1_MDC_B */
+ { RCAR_GP_PIN(3, 4), 16, 3 }, /* TSN0_MDC_B */
+ { RCAR_GP_PIN(3, 3), 12, 3 }, /* TSN2_MDC_B */
+ { RCAR_GP_PIN(3, 2), 8, 3 }, /* TSN0_MDIO_B */
+ { RCAR_GP_PIN(3, 1), 4, 3 }, /* TSN2_MDIO_B */
+ { RCAR_GP_PIN(3, 0), 0, 3 }, /* TSN1_MDIO_B */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL3", 0xe6051884) {
+ { RCAR_GP_PIN(3, 15), 28, 3 }, /* TSN1_AVTP_CAPTURE_B */
+ { RCAR_GP_PIN(3, 14), 24, 3 }, /* TSN1_AVTP_MATCH_B */
+ { RCAR_GP_PIN(3, 13), 20, 3 }, /* TSN1_AVTP_PPS */
+ { RCAR_GP_PIN(3, 12), 16, 3 }, /* TSN0_MAGIC_B */
+ { RCAR_GP_PIN(3, 11), 12, 3 }, /* TSN1_PHY_INT_B */
+ { RCAR_GP_PIN(3, 10), 8, 3 }, /* TSN0_PHY_INT_B */
+ { RCAR_GP_PIN(3, 9), 4, 3 }, /* TSN2_PHY_INT_B */
+ { RCAR_GP_PIN(3, 8), 0, 3 }, /* TSN0_LINK_B */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL3", 0xe6051888) {
+ { RCAR_GP_PIN(3, 18), 8, 3 }, /* TSN0_AVTP_CAPTURE_B */
+ { RCAR_GP_PIN(3, 17), 4, 3 }, /* TSN0_AVTP_MATCH_B */
+ { RCAR_GP_PIN(3, 16), 0, 3 }, /* TSN0_AVTP_PPS */
+ } },
+ { /* sentinel */ },
+};
+
+enum ioctrl_regs {
+ POC0,
+ POC1,
+ POC3,
+ TD0SEL1,
+};
+
+static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = {
+ [POC0] = { 0xe60500a0, },
+ [POC1] = { 0xe60508a0, },
+ [POC3] = { 0xe60518a0, },
+ [TD0SEL1] = { 0xe6050920, },
+ { /* sentinel */ },
+};
+
+static int r8a779f0_pin_to_pocctrl(unsigned int pin, u32 *pocctrl)
+{
+ int bit = pin & 0x1f;
+
+ *pocctrl = pinmux_ioctrl_regs[POC0].reg;
+ if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 20))
+ return bit;
+
+ *pocctrl = pinmux_ioctrl_regs[POC1].reg;
+ if (pin >= RCAR_GP_PIN(1, 0) && pin <= RCAR_GP_PIN(1, 24))
+ return bit;
+
+ *pocctrl = pinmux_ioctrl_regs[POC3].reg;
+ if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 18))
+ return bit;
+
+ return -EINVAL;
+}
+
+static const struct pinmux_bias_reg pinmux_bias_regs[] = {
+ { PINMUX_BIAS_REG("PUEN0", 0xe60500c0, "PUD0", 0xe60500e0) {
+ [ 0] = RCAR_GP_PIN(0, 0), /* SCIF_CLK */
+ [ 1] = RCAR_GP_PIN(0, 1), /* HSCK0 */
+ [ 2] = RCAR_GP_PIN(0, 2), /* HRX0 */
+ [ 3] = RCAR_GP_PIN(0, 3), /* HTX0 */
+ [ 4] = RCAR_GP_PIN(0, 4), /* HCTS0_N */
+ [ 5] = RCAR_GP_PIN(0, 5), /* HRTS0_N */
+ [ 6] = RCAR_GP_PIN(0, 6), /* RX0 */
+ [ 7] = RCAR_GP_PIN(0, 7), /* TX0 */
+ [ 8] = RCAR_GP_PIN(0, 8), /* SCK0 */
+ [ 9] = RCAR_GP_PIN(0, 9), /* RTS0_N */
+ [10] = RCAR_GP_PIN(0, 10), /* CTS0_N */
+ [11] = RCAR_GP_PIN(0, 11), /* MSIOF0_SYNC */
+ [12] = RCAR_GP_PIN(0, 12), /* MSIOF0_RXD */
+ [13] = RCAR_GP_PIN(0, 13), /* MSIOF0_TXD */
+ [14] = RCAR_GP_PIN(0, 14), /* MSIOF0_SCK */
+ [15] = RCAR_GP_PIN(0, 15), /* MSIOF0_SS1 */
+ [16] = RCAR_GP_PIN(0, 16), /* MSIOF0_SS2 */
+ [17] = RCAR_GP_PIN(0, 17), /* IRQ0 */
+ [18] = RCAR_GP_PIN(0, 18), /* IRQ1 */
+ [19] = RCAR_GP_PIN(0, 19), /* IRQ2 */
+ [20] = RCAR_GP_PIN(0, 20), /* IRQ3 */
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN1", 0xe60508c0, "PUD1", 0xe60508e0) {
+ [ 0] = RCAR_GP_PIN(1, 0), /* GP1_00 */
+ [ 1] = RCAR_GP_PIN(1, 1), /* GP1_01 */
+ [ 2] = RCAR_GP_PIN(1, 2), /* GP1_02 */
+ [ 3] = RCAR_GP_PIN(1, 3), /* GP1_03 */
+ [ 4] = RCAR_GP_PIN(1, 4), /* GP1_04 */
+ [ 5] = RCAR_GP_PIN(1, 5), /* GP1_05 */
+ [ 6] = RCAR_GP_PIN(1, 6), /* GP1_06 */
+ [ 7] = RCAR_GP_PIN(1, 7), /* GP1_07 */
+ [ 8] = RCAR_GP_PIN(1, 8), /* GP1_08 */
+ [ 9] = RCAR_GP_PIN(1, 9), /* GP1_09 */
+ [10] = RCAR_GP_PIN(1, 10), /* GP1_10 */
+ [11] = RCAR_GP_PIN(1, 11), /* GP1_11 */
+ [12] = RCAR_GP_PIN(1, 12), /* MMC_SD_CLK */
+ [13] = RCAR_GP_PIN(1, 13), /* MMC_SD_D0 */
+ [14] = RCAR_GP_PIN(1, 14), /* MMC_SD_D1 */
+ [15] = RCAR_GP_PIN(1, 15), /* MMC_SD_D2 */
+ [16] = RCAR_GP_PIN(1, 16), /* MMC_SD_D3 */
+ [17] = RCAR_GP_PIN(1, 17), /* MMC_D5 */
+ [18] = RCAR_GP_PIN(1, 18), /* MMC_D4 */
+ [19] = RCAR_GP_PIN(1, 19), /* MMC_D6 */
+ [20] = RCAR_GP_PIN(1, 20), /* MMC_DS */
+ [21] = RCAR_GP_PIN(1, 21), /* MMC_D7 */
+ [22] = RCAR_GP_PIN(1, 22), /* MMC_SD_CMD */
+ [23] = RCAR_GP_PIN(1, 23), /* SD_CD */
+ [24] = RCAR_GP_PIN(1, 24), /* SD_WP */
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN2", 0xe60510c0, "PUD2", 0xe60510e0) {
+ [ 0] = RCAR_GP_PIN(2, 0), /* RPC_INT_N */
+ [ 1] = RCAR_GP_PIN(2, 1), /* RPC_WP_N */
+ [ 2] = RCAR_GP_PIN(2, 2), /* RPC_RESET_N */
+ [ 3] = RCAR_GP_PIN(2, 3), /* QSPI1_SSL */
+ [ 4] = RCAR_GP_PIN(2, 4), /* QSPI1_IO3 */
+ [ 5] = RCAR_GP_PIN(2, 5), /* QSPI1_MISO_IO1 */
+ [ 6] = RCAR_GP_PIN(2, 6), /* QSPI1_IO2 */
+ [ 7] = RCAR_GP_PIN(2, 7), /* QSPI1_MOSI_IO0 */
+ [ 8] = RCAR_GP_PIN(2, 8), /* QSPI1_SPCLK */
+ [ 9] = RCAR_GP_PIN(2, 9), /* QSPI0_MOSI_IO0 */
+ [10] = RCAR_GP_PIN(2, 10), /* QSPI0_SPCLK */
+ [11] = RCAR_GP_PIN(2, 11), /* QSPI0_IO2 */
+ [12] = RCAR_GP_PIN(2, 12), /* QSPI0_MISO_IO1 */
+ [13] = RCAR_GP_PIN(2, 13), /* QSPI0_SSL */
+ [14] = RCAR_GP_PIN(2, 14), /* QSPI0_IO3 */
+ [15] = RCAR_GP_PIN(2, 15), /* PCIE0_CLKREQ_N */
+ [16] = RCAR_GP_PIN(2, 16), /* PCIE1_CLKREQ_N */
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN3", 0xe60518c0, "PUD3", 0xe60518e0) {
+ [ 0] = RCAR_GP_PIN(3, 0), /* TSN1_MDIO_B */
+ [ 1] = RCAR_GP_PIN(3, 1), /* TSN2_MDIO_B */
+ [ 2] = RCAR_GP_PIN(3, 2), /* TSN0_MDIO_B */
+ [ 3] = RCAR_GP_PIN(3, 3), /* TSN2_MDC_B */
+ [ 4] = RCAR_GP_PIN(3, 4), /* TSN0_MDC_B */
+ [ 5] = RCAR_GP_PIN(3, 5), /* TSN1_MDC_B */
+ [ 6] = RCAR_GP_PIN(3, 6), /* TSN1_LINK_B */
+ [ 7] = RCAR_GP_PIN(3, 7), /* TSN2_LINK_B */
+ [ 8] = RCAR_GP_PIN(3, 8), /* TSN0_LINK_B */
+ [ 9] = RCAR_GP_PIN(3, 9), /* TSN2_PHY_INT_B */
+ [10] = RCAR_GP_PIN(3, 10), /* TSN0_PHY_INT_B */
+ [11] = RCAR_GP_PIN(3, 11), /* TSN1_PHY_INT_B */
+ [12] = RCAR_GP_PIN(3, 12), /* TSN0_MAGIC_B */
+ [13] = RCAR_GP_PIN(3, 13), /* TSN1_AVTP_PPS */
+ [14] = RCAR_GP_PIN(3, 14), /* TSN1_AVTP_MATCH_B */
+ [15] = RCAR_GP_PIN(3, 15), /* TSN1_AVTP_CAPTURE_B */
+ [16] = RCAR_GP_PIN(3, 16), /* TSN0_AVTP_PPS */
+ [17] = RCAR_GP_PIN(3, 17), /* TSN0_AVTP_MATCH_B */
+ [18] = RCAR_GP_PIN(3, 18), /* TSN0_AVTP_CAPTURE_B */
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { /* sentinel */ },
+};
+
+static const struct sh_pfc_soc_operations r8a779f0_pfc_ops = {
+ .pin_to_pocctrl = r8a779f0_pin_to_pocctrl,
+ .get_bias = rcar_pinmux_get_bias,
+ .set_bias = rcar_pinmux_set_bias,
+};
+
+const struct sh_pfc_soc_info r8a779f0_pinmux_info = {
+ .name = "r8a779f0_pfc",
+ .ops = &r8a779f0_pfc_ops,
+ .unlock_reg = 0x1ff, /* PMMRn mask */
+
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .pins = pinmux_pins,
+ .nr_pins = ARRAY_SIZE(pinmux_pins),
+ .groups = pinmux_groups,
+ .nr_groups = ARRAY_SIZE(pinmux_groups),
+ .functions = pinmux_functions,
+ .nr_functions = ARRAY_SIZE(pinmux_functions),
+
+ .cfg_regs = pinmux_config_regs,
+ .drive_regs = pinmux_drive_regs,
+ .bias_regs = pinmux_bias_regs,
+ .ioctrl_regs = pinmux_ioctrl_regs,
+
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
+};
diff --git a/drivers/pinctrl/renesas/pfc-r8a779g0.c b/drivers/pinctrl/renesas/pfc-r8a779g0.c
new file mode 100644
index 00000000000..78a91f426d9
--- /dev/null
+++ b/drivers/pinctrl/renesas/pfc-r8a779g0.c
@@ -0,0 +1,4265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R8A779A0 processor support - PFC hardware block.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * This file is based on the drivers/pinctrl/renesas/pfc-r8a779a0.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+
+#include "sh_pfc.h"
+
+#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
+#define CPU_ALL_GP(fn, sfx) \
+ PORT_GP_CFG_19(0, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \
+ PORT_GP_CFG_23(1, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \
+ PORT_GP_CFG_1(1, 23, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(1, 24, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(1, 25, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(1, 26, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(1, 27, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(1, 28, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_20(2, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_13(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \
+ PORT_GP_CFG_1(3, 13, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 14, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 15, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 16, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 17, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 18, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 19, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 20, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 21, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 22, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 23, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 24, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 25, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 26, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 27, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 28, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_1(3, 29, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_25(4, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_21(5, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_21(6, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_21(7, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_14(8, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33)
+
+/* GPSR0 */
+#define GPSR0_18 F_(MSIOF2_RXD, IP2SR0_11_8)
+#define GPSR0_17 F_(MSIOF2_SCK, IP2SR0_7_4)
+#define GPSR0_16 F_(MSIOF2_TXD, IP2SR0_3_0)
+#define GPSR0_15 F_(MSIOF2_SYNC, IP1SR0_31_28)
+#define GPSR0_14 F_(MSIOF2_SS1, IP1SR0_27_24)
+#define GPSR0_13 F_(MSIOF2_SS2, IP1SR0_23_20)
+#define GPSR0_12 F_(MSIOF5_RXD, IP1SR0_19_16)
+#define GPSR0_11 F_(MSIOF5_SCK, IP1SR0_15_12)
+#define GPSR0_10 F_(MSIOF5_TXD, IP1SR0_11_8)
+#define GPSR0_9 F_(MSIOF5_SYNC, IP1SR0_7_4)
+#define GPSR0_8 F_(MSIOF5_SS1, IP1SR0_3_0)
+#define GPSR0_7 F_(MSIOF5_SS2, IP0SR0_31_28)
+#define GPSR0_6 F_(IRQ0, IP0SR0_27_24)
+#define GPSR0_5 F_(IRQ1, IP0SR0_23_20)
+#define GPSR0_4 F_(IRQ2, IP0SR0_19_16)
+#define GPSR0_3 F_(IRQ3, IP0SR0_15_12)
+#define GPSR0_2 F_(GP0_02, IP0SR0_11_8)
+#define GPSR0_1 F_(GP0_01, IP0SR0_7_4)
+#define GPSR0_0 F_(GP0_00, IP0SR0_3_0)
+
+/* GPSR1 */
+#define GPSR1_28 F_(HTX3, IP3SR1_19_16)
+#define GPSR1_27 F_(HCTS3_N, IP3SR1_15_12)
+#define GPSR1_26 F_(HRTS3_N, IP3SR1_11_8)
+#define GPSR1_25 F_(HSCK3, IP3SR1_7_4)
+#define GPSR1_24 F_(HRX3, IP3SR1_3_0)
+#define GPSR1_23 F_(GP1_23, IP2SR1_31_28)
+#define GPSR1_22 F_(AUDIO_CLKIN, IP2SR1_27_24)
+#define GPSR1_21 F_(AUDIO_CLKOUT, IP2SR1_23_20)
+#define GPSR1_20 F_(SSI_SD, IP2SR1_19_16)
+#define GPSR1_19 F_(SSI_WS, IP2SR1_15_12)
+#define GPSR1_18 F_(SSI_SCK, IP2SR1_11_8)
+#define GPSR1_17 F_(SCIF_CLK, IP2SR1_7_4)
+#define GPSR1_16 F_(HRX0, IP2SR1_3_0)
+#define GPSR1_15 F_(HSCK0, IP1SR1_31_28)
+#define GPSR1_14 F_(HRTS0_N, IP1SR1_27_24)
+#define GPSR1_13 F_(HCTS0_N, IP1SR1_23_20)
+#define GPSR1_12 F_(HTX0, IP1SR1_19_16)
+#define GPSR1_11 F_(MSIOF0_RXD, IP1SR1_15_12)
+#define GPSR1_10 F_(MSIOF0_SCK, IP1SR1_11_8)
+#define GPSR1_9 F_(MSIOF0_TXD, IP1SR1_7_4)
+#define GPSR1_8 F_(MSIOF0_SYNC, IP1SR1_3_0)
+#define GPSR1_7 F_(MSIOF0_SS1, IP0SR1_31_28)
+#define GPSR1_6 F_(MSIOF0_SS2, IP0SR1_27_24)
+#define GPSR1_5 F_(MSIOF1_RXD, IP0SR1_23_20)
+#define GPSR1_4 F_(MSIOF1_TXD, IP0SR1_19_16)
+#define GPSR1_3 F_(MSIOF1_SCK, IP0SR1_15_12)
+#define GPSR1_2 F_(MSIOF1_SYNC, IP0SR1_11_8)
+#define GPSR1_1 F_(MSIOF1_SS1, IP0SR1_7_4)
+#define GPSR1_0 F_(MSIOF1_SS2, IP0SR1_3_0)
+
+/* GPSR2 */
+#define GPSR2_19 F_(CANFD7_RX, IP2SR2_15_12)
+#define GPSR2_18 F_(CANFD7_TX, IP2SR2_11_8)
+#define GPSR2_17 F_(CANFD4_RX, IP2SR2_7_4)
+#define GPSR2_16 F_(CANFD4_TX, IP2SR2_3_0)
+#define GPSR2_15 F_(CANFD3_RX, IP1SR2_31_28)
+#define GPSR2_14 F_(CANFD3_TX, IP1SR2_27_24)
+#define GPSR2_13 F_(CANFD2_RX, IP1SR2_23_20)
+#define GPSR2_12 F_(CANFD2_TX, IP1SR2_19_16)
+#define GPSR2_11 F_(CANFD0_RX, IP1SR2_15_12)
+#define GPSR2_10 F_(CANFD0_TX, IP1SR2_11_8)
+#define GPSR2_9 F_(CAN_CLK, IP1SR2_7_4)
+#define GPSR2_8 F_(TPU0TO0, IP1SR2_3_0)
+#define GPSR2_7 F_(TPU0TO1, IP0SR2_31_28)
+#define GPSR2_6 F_(FXR_TXDB, IP0SR2_27_24)
+#define GPSR2_5 F_(FXR_TXENB_N, IP0SR2_23_20)
+#define GPSR2_4 F_(RXDB_EXTFXR, IP0SR2_19_16)
+#define GPSR2_3 F_(CLK_EXTFXR, IP0SR2_15_12)
+#define GPSR2_2 F_(RXDA_EXTFXR, IP0SR2_11_8)
+#define GPSR2_1 F_(FXR_TXENA_N, IP0SR2_7_4)
+#define GPSR2_0 F_(FXR_TXDA, IP0SR2_3_0)
+
+/* GPSR3 */
+#define GPSR3_29 F_(RPC_INT_N, IP3SR3_23_20)
+#define GPSR3_28 F_(RPC_WP_N, IP3SR3_19_16)
+#define GPSR3_27 F_(RPC_RESET_N, IP3SR3_15_12)
+#define GPSR3_26 F_(QSPI1_IO3, IP3SR3_11_8)
+#define GPSR3_25 F_(QSPI1_SSL, IP3SR3_7_4)
+#define GPSR3_24 F_(QSPI1_IO2, IP3SR3_3_0)
+#define GPSR3_23 F_(QSPI1_MISO_IO1, IP2SR3_31_28)
+#define GPSR3_22 F_(QSPI1_SPCLK, IP2SR3_27_24)
+#define GPSR3_21 F_(QSPI1_MOSI_IO0, IP2SR3_23_20)
+#define GPSR3_20 F_(QSPI0_SPCLK, IP2SR3_19_16)
+#define GPSR3_19 F_(QSPI0_MOSI_IO0, IP2SR3_15_12)
+#define GPSR3_18 F_(QSPI0_MISO_IO1, IP2SR3_11_8)
+#define GPSR3_17 F_(QSPI0_IO2, IP2SR3_7_4)
+#define GPSR3_16 F_(QSPI0_IO3, IP2SR3_3_0)
+#define GPSR3_15 F_(QSPI0_SSL, IP1SR3_31_28)
+#define GPSR3_14 F_(IPC_CLKOUT, IP1SR3_27_24)
+#define GPSR3_13 F_(IPC_CLKIN, IP1SR3_23_20)
+#define GPSR3_12 F_(SD_WP, IP1SR3_19_16)
+#define GPSR3_11 F_(SD_CD, IP1SR3_15_12)
+#define GPSR3_10 F_(MMC_SD_CMD, IP1SR3_11_8)
+#define GPSR3_9 F_(MMC_D6, IP1SR3_7_4)
+#define GPSR3_8 F_(MMC_D7, IP1SR3_3_0)
+#define GPSR3_7 F_(MMC_D4, IP0SR3_31_28)
+#define GPSR3_6 F_(MMC_D5, IP0SR3_27_24)
+#define GPSR3_5 F_(MMC_SD_D3, IP0SR3_23_20)
+#define GPSR3_4 F_(MMC_DS, IP0SR3_19_16)
+#define GPSR3_3 F_(MMC_SD_CLK, IP0SR3_15_12)
+#define GPSR3_2 F_(MMC_SD_D2, IP0SR3_11_8)
+#define GPSR3_1 F_(MMC_SD_D0, IP0SR3_7_4)
+#define GPSR3_0 F_(MMC_SD_D1, IP0SR3_3_0)
+
+/* GPSR4 */
+#define GPSR4_24 FM(AVS1)
+#define GPSR4_23 FM(AVS0)
+#define GPSR4_22 FM(PCIE1_CLKREQ_N)
+#define GPSR4_21 FM(PCIE0_CLKREQ_N)
+#define GPSR4_20 FM(TSN0_TXCREFCLK)
+#define GPSR4_19 FM(TSN0_TD2)
+#define GPSR4_18 FM(TSN0_TD3)
+#define GPSR4_17 FM(TSN0_RD2)
+#define GPSR4_16 FM(TSN0_RD3)
+#define GPSR4_15 FM(TSN0_TD0)
+#define GPSR4_14 FM(TSN0_TD1)
+#define GPSR4_13 FM(TSN0_RD1)
+#define GPSR4_12 FM(TSN0_TXC)
+#define GPSR4_11 FM(TSN0_RXC)
+#define GPSR4_10 FM(TSN0_RD0)
+#define GPSR4_9 FM(TSN0_TX_CTL)
+#define GPSR4_8 FM(TSN0_AVTP_PPS0)
+#define GPSR4_7 FM(TSN0_RX_CTL)
+#define GPSR4_6 FM(TSN0_AVTP_CAPTURE)
+#define GPSR4_5 FM(TSN0_AVTP_MATCH)
+#define GPSR4_4 FM(TSN0_LINK)
+#define GPSR4_3 FM(TSN0_PHY_INT)
+#define GPSR4_2 FM(TSN0_AVTP_PPS1)
+#define GPSR4_1 FM(TSN0_MDC)
+#define GPSR4_0 FM(TSN0_MDIO)
+
+/* GPSR 5 */
+#define GPSR5_20 FM(AVB2_RX_CTL)
+#define GPSR5_19 FM(AVB2_TX_CTL)
+#define GPSR5_18 FM(AVB2_RXC)
+#define GPSR5_17 FM(AVB2_RD0)
+#define GPSR5_16 FM(AVB2_TXC)
+#define GPSR5_15 FM(AVB2_TD0)
+#define GPSR5_14 FM(AVB2_RD1)
+#define GPSR5_13 FM(AVB2_RD2)
+#define GPSR5_12 FM(AVB2_TD1)
+#define GPSR5_11 FM(AVB2_TD2)
+#define GPSR5_10 FM(AVB2_MDIO)
+#define GPSR5_9 FM(AVB2_RD3)
+#define GPSR5_8 FM(AVB2_TD3)
+#define GPSR5_7 FM(AVB2_TXCREFCLK)
+#define GPSR5_6 FM(AVB2_MDC)
+#define GPSR5_5 FM(AVB2_MAGIC)
+#define GPSR5_4 FM(AVB2_PHY_INT)
+#define GPSR5_3 FM(AVB2_LINK)
+#define GPSR5_2 FM(AVB2_AVTP_MATCH)
+#define GPSR5_1 FM(AVB2_AVTP_CAPTURE)
+#define GPSR5_0 FM(AVB2_AVTP_PPS)
+
+/* GPSR 6 */
+#define GPSR6_20 F_(AVB1_TXCREFCLK, IP2SR6_19_16)
+#define GPSR6_19 F_(AVB1_RD3, IP2SR6_15_12)
+#define GPSR6_18 F_(AVB1_TD3, IP2SR6_11_8)
+#define GPSR6_17 F_(AVB1_RD2, IP2SR6_7_4)
+#define GPSR6_16 F_(AVB1_TD2, IP2SR6_3_0)
+#define GPSR6_15 F_(AVB1_RD0, IP1SR6_31_28)
+#define GPSR6_14 F_(AVB1_RD1, IP1SR6_27_24)
+#define GPSR6_13 F_(AVB1_TD0, IP1SR6_23_20)
+#define GPSR6_12 F_(AVB1_TD1, IP1SR6_19_16)
+#define GPSR6_11 F_(AVB1_AVTP_CAPTURE, IP1SR6_15_12)
+#define GPSR6_10 F_(AVB1_AVTP_PPS, IP1SR6_11_8)
+#define GPSR6_9 F_(AVB1_RX_CTL, IP1SR6_7_4)
+#define GPSR6_8 F_(AVB1_RXC, IP1SR6_3_0)
+#define GPSR6_7 F_(AVB1_TX_CTL, IP0SR6_31_28)
+#define GPSR6_6 F_(AVB1_TXC, IP0SR6_27_24)
+#define GPSR6_5 F_(AVB1_AVTP_MATCH, IP0SR6_23_20)
+#define GPSR6_4 F_(AVB1_LINK, IP0SR6_19_16)
+#define GPSR6_3 F_(AVB1_PHY_INT, IP0SR6_15_12)
+#define GPSR6_2 F_(AVB1_MDC, IP0SR6_11_8)
+#define GPSR6_1 F_(AVB1_MAGIC, IP0SR6_7_4)
+#define GPSR6_0 F_(AVB1_MDIO, IP0SR6_3_0)
+
+/* GPSR7 */
+#define GPSR7_20 F_(AVB0_RX_CTL, IP2SR7_19_16)
+#define GPSR7_19 F_(AVB0_RXC, IP2SR7_15_12)
+#define GPSR7_18 F_(AVB0_RD0, IP2SR7_11_8)
+#define GPSR7_17 F_(AVB0_RD1, IP2SR7_7_4)
+#define GPSR7_16 F_(AVB0_TX_CTL, IP2SR7_3_0)
+#define GPSR7_15 F_(AVB0_TXC, IP1SR7_31_28)
+#define GPSR7_14 F_(AVB0_MDIO, IP1SR7_27_24)
+#define GPSR7_13 F_(AVB0_MDC, IP1SR7_23_20)
+#define GPSR7_12 F_(AVB0_RD2, IP1SR7_19_16)
+#define GPSR7_11 F_(AVB0_TD0, IP1SR7_15_12)
+#define GPSR7_10 F_(AVB0_MAGIC, IP1SR7_11_8)
+#define GPSR7_9 F_(AVB0_TXCREFCLK, IP1SR7_7_4)
+#define GPSR7_8 F_(AVB0_RD3, IP1SR7_3_0)
+#define GPSR7_7 F_(AVB0_TD1, IP0SR7_31_28)
+#define GPSR7_6 F_(AVB0_TD2, IP0SR7_27_24)
+#define GPSR7_5 F_(AVB0_PHY_INT, IP0SR7_23_20)
+#define GPSR7_4 F_(AVB0_LINK, IP0SR7_19_16)
+#define GPSR7_3 F_(AVB0_TD3, IP0SR7_15_12)
+#define GPSR7_2 F_(AVB0_AVTP_MATCH, IP0SR7_11_8)
+#define GPSR7_1 F_(AVB0_AVTP_CAPTURE, IP0SR7_7_4)
+#define GPSR7_0 F_(AVB0_AVTP_PPS, IP0SR7_3_0)
+
+/* GPSR8 */
+#define GPSR8_13 F_(GP8_13, IP1SR8_23_20)
+#define GPSR8_12 F_(GP8_12, IP1SR8_19_16)
+#define GPSR8_11 F_(SDA5, IP1SR8_15_12)
+#define GPSR8_10 F_(SCL5, IP1SR8_11_8)
+#define GPSR8_9 F_(SDA4, IP1SR8_7_4)
+#define GPSR8_8 F_(SCL4, IP1SR8_3_0)
+#define GPSR8_7 F_(SDA3, IP0SR8_31_28)
+#define GPSR8_6 F_(SCL3, IP0SR8_27_24)
+#define GPSR8_5 F_(SDA2, IP0SR8_23_20)
+#define GPSR8_4 F_(SCL2, IP0SR8_19_16)
+#define GPSR8_3 F_(SDA1, IP0SR8_15_12)
+#define GPSR8_2 F_(SCL1, IP0SR8_11_8)
+#define GPSR8_1 F_(SDA0, IP0SR8_7_4)
+#define GPSR8_0 F_(SCL0, IP0SR8_3_0)
+
+/* SR0 */
+/* IP0SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR0_3_0 F_(0, 0) FM(ERROROUTC_B) FM(TCLK2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_7_4 F_(0, 0) FM(MSIOF3_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_11_8 F_(0, 0) FM(MSIOF3_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_15_12 FM(IRQ3) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_19_16 FM(IRQ2) FM(MSIOF3_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_23_20 FM(IRQ1) FM(MSIOF3_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_27_24 FM(IRQ0) FM(MSIOF3_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR0_31_28 FM(MSIOF5_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR0_3_0 FM(MSIOF5_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_7_4 FM(MSIOF5_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_11_8 FM(MSIOF5_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_15_12 FM(MSIOF5_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_19_16 FM(MSIOF5_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_23_20 FM(MSIOF2_SS2) FM(TCLK1) FM(IRQ2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_27_24 FM(MSIOF2_SS1) FM(HTX1) FM(TX1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR0_31_28 FM(MSIOF2_SYNC) FM(HRX1) FM(RX1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP2SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP2SR0_3_0 FM(MSIOF2_TXD) FM(HCTS1_N) FM(CTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR0_7_4 FM(MSIOF2_SCK) FM(HRTS1_N) FM(RTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR0_11_8 FM(MSIOF2_RXD) FM(HSCK1) FM(SCK1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* SR1 */
+/* IP0SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR1_3_0 FM(MSIOF1_SS2) FM(HTX3_A) FM(TX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_7_4 FM(MSIOF1_SS1) FM(HCTS3_N_A) FM(RX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_11_8 FM(MSIOF1_SYNC) FM(HRTS3_N_A) FM(RTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_15_12 FM(MSIOF1_SCK) FM(HSCK3_A) FM(CTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_19_16 FM(MSIOF1_TXD) FM(HRX3_A) FM(SCK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_23_20 FM(MSIOF1_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_27_24 FM(MSIOF0_SS2) FM(HTX1_X) FM(TX1_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR1_31_28 FM(MSIOF0_SS1) FM(HRX1_X) FM(RX1_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR1_3_0 FM(MSIOF0_SYNC) FM(HCTS1_N_X) FM(CTS1_N_X) FM(CANFD5_TX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_7_4 FM(MSIOF0_TXD) FM(HRTS1_N_X) FM(RTS1_N_X) FM(CANFD5_RX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_11_8 FM(MSIOF0_SCK) FM(HSCK1_X) FM(SCK1_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_15_12 FM(MSIOF0_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_19_16 FM(HTX0) FM(TX0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_23_20 FM(HCTS0_N) FM(CTS0_N) FM(PWM8_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_27_24 FM(HRTS0_N) FM(RTS0_N) FM(PWM9_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR1_31_28 FM(HSCK0) FM(SCK0) FM(PWM0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP2SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP2SR1_3_0 FM(HRX0) FM(RX0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_7_4 FM(SCIF_CLK) FM(IRQ4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_11_8 FM(SSI_SCK) FM(TCLK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_15_12 FM(SSI_WS) FM(TCLK4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_19_16 FM(SSI_SD) FM(IRQ0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_23_20 FM(AUDIO_CLKOUT) FM(IRQ1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_27_24 FM(AUDIO_CLKIN) FM(PWM3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR1_31_28 F_(0, 0) FM(TCLK2) FM(MSIOF4_SS1) FM(IRQ3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP3SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP3SR1_3_0 FM(HRX3) FM(SCK3_A) FM(MSIOF4_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR1_7_4 FM(HSCK3) FM(CTS3_N_A) FM(MSIOF4_SCK) FM(TPU0TO0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR1_11_8 FM(HRTS3_N) FM(RTS3_N_A) FM(MSIOF4_TXD) FM(TPU0TO1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR1_15_12 FM(HCTS3_N) FM(RX3_A) FM(MSIOF4_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR1_19_16 FM(HTX3) FM(TX3_A) FM(MSIOF4_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* SR2 */
+/* IP0SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR2_3_0 FM(FXR_TXDA) FM(CANFD1_TX) FM(TPU0TO2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_7_4 FM(FXR_TXENA_N) FM(CANFD1_RX) FM(TPU0TO3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_11_8 FM(RXDA_EXTFXR) FM(CANFD5_TX) FM(IRQ5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_15_12 FM(CLK_EXTFXR) FM(CANFD5_RX) FM(IRQ4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_19_16 FM(RXDB_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_23_20 FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_27_24 FM(FXR_TXDB) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR2_31_28 FM(TPU0TO1) FM(CANFD6_TX) F_(0, 0) FM(TCLK2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR2_3_0 FM(TPU0TO0) FM(CANFD6_RX) F_(0, 0) FM(TCLK1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_7_4 FM(CAN_CLK) FM(FXR_TXENA_N_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_11_8 FM(CANFD0_TX) FM(FXR_TXENB_N_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_15_12 FM(CANFD0_RX) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_19_16 FM(CANFD2_TX) FM(TPU0TO2) F_(0, 0) FM(TCLK3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_23_20 FM(CANFD2_RX) FM(TPU0TO3) FM(PWM1_B) FM(TCLK4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_27_24 FM(CANFD3_TX) F_(0, 0) FM(PWM2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR2_31_28 FM(CANFD3_RX) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP2SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP2SR2_3_0 FM(CANFD4_TX) F_(0, 0) FM(PWM4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR2_7_4 FM(CANFD4_RX) F_(0, 0) FM(PWM5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR2_11_8 FM(CANFD7_TX) F_(0, 0) FM(PWM6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR2_15_12 FM(CANFD7_RX) F_(0, 0) FM(PWM7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* SR3 */
+/* IP0SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR3_3_0 FM(MMC_SD_D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_7_4 FM(MMC_SD_D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_11_8 FM(MMC_SD_D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_15_12 FM(MMC_SD_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_19_16 FM(MMC_DS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_23_20 FM(MMC_SD_D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_27_24 FM(MMC_D5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR3_31_28 FM(MMC_D4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR3_3_0 FM(MMC_D7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_7_4 FM(MMC_D6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_11_8 FM(MMC_SD_CMD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_15_12 FM(SD_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_19_16 FM(SD_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_23_20 FM(IPC_CLKIN) FM(IPC_CLKEN_IN) FM(PWM1_A) FM(TCLK3_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_27_24 FM(IPC_CLKOUT) FM(IPC_CLKEN_OUT) FM(ERROROUTC_A) FM(TCLK4_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR3_31_28 FM(QSPI0_SSL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP2SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP2SR3_3_0 FM(QSPI0_IO3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_7_4 FM(QSPI0_IO2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_11_8 FM(QSPI0_MISO_IO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_15_12 FM(QSPI0_MOSI_IO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_19_16 FM(QSPI0_SPCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_23_20 FM(QSPI1_MOSI_IO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_27_24 FM(QSPI1_SPCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR3_31_28 FM(QSPI1_MISO_IO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP3SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP3SR3_3_0 FM(QSPI1_IO2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR3_7_4 FM(QSPI1_SSL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR3_11_8 FM(QSPI1_IO3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR3_15_12 FM(RPC_RESET_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR3_19_16 FM(RPC_WP_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP3SR3_23_20 FM(RPC_INT_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* SR6 */
+/* IP0SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR6_3_0 FM(AVB1_MDIO) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_7_4 FM(AVB1_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_11_8 FM(AVB1_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_15_12 FM(AVB1_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_19_16 FM(AVB1_LINK) FM(AVB1_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_23_20 FM(AVB1_AVTP_MATCH) FM(AVB1_MII_RX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_27_24 FM(AVB1_TXC) FM(AVB1_MII_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR6_31_28 FM(AVB1_TX_CTL) FM(AVB1_MII_TX_EN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR6_3_0 FM(AVB1_RXC) FM(AVB1_MII_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_7_4 FM(AVB1_RX_CTL) FM(AVB1_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_11_8 FM(AVB1_AVTP_PPS) FM(AVB1_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_15_12 FM(AVB1_AVTP_CAPTURE) FM(AVB1_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_19_16 FM(AVB1_TD1) FM(AVB1_MII_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_23_20 FM(AVB1_TD0) FM(AVB1_MII_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_27_24 FM(AVB1_RD1) FM(AVB1_MII_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR6_31_28 FM(AVB1_RD0) FM(AVB1_MII_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP2SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP2SR6_3_0 FM(AVB1_TD2) FM(AVB1_MII_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR6_7_4 FM(AVB1_RD2) FM(AVB1_MII_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR6_11_8 FM(AVB1_TD3) FM(AVB1_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR6_15_12 FM(AVB1_RD3) FM(AVB1_MII_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR6_19_16 FM(AVB1_TXCREFCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* SR7 */
+/* IP0SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR7_3_0 FM(AVB0_AVTP_PPS) FM(AVB0_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_7_4 FM(AVB0_AVTP_CAPTURE) FM(AVB0_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) FM(AVB0_MII_RX_ER) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_15_12 FM(AVB0_TD3) FM(AVB0_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_19_16 FM(AVB0_LINK) FM(AVB0_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_23_20 FM(AVB0_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_27_24 FM(AVB0_TD2) FM(AVB0_MII_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR7_31_28 FM(AVB0_TD1) FM(AVB0_MII_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR7_3_0 FM(AVB0_RD3) FM(AVB0_MII_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_7_4 FM(AVB0_TXCREFCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_11_8 FM(AVB0_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_15_12 FM(AVB0_TD0) FM(AVB0_MII_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_19_16 FM(AVB0_RD2) FM(AVB0_MII_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_23_20 FM(AVB0_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_27_24 FM(AVB0_MDIO) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR7_31_28 FM(AVB0_TXC) FM(AVB0_MII_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP2SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP2SR7_3_0 FM(AVB0_TX_CTL) FM(AVB0_MII_TX_EN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR7_7_4 FM(AVB0_RD1) FM(AVB0_MII_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR7_11_8 FM(AVB0_RD0) FM(AVB0_MII_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR7_15_12 FM(AVB0_RXC) FM(AVB0_MII_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP2SR7_19_16 FM(AVB0_RX_CTL) FM(AVB0_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* SR8 */
+/* IP0SR8 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP0SR8_3_0 FM(SCL0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_7_4 FM(SDA0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_11_8 FM(SCL1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_15_12 FM(SDA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_19_16 FM(SCL2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_23_20 FM(SDA2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_27_24 FM(SCL3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP0SR8_31_28 FM(SDA3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+/* IP1SR8 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */
+#define IP1SR8_3_0 FM(SCL4) FM(HRX2) FM(SCK4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR8_7_4 FM(SDA4) FM(HTX2) FM(CTS4_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR8_11_8 FM(SCL5) FM(HRTS2_N) FM(RTS4_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR8_15_12 FM(SDA5) FM(SCIF_CLK2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR8_19_16 F_(0, 0) FM(HCTS2_N) FM(TX4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1SR8_23_20 F_(0, 0) FM(HSCK2) FM(RX4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+
+#define PINMUX_GPSR \
+ GPSR3_29 \
+ GPSR1_28 GPSR3_28 \
+ GPSR1_27 GPSR3_27 \
+ GPSR1_26 GPSR3_26 \
+ GPSR1_25 GPSR3_25 \
+ GPSR1_24 GPSR3_24 GPSR4_24 \
+ GPSR1_23 GPSR3_23 GPSR4_23 \
+ GPSR1_22 GPSR3_22 GPSR4_22 \
+ GPSR1_21 GPSR3_21 GPSR4_21 \
+ GPSR1_20 GPSR3_20 GPSR4_20 GPSR5_20 GPSR6_20 GPSR7_20 \
+ GPSR1_19 GPSR2_19 GPSR3_19 GPSR4_19 GPSR5_19 GPSR6_19 GPSR7_19 \
+GPSR0_18 GPSR1_18 GPSR2_18 GPSR3_18 GPSR4_18 GPSR5_18 GPSR6_18 GPSR7_18 \
+GPSR0_17 GPSR1_17 GPSR2_17 GPSR3_17 GPSR4_17 GPSR5_17 GPSR6_17 GPSR7_17 \
+GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 GPSR4_16 GPSR5_16 GPSR6_16 GPSR7_16 \
+GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 GPSR4_15 GPSR5_15 GPSR6_15 GPSR7_15 \
+GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR4_14 GPSR5_14 GPSR6_14 GPSR7_14 \
+GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR4_13 GPSR5_13 GPSR6_13 GPSR7_13 GPSR8_13 \
+GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR4_12 GPSR5_12 GPSR6_12 GPSR7_12 GPSR8_12 \
+GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR4_11 GPSR5_11 GPSR6_11 GPSR7_11 GPSR8_11 \
+GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR4_10 GPSR5_10 GPSR6_10 GPSR7_10 GPSR8_10 \
+GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR4_9 GPSR5_9 GPSR6_9 GPSR7_9 GPSR8_9 \
+GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR4_8 GPSR5_8 GPSR6_8 GPSR7_8 GPSR8_8 \
+GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR4_7 GPSR5_7 GPSR6_7 GPSR7_7 GPSR8_7 \
+GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR4_6 GPSR5_6 GPSR6_6 GPSR7_6 GPSR8_6 \
+GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 GPSR6_5 GPSR7_5 GPSR8_5 \
+GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 GPSR6_4 GPSR7_4 GPSR8_4 \
+GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 GPSR6_3 GPSR7_3 GPSR8_3 \
+GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 GPSR6_2 GPSR7_2 GPSR8_2 \
+GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 GPSR6_1 GPSR7_1 GPSR8_1 \
+GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0 GPSR6_0 GPSR7_0 GPSR8_0
+
+#define PINMUX_IPSR \
+\
+FM(IP0SR0_3_0) IP0SR0_3_0 FM(IP1SR0_3_0) IP1SR0_3_0 FM(IP2SR0_3_0) IP2SR0_3_0 \
+FM(IP0SR0_7_4) IP0SR0_7_4 FM(IP1SR0_7_4) IP1SR0_7_4 FM(IP2SR0_7_4) IP2SR0_7_4 \
+FM(IP0SR0_11_8) IP0SR0_11_8 FM(IP1SR0_11_8) IP1SR0_11_8 FM(IP2SR0_11_8) IP2SR0_11_8 \
+FM(IP0SR0_15_12) IP0SR0_15_12 FM(IP1SR0_15_12) IP1SR0_15_12 \
+FM(IP0SR0_19_16) IP0SR0_19_16 FM(IP1SR0_19_16) IP1SR0_19_16 \
+FM(IP0SR0_23_20) IP0SR0_23_20 FM(IP1SR0_23_20) IP1SR0_23_20 \
+FM(IP0SR0_27_24) IP0SR0_27_24 FM(IP1SR0_27_24) IP1SR0_27_24 \
+FM(IP0SR0_31_28) IP0SR0_31_28 FM(IP1SR0_31_28) IP1SR0_31_28 \
+\
+FM(IP0SR1_3_0) IP0SR1_3_0 FM(IP1SR1_3_0) IP1SR1_3_0 FM(IP2SR1_3_0) IP2SR1_3_0 FM(IP3SR1_3_0) IP3SR1_3_0 \
+FM(IP0SR1_7_4) IP0SR1_7_4 FM(IP1SR1_7_4) IP1SR1_7_4 FM(IP2SR1_7_4) IP2SR1_7_4 FM(IP3SR1_7_4) IP3SR1_7_4 \
+FM(IP0SR1_11_8) IP0SR1_11_8 FM(IP1SR1_11_8) IP1SR1_11_8 FM(IP2SR1_11_8) IP2SR1_11_8 FM(IP3SR1_11_8) IP3SR1_11_8 \
+FM(IP0SR1_15_12) IP0SR1_15_12 FM(IP1SR1_15_12) IP1SR1_15_12 FM(IP2SR1_15_12) IP2SR1_15_12 FM(IP3SR1_15_12) IP3SR1_15_12 \
+FM(IP0SR1_19_16) IP0SR1_19_16 FM(IP1SR1_19_16) IP1SR1_19_16 FM(IP2SR1_19_16) IP2SR1_19_16 FM(IP3SR1_19_16) IP3SR1_19_16 \
+FM(IP0SR1_23_20) IP0SR1_23_20 FM(IP1SR1_23_20) IP1SR1_23_20 FM(IP2SR1_23_20) IP2SR1_23_20 \
+FM(IP0SR1_27_24) IP0SR1_27_24 FM(IP1SR1_27_24) IP1SR1_27_24 FM(IP2SR1_27_24) IP2SR1_27_24 \
+FM(IP0SR1_31_28) IP0SR1_31_28 FM(IP1SR1_31_28) IP1SR1_31_28 FM(IP2SR1_31_28) IP2SR1_31_28 \
+\
+FM(IP0SR2_3_0) IP0SR2_3_0 FM(IP1SR2_3_0) IP1SR2_3_0 FM(IP2SR2_3_0) IP2SR2_3_0 \
+FM(IP0SR2_7_4) IP0SR2_7_4 FM(IP1SR2_7_4) IP1SR2_7_4 FM(IP2SR2_7_4) IP2SR2_7_4 \
+FM(IP0SR2_11_8) IP0SR2_11_8 FM(IP1SR2_11_8) IP1SR2_11_8 FM(IP2SR2_11_8) IP2SR2_11_8 \
+FM(IP0SR2_15_12) IP0SR2_15_12 FM(IP1SR2_15_12) IP1SR2_15_12 FM(IP2SR2_15_12) IP2SR2_15_12 \
+FM(IP0SR2_19_16) IP0SR2_19_16 FM(IP1SR2_19_16) IP1SR2_19_16 \
+FM(IP0SR2_23_20) IP0SR2_23_20 FM(IP1SR2_23_20) IP1SR2_23_20 \
+FM(IP0SR2_27_24) IP0SR2_27_24 FM(IP1SR2_27_24) IP1SR2_27_24 \
+FM(IP0SR2_31_28) IP0SR2_31_28 FM(IP1SR2_31_28) IP1SR2_31_28 \
+\
+FM(IP0SR3_3_0) IP0SR3_3_0 FM(IP1SR3_3_0) IP1SR3_3_0 FM(IP2SR3_3_0) IP2SR3_3_0 FM(IP3SR3_3_0) IP3SR3_3_0 \
+FM(IP0SR3_7_4) IP0SR3_7_4 FM(IP1SR3_7_4) IP1SR3_7_4 FM(IP2SR3_7_4) IP2SR3_7_4 FM(IP3SR3_7_4) IP3SR3_7_4 \
+FM(IP0SR3_11_8) IP0SR3_11_8 FM(IP1SR3_11_8) IP1SR3_11_8 FM(IP2SR3_11_8) IP2SR3_11_8 FM(IP3SR3_11_8) IP3SR3_11_8 \
+FM(IP0SR3_15_12) IP0SR3_15_12 FM(IP1SR3_15_12) IP1SR3_15_12 FM(IP2SR3_15_12) IP2SR3_15_12 FM(IP3SR3_15_12) IP3SR3_15_12 \
+FM(IP0SR3_19_16) IP0SR3_19_16 FM(IP1SR3_19_16) IP1SR3_19_16 FM(IP2SR3_19_16) IP2SR3_19_16 FM(IP3SR3_19_16) IP3SR3_19_16 \
+FM(IP0SR3_23_20) IP0SR3_23_20 FM(IP1SR3_23_20) IP1SR3_23_20 FM(IP2SR3_23_20) IP2SR3_23_20 FM(IP3SR3_23_20) IP3SR3_23_20 \
+FM(IP0SR3_27_24) IP0SR3_27_24 FM(IP1SR3_27_24) IP1SR3_27_24 FM(IP2SR3_27_24) IP2SR3_27_24 \
+FM(IP0SR3_31_28) IP0SR3_31_28 FM(IP1SR3_31_28) IP1SR3_31_28 FM(IP2SR3_31_28) IP2SR3_31_28 \
+\
+FM(IP0SR6_3_0) IP0SR6_3_0 FM(IP1SR6_3_0) IP1SR6_3_0 FM(IP2SR6_3_0) IP2SR6_3_0 \
+FM(IP0SR6_7_4) IP0SR6_7_4 FM(IP1SR6_7_4) IP1SR6_7_4 FM(IP2SR6_7_4) IP2SR6_7_4 \
+FM(IP0SR6_11_8) IP0SR6_11_8 FM(IP1SR6_11_8) IP1SR6_11_8 FM(IP2SR6_11_8) IP2SR6_11_8 \
+FM(IP0SR6_15_12) IP0SR6_15_12 FM(IP1SR6_15_12) IP1SR6_15_12 FM(IP2SR6_15_12) IP2SR6_15_12 \
+FM(IP0SR6_19_16) IP0SR6_19_16 FM(IP1SR6_19_16) IP1SR6_19_16 FM(IP2SR6_19_16) IP2SR6_19_16 \
+FM(IP0SR6_23_20) IP0SR6_23_20 FM(IP1SR6_23_20) IP1SR6_23_20 \
+FM(IP0SR6_27_24) IP0SR6_27_24 FM(IP1SR6_27_24) IP1SR6_27_24 \
+FM(IP0SR6_31_28) IP0SR6_31_28 FM(IP1SR6_31_28) IP1SR6_31_28 \
+\
+FM(IP0SR7_3_0) IP0SR7_3_0 FM(IP1SR7_3_0) IP1SR7_3_0 FM(IP2SR7_3_0) IP2SR7_3_0 \
+FM(IP0SR7_7_4) IP0SR7_7_4 FM(IP1SR7_7_4) IP1SR7_7_4 FM(IP2SR7_7_4) IP2SR7_7_4 \
+FM(IP0SR7_11_8) IP0SR7_11_8 FM(IP1SR7_11_8) IP1SR7_11_8 FM(IP2SR7_11_8) IP2SR7_11_8 \
+FM(IP0SR7_15_12) IP0SR7_15_12 FM(IP1SR7_15_12) IP1SR7_15_12 FM(IP2SR7_15_12) IP2SR7_15_12 \
+FM(IP0SR7_19_16) IP0SR7_19_16 FM(IP1SR7_19_16) IP1SR7_19_16 FM(IP2SR7_19_16) IP2SR7_19_16 \
+FM(IP0SR7_23_20) IP0SR7_23_20 FM(IP1SR7_23_20) IP1SR7_23_20 \
+FM(IP0SR7_27_24) IP0SR7_27_24 FM(IP1SR7_27_24) IP1SR7_27_24 \
+FM(IP0SR7_31_28) IP0SR7_31_28 FM(IP1SR7_31_28) IP1SR7_31_28 \
+\
+FM(IP0SR8_3_0) IP0SR8_3_0 FM(IP1SR8_3_0) IP1SR8_3_0 \
+FM(IP0SR8_7_4) IP0SR8_7_4 FM(IP1SR8_7_4) IP1SR8_7_4 \
+FM(IP0SR8_11_8) IP0SR8_11_8 FM(IP1SR8_11_8) IP1SR8_11_8 \
+FM(IP0SR8_15_12) IP0SR8_15_12 FM(IP1SR8_15_12) IP1SR8_15_12 \
+FM(IP0SR8_19_16) IP0SR8_19_16 FM(IP1SR8_19_16) IP1SR8_19_16 \
+FM(IP0SR8_23_20) IP0SR8_23_20 FM(IP1SR8_23_20) IP1SR8_23_20 \
+FM(IP0SR8_27_24) IP0SR8_27_24 \
+FM(IP0SR8_31_28) IP0SR8_31_28
+
+/* MOD_SEL4 */ /* 0 */ /* 1 */
+#define MOD_SEL4_19 FM(SEL_TSN0_TD2_0) FM(SEL_TSN0_TD2_1)
+#define MOD_SEL4_18 FM(SEL_TSN0_TD3_0) FM(SEL_TSN0_TD3_1)
+#define MOD_SEL4_15 FM(SEL_TSN0_TD0_0) FM(SEL_TSN0_TD0_1)
+#define MOD_SEL4_14 FM(SEL_TSN0_TD1_0) FM(SEL_TSN0_TD1_1)
+#define MOD_SEL4_12 FM(SEL_TSN0_TXC_0) FM(SEL_TSN0_TXC_1)
+#define MOD_SEL4_9 FM(SEL_TSN0_TX_CTL_0) FM(SEL_TSN0_TX_CTL_1)
+#define MOD_SEL4_8 FM(SEL_TSN0_AVTP_PPS0_0) FM(SEL_TSN0_AVTP_PPS0_1)
+#define MOD_SEL4_5 FM(SEL_TSN0_AVTP_MATCH_0) FM(SEL_TSN0_AVTP_MATCH_1)
+#define MOD_SEL4_2 FM(SEL_TSN0_AVTP_PPS1_0) FM(SEL_TSN0_AVTP_PPS1_1)
+#define MOD_SEL4_1 FM(SEL_TSN0_MDC_0) FM(SEL_TSN0_MDC_1)
+
+/* MOD_SEL5 */ /* 0 */ /* 1 */
+#define MOD_SEL5_19 FM(SEL_AVB2_TX_CTL_0) FM(SEL_AVB2_TX_CTL_1)
+#define MOD_SEL5_16 FM(SEL_AVB2_TXC_0) FM(SEL_AVB2_TXC_1)
+#define MOD_SEL5_15 FM(SEL_AVB2_TD0_0) FM(SEL_AVB2_TD0_1)
+#define MOD_SEL5_12 FM(SEL_AVB2_TD1_0) FM(SEL_AVB2_TD1_1)
+#define MOD_SEL5_11 FM(SEL_AVB2_TD2_0) FM(SEL_AVB2_TD2_1)
+#define MOD_SEL5_8 FM(SEL_AVB2_TD3_0) FM(SEL_AVB2_TD3_1)
+#define MOD_SEL5_6 FM(SEL_AVB2_MDC_0) FM(SEL_AVB2_MDC_1)
+#define MOD_SEL5_5 FM(SEL_AVB2_MAGIC_0) FM(SEL_AVB2_MAGIC_1)
+#define MOD_SEL5_2 FM(SEL_AVB2_AVTP_MATCH_0) FM(SEL_AVB2_AVTP_MATCH_1)
+#define MOD_SEL5_0 FM(SEL_AVB2_AVTP_PPS_0) FM(SEL_AVB2_AVTP_PPS_1)
+
+/* MOD_SEL6 */ /* 0 */ /* 1 */
+#define MOD_SEL6_18 FM(SEL_AVB1_TD3_0) FM(SEL_AVB1_TD3_1)
+#define MOD_SEL6_16 FM(SEL_AVB1_TD2_0) FM(SEL_AVB1_TD2_1)
+#define MOD_SEL6_13 FM(SEL_AVB1_TD0_0) FM(SEL_AVB1_TD0_1)
+#define MOD_SEL6_12 FM(SEL_AVB1_TD1_0) FM(SEL_AVB1_TD1_1)
+#define MOD_SEL6_10 FM(SEL_AVB1_AVTP_PPS_0) FM(SEL_AVB1_AVTP_PPS_1)
+#define MOD_SEL6_7 FM(SEL_AVB1_TX_CTL_0) FM(SEL_AVB1_TX_CTL_1)
+#define MOD_SEL6_6 FM(SEL_AVB1_TXC_0) FM(SEL_AVB1_TXC_1)
+#define MOD_SEL6_5 FM(SEL_AVB1_AVTP_MATCH_0) FM(SEL_AVB1_AVTP_MATCH_1)
+#define MOD_SEL6_2 FM(SEL_AVB1_MDC_0) FM(SEL_AVB1_MDC_1)
+#define MOD_SEL6_1 FM(SEL_AVB1_MAGIC_0) FM(SEL_AVB1_MAGIC_1)
+
+/* MOD_SEL7 */ /* 0 */ /* 1 */
+#define MOD_SEL7_16 FM(SEL_AVB0_TX_CTL_0) FM(SEL_AVB0_TX_CTL_1)
+#define MOD_SEL7_15 FM(SEL_AVB0_TXC_0) FM(SEL_AVB0_TXC_1)
+#define MOD_SEL7_13 FM(SEL_AVB0_MDC_0) FM(SEL_AVB0_MDC_1)
+#define MOD_SEL7_11 FM(SEL_AVB0_TD0_0) FM(SEL_AVB0_TD0_1)
+#define MOD_SEL7_10 FM(SEL_AVB0_MAGIC_0) FM(SEL_AVB0_MAGIC_1)
+#define MOD_SEL7_7 FM(SEL_AVB0_TD1_0) FM(SEL_AVB0_TD1_1)
+#define MOD_SEL7_6 FM(SEL_AVB0_TD2_0) FM(SEL_AVB0_TD2_1)
+#define MOD_SEL7_3 FM(SEL_AVB0_TD3_0) FM(SEL_AVB0_TD3_1)
+#define MOD_SEL7_2 FM(SEL_AVB0_AVTP_MATCH_0) FM(SEL_AVB0_AVTP_MATCH_1)
+#define MOD_SEL7_0 FM(SEL_AVB0_AVTP_PPS_0) FM(SEL_AVB0_AVTP_PPS_1)
+
+/* MOD_SEL8 */ /* 0 */ /* 1 */
+#define MOD_SEL8_11 FM(SEL_SDA5_0) FM(SEL_SDA5_1)
+#define MOD_SEL8_10 FM(SEL_SCL5_0) FM(SEL_SCL5_1)
+#define MOD_SEL8_9 FM(SEL_SDA4_0) FM(SEL_SDA4_1)
+#define MOD_SEL8_8 FM(SEL_SCL4_0) FM(SEL_SCL4_1)
+#define MOD_SEL8_7 FM(SEL_SDA3_0) FM(SEL_SDA3_1)
+#define MOD_SEL8_6 FM(SEL_SCL3_0) FM(SEL_SCL3_1)
+#define MOD_SEL8_5 FM(SEL_SDA2_0) FM(SEL_SDA2_1)
+#define MOD_SEL8_4 FM(SEL_SCL2_0) FM(SEL_SCL2_1)
+#define MOD_SEL8_3 FM(SEL_SDA1_0) FM(SEL_SDA1_1)
+#define MOD_SEL8_2 FM(SEL_SCL1_0) FM(SEL_SCL1_1)
+#define MOD_SEL8_1 FM(SEL_SDA0_0) FM(SEL_SDA0_1)
+#define MOD_SEL8_0 FM(SEL_SCL0_0) FM(SEL_SCL0_1)
+
+#define PINMUX_MOD_SELS \
+\
+MOD_SEL4_19 MOD_SEL5_19 \
+MOD_SEL4_18 MOD_SEL6_18 \
+ \
+ MOD_SEL5_16 MOD_SEL6_16 MOD_SEL7_16 \
+MOD_SEL4_15 MOD_SEL5_15 MOD_SEL7_15 \
+MOD_SEL4_14 \
+ MOD_SEL6_13 MOD_SEL7_13 \
+MOD_SEL4_12 MOD_SEL5_12 MOD_SEL6_12 \
+ MOD_SEL5_11 MOD_SEL7_11 MOD_SEL8_11 \
+ MOD_SEL6_10 MOD_SEL7_10 MOD_SEL8_10 \
+MOD_SEL4_9 MOD_SEL8_9 \
+MOD_SEL4_8 MOD_SEL5_8 MOD_SEL8_8 \
+ MOD_SEL6_7 MOD_SEL7_7 MOD_SEL8_7 \
+ MOD_SEL5_6 MOD_SEL6_6 MOD_SEL7_6 MOD_SEL8_6 \
+MOD_SEL4_5 MOD_SEL5_5 MOD_SEL6_5 MOD_SEL8_5 \
+ MOD_SEL8_4 \
+ MOD_SEL7_3 MOD_SEL8_3 \
+MOD_SEL4_2 MOD_SEL5_2 MOD_SEL6_2 MOD_SEL7_2 MOD_SEL8_2 \
+MOD_SEL4_1 MOD_SEL6_1 MOD_SEL8_1 \
+ MOD_SEL5_0 MOD_SEL7_0 MOD_SEL8_0
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ GP_ALL(DATA),
+ PINMUX_DATA_END,
+
+#define F_(x, y)
+#define FM(x) FN_##x,
+ PINMUX_FUNCTION_BEGIN,
+ GP_ALL(FN),
+ PINMUX_GPSR
+ PINMUX_IPSR
+ PINMUX_MOD_SELS
+ PINMUX_FUNCTION_END,
+#undef F_
+#undef FM
+
+#define F_(x, y)
+#define FM(x) x##_MARK,
+ PINMUX_MARK_BEGIN,
+ PINMUX_GPSR
+ PINMUX_IPSR
+ PINMUX_MOD_SELS
+ PINMUX_MARK_END,
+#undef F_
+#undef FM
+};
+
+static const u16 pinmux_data[] = {
+ PINMUX_DATA_GP_ALL(),
+
+ PINMUX_SINGLE(AVS1),
+ PINMUX_SINGLE(AVS0),
+ PINMUX_SINGLE(PCIE1_CLKREQ_N),
+ PINMUX_SINGLE(PCIE0_CLKREQ_N),
+
+ /* TSN0 without MODSEL4 */
+ PINMUX_SINGLE(TSN0_TXCREFCLK),
+ PINMUX_SINGLE(TSN0_RD2),
+ PINMUX_SINGLE(TSN0_RD3),
+ PINMUX_SINGLE(TSN0_RD1),
+ PINMUX_SINGLE(TSN0_RXC),
+ PINMUX_SINGLE(TSN0_RD0),
+ PINMUX_SINGLE(TSN0_RX_CTL),
+ PINMUX_SINGLE(TSN0_AVTP_CAPTURE),
+ PINMUX_SINGLE(TSN0_LINK),
+ PINMUX_SINGLE(TSN0_PHY_INT),
+ PINMUX_SINGLE(TSN0_MDIO),
+ /* TSN0 with MODSEL4 */
+ PINMUX_IPSR_NOGM(0, TSN0_TD2, SEL_TSN0_TD2_1),
+ PINMUX_IPSR_NOGM(0, TSN0_TD3, SEL_TSN0_TD3_1),
+ PINMUX_IPSR_NOGM(0, TSN0_TD0, SEL_TSN0_TD0_1),
+ PINMUX_IPSR_NOGM(0, TSN0_TD1, SEL_TSN0_TD1_1),
+ PINMUX_IPSR_NOGM(0, TSN0_TXC, SEL_TSN0_TXC_1),
+ PINMUX_IPSR_NOGM(0, TSN0_TX_CTL, SEL_TSN0_TX_CTL_1),
+ PINMUX_IPSR_NOGM(0, TSN0_AVTP_PPS0, SEL_TSN0_AVTP_PPS0_1),
+ PINMUX_IPSR_NOGM(0, TSN0_AVTP_MATCH, SEL_TSN0_AVTP_MATCH_1),
+ PINMUX_IPSR_NOGM(0, TSN0_AVTP_PPS1, SEL_TSN0_AVTP_PPS1_1),
+ PINMUX_IPSR_NOGM(0, TSN0_MDC, SEL_TSN0_MDC_1),
+
+ /* TSN0 without MODSEL5 */
+ PINMUX_SINGLE(AVB2_RX_CTL),
+ PINMUX_SINGLE(AVB2_RXC),
+ PINMUX_SINGLE(AVB2_RD0),
+ PINMUX_SINGLE(AVB2_RD1),
+ PINMUX_SINGLE(AVB2_RD2),
+ PINMUX_SINGLE(AVB2_MDIO),
+ PINMUX_SINGLE(AVB2_RD3),
+ PINMUX_SINGLE(AVB2_TXCREFCLK),
+ PINMUX_SINGLE(AVB2_PHY_INT),
+ PINMUX_SINGLE(AVB2_LINK),
+ PINMUX_SINGLE(AVB2_AVTP_CAPTURE),
+ /* TSN0 with MODSEL5 */
+ PINMUX_IPSR_NOGM(0, AVB2_TX_CTL, SEL_AVB2_TX_CTL_1),
+ PINMUX_IPSR_NOGM(0, AVB2_TXC, SEL_AVB2_TXC_1),
+ PINMUX_IPSR_NOGM(0, AVB2_TD0, SEL_AVB2_TD0_1),
+ PINMUX_IPSR_NOGM(0, AVB2_TD1, SEL_AVB2_TD1_1),
+ PINMUX_IPSR_NOGM(0, AVB2_TD2, SEL_AVB2_TD2_1),
+ PINMUX_IPSR_NOGM(0, AVB2_TD3, SEL_AVB2_TD3_1),
+ PINMUX_IPSR_NOGM(0, AVB2_MDC, SEL_AVB2_MDC_1),
+ PINMUX_IPSR_NOGM(0, AVB2_MAGIC, SEL_AVB2_MAGIC_1),
+ PINMUX_IPSR_NOGM(0, AVB2_AVTP_MATCH, SEL_AVB2_AVTP_MATCH_1),
+ PINMUX_IPSR_NOGM(0, AVB2_AVTP_PPS, SEL_AVB2_AVTP_PPS_1),
+
+ /* IP0SR0 */
+ PINMUX_IPSR_GPSR(IP0SR0_3_0, ERROROUTC_B),
+ PINMUX_IPSR_GPSR(IP0SR0_3_0, TCLK2_A),
+
+ PINMUX_IPSR_GPSR(IP0SR0_7_4, MSIOF3_SS1),
+
+ PINMUX_IPSR_GPSR(IP0SR0_11_8, MSIOF3_SS2),
+
+ PINMUX_IPSR_GPSR(IP0SR0_15_12, IRQ3),
+ PINMUX_IPSR_GPSR(IP0SR0_15_12, MSIOF3_SCK),
+
+ PINMUX_IPSR_GPSR(IP0SR0_19_16, IRQ2),
+ PINMUX_IPSR_GPSR(IP0SR0_19_16, MSIOF3_TXD),
+
+ PINMUX_IPSR_GPSR(IP0SR0_23_20, IRQ1),
+ PINMUX_IPSR_GPSR(IP0SR0_23_20, MSIOF3_RXD),
+
+ PINMUX_IPSR_GPSR(IP0SR0_27_24, IRQ0),
+ PINMUX_IPSR_GPSR(IP0SR0_27_24, MSIOF3_SYNC),
+
+ PINMUX_IPSR_GPSR(IP0SR0_31_28, MSIOF5_SS2),
+
+ /* IP1SR0 */
+ PINMUX_IPSR_GPSR(IP1SR0_3_0, MSIOF5_SS1),
+
+ PINMUX_IPSR_GPSR(IP1SR0_7_4, MSIOF5_SYNC),
+
+ PINMUX_IPSR_GPSR(IP1SR0_11_8, MSIOF5_TXD),
+
+ PINMUX_IPSR_GPSR(IP1SR0_15_12, MSIOF5_SCK),
+
+ PINMUX_IPSR_GPSR(IP1SR0_19_16, MSIOF5_RXD),
+
+ PINMUX_IPSR_GPSR(IP1SR0_23_20, MSIOF2_SS2),
+ PINMUX_IPSR_GPSR(IP1SR0_23_20, TCLK1),
+ PINMUX_IPSR_GPSR(IP1SR0_23_20, IRQ2_A),
+
+ PINMUX_IPSR_GPSR(IP1SR0_27_24, MSIOF2_SS1),
+ PINMUX_IPSR_GPSR(IP1SR0_27_24, HTX1),
+ PINMUX_IPSR_GPSR(IP1SR0_27_24, TX1),
+
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, MSIOF2_SYNC),
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, HRX1),
+ PINMUX_IPSR_GPSR(IP1SR0_31_28, RX1),
+
+ /* IP2SR0 */
+ PINMUX_IPSR_GPSR(IP2SR0_3_0, MSIOF2_TXD),
+ PINMUX_IPSR_GPSR(IP2SR0_3_0, HCTS1_N),
+ PINMUX_IPSR_GPSR(IP2SR0_3_0, CTS1_N),
+
+ PINMUX_IPSR_GPSR(IP2SR0_7_4, MSIOF2_SCK),
+ PINMUX_IPSR_GPSR(IP2SR0_7_4, HRTS1_N),
+ PINMUX_IPSR_GPSR(IP2SR0_7_4, RTS1_N),
+
+ PINMUX_IPSR_GPSR(IP2SR0_11_8, MSIOF2_RXD),
+ PINMUX_IPSR_GPSR(IP2SR0_11_8, HSCK1),
+ PINMUX_IPSR_GPSR(IP2SR0_11_8, SCK1),
+
+ /* IP0SR1 */
+ PINMUX_IPSR_GPSR(IP0SR1_3_0, MSIOF1_SS2),
+ PINMUX_IPSR_GPSR(IP0SR1_3_0, HTX3_A),
+ PINMUX_IPSR_GPSR(IP0SR1_3_0, TX3),
+
+ PINMUX_IPSR_GPSR(IP0SR1_7_4, MSIOF1_SS1),
+ PINMUX_IPSR_GPSR(IP0SR1_7_4, HCTS3_N_A),
+ PINMUX_IPSR_GPSR(IP0SR1_7_4, RX3),
+
+ PINMUX_IPSR_GPSR(IP0SR1_11_8, MSIOF1_SYNC),
+ PINMUX_IPSR_GPSR(IP0SR1_11_8, HRTS3_N_A),
+ PINMUX_IPSR_GPSR(IP0SR1_11_8, RTS3_N),
+
+ PINMUX_IPSR_GPSR(IP0SR1_15_12, MSIOF1_SCK),
+ PINMUX_IPSR_GPSR(IP0SR1_15_12, HSCK3_A),
+ PINMUX_IPSR_GPSR(IP0SR1_15_12, CTS3_N),
+
+ PINMUX_IPSR_GPSR(IP0SR1_19_16, MSIOF1_TXD),
+ PINMUX_IPSR_GPSR(IP0SR1_19_16, HRX3_A),
+ PINMUX_IPSR_GPSR(IP0SR1_19_16, SCK3),
+
+ PINMUX_IPSR_GPSR(IP0SR1_23_20, MSIOF1_RXD),
+
+ PINMUX_IPSR_GPSR(IP0SR1_27_24, MSIOF0_SS2),
+ PINMUX_IPSR_GPSR(IP0SR1_27_24, HTX1_X),
+ PINMUX_IPSR_GPSR(IP0SR1_27_24, TX1_X),
+
+ PINMUX_IPSR_GPSR(IP0SR1_31_28, MSIOF0_SS1),
+ PINMUX_IPSR_GPSR(IP0SR1_31_28, HRX1_X),
+ PINMUX_IPSR_GPSR(IP0SR1_31_28, RX1_X),
+
+ /* IP1SR1 */
+ PINMUX_IPSR_GPSR(IP1SR1_3_0, MSIOF0_SYNC),
+ PINMUX_IPSR_GPSR(IP1SR1_3_0, HCTS1_N_X),
+ PINMUX_IPSR_GPSR(IP1SR1_3_0, CTS1_N_X),
+ PINMUX_IPSR_GPSR(IP1SR1_3_0, CANFD5_TX_B),
+
+ PINMUX_IPSR_GPSR(IP1SR1_7_4, MSIOF0_TXD),
+ PINMUX_IPSR_GPSR(IP1SR1_7_4, HRTS1_N_X),
+ PINMUX_IPSR_GPSR(IP1SR1_7_4, RTS1_N_X),
+ PINMUX_IPSR_GPSR(IP1SR1_7_4, CANFD5_RX_B),
+
+ PINMUX_IPSR_GPSR(IP1SR1_11_8, MSIOF0_SCK),
+ PINMUX_IPSR_GPSR(IP1SR1_11_8, HSCK1_X),
+ PINMUX_IPSR_GPSR(IP1SR1_11_8, SCK1_X),
+
+ PINMUX_IPSR_GPSR(IP1SR1_15_12, MSIOF0_RXD),
+
+ PINMUX_IPSR_GPSR(IP1SR1_19_16, HTX0),
+ PINMUX_IPSR_GPSR(IP1SR1_19_16, TX0),
+
+ PINMUX_IPSR_GPSR(IP1SR1_23_20, HCTS0_N),
+ PINMUX_IPSR_GPSR(IP1SR1_23_20, CTS0_N),
+ PINMUX_IPSR_GPSR(IP1SR1_23_20, PWM8_A),
+
+ PINMUX_IPSR_GPSR(IP1SR1_27_24, HRTS0_N),
+ PINMUX_IPSR_GPSR(IP1SR1_27_24, RTS0_N),
+ PINMUX_IPSR_GPSR(IP1SR1_27_24, PWM9_A),
+
+ PINMUX_IPSR_GPSR(IP1SR1_31_28, HSCK0),
+ PINMUX_IPSR_GPSR(IP1SR1_31_28, SCK0),
+ PINMUX_IPSR_GPSR(IP1SR1_31_28, PWM0_A),
+
+ /* IP2SR1 */
+ PINMUX_IPSR_GPSR(IP2SR1_3_0, HRX0),
+ PINMUX_IPSR_GPSR(IP2SR1_3_0, RX0),
+
+ PINMUX_IPSR_GPSR(IP2SR1_7_4, SCIF_CLK),
+ PINMUX_IPSR_GPSR(IP2SR1_7_4, IRQ4_A),
+
+ PINMUX_IPSR_GPSR(IP2SR1_11_8, SSI_SCK),
+ PINMUX_IPSR_GPSR(IP2SR1_11_8, TCLK3),
+
+ PINMUX_IPSR_GPSR(IP2SR1_15_12, SSI_WS),
+ PINMUX_IPSR_GPSR(IP2SR1_15_12, TCLK4),
+
+ PINMUX_IPSR_GPSR(IP2SR1_19_16, SSI_SD),
+ PINMUX_IPSR_GPSR(IP2SR1_19_16, IRQ0_A),
+
+ PINMUX_IPSR_GPSR(IP2SR1_23_20, AUDIO_CLKOUT),
+ PINMUX_IPSR_GPSR(IP2SR1_23_20, IRQ1_A),
+
+ PINMUX_IPSR_GPSR(IP2SR1_27_24, AUDIO_CLKIN),
+ PINMUX_IPSR_GPSR(IP2SR1_27_24, PWM3_A),
+
+ PINMUX_IPSR_GPSR(IP2SR1_31_28, TCLK2),
+ PINMUX_IPSR_GPSR(IP2SR1_31_28, MSIOF4_SS1),
+ PINMUX_IPSR_GPSR(IP2SR1_31_28, IRQ3_B),
+
+ /* IP3SR1 */
+ PINMUX_IPSR_GPSR(IP3SR1_3_0, HRX3),
+ PINMUX_IPSR_GPSR(IP3SR1_3_0, SCK3_A),
+ PINMUX_IPSR_GPSR(IP3SR1_3_0, MSIOF4_SS2),
+
+ PINMUX_IPSR_GPSR(IP3SR1_7_4, HSCK3),
+ PINMUX_IPSR_GPSR(IP3SR1_7_4, CTS3_N_A),
+ PINMUX_IPSR_GPSR(IP3SR1_7_4, MSIOF4_SCK),
+ PINMUX_IPSR_GPSR(IP3SR1_7_4, TPU0TO0_A),
+
+ PINMUX_IPSR_GPSR(IP3SR1_11_8, HRTS3_N),
+ PINMUX_IPSR_GPSR(IP3SR1_11_8, RTS3_N_A),
+ PINMUX_IPSR_GPSR(IP3SR1_11_8, MSIOF4_TXD),
+ PINMUX_IPSR_GPSR(IP3SR1_11_8, TPU0TO1_A),
+
+ PINMUX_IPSR_GPSR(IP3SR1_15_12, HCTS3_N),
+ PINMUX_IPSR_GPSR(IP3SR1_15_12, RX3_A),
+ PINMUX_IPSR_GPSR(IP3SR1_15_12, MSIOF4_RXD),
+
+ PINMUX_IPSR_GPSR(IP3SR1_19_16, HTX3),
+ PINMUX_IPSR_GPSR(IP3SR1_19_16, TX3_A),
+ PINMUX_IPSR_GPSR(IP3SR1_19_16, MSIOF4_SYNC),
+
+ /* IP0SR2 */
+ PINMUX_IPSR_GPSR(IP0SR2_3_0, FXR_TXDA),
+ PINMUX_IPSR_GPSR(IP0SR2_3_0, CANFD1_TX),
+ PINMUX_IPSR_GPSR(IP0SR2_3_0, TPU0TO2_A),
+
+ PINMUX_IPSR_GPSR(IP0SR2_7_4, FXR_TXENA_N),
+ PINMUX_IPSR_GPSR(IP0SR2_7_4, CANFD1_RX),
+ PINMUX_IPSR_GPSR(IP0SR2_7_4, TPU0TO3_A),
+
+ PINMUX_IPSR_GPSR(IP0SR2_11_8, RXDA_EXTFXR),
+ PINMUX_IPSR_GPSR(IP0SR2_11_8, CANFD5_TX),
+ PINMUX_IPSR_GPSR(IP0SR2_11_8, IRQ5),
+
+ PINMUX_IPSR_GPSR(IP0SR2_15_12, CLK_EXTFXR),
+ PINMUX_IPSR_GPSR(IP0SR2_15_12, CANFD5_RX),
+ PINMUX_IPSR_GPSR(IP0SR2_15_12, IRQ4_B),
+
+ PINMUX_IPSR_GPSR(IP0SR2_19_16, RXDB_EXTFXR),
+
+ PINMUX_IPSR_GPSR(IP0SR2_23_20, FXR_TXENB_N),
+
+ PINMUX_IPSR_GPSR(IP0SR2_27_24, FXR_TXDB),
+
+ PINMUX_IPSR_GPSR(IP0SR2_31_28, TPU0TO1),
+ PINMUX_IPSR_GPSR(IP0SR2_31_28, CANFD6_TX),
+ PINMUX_IPSR_GPSR(IP0SR2_31_28, TCLK2_B),
+
+ /* IP1SR2 */
+ PINMUX_IPSR_GPSR(IP1SR2_3_0, TPU0TO0),
+ PINMUX_IPSR_GPSR(IP1SR2_3_0, CANFD6_RX),
+ PINMUX_IPSR_GPSR(IP1SR2_3_0, TCLK1_A),
+
+ PINMUX_IPSR_GPSR(IP1SR2_7_4, CAN_CLK),
+ PINMUX_IPSR_GPSR(IP1SR2_7_4, FXR_TXENA_N_X),
+
+ PINMUX_IPSR_GPSR(IP1SR2_11_8, CANFD0_TX),
+ PINMUX_IPSR_GPSR(IP1SR2_11_8, FXR_TXENB_N_X),
+
+ PINMUX_IPSR_GPSR(IP1SR2_15_12, CANFD0_RX),
+ PINMUX_IPSR_GPSR(IP1SR2_15_12, STPWT_EXTFXR),
+
+ PINMUX_IPSR_GPSR(IP1SR2_19_16, CANFD2_TX),
+ PINMUX_IPSR_GPSR(IP1SR2_19_16, TPU0TO2),
+ PINMUX_IPSR_GPSR(IP1SR2_19_16, TCLK3_A),
+
+ PINMUX_IPSR_GPSR(IP1SR2_23_20, CANFD2_RX),
+ PINMUX_IPSR_GPSR(IP1SR2_23_20, TPU0TO3),
+ PINMUX_IPSR_GPSR(IP1SR2_23_20, PWM1_B),
+ PINMUX_IPSR_GPSR(IP1SR2_23_20, TCLK4_A),
+
+ PINMUX_IPSR_GPSR(IP1SR2_27_24, CANFD3_TX),
+ PINMUX_IPSR_GPSR(IP1SR2_27_24, PWM2_B),
+
+ PINMUX_IPSR_GPSR(IP1SR2_31_28, CANFD3_RX),
+ PINMUX_IPSR_GPSR(IP1SR2_31_28, PWM3_B),
+
+ /* IP2SR2 */
+ PINMUX_IPSR_GPSR(IP2SR2_3_0, CANFD4_TX),
+ PINMUX_IPSR_GPSR(IP2SR2_3_0, PWM4),
+
+ PINMUX_IPSR_GPSR(IP2SR2_7_4, CANFD4_RX),
+ PINMUX_IPSR_GPSR(IP2SR2_7_4, PWM5),
+
+ PINMUX_IPSR_GPSR(IP2SR2_11_8, CANFD7_TX),
+ PINMUX_IPSR_GPSR(IP2SR2_11_8, PWM6),
+
+ PINMUX_IPSR_GPSR(IP2SR2_15_12, CANFD7_RX),
+ PINMUX_IPSR_GPSR(IP2SR2_15_12, PWM7),
+
+ /* IP0SR3 */
+ PINMUX_IPSR_GPSR(IP0SR3_3_0, MMC_SD_D1),
+ PINMUX_IPSR_GPSR(IP0SR3_7_4, MMC_SD_D0),
+ PINMUX_IPSR_GPSR(IP0SR3_11_8, MMC_SD_D2),
+ PINMUX_IPSR_GPSR(IP0SR3_15_12, MMC_SD_CLK),
+ PINMUX_IPSR_GPSR(IP0SR3_19_16, MMC_DS),
+ PINMUX_IPSR_GPSR(IP0SR3_23_20, MMC_SD_D3),
+ PINMUX_IPSR_GPSR(IP0SR3_27_24, MMC_D5),
+ PINMUX_IPSR_GPSR(IP0SR3_31_28, MMC_D4),
+
+ /* IP1SR3 */
+ PINMUX_IPSR_GPSR(IP1SR3_3_0, MMC_D7),
+
+ PINMUX_IPSR_GPSR(IP1SR3_7_4, MMC_D6),
+
+ PINMUX_IPSR_GPSR(IP1SR3_11_8, MMC_SD_CMD),
+
+ PINMUX_IPSR_GPSR(IP1SR3_15_12, SD_CD),
+
+ PINMUX_IPSR_GPSR(IP1SR3_19_16, SD_WP),
+
+ PINMUX_IPSR_GPSR(IP1SR3_23_20, IPC_CLKIN),
+ PINMUX_IPSR_GPSR(IP1SR3_23_20, IPC_CLKEN_IN),
+ PINMUX_IPSR_GPSR(IP1SR3_23_20, PWM1_A),
+ PINMUX_IPSR_GPSR(IP1SR3_23_20, TCLK3_X),
+
+ PINMUX_IPSR_GPSR(IP1SR3_27_24, IPC_CLKOUT),
+ PINMUX_IPSR_GPSR(IP1SR3_27_24, IPC_CLKEN_OUT),
+ PINMUX_IPSR_GPSR(IP1SR3_27_24, ERROROUTC_A),
+ PINMUX_IPSR_GPSR(IP1SR3_27_24, TCLK4_X),
+
+ PINMUX_IPSR_GPSR(IP1SR3_31_28, QSPI0_SSL),
+
+ /* IP2SR3 */
+ PINMUX_IPSR_GPSR(IP2SR3_3_0, QSPI0_IO3),
+ PINMUX_IPSR_GPSR(IP2SR3_7_4, QSPI0_IO2),
+ PINMUX_IPSR_GPSR(IP2SR3_11_8, QSPI0_MISO_IO1),
+ PINMUX_IPSR_GPSR(IP2SR3_15_12, QSPI0_MOSI_IO0),
+ PINMUX_IPSR_GPSR(IP2SR3_19_16, QSPI0_SPCLK),
+ PINMUX_IPSR_GPSR(IP2SR3_23_20, QSPI1_MOSI_IO0),
+ PINMUX_IPSR_GPSR(IP2SR3_27_24, QSPI1_SPCLK),
+ PINMUX_IPSR_GPSR(IP2SR3_31_28, QSPI1_MISO_IO1),
+
+ /* IP3SR3 */
+ PINMUX_IPSR_GPSR(IP3SR3_3_0, QSPI1_IO2),
+ PINMUX_IPSR_GPSR(IP3SR3_7_4, QSPI1_SSL),
+ PINMUX_IPSR_GPSR(IP3SR3_11_8, QSPI1_IO3),
+ PINMUX_IPSR_GPSR(IP3SR3_15_12, RPC_RESET_N),
+ PINMUX_IPSR_GPSR(IP3SR3_19_16, RPC_WP_N),
+ PINMUX_IPSR_GPSR(IP3SR3_23_20, RPC_INT_N),
+
+ /* IP0SR6 */
+ PINMUX_IPSR_GPSR(IP0SR6_3_0, AVB1_MDIO),
+
+ PINMUX_IPSR_MSEL(IP0SR6_7_4, AVB1_MAGIC, SEL_AVB1_MAGIC_1),
+
+ PINMUX_IPSR_MSEL(IP0SR6_11_8, AVB1_MDC, SEL_AVB1_MDC_1),
+
+ PINMUX_IPSR_GPSR(IP0SR6_15_12, AVB1_PHY_INT),
+
+ PINMUX_IPSR_GPSR(IP0SR6_19_16, AVB1_LINK),
+ PINMUX_IPSR_GPSR(IP0SR6_19_16, AVB1_MII_TX_ER),
+
+ PINMUX_IPSR_MSEL(IP0SR6_23_20, AVB1_AVTP_MATCH, SEL_AVB1_AVTP_MATCH_1),
+ PINMUX_IPSR_MSEL(IP0SR6_23_20, AVB1_MII_RX_ER, SEL_AVB1_AVTP_MATCH_0),
+
+ PINMUX_IPSR_MSEL(IP0SR6_27_24, AVB1_TXC, SEL_AVB1_TXC_1),
+ PINMUX_IPSR_MSEL(IP0SR6_27_24, AVB1_MII_TXC, SEL_AVB1_TXC_0),
+
+ PINMUX_IPSR_MSEL(IP0SR6_31_28, AVB1_TX_CTL, SEL_AVB1_TX_CTL_1),
+ PINMUX_IPSR_MSEL(IP0SR6_31_28, AVB1_MII_TX_EN, SEL_AVB1_TX_CTL_0),
+
+ /* IP1SR6 */
+ PINMUX_IPSR_GPSR(IP1SR6_3_0, AVB1_RXC),
+ PINMUX_IPSR_GPSR(IP1SR6_3_0, AVB1_MII_RXC),
+
+ PINMUX_IPSR_GPSR(IP1SR6_7_4, AVB1_RX_CTL),
+ PINMUX_IPSR_GPSR(IP1SR6_7_4, AVB1_MII_RX_DV),
+
+ PINMUX_IPSR_MSEL(IP1SR6_11_8, AVB1_AVTP_PPS, SEL_AVB1_AVTP_PPS_1),
+ PINMUX_IPSR_MSEL(IP1SR6_11_8, AVB1_MII_COL, SEL_AVB1_AVTP_PPS_0),
+
+ PINMUX_IPSR_GPSR(IP1SR6_15_12, AVB1_AVTP_CAPTURE),
+ PINMUX_IPSR_GPSR(IP1SR6_15_12, AVB1_MII_CRS),
+
+ PINMUX_IPSR_MSEL(IP1SR6_19_16, AVB1_TD1, SEL_AVB1_TD1_1),
+ PINMUX_IPSR_MSEL(IP1SR6_19_16, AVB1_MII_TD1, SEL_AVB1_TD1_0),
+
+ PINMUX_IPSR_MSEL(IP1SR6_23_20, AVB1_TD0, SEL_AVB1_TD0_1),
+ PINMUX_IPSR_MSEL(IP1SR6_23_20, AVB1_MII_TD0, SEL_AVB1_TD0_0),
+
+ PINMUX_IPSR_GPSR(IP1SR6_27_24, AVB1_RD1),
+ PINMUX_IPSR_GPSR(IP1SR6_27_24, AVB1_MII_RD1),
+
+ PINMUX_IPSR_GPSR(IP1SR6_31_28, AVB1_RD0),
+ PINMUX_IPSR_GPSR(IP1SR6_31_28, AVB1_MII_RD0),
+
+ /* IP2SR6 */
+ PINMUX_IPSR_MSEL(IP2SR6_3_0, AVB1_TD2, SEL_AVB1_TD2_1),
+ PINMUX_IPSR_MSEL(IP2SR6_3_0, AVB1_MII_TD2, SEL_AVB1_TD2_0),
+
+ PINMUX_IPSR_GPSR(IP2SR6_7_4, AVB1_RD2),
+ PINMUX_IPSR_GPSR(IP2SR6_7_4, AVB1_MII_RD2),
+
+ PINMUX_IPSR_MSEL(IP2SR6_11_8, AVB1_TD3, SEL_AVB1_TD3_1),
+ PINMUX_IPSR_MSEL(IP2SR6_11_8, AVB1_MII_TD3, SEL_AVB1_TD3_0),
+
+ PINMUX_IPSR_GPSR(IP2SR6_15_12, AVB1_RD3),
+ PINMUX_IPSR_GPSR(IP2SR6_15_12, AVB1_MII_RD3),
+
+ PINMUX_IPSR_GPSR(IP2SR6_19_16, AVB1_TXCREFCLK),
+
+ /* IP0SR7 */
+ PINMUX_IPSR_MSEL(IP0SR7_3_0, AVB0_AVTP_PPS, SEL_AVB0_AVTP_PPS_1),
+ PINMUX_IPSR_MSEL(IP0SR7_3_0, AVB0_MII_COL, SEL_AVB0_AVTP_PPS_0),
+
+ PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_AVTP_CAPTURE),
+ PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_MII_CRS),
+
+ PINMUX_IPSR_MSEL(IP0SR7_11_8, AVB0_AVTP_MATCH, SEL_AVB0_AVTP_MATCH_1),
+ PINMUX_IPSR_MSEL(IP0SR7_11_8, AVB0_MII_RX_ER, SEL_AVB0_AVTP_MATCH_0),
+ PINMUX_IPSR_MSEL(IP0SR7_11_8, CC5_OSCOUT, SEL_AVB0_AVTP_MATCH_0),
+
+ PINMUX_IPSR_MSEL(IP0SR7_15_12, AVB0_TD3, SEL_AVB0_TD3_1),
+ PINMUX_IPSR_MSEL(IP0SR7_15_12, AVB0_MII_TD3, SEL_AVB0_TD3_0),
+
+ PINMUX_IPSR_GPSR(IP0SR7_19_16, AVB0_LINK),
+ PINMUX_IPSR_GPSR(IP0SR7_19_16, AVB0_MII_TX_ER),
+
+ PINMUX_IPSR_GPSR(IP0SR7_23_20, AVB0_PHY_INT),
+
+ PINMUX_IPSR_MSEL(IP0SR7_27_24, AVB0_TD2, SEL_AVB0_TD2_1),
+ PINMUX_IPSR_MSEL(IP0SR7_27_24, AVB0_MII_TD2, SEL_AVB0_TD2_0),
+
+ PINMUX_IPSR_MSEL(IP0SR7_31_28, AVB0_TD1, SEL_AVB0_TD1_1),
+ PINMUX_IPSR_MSEL(IP0SR7_31_28, AVB0_MII_TD1, SEL_AVB0_TD1_0),
+
+ /* IP1SR7 */
+ PINMUX_IPSR_GPSR(IP1SR7_3_0, AVB0_RD3),
+ PINMUX_IPSR_GPSR(IP1SR7_3_0, AVB0_MII_RD3),
+
+ PINMUX_IPSR_GPSR(IP1SR7_7_4, AVB0_TXCREFCLK),
+
+ PINMUX_IPSR_MSEL(IP1SR7_11_8, AVB0_MAGIC, SEL_AVB0_MAGIC_1),
+
+ PINMUX_IPSR_MSEL(IP1SR7_15_12, AVB0_TD0, SEL_AVB0_TD0_1),
+ PINMUX_IPSR_MSEL(IP1SR7_15_12, AVB0_MII_TD0, SEL_AVB0_TD0_0),
+
+ PINMUX_IPSR_GPSR(IP1SR7_19_16, AVB0_RD2),
+ PINMUX_IPSR_GPSR(IP1SR7_19_16, AVB0_MII_RD2),
+
+ PINMUX_IPSR_MSEL(IP1SR7_23_20, AVB0_MDC, SEL_AVB0_MDC_1),
+
+ PINMUX_IPSR_GPSR(IP1SR7_27_24, AVB0_MDIO),
+
+ PINMUX_IPSR_MSEL(IP1SR7_31_28, AVB0_TXC, SEL_AVB0_TXC_1),
+ PINMUX_IPSR_MSEL(IP1SR7_31_28, AVB0_MII_TXC, SEL_AVB0_TXC_0),
+
+ /* IP2SR7 */
+ PINMUX_IPSR_MSEL(IP2SR7_3_0, AVB0_TX_CTL, SEL_AVB0_TX_CTL_1),
+ PINMUX_IPSR_MSEL(IP2SR7_3_0, AVB0_MII_TX_EN, SEL_AVB0_TX_CTL_0),
+
+ PINMUX_IPSR_GPSR(IP2SR7_7_4, AVB0_RD1),
+ PINMUX_IPSR_GPSR(IP2SR7_7_4, AVB0_MII_RD1),
+
+ PINMUX_IPSR_GPSR(IP2SR7_11_8, AVB0_RD0),
+ PINMUX_IPSR_GPSR(IP2SR7_11_8, AVB0_MII_RD0),
+
+ PINMUX_IPSR_GPSR(IP2SR7_15_12, AVB0_RXC),
+ PINMUX_IPSR_GPSR(IP2SR7_15_12, AVB0_MII_RXC),
+
+ PINMUX_IPSR_GPSR(IP2SR7_19_16, AVB0_RX_CTL),
+ PINMUX_IPSR_GPSR(IP2SR7_19_16, AVB0_MII_RX_DV),
+
+ /* IP0SR8 */
+ PINMUX_IPSR_MSEL(IP0SR8_3_0, SCL0, SEL_SCL0_0),
+ PINMUX_IPSR_MSEL(IP0SR8_7_4, SDA0, SEL_SDA0_0),
+ PINMUX_IPSR_MSEL(IP0SR8_11_8, SCL1, SEL_SCL1_0),
+ PINMUX_IPSR_MSEL(IP0SR8_15_12, SDA1, SEL_SDA1_0),
+ PINMUX_IPSR_MSEL(IP0SR8_19_16, SCL2, SEL_SCL2_0),
+ PINMUX_IPSR_MSEL(IP0SR8_23_20, SDA2, SEL_SDA2_0),
+ PINMUX_IPSR_MSEL(IP0SR8_27_24, SCL3, SEL_SCL3_0),
+ PINMUX_IPSR_MSEL(IP0SR8_31_28, SDA3, SEL_SDA3_0),
+
+ /* IP1SR8 */
+ PINMUX_IPSR_MSEL(IP1SR8_3_0, SCL4, SEL_SCL4_0),
+ PINMUX_IPSR_MSEL(IP1SR8_3_0, HRX2, SEL_SCL4_0),
+ PINMUX_IPSR_MSEL(IP1SR8_3_0, SCK4, SEL_SCL4_0),
+
+ PINMUX_IPSR_MSEL(IP1SR8_7_4, SDA4, SEL_SDA4_0),
+ PINMUX_IPSR_MSEL(IP1SR8_7_4, HTX2, SEL_SDA4_0),
+ PINMUX_IPSR_MSEL(IP1SR8_7_4, CTS4_N, SEL_SDA4_0),
+
+ PINMUX_IPSR_MSEL(IP1SR8_11_8, SCL5, SEL_SCL5_0),
+ PINMUX_IPSR_MSEL(IP1SR8_11_8, HRTS2_N, SEL_SCL5_0),
+ PINMUX_IPSR_MSEL(IP1SR8_11_8, RTS4_N, SEL_SCL5_0),
+
+ PINMUX_IPSR_MSEL(IP1SR8_15_12, SDA5, SEL_SDA5_0),
+ PINMUX_IPSR_MSEL(IP1SR8_15_12, SCIF_CLK2, SEL_SDA5_0),
+
+ PINMUX_IPSR_GPSR(IP1SR8_19_16, HCTS2_N),
+ PINMUX_IPSR_GPSR(IP1SR8_19_16, TX4),
+
+ PINMUX_IPSR_GPSR(IP1SR8_23_20, HSCK2),
+ PINMUX_IPSR_GPSR(IP1SR8_23_20, RX4),
+};
+
+/*
+ * Pins not associated with a GPIO port.
+ */
+enum {
+ GP_ASSIGN_LAST(),
+};
+
+static const struct sh_pfc_pin pinmux_pins[] = {
+ PINMUX_GPIO_GP_ALL(),
+};
+
+/* - AVB0 ------------------------------------------------ */
+static const unsigned int avb0_link_pins[] = {
+ /* AVB0_LINK */
+ RCAR_GP_PIN(7, 4),
+};
+static const unsigned int avb0_link_mux[] = {
+ AVB0_LINK_MARK,
+};
+static const unsigned int avb0_magic_pins[] = {
+ /* AVB0_MAGIC */
+ RCAR_GP_PIN(7, 10),
+};
+static const unsigned int avb0_magic_mux[] = {
+ AVB0_MAGIC_MARK,
+};
+static const unsigned int avb0_phy_int_pins[] = {
+ /* AVB0_PHY_INT */
+ RCAR_GP_PIN(7, 5),
+};
+static const unsigned int avb0_phy_int_mux[] = {
+ AVB0_PHY_INT_MARK,
+};
+static const unsigned int avb0_mdio_pins[] = {
+ /* AVB0_MDC, AVB0_MDIO */
+ RCAR_GP_PIN(7, 13), RCAR_GP_PIN(7, 14),
+};
+static const unsigned int avb0_mdio_mux[] = {
+ AVB0_MDC_MARK, AVB0_MDIO_MARK,
+};
+static const unsigned int avb0_rgmii_pins[] = {
+ /*
+ * AVB0_TX_CTL, AVB0_TXC, AVB0_TD0, AVB0_TD1, AVB0_TD2, AVB0_TD3,
+ * AVB0_RX_CTL, AVB0_RXC, AVB0_RD0, AVB0_RD1, AVB0_RD2, AVB0_RD3,
+ */
+ RCAR_GP_PIN(7, 16), RCAR_GP_PIN(7, 15),
+ RCAR_GP_PIN(7, 11), RCAR_GP_PIN(7, 7),
+ RCAR_GP_PIN(7, 6), RCAR_GP_PIN(7, 3),
+ RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 19),
+ RCAR_GP_PIN(7, 18), RCAR_GP_PIN(7, 17),
+ RCAR_GP_PIN(7, 12), RCAR_GP_PIN(7, 8),
+};
+static const unsigned int avb0_rgmii_mux[] = {
+ AVB0_TX_CTL_MARK, AVB0_TXC_MARK,
+ AVB0_TD0_MARK, AVB0_TD1_MARK,
+ AVB0_TD2_MARK, AVB0_TD3_MARK,
+ AVB0_RX_CTL_MARK, AVB0_RXC_MARK,
+ AVB0_RD0_MARK, AVB0_RD1_MARK,
+ AVB0_RD2_MARK, AVB0_RD3_MARK,
+};
+static const unsigned int avb0_txcrefclk_pins[] = {
+ /* AVB0_TXCREFCLK */
+ RCAR_GP_PIN(7, 9),
+};
+static const unsigned int avb0_txcrefclk_mux[] = {
+ AVB0_TXCREFCLK_MARK,
+};
+static const unsigned int avb0_avtp_pps_pins[] = {
+ /* AVB0_AVTP_PPS */
+ RCAR_GP_PIN(7, 0),
+};
+static const unsigned int avb0_avtp_pps_mux[] = {
+ AVB0_AVTP_PPS_MARK,
+};
+static const unsigned int avb0_avtp_capture_pins[] = {
+ /* AVB0_AVTP_CAPTURE */
+ RCAR_GP_PIN(7, 1),
+};
+static const unsigned int avb0_avtp_capture_mux[] = {
+ AVB0_AVTP_CAPTURE_MARK,
+};
+static const unsigned int avb0_avtp_match_pins[] = {
+ /* AVB0_AVTP_MATCH */
+ RCAR_GP_PIN(7, 2),
+};
+static const unsigned int avb0_avtp_match_mux[] = {
+ AVB0_AVTP_MATCH_MARK,
+};
+
+/* - AVB1 ------------------------------------------------ */
+static const unsigned int avb1_link_pins[] = {
+ /* AVB1_LINK */
+ RCAR_GP_PIN(6, 4),
+};
+static const unsigned int avb1_link_mux[] = {
+ AVB1_LINK_MARK,
+};
+static const unsigned int avb1_magic_pins[] = {
+ /* AVB1_MAGIC */
+ RCAR_GP_PIN(6, 1),
+};
+static const unsigned int avb1_magic_mux[] = {
+ AVB1_MAGIC_MARK,
+};
+static const unsigned int avb1_phy_int_pins[] = {
+ /* AVB1_PHY_INT */
+ RCAR_GP_PIN(6, 3),
+};
+static const unsigned int avb1_phy_int_mux[] = {
+ AVB1_PHY_INT_MARK,
+};
+static const unsigned int avb1_mdio_pins[] = {
+ /* AVB1_MDC, AVB1_MDIO */
+ RCAR_GP_PIN(6, 2), RCAR_GP_PIN(6, 0),
+};
+static const unsigned int avb1_mdio_mux[] = {
+ AVB1_MDC_MARK, AVB1_MDIO_MARK,
+};
+static const unsigned int avb1_rgmii_pins[] = {
+ /*
+ * AVB1_TX_CTL, AVB1_TXC, AVB1_TD0, AVB1_TD1, AVB1_TD2, AVB1_TD3,
+ * AVB1_RX_CTL, AVB1_RXC, AVB1_RD0, AVB1_RD1, AVB1_RD2, AVB1_RD3,
+ */
+ RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
+ RCAR_GP_PIN(6, 13), RCAR_GP_PIN(6, 12),
+ RCAR_GP_PIN(6, 16), RCAR_GP_PIN(6, 18),
+ RCAR_GP_PIN(6, 9), RCAR_GP_PIN(6, 8),
+ RCAR_GP_PIN(6, 15), RCAR_GP_PIN(6, 14),
+ RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 19),
+};
+static const unsigned int avb1_rgmii_mux[] = {
+ AVB1_TX_CTL_MARK, AVB1_TXC_MARK,
+ AVB1_TD0_MARK, AVB1_TD1_MARK,
+ AVB1_TD2_MARK, AVB1_TD3_MARK,
+ AVB1_RX_CTL_MARK, AVB1_RXC_MARK,
+ AVB1_RD0_MARK, AVB1_RD1_MARK,
+ AVB1_RD2_MARK, AVB1_RD3_MARK,
+};
+static const unsigned int avb1_txcrefclk_pins[] = {
+ /* AVB1_TXCREFCLK */
+ RCAR_GP_PIN(6, 20),
+};
+static const unsigned int avb1_txcrefclk_mux[] = {
+ AVB1_TXCREFCLK_MARK,
+};
+static const unsigned int avb1_avtp_pps_pins[] = {
+ /* AVB1_AVTP_PPS */
+ RCAR_GP_PIN(6, 10),
+};
+static const unsigned int avb1_avtp_pps_mux[] = {
+ AVB1_AVTP_PPS_MARK,
+};
+static const unsigned int avb1_avtp_capture_pins[] = {
+ /* AVB1_AVTP_CAPTURE */
+ RCAR_GP_PIN(6, 11),
+};
+static const unsigned int avb1_avtp_capture_mux[] = {
+ AVB1_AVTP_CAPTURE_MARK,
+};
+static const unsigned int avb1_avtp_match_pins[] = {
+ /* AVB1_AVTP_MATCH */
+ RCAR_GP_PIN(6, 5),
+};
+static const unsigned int avb1_avtp_match_mux[] = {
+ AVB1_AVTP_MATCH_MARK,
+};
+
+/* - AVB2 ------------------------------------------------ */
+static const unsigned int avb2_link_pins[] = {
+ /* AVB2_LINK */
+ RCAR_GP_PIN(5, 3),
+};
+static const unsigned int avb2_link_mux[] = {
+ AVB2_LINK_MARK,
+};
+static const unsigned int avb2_magic_pins[] = {
+ /* AVB2_MAGIC */
+ RCAR_GP_PIN(5, 5),
+};
+static const unsigned int avb2_magic_mux[] = {
+ AVB2_MAGIC_MARK,
+};
+static const unsigned int avb2_phy_int_pins[] = {
+ /* AVB2_PHY_INT */
+ RCAR_GP_PIN(5, 4),
+};
+static const unsigned int avb2_phy_int_mux[] = {
+ AVB2_PHY_INT_MARK,
+};
+static const unsigned int avb2_mdio_pins[] = {
+ /* AVB2_MDC, AVB2_MDIO */
+ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 10),
+};
+static const unsigned int avb2_mdio_mux[] = {
+ AVB2_MDC_MARK, AVB2_MDIO_MARK,
+};
+static const unsigned int avb2_rgmii_pins[] = {
+ /*
+ * AVB2_TX_CTL, AVB2_TXC, AVB2_TD0, AVB2_TD1, AVB2_TD2, AVB2_TD3,
+ * AVB2_RX_CTL, AVB2_RXC, AVB2_RD0, AVB2_RD1, AVB2_RD2, AVB2_RD3,
+ */
+ RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 16),
+ RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 12),
+ RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 8),
+ RCAR_GP_PIN(5, 20), RCAR_GP_PIN(5, 18),
+ RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 14),
+ RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 9),
+};
+static const unsigned int avb2_rgmii_mux[] = {
+ AVB2_TX_CTL_MARK, AVB2_TXC_MARK,
+ AVB2_TD0_MARK, AVB2_TD1_MARK,
+ AVB2_TD2_MARK, AVB2_TD3_MARK,
+ AVB2_RX_CTL_MARK, AVB2_RXC_MARK,
+ AVB2_RD0_MARK, AVB2_RD1_MARK,
+ AVB2_RD2_MARK, AVB2_RD3_MARK,
+};
+static const unsigned int avb2_txcrefclk_pins[] = {
+ /* AVB2_TXCREFCLK */
+ RCAR_GP_PIN(5, 7),
+};
+static const unsigned int avb2_txcrefclk_mux[] = {
+ AVB2_TXCREFCLK_MARK,
+};
+static const unsigned int avb2_avtp_pps_pins[] = {
+ /* AVB2_AVTP_PPS */
+ RCAR_GP_PIN(5, 0),
+};
+static const unsigned int avb2_avtp_pps_mux[] = {
+ AVB2_AVTP_PPS_MARK,
+};
+static const unsigned int avb2_avtp_capture_pins[] = {
+ /* AVB2_AVTP_CAPTURE */
+ RCAR_GP_PIN(5, 1),
+};
+static const unsigned int avb2_avtp_capture_mux[] = {
+ AVB2_AVTP_CAPTURE_MARK,
+};
+static const unsigned int avb2_avtp_match_pins[] = {
+ /* AVB2_AVTP_MATCH */
+ RCAR_GP_PIN(5, 2),
+};
+static const unsigned int avb2_avtp_match_mux[] = {
+ AVB2_AVTP_MATCH_MARK,
+};
+
+/* - CANFD0 ----------------------------------------------------------------- */
+static const unsigned int canfd0_data_pins[] = {
+ /* CANFD0_TX, CANFD0_RX */
+ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
+};
+static const unsigned int canfd0_data_mux[] = {
+ CANFD0_TX_MARK, CANFD0_RX_MARK,
+};
+
+/* - CANFD1 ----------------------------------------------------------------- */
+static const unsigned int canfd1_data_pins[] = {
+ /* CANFD1_TX, CANFD1_RX */
+ RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int canfd1_data_mux[] = {
+ CANFD1_TX_MARK, CANFD1_RX_MARK,
+};
+
+/* - CANFD2 ----------------------------------------------------------------- */
+static const unsigned int canfd2_data_pins[] = {
+ /* CANFD2_TX, CANFD2_RX */
+ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13),
+};
+static const unsigned int canfd2_data_mux[] = {
+ CANFD2_TX_MARK, CANFD2_RX_MARK,
+};
+
+/* - CANFD3 ----------------------------------------------------------------- */
+static const unsigned int canfd3_data_pins[] = {
+ /* CANFD3_TX, CANFD3_RX */
+ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15),
+};
+static const unsigned int canfd3_data_mux[] = {
+ CANFD3_TX_MARK, CANFD3_RX_MARK,
+};
+
+/* - CANFD4 ----------------------------------------------------------------- */
+static const unsigned int canfd4_data_pins[] = {
+ /* CANFD4_TX, CANFD4_RX */
+ RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17),
+};
+static const unsigned int canfd4_data_mux[] = {
+ CANFD4_TX_MARK, CANFD4_RX_MARK,
+};
+
+/* - CANFD5 ----------------------------------------------------------------- */
+static const unsigned int canfd5_data_pins[] = {
+ /* CANFD5_TX, CANFD5_RX */
+ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3),
+};
+static const unsigned int canfd5_data_mux[] = {
+ CANFD5_TX_MARK, CANFD5_RX_MARK,
+};
+
+/* - CANFD5_B ----------------------------------------------------------------- */
+static const unsigned int canfd5_data_b_pins[] = {
+ /* CANFD5_TX_B, CANFD5_RX_B */
+ RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 9),
+};
+static const unsigned int canfd5_data_b_mux[] = {
+ CANFD5_TX_B_MARK, CANFD5_RX_B_MARK,
+};
+
+/* - CANFD6 ----------------------------------------------------------------- */
+static const unsigned int canfd6_data_pins[] = {
+ /* CANFD6_TX, CANFD6_RX */
+ RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+};
+static const unsigned int canfd6_data_mux[] = {
+ CANFD6_TX_MARK, CANFD6_RX_MARK,
+};
+
+/* - CANFD7 ----------------------------------------------------------------- */
+static const unsigned int canfd7_data_pins[] = {
+ /* CANFD7_TX, CANFD7_RX */
+ RCAR_GP_PIN(2, 18), RCAR_GP_PIN(2, 19),
+};
+static const unsigned int canfd7_data_mux[] = {
+ CANFD7_TX_MARK, CANFD7_RX_MARK,
+};
+
+/* - CANFD Clock ------------------------------------------------------------ */
+static const unsigned int can_clk_pins[] = {
+ /* CAN_CLK */
+ RCAR_GP_PIN(2, 9),
+};
+static const unsigned int can_clk_mux[] = {
+ CAN_CLK_MARK,
+};
+
+/* - HSCIF0 ----------------------------------------------------------------- */
+static const unsigned int hscif0_data_pins[] = {
+ /* HRX0, HTX0 */
+ RCAR_GP_PIN(1, 16), RCAR_GP_PIN(1, 12),
+};
+static const unsigned int hscif0_data_mux[] = {
+ HRX0_MARK, HTX0_MARK,
+};
+static const unsigned int hscif0_clk_pins[] = {
+ /* HSCK0 */
+ RCAR_GP_PIN(1, 15),
+};
+static const unsigned int hscif0_clk_mux[] = {
+ HSCK0_MARK,
+};
+static const unsigned int hscif0_ctrl_pins[] = {
+ /* HRTS0_N, HCTS0_N */
+ RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13),
+};
+static const unsigned int hscif0_ctrl_mux[] = {
+ HRTS0_N_MARK, HCTS0_N_MARK,
+};
+
+/* - HSCIF1 ----------------------------------------------------------------- */
+static const unsigned int hscif1_data_pins[] = {
+ /* HRX1, HTX1 */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14),
+};
+static const unsigned int hscif1_data_mux[] = {
+ HRX1_MARK, HTX1_MARK,
+};
+static const unsigned int hscif1_clk_pins[] = {
+ /* HSCK1 */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int hscif1_clk_mux[] = {
+ HSCK1_MARK,
+};
+static const unsigned int hscif1_ctrl_pins[] = {
+ /* HRTS1_N, HCTS1_N */
+ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16),
+};
+static const unsigned int hscif1_ctrl_mux[] = {
+ HRTS1_N_MARK, HCTS1_N_MARK,
+};
+
+/* - HSCIF1_X---------------------------------------------------------------- */
+static const unsigned int hscif1_data_x_pins[] = {
+ /* HRX1_X, HTX1_X */
+ RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int hscif1_data_x_mux[] = {
+ HRX1_X_MARK, HTX1_X_MARK,
+};
+static const unsigned int hscif1_clk_x_pins[] = {
+ /* HSCK1_X */
+ RCAR_GP_PIN(1, 10),
+};
+static const unsigned int hscif1_clk_x_mux[] = {
+ HSCK1_X_MARK,
+};
+static const unsigned int hscif1_ctrl_x_pins[] = {
+ /* HRTS1_N_X, HCTS1_N_X */
+ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8),
+};
+static const unsigned int hscif1_ctrl_x_mux[] = {
+ HRTS1_N_X_MARK, HCTS1_N_X_MARK,
+};
+
+/* - HSCIF2 ----------------------------------------------------------------- */
+static const unsigned int hscif2_data_pins[] = {
+ /* HRX2, HTX2 */
+ RCAR_GP_PIN(8, 8), RCAR_GP_PIN(8, 9),
+};
+static const unsigned int hscif2_data_mux[] = {
+ HRX2_MARK, HTX2_MARK,
+};
+static const unsigned int hscif2_clk_pins[] = {
+ /* HSCK2 */
+ RCAR_GP_PIN(8, 13),
+};
+static const unsigned int hscif2_clk_mux[] = {
+ HSCK2_MARK,
+};
+static const unsigned int hscif2_ctrl_pins[] = {
+ /* HRTS2_N, HCTS2_N */
+ RCAR_GP_PIN(8, 10), RCAR_GP_PIN(8, 12),
+};
+static const unsigned int hscif2_ctrl_mux[] = {
+ HRTS2_N_MARK, HCTS2_N_MARK,
+};
+
+/* - HSCIF3 ----------------------------------------------------------------- */
+static const unsigned int hscif3_data_pins[] = {
+ /* HRX3, HTX3 */
+ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 28),
+};
+static const unsigned int hscif3_data_mux[] = {
+ HRX3_MARK, HTX3_MARK,
+};
+static const unsigned int hscif3_clk_pins[] = {
+ /* HSCK3 */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int hscif3_clk_mux[] = {
+ HSCK3_MARK,
+};
+static const unsigned int hscif3_ctrl_pins[] = {
+ /* HRTS3_N, HCTS3_N */
+ RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 27),
+};
+static const unsigned int hscif3_ctrl_mux[] = {
+ HRTS3_N_MARK, HCTS3_N_MARK,
+};
+
+/* - HSCIF3_A ----------------------------------------------------------------- */
+static const unsigned int hscif3_data_a_pins[] = {
+ /* HRX3_A, HTX3_A */
+ RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 0),
+};
+static const unsigned int hscif3_data_a_mux[] = {
+ HRX3_A_MARK, HTX3_A_MARK,
+};
+static const unsigned int hscif3_clk_a_pins[] = {
+ /* HSCK3_A */
+ RCAR_GP_PIN(1, 3),
+};
+static const unsigned int hscif3_clk_a_mux[] = {
+ HSCK3_A_MARK,
+};
+static const unsigned int hscif3_ctrl_a_pins[] = {
+ /* HRTS3_N_A, HCTS3_N_A */
+ RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 1),
+};
+static const unsigned int hscif3_ctrl_a_mux[] = {
+ HRTS3_N_A_MARK, HCTS3_N_A_MARK,
+};
+
+/* - I2C0 ------------------------------------------------------------------- */
+static const unsigned int i2c0_pins[] = {
+ /* SDA0, SCL0 */
+ RCAR_GP_PIN(8, 1), RCAR_GP_PIN(8, 0),
+};
+static const unsigned int i2c0_mux[] = {
+ SDA0_MARK, SCL0_MARK,
+};
+
+/* - I2C1 ------------------------------------------------------------------- */
+static const unsigned int i2c1_pins[] = {
+ /* SDA1, SCL1 */
+ RCAR_GP_PIN(8, 3), RCAR_GP_PIN(8, 2),
+};
+static const unsigned int i2c1_mux[] = {
+ SDA1_MARK, SCL1_MARK,
+};
+
+/* - I2C2 ------------------------------------------------------------------- */
+static const unsigned int i2c2_pins[] = {
+ /* SDA2, SCL2 */
+ RCAR_GP_PIN(8, 5), RCAR_GP_PIN(8, 4),
+};
+static const unsigned int i2c2_mux[] = {
+ SDA2_MARK, SCL2_MARK,
+};
+
+/* - I2C3 ------------------------------------------------------------------- */
+static const unsigned int i2c3_pins[] = {
+ /* SDA3, SCL3 */
+ RCAR_GP_PIN(8, 7), RCAR_GP_PIN(8, 6),
+};
+static const unsigned int i2c3_mux[] = {
+ SDA3_MARK, SCL3_MARK,
+};
+
+/* - I2C4 ------------------------------------------------------------------- */
+static const unsigned int i2c4_pins[] = {
+ /* SDA4, SCL4 */
+ RCAR_GP_PIN(8, 9), RCAR_GP_PIN(8, 8),
+};
+static const unsigned int i2c4_mux[] = {
+ SDA4_MARK, SCL4_MARK,
+};
+
+/* - I2C5 ------------------------------------------------------------------- */
+static const unsigned int i2c5_pins[] = {
+ /* SDA5, SCL5 */
+ RCAR_GP_PIN(8, 11), RCAR_GP_PIN(8, 10),
+};
+static const unsigned int i2c5_mux[] = {
+ SDA5_MARK, SCL5_MARK,
+};
+
+/* - MMC -------------------------------------------------------------------- */
+static const unsigned int mmc_data_pins[] = {
+ /* MMC_SD_D[0:3], MMC_D[4:7] */
+ RCAR_GP_PIN(3, 1), RCAR_GP_PIN(3, 0),
+ RCAR_GP_PIN(3, 2), RCAR_GP_PIN(3, 5),
+ RCAR_GP_PIN(3, 7), RCAR_GP_PIN(3, 6),
+ RCAR_GP_PIN(3, 9), RCAR_GP_PIN(3, 8),
+};
+static const unsigned int mmc_data_mux[] = {
+ MMC_SD_D0_MARK, MMC_SD_D1_MARK,
+ MMC_SD_D2_MARK, MMC_SD_D3_MARK,
+ MMC_D4_MARK, MMC_D5_MARK,
+ MMC_D6_MARK, MMC_D7_MARK,
+};
+static const unsigned int mmc_ctrl_pins[] = {
+ /* MMC_SD_CLK, MMC_SD_CMD */
+ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 10),
+};
+static const unsigned int mmc_ctrl_mux[] = {
+ MMC_SD_CLK_MARK, MMC_SD_CMD_MARK,
+};
+static const unsigned int mmc_cd_pins[] = {
+ /* SD_CD */
+ RCAR_GP_PIN(3, 11),
+};
+static const unsigned int mmc_cd_mux[] = {
+ SD_CD_MARK,
+};
+static const unsigned int mmc_wp_pins[] = {
+ /* SD_WP */
+ RCAR_GP_PIN(3, 12),
+};
+static const unsigned int mmc_wp_mux[] = {
+ SD_WP_MARK,
+};
+static const unsigned int mmc_ds_pins[] = {
+ /* MMC_DS */
+ RCAR_GP_PIN(3, 4),
+};
+static const unsigned int mmc_ds_mux[] = {
+ MMC_DS_MARK,
+};
+
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_clk_pins[] = {
+ /* MSIOF0_SCK */
+ RCAR_GP_PIN(1, 10),
+};
+static const unsigned int msiof0_clk_mux[] = {
+ MSIOF0_SCK_MARK,
+};
+static const unsigned int msiof0_sync_pins[] = {
+ /* MSIOF0_SYNC */
+ RCAR_GP_PIN(1, 8),
+};
+static const unsigned int msiof0_sync_mux[] = {
+ MSIOF0_SYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+ /* MSIOF0_SS1 */
+ RCAR_GP_PIN(1, 7),
+};
+static const unsigned int msiof0_ss1_mux[] = {
+ MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+ /* MSIOF0_SS2 */
+ RCAR_GP_PIN(1, 6),
+};
+static const unsigned int msiof0_ss2_mux[] = {
+ MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_txd_pins[] = {
+ /* MSIOF0_TXD */
+ RCAR_GP_PIN(1, 9),
+};
+static const unsigned int msiof0_txd_mux[] = {
+ MSIOF0_TXD_MARK,
+};
+static const unsigned int msiof0_rxd_pins[] = {
+ /* MSIOF0_RXD */
+ RCAR_GP_PIN(1, 11),
+};
+static const unsigned int msiof0_rxd_mux[] = {
+ MSIOF0_RXD_MARK,
+};
+
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_clk_pins[] = {
+ /* MSIOF1_SCK */
+ RCAR_GP_PIN(1, 3),
+};
+static const unsigned int msiof1_clk_mux[] = {
+ MSIOF1_SCK_MARK,
+};
+static const unsigned int msiof1_sync_pins[] = {
+ /* MSIOF1_SYNC */
+ RCAR_GP_PIN(1, 2),
+};
+static const unsigned int msiof1_sync_mux[] = {
+ MSIOF1_SYNC_MARK,
+};
+static const unsigned int msiof1_ss1_pins[] = {
+ /* MSIOF1_SS1 */
+ RCAR_GP_PIN(1, 1),
+};
+static const unsigned int msiof1_ss1_mux[] = {
+ MSIOF1_SS1_MARK,
+};
+static const unsigned int msiof1_ss2_pins[] = {
+ /* MSIOF1_SS2 */
+ RCAR_GP_PIN(1, 0),
+};
+static const unsigned int msiof1_ss2_mux[] = {
+ MSIOF1_SS2_MARK,
+};
+static const unsigned int msiof1_txd_pins[] = {
+ /* MSIOF1_TXD */
+ RCAR_GP_PIN(1, 4),
+};
+static const unsigned int msiof1_txd_mux[] = {
+ MSIOF1_TXD_MARK,
+};
+static const unsigned int msiof1_rxd_pins[] = {
+ /* MSIOF1_RXD */
+ RCAR_GP_PIN(1, 5),
+};
+static const unsigned int msiof1_rxd_mux[] = {
+ MSIOF1_RXD_MARK,
+};
+
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_clk_pins[] = {
+ /* MSIOF2_SCK */
+ RCAR_GP_PIN(0, 17),
+};
+static const unsigned int msiof2_clk_mux[] = {
+ MSIOF2_SCK_MARK,
+};
+static const unsigned int msiof2_sync_pins[] = {
+ /* MSIOF2_SYNC */
+ RCAR_GP_PIN(0, 15),
+};
+static const unsigned int msiof2_sync_mux[] = {
+ MSIOF2_SYNC_MARK,
+};
+static const unsigned int msiof2_ss1_pins[] = {
+ /* MSIOF2_SS1 */
+ RCAR_GP_PIN(0, 14),
+};
+static const unsigned int msiof2_ss1_mux[] = {
+ MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss2_pins[] = {
+ /* MSIOF2_SS2 */
+ RCAR_GP_PIN(0, 13),
+};
+static const unsigned int msiof2_ss2_mux[] = {
+ MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_txd_pins[] = {
+ /* MSIOF2_TXD */
+ RCAR_GP_PIN(0, 16),
+};
+static const unsigned int msiof2_txd_mux[] = {
+ MSIOF2_TXD_MARK,
+};
+static const unsigned int msiof2_rxd_pins[] = {
+ /* MSIOF2_RXD */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int msiof2_rxd_mux[] = {
+ MSIOF2_RXD_MARK,
+};
+
+/* - MSIOF3 ----------------------------------------------------------------- */
+static const unsigned int msiof3_clk_pins[] = {
+ /* MSIOF3_SCK */
+ RCAR_GP_PIN(0, 3),
+};
+static const unsigned int msiof3_clk_mux[] = {
+ MSIOF3_SCK_MARK,
+};
+static const unsigned int msiof3_sync_pins[] = {
+ /* MSIOF3_SYNC */
+ RCAR_GP_PIN(0, 6),
+};
+static const unsigned int msiof3_sync_mux[] = {
+ MSIOF3_SYNC_MARK,
+};
+static const unsigned int msiof3_ss1_pins[] = {
+ /* MSIOF3_SS1 */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int msiof3_ss1_mux[] = {
+ MSIOF3_SS1_MARK,
+};
+static const unsigned int msiof3_ss2_pins[] = {
+ /* MSIOF3_SS2 */
+ RCAR_GP_PIN(0, 2),
+};
+static const unsigned int msiof3_ss2_mux[] = {
+ MSIOF3_SS2_MARK,
+};
+static const unsigned int msiof3_txd_pins[] = {
+ /* MSIOF3_TXD */
+ RCAR_GP_PIN(0, 4),
+};
+static const unsigned int msiof3_txd_mux[] = {
+ MSIOF3_TXD_MARK,
+};
+static const unsigned int msiof3_rxd_pins[] = {
+ /* MSIOF3_RXD */
+ RCAR_GP_PIN(0, 5),
+};
+static const unsigned int msiof3_rxd_mux[] = {
+ MSIOF3_RXD_MARK,
+};
+
+/* - MSIOF4 ----------------------------------------------------------------- */
+static const unsigned int msiof4_clk_pins[] = {
+ /* MSIOF4_SCK */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int msiof4_clk_mux[] = {
+ MSIOF4_SCK_MARK,
+};
+static const unsigned int msiof4_sync_pins[] = {
+ /* MSIOF4_SYNC */
+ RCAR_GP_PIN(1, 28),
+};
+static const unsigned int msiof4_sync_mux[] = {
+ MSIOF4_SYNC_MARK,
+};
+static const unsigned int msiof4_ss1_pins[] = {
+ /* MSIOF4_SS1 */
+ RCAR_GP_PIN(1, 23),
+};
+static const unsigned int msiof4_ss1_mux[] = {
+ MSIOF4_SS1_MARK,
+};
+static const unsigned int msiof4_ss2_pins[] = {
+ /* MSIOF4_SS2 */
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int msiof4_ss2_mux[] = {
+ MSIOF4_SS2_MARK,
+};
+static const unsigned int msiof4_txd_pins[] = {
+ /* MSIOF4_TXD */
+ RCAR_GP_PIN(1, 26),
+};
+static const unsigned int msiof4_txd_mux[] = {
+ MSIOF4_TXD_MARK,
+};
+static const unsigned int msiof4_rxd_pins[] = {
+ /* MSIOF4_RXD */
+ RCAR_GP_PIN(1, 27),
+};
+static const unsigned int msiof4_rxd_mux[] = {
+ MSIOF4_RXD_MARK,
+};
+
+/* - MSIOF5 ----------------------------------------------------------------- */
+static const unsigned int msiof5_clk_pins[] = {
+ /* MSIOF5_SCK */
+ RCAR_GP_PIN(0, 11),
+};
+static const unsigned int msiof5_clk_mux[] = {
+ MSIOF5_SCK_MARK,
+};
+static const unsigned int msiof5_sync_pins[] = {
+ /* MSIOF5_SYNC */
+ RCAR_GP_PIN(0, 9),
+};
+static const unsigned int msiof5_sync_mux[] = {
+ MSIOF5_SYNC_MARK,
+};
+static const unsigned int msiof5_ss1_pins[] = {
+ /* MSIOF5_SS1 */
+ RCAR_GP_PIN(0, 8),
+};
+static const unsigned int msiof5_ss1_mux[] = {
+ MSIOF5_SS1_MARK,
+};
+static const unsigned int msiof5_ss2_pins[] = {
+ /* MSIOF5_SS2 */
+ RCAR_GP_PIN(0, 7),
+};
+static const unsigned int msiof5_ss2_mux[] = {
+ MSIOF5_SS2_MARK,
+};
+static const unsigned int msiof5_txd_pins[] = {
+ /* MSIOF5_TXD */
+ RCAR_GP_PIN(0, 10),
+};
+static const unsigned int msiof5_txd_mux[] = {
+ MSIOF5_TXD_MARK,
+};
+static const unsigned int msiof5_rxd_pins[] = {
+ /* MSIOF5_RXD */
+ RCAR_GP_PIN(0, 12),
+};
+static const unsigned int msiof5_rxd_mux[] = {
+ MSIOF5_RXD_MARK,
+};
+
+/* - PCIE ------------------------------------------------------------------- */
+static const unsigned int pcie0_clkreq_n_pins[] = {
+ /* PCIE0_CLKREQ_N */
+ RCAR_GP_PIN(4, 21),
+};
+
+static const unsigned int pcie0_clkreq_n_mux[] = {
+ PCIE0_CLKREQ_N_MARK,
+};
+
+static const unsigned int pcie1_clkreq_n_pins[] = {
+ /* PCIE1_CLKREQ_N */
+ RCAR_GP_PIN(4, 22),
+};
+
+static const unsigned int pcie1_clkreq_n_mux[] = {
+ PCIE1_CLKREQ_N_MARK,
+};
+
+/* - PWM0_A ------------------------------------------------------------------- */
+static const unsigned int pwm0_a_pins[] = {
+ /* PWM0_A */
+ RCAR_GP_PIN(1, 15),
+};
+static const unsigned int pwm0_a_mux[] = {
+ PWM0_A_MARK,
+};
+
+/* - PWM1_A ------------------------------------------------------------------- */
+static const unsigned int pwm1_a_pins[] = {
+ /* PWM1_A */
+ RCAR_GP_PIN(3, 13),
+};
+static const unsigned int pwm1_a_mux[] = {
+ PWM1_A_MARK,
+};
+
+/* - PWM1_B ------------------------------------------------------------------- */
+static const unsigned int pwm1_b_pins[] = {
+ /* PWM1_B */
+ RCAR_GP_PIN(2, 13),
+};
+static const unsigned int pwm1_b_mux[] = {
+ PWM1_B_MARK,
+};
+
+/* - PWM2_B ------------------------------------------------------------------- */
+static const unsigned int pwm2_b_pins[] = {
+ /* PWM2_B */
+ RCAR_GP_PIN(2, 14),
+};
+static const unsigned int pwm2_b_mux[] = {
+ PWM2_B_MARK,
+};
+
+/* - PWM3_A ------------------------------------------------------------------- */
+static const unsigned int pwm3_a_pins[] = {
+ /* PWM3_A */
+ RCAR_GP_PIN(1, 22),
+};
+static const unsigned int pwm3_a_mux[] = {
+ PWM3_A_MARK,
+};
+
+/* - PWM3_B ------------------------------------------------------------------- */
+static const unsigned int pwm3_b_pins[] = {
+ /* PWM3_B */
+ RCAR_GP_PIN(2, 15),
+};
+static const unsigned int pwm3_b_mux[] = {
+ PWM3_B_MARK,
+};
+
+/* - PWM4 ------------------------------------------------------------------- */
+static const unsigned int pwm4_pins[] = {
+ /* PWM4 */
+ RCAR_GP_PIN(2, 16),
+};
+static const unsigned int pwm4_mux[] = {
+ PWM4_MARK,
+};
+
+/* - PWM5 ------------------------------------------------------------------- */
+static const unsigned int pwm5_pins[] = {
+ /* PWM5 */
+ RCAR_GP_PIN(2, 17),
+};
+static const unsigned int pwm5_mux[] = {
+ PWM5_MARK,
+};
+
+/* - PWM6 ------------------------------------------------------------------- */
+static const unsigned int pwm6_pins[] = {
+ /* PWM6 */
+ RCAR_GP_PIN(2, 18),
+};
+static const unsigned int pwm6_mux[] = {
+ PWM6_MARK,
+};
+
+/* - PWM7 ------------------------------------------------------------------- */
+static const unsigned int pwm7_pins[] = {
+ /* PWM7 */
+ RCAR_GP_PIN(2, 19),
+};
+static const unsigned int pwm7_mux[] = {
+ PWM7_MARK,
+};
+
+/* - PWM8_A ------------------------------------------------------------------- */
+static const unsigned int pwm8_a_pins[] = {
+ /* PWM8_A */
+ RCAR_GP_PIN(1, 13),
+};
+static const unsigned int pwm8_a_mux[] = {
+ PWM8_A_MARK,
+};
+
+/* - PWM9_A ------------------------------------------------------------------- */
+static const unsigned int pwm9_a_pins[] = {
+ /* PWM9_A */
+ RCAR_GP_PIN(1, 14),
+};
+static const unsigned int pwm9_a_mux[] = {
+ PWM9_A_MARK,
+};
+
+/* - QSPI0 ------------------------------------------------------------------ */
+static const unsigned int qspi0_ctrl_pins[] = {
+ /* SPCLK, SSL */
+ RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 15),
+};
+static const unsigned int qspi0_ctrl_mux[] = {
+ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK,
+};
+static const unsigned int qspi0_data_pins[] = {
+ /* MOSI_IO0, MISO_IO1, IO2, IO3 */
+ RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 18),
+ RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 16),
+};
+static const unsigned int qspi0_data_mux[] = {
+ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+ QSPI0_IO2_MARK, QSPI0_IO3_MARK
+};
+
+/* - QSPI1 ------------------------------------------------------------------ */
+static const unsigned int qspi1_ctrl_pins[] = {
+ /* SPCLK, SSL */
+ RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 25),
+};
+static const unsigned int qspi1_ctrl_mux[] = {
+ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK,
+};
+static const unsigned int qspi1_data_pins[] = {
+ /* MOSI_IO0, MISO_IO1, IO2, IO3 */
+ RCAR_GP_PIN(3, 21), RCAR_GP_PIN(3, 23),
+ RCAR_GP_PIN(3, 24), RCAR_GP_PIN(3, 26),
+};
+static const unsigned int qspi1_data_mux[] = {
+ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+ QSPI1_IO2_MARK, QSPI1_IO3_MARK
+};
+
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+ /* RX0, TX0 */
+ RCAR_GP_PIN(1, 16), RCAR_GP_PIN(1, 12),
+};
+static const unsigned int scif0_data_mux[] = {
+ RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_clk_pins[] = {
+ /* SCK0 */
+ RCAR_GP_PIN(1, 15),
+};
+static const unsigned int scif0_clk_mux[] = {
+ SCK0_MARK,
+};
+static const unsigned int scif0_ctrl_pins[] = {
+ /* RTS0_N, CTS0_N */
+ RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13),
+};
+static const unsigned int scif0_ctrl_mux[] = {
+ RTS0_N_MARK, CTS0_N_MARK,
+};
+
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_pins[] = {
+ /* RX1, TX1 */
+ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14),
+};
+static const unsigned int scif1_data_mux[] = {
+ RX1_MARK, TX1_MARK,
+};
+static const unsigned int scif1_clk_pins[] = {
+ /* SCK1 */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int scif1_clk_mux[] = {
+ SCK1_MARK,
+};
+static const unsigned int scif1_ctrl_pins[] = {
+ /* RTS1_N, CTS1_N */
+ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16),
+};
+static const unsigned int scif1_ctrl_mux[] = {
+ RTS1_N_MARK, CTS1_N_MARK,
+};
+
+/* - SCIF1_X ------------------------------------------------------------------ */
+static const unsigned int scif1_data_x_pins[] = {
+ /* RX1_X, TX1_X */
+ RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int scif1_data_x_mux[] = {
+ RX1_X_MARK, TX1_X_MARK,
+};
+static const unsigned int scif1_clk_x_pins[] = {
+ /* SCK1_X */
+ RCAR_GP_PIN(1, 10),
+};
+static const unsigned int scif1_clk_x_mux[] = {
+ SCK1_X_MARK,
+};
+static const unsigned int scif1_ctrl_x_pins[] = {
+ /* RTS1_N_X, CTS1_N_X */
+ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8),
+};
+static const unsigned int scif1_ctrl_x_mux[] = {
+ RTS1_N_X_MARK, CTS1_N_X_MARK,
+};
+
+/* - SCIF3 ------------------------------------------------------------------ */
+static const unsigned int scif3_data_pins[] = {
+ /* RX3, TX3 */
+ RCAR_GP_PIN(1, 1), RCAR_GP_PIN(1, 0),
+};
+static const unsigned int scif3_data_mux[] = {
+ RX3_MARK, TX3_MARK,
+};
+static const unsigned int scif3_clk_pins[] = {
+ /* SCK3 */
+ RCAR_GP_PIN(1, 4),
+};
+static const unsigned int scif3_clk_mux[] = {
+ SCK3_MARK,
+};
+static const unsigned int scif3_ctrl_pins[] = {
+ /* RTS3_N, CTS3_N */
+ RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 3),
+};
+static const unsigned int scif3_ctrl_mux[] = {
+ RTS3_N_MARK, CTS3_N_MARK,
+};
+
+/* - SCIF3_A ------------------------------------------------------------------ */
+static const unsigned int scif3_data_a_pins[] = {
+ /* RX3_A, TX3_A */
+ RCAR_GP_PIN(1, 27), RCAR_GP_PIN(1, 28),
+};
+static const unsigned int scif3_data_a_mux[] = {
+ RX3_A_MARK, TX3_A_MARK,
+};
+static const unsigned int scif3_clk_a_pins[] = {
+ /* SCK3_A */
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int scif3_clk_a_mux[] = {
+ SCK3_A_MARK,
+};
+static const unsigned int scif3_ctrl_a_pins[] = {
+ /* RTS3_N_A, CTS3_N_A */
+ RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25),
+};
+static const unsigned int scif3_ctrl_a_mux[] = {
+ RTS3_N_A_MARK, CTS3_N_A_MARK,
+};
+
+/* - SCIF4 ------------------------------------------------------------------ */
+static const unsigned int scif4_data_pins[] = {
+ /* RX4, TX4 */
+ RCAR_GP_PIN(8, 13), RCAR_GP_PIN(8, 12),
+};
+static const unsigned int scif4_data_mux[] = {
+ RX4_MARK, TX4_MARK,
+};
+static const unsigned int scif4_clk_pins[] = {
+ /* SCK4 */
+ RCAR_GP_PIN(8, 8),
+};
+static const unsigned int scif4_clk_mux[] = {
+ SCK4_MARK,
+};
+static const unsigned int scif4_ctrl_pins[] = {
+ /* RTS4_N, CTS4_N */
+ RCAR_GP_PIN(8, 10), RCAR_GP_PIN(8, 9),
+};
+static const unsigned int scif4_ctrl_mux[] = {
+ RTS4_N_MARK, CTS4_N_MARK,
+};
+
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(1, 17),
+};
+static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+};
+
+/* - TPU ------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ /* TPU0TO0 */
+ RCAR_GP_PIN(2, 8),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPU0TO0_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ /* TPU0TO1 */
+ RCAR_GP_PIN(2, 7),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPU0TO1_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ /* TPU0TO2 */
+ RCAR_GP_PIN(2, 12),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPU0TO2_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ /* TPU0TO3 */
+ RCAR_GP_PIN(2, 13),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPU0TO3_MARK,
+};
+
+/* - TPU_A ------------------------------------------------------------------- */
+static const unsigned int tpu_to0_a_pins[] = {
+ /* TPU0TO0_A */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int tpu_to0_a_mux[] = {
+ TPU0TO0_A_MARK,
+};
+static const unsigned int tpu_to1_a_pins[] = {
+ /* TPU0TO1_A */
+ RCAR_GP_PIN(1, 26),
+};
+static const unsigned int tpu_to1_a_mux[] = {
+ TPU0TO1_A_MARK,
+};
+static const unsigned int tpu_to2_a_pins[] = {
+ /* TPU0TO2_A */
+ RCAR_GP_PIN(2, 0),
+};
+static const unsigned int tpu_to2_a_mux[] = {
+ TPU0TO2_A_MARK,
+};
+static const unsigned int tpu_to3_a_pins[] = {
+ /* TPU0TO3_A */
+ RCAR_GP_PIN(2, 1),
+};
+static const unsigned int tpu_to3_a_mux[] = {
+ TPU0TO3_A_MARK,
+};
+
+/* - TSN0 ------------------------------------------------ */
+static const unsigned int tsn0_link_pins[] = {
+ /* TSN0_LINK */
+ RCAR_GP_PIN(4, 4),
+};
+static const unsigned int tsn0_link_mux[] = {
+ TSN0_LINK_MARK,
+};
+static const unsigned int tsn0_phy_int_pins[] = {
+ /* TSN0_PHY_INT */
+ RCAR_GP_PIN(4, 3),
+};
+static const unsigned int tsn0_phy_int_mux[] = {
+ TSN0_PHY_INT_MARK,
+};
+static const unsigned int tsn0_mdio_pins[] = {
+ /* TSN0_MDC, TSN0_MDIO */
+ RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0),
+};
+static const unsigned int tsn0_mdio_mux[] = {
+ TSN0_MDC_MARK, TSN0_MDIO_MARK,
+};
+static const unsigned int tsn0_rgmii_pins[] = {
+ /*
+ * TSN0_TX_CTL, TSN0_TXC, TSN0_TD0, TSN0_TD1, TSN0_TD2, TSN0_TD3,
+ * TSN0_RX_CTL, TSN0_RXC, TSN0_RD0, TSN0_RD1, TSN0_RD2, TSN0_RD3,
+ */
+ RCAR_GP_PIN(4, 9), RCAR_GP_PIN(4, 12),
+ RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 14),
+ RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 18),
+ RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 11),
+ RCAR_GP_PIN(4, 10), RCAR_GP_PIN(4, 13),
+ RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 16),
+};
+static const unsigned int tsn0_rgmii_mux[] = {
+ TSN0_TX_CTL_MARK, TSN0_TXC_MARK,
+ TSN0_TD0_MARK, TSN0_TD1_MARK,
+ TSN0_TD2_MARK, TSN0_TD3_MARK,
+ TSN0_RX_CTL_MARK, TSN0_RXC_MARK,
+ TSN0_RD0_MARK, TSN0_RD1_MARK,
+ TSN0_RD2_MARK, TSN0_RD3_MARK,
+};
+static const unsigned int tsn0_txcrefclk_pins[] = {
+ /* TSN0_TXCREFCLK */
+ RCAR_GP_PIN(4, 20),
+};
+static const unsigned int tsn0_txcrefclk_mux[] = {
+ TSN0_TXCREFCLK_MARK,
+};
+static const unsigned int tsn0_avtp_pps_pins[] = {
+ /* TSN0_AVTP_PPS0, TSN0_AVTP_PPS1 */
+ RCAR_GP_PIN(4, 8), RCAR_GP_PIN(4, 2),
+};
+static const unsigned int tsn0_avtp_pps_mux[] = {
+ TSN0_AVTP_PPS0_MARK, TSN0_AVTP_PPS1_MARK,
+};
+static const unsigned int tsn0_avtp_capture_pins[] = {
+ /* TSN0_AVTP_CAPTURE */
+ RCAR_GP_PIN(4, 6),
+};
+static const unsigned int tsn0_avtp_capture_mux[] = {
+ TSN0_AVTP_CAPTURE_MARK,
+};
+static const unsigned int tsn0_avtp_match_pins[] = {
+ /* TSN0_AVTP_MATCH */
+ RCAR_GP_PIN(4, 5),
+};
+static const unsigned int tsn0_avtp_match_mux[] = {
+ TSN0_AVTP_MATCH_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(avb0_link),
+ SH_PFC_PIN_GROUP(avb0_magic),
+ SH_PFC_PIN_GROUP(avb0_phy_int),
+ SH_PFC_PIN_GROUP(avb0_mdio),
+ SH_PFC_PIN_GROUP(avb0_rgmii),
+ SH_PFC_PIN_GROUP(avb0_txcrefclk),
+ SH_PFC_PIN_GROUP(avb0_avtp_pps),
+ SH_PFC_PIN_GROUP(avb0_avtp_capture),
+ SH_PFC_PIN_GROUP(avb0_avtp_match),
+
+ SH_PFC_PIN_GROUP(avb1_link),
+ SH_PFC_PIN_GROUP(avb1_magic),
+ SH_PFC_PIN_GROUP(avb1_phy_int),
+ SH_PFC_PIN_GROUP(avb1_mdio),
+ SH_PFC_PIN_GROUP(avb1_rgmii),
+ SH_PFC_PIN_GROUP(avb1_txcrefclk),
+ SH_PFC_PIN_GROUP(avb1_avtp_pps),
+ SH_PFC_PIN_GROUP(avb1_avtp_capture),
+ SH_PFC_PIN_GROUP(avb1_avtp_match),
+
+ SH_PFC_PIN_GROUP(avb2_link),
+ SH_PFC_PIN_GROUP(avb2_magic),
+ SH_PFC_PIN_GROUP(avb2_phy_int),
+ SH_PFC_PIN_GROUP(avb2_mdio),
+ SH_PFC_PIN_GROUP(avb2_rgmii),
+ SH_PFC_PIN_GROUP(avb2_txcrefclk),
+ SH_PFC_PIN_GROUP(avb2_avtp_pps),
+ SH_PFC_PIN_GROUP(avb2_avtp_capture),
+ SH_PFC_PIN_GROUP(avb2_avtp_match),
+
+ SH_PFC_PIN_GROUP(canfd0_data),
+ SH_PFC_PIN_GROUP(canfd1_data),
+ SH_PFC_PIN_GROUP(canfd2_data),
+ SH_PFC_PIN_GROUP(canfd3_data),
+ SH_PFC_PIN_GROUP(canfd4_data),
+ SH_PFC_PIN_GROUP(canfd5_data), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(canfd5_data_b), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(canfd6_data),
+ SH_PFC_PIN_GROUP(canfd7_data),
+ SH_PFC_PIN_GROUP(can_clk),
+
+ SH_PFC_PIN_GROUP(hscif0_data),
+ SH_PFC_PIN_GROUP(hscif0_clk),
+ SH_PFC_PIN_GROUP(hscif0_ctrl),
+ SH_PFC_PIN_GROUP(hscif1_data), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif1_clk), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif1_ctrl), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif1_data_x), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif1_clk_x), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif1_ctrl_x), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif2_data),
+ SH_PFC_PIN_GROUP(hscif2_clk),
+ SH_PFC_PIN_GROUP(hscif2_ctrl),
+ SH_PFC_PIN_GROUP(hscif3_data), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif3_clk), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif3_ctrl), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif3_data_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif3_clk_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(hscif3_ctrl_a), /* suffix might be updated */
+
+ SH_PFC_PIN_GROUP(i2c0),
+ SH_PFC_PIN_GROUP(i2c1),
+ SH_PFC_PIN_GROUP(i2c2),
+ SH_PFC_PIN_GROUP(i2c3),
+ SH_PFC_PIN_GROUP(i2c4),
+ SH_PFC_PIN_GROUP(i2c5),
+
+ BUS_DATA_PIN_GROUP(mmc_data, 1),
+ BUS_DATA_PIN_GROUP(mmc_data, 4),
+ BUS_DATA_PIN_GROUP(mmc_data, 8),
+ SH_PFC_PIN_GROUP(mmc_ctrl),
+ SH_PFC_PIN_GROUP(mmc_cd),
+ SH_PFC_PIN_GROUP(mmc_wp),
+ SH_PFC_PIN_GROUP(mmc_ds),
+
+ SH_PFC_PIN_GROUP(msiof0_clk),
+ SH_PFC_PIN_GROUP(msiof0_sync),
+ SH_PFC_PIN_GROUP(msiof0_ss1),
+ SH_PFC_PIN_GROUP(msiof0_ss2),
+ SH_PFC_PIN_GROUP(msiof0_txd),
+ SH_PFC_PIN_GROUP(msiof0_rxd),
+
+ SH_PFC_PIN_GROUP(msiof1_clk),
+ SH_PFC_PIN_GROUP(msiof1_sync),
+ SH_PFC_PIN_GROUP(msiof1_ss1),
+ SH_PFC_PIN_GROUP(msiof1_ss2),
+ SH_PFC_PIN_GROUP(msiof1_txd),
+ SH_PFC_PIN_GROUP(msiof1_rxd),
+
+ SH_PFC_PIN_GROUP(msiof2_clk),
+ SH_PFC_PIN_GROUP(msiof2_sync),
+ SH_PFC_PIN_GROUP(msiof2_ss1),
+ SH_PFC_PIN_GROUP(msiof2_ss2),
+ SH_PFC_PIN_GROUP(msiof2_txd),
+ SH_PFC_PIN_GROUP(msiof2_rxd),
+
+ SH_PFC_PIN_GROUP(msiof3_clk),
+ SH_PFC_PIN_GROUP(msiof3_sync),
+ SH_PFC_PIN_GROUP(msiof3_ss1),
+ SH_PFC_PIN_GROUP(msiof3_ss2),
+ SH_PFC_PIN_GROUP(msiof3_txd),
+ SH_PFC_PIN_GROUP(msiof3_rxd),
+
+ SH_PFC_PIN_GROUP(msiof4_clk),
+ SH_PFC_PIN_GROUP(msiof4_sync),
+ SH_PFC_PIN_GROUP(msiof4_ss1),
+ SH_PFC_PIN_GROUP(msiof4_ss2),
+ SH_PFC_PIN_GROUP(msiof4_txd),
+ SH_PFC_PIN_GROUP(msiof4_rxd),
+
+ SH_PFC_PIN_GROUP(msiof5_clk),
+ SH_PFC_PIN_GROUP(msiof5_sync),
+ SH_PFC_PIN_GROUP(msiof5_ss1),
+ SH_PFC_PIN_GROUP(msiof5_ss2),
+ SH_PFC_PIN_GROUP(msiof5_txd),
+ SH_PFC_PIN_GROUP(msiof5_rxd),
+
+ SH_PFC_PIN_GROUP(pcie0_clkreq_n),
+ SH_PFC_PIN_GROUP(pcie1_clkreq_n),
+
+ SH_PFC_PIN_GROUP(pwm0_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(pwm1_a),
+ SH_PFC_PIN_GROUP(pwm1_b),
+ SH_PFC_PIN_GROUP(pwm2_b), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(pwm3_a),
+ SH_PFC_PIN_GROUP(pwm3_b),
+ SH_PFC_PIN_GROUP(pwm4),
+ SH_PFC_PIN_GROUP(pwm5),
+ SH_PFC_PIN_GROUP(pwm6),
+ SH_PFC_PIN_GROUP(pwm7),
+ SH_PFC_PIN_GROUP(pwm8_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(pwm9_a), /* suffix might be updated */
+
+ SH_PFC_PIN_GROUP(qspi0_ctrl),
+ BUS_DATA_PIN_GROUP(qspi0_data, 2),
+ BUS_DATA_PIN_GROUP(qspi0_data, 4),
+ SH_PFC_PIN_GROUP(qspi1_ctrl),
+ BUS_DATA_PIN_GROUP(qspi1_data, 2),
+ BUS_DATA_PIN_GROUP(qspi1_data, 4),
+
+ SH_PFC_PIN_GROUP(scif0_data),
+ SH_PFC_PIN_GROUP(scif0_clk),
+ SH_PFC_PIN_GROUP(scif0_ctrl),
+ SH_PFC_PIN_GROUP(scif1_data), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif1_clk), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif1_ctrl), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif1_data_x), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif1_clk_x), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif1_ctrl_x), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif3_data), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif3_clk), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif3_ctrl), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif3_data_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif3_clk_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif3_ctrl_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(scif4_data),
+ SH_PFC_PIN_GROUP(scif4_clk),
+ SH_PFC_PIN_GROUP(scif4_ctrl),
+ SH_PFC_PIN_GROUP(scif_clk),
+
+ SH_PFC_PIN_GROUP(tpu_to0), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to0_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to1), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to1_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to2), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to2_a), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to3), /* suffix might be updated */
+ SH_PFC_PIN_GROUP(tpu_to3_a), /* suffix might be updated */
+
+ SH_PFC_PIN_GROUP(tsn0_link),
+ SH_PFC_PIN_GROUP(tsn0_phy_int),
+ SH_PFC_PIN_GROUP(tsn0_mdio),
+ SH_PFC_PIN_GROUP(tsn0_rgmii),
+ SH_PFC_PIN_GROUP(tsn0_txcrefclk),
+ SH_PFC_PIN_GROUP(tsn0_avtp_pps),
+ SH_PFC_PIN_GROUP(tsn0_avtp_capture),
+ SH_PFC_PIN_GROUP(tsn0_avtp_match),
+};
+
+static const char * const avb0_groups[] = {
+ "avb0_link",
+ "avb0_magic",
+ "avb0_phy_int",
+ "avb0_mdio",
+ "avb0_rgmii",
+ "avb0_txcrefclk",
+ "avb0_avtp_pps",
+ "avb0_avtp_capture",
+ "avb0_avtp_match",
+};
+
+static const char * const avb1_groups[] = {
+ "avb1_link",
+ "avb1_magic",
+ "avb1_phy_int",
+ "avb1_mdio",
+ "avb1_rgmii",
+ "avb1_txcrefclk",
+ "avb1_avtp_pps",
+ "avb1_avtp_capture",
+ "avb1_avtp_match",
+};
+
+static const char * const avb2_groups[] = {
+ "avb2_link",
+ "avb2_magic",
+ "avb2_phy_int",
+ "avb2_mdio",
+ "avb2_rgmii",
+ "avb2_txcrefclk",
+ "avb2_avtp_pps",
+ "avb2_avtp_capture",
+ "avb2_avtp_match",
+};
+
+static const char * const canfd0_groups[] = {
+ "canfd0_data",
+};
+
+static const char * const canfd1_groups[] = {
+ "canfd1_data",
+};
+
+static const char * const canfd2_groups[] = {
+ "canfd2_data",
+};
+
+static const char * const canfd3_groups[] = {
+ "canfd3_data",
+};
+
+static const char * const canfd4_groups[] = {
+ "canfd4_data",
+};
+
+static const char * const canfd5_groups[] = {
+ /* suffix might be updated */
+ "canfd5_data",
+ "canfd5_data_b",
+};
+
+static const char * const canfd6_groups[] = {
+ "canfd6_data",
+};
+
+static const char * const canfd7_groups[] = {
+ "canfd7_data",
+};
+
+static const char * const can_clk_groups[] = {
+ "can_clk",
+};
+
+static const char * const hscif0_groups[] = {
+ "hscif0_data",
+ "hscif0_clk",
+ "hscif0_ctrl",
+};
+
+static const char * const hscif1_groups[] = {
+ /* suffix might be updated */
+ "hscif1_data",
+ "hscif1_clk",
+ "hscif1_ctrl",
+ "hscif1_data_x",
+ "hscif1_clk_x",
+ "hscif1_ctrl_x",
+};
+
+static const char * const hscif2_groups[] = {
+ "hscif2_data",
+ "hscif2_clk",
+ "hscif2_ctrl",
+};
+
+static const char * const hscif3_groups[] = {
+ /* suffix might be updated */
+ "hscif3_data",
+ "hscif3_clk",
+ "hscif3_ctrl",
+ "hscif3_data_a",
+ "hscif3_clk_a",
+ "hscif3_ctrl_a",
+};
+
+static const char * const i2c0_groups[] = {
+ "i2c0",
+};
+
+static const char * const i2c1_groups[] = {
+ "i2c1",
+};
+
+static const char * const i2c2_groups[] = {
+ "i2c2",
+};
+
+static const char * const i2c3_groups[] = {
+ "i2c3",
+};
+
+static const char * const i2c4_groups[] = {
+ "i2c4",
+};
+
+static const char * const i2c5_groups[] = {
+ "i2c5",
+};
+
+static const char * const mmc_groups[] = {
+ "mmc_data1",
+ "mmc_data4",
+ "mmc_data8",
+ "mmc_ctrl",
+ "mmc_cd",
+ "mmc_wp",
+ "mmc_ds",
+};
+
+static const char * const msiof0_groups[] = {
+ "msiof0_clk",
+ "msiof0_sync",
+ "msiof0_ss1",
+ "msiof0_ss2",
+ "msiof0_txd",
+ "msiof0_rxd",
+};
+
+static const char * const msiof1_groups[] = {
+ "msiof1_clk",
+ "msiof1_sync",
+ "msiof1_ss1",
+ "msiof1_ss2",
+ "msiof1_txd",
+ "msiof1_rxd",
+};
+
+static const char * const msiof2_groups[] = {
+ "msiof2_clk",
+ "msiof2_sync",
+ "msiof2_ss1",
+ "msiof2_ss2",
+ "msiof2_txd",
+ "msiof2_rxd",
+};
+
+static const char * const msiof3_groups[] = {
+ "msiof3_clk",
+ "msiof3_sync",
+ "msiof3_ss1",
+ "msiof3_ss2",
+ "msiof3_txd",
+ "msiof3_rxd",
+};
+
+static const char * const msiof4_groups[] = {
+ "msiof4_clk",
+ "msiof4_sync",
+ "msiof4_ss1",
+ "msiof4_ss2",
+ "msiof4_txd",
+ "msiof4_rxd",
+};
+
+static const char * const msiof5_groups[] = {
+ "msiof5_clk",
+ "msiof5_sync",
+ "msiof5_ss1",
+ "msiof5_ss2",
+ "msiof5_txd",
+ "msiof5_rxd",
+};
+
+static const char * const pcie_groups[] = {
+ "pcie0_clkreq_n",
+ "pcie1_clkreq_n",
+};
+
+static const char * const pwm0_groups[] = {
+ /* suffix might be updated */
+ "pwm0_a",
+};
+
+static const char * const pwm1_groups[] = {
+ "pwm1_a",
+ "pwm1_b",
+};
+
+static const char * const pwm2_groups[] = {
+ /* suffix might be updated */
+ "pwm2_b",
+};
+
+static const char * const pwm3_groups[] = {
+ "pwm3_a",
+ "pwm3_b",
+};
+
+static const char * const pwm4_groups[] = {
+ "pwm4",
+};
+
+static const char * const pwm5_groups[] = {
+ "pwm5",
+};
+
+static const char * const pwm6_groups[] = {
+ "pwm6",
+};
+
+static const char * const pwm7_groups[] = {
+ "pwm7",
+};
+
+static const char * const pwm8_groups[] = {
+ /* suffix might be updated */
+ "pwm8_a",
+};
+
+static const char * const pwm9_groups[] = {
+ /* suffix might be updated */
+ "pwm9_a",
+};
+
+static const char * const qspi0_groups[] = {
+ "qspi0_ctrl",
+ "qspi0_data2",
+ "qspi0_data4",
+};
+
+static const char * const qspi1_groups[] = {
+ "qspi1_ctrl",
+ "qspi1_data2",
+ "qspi1_data4",
+};
+
+static const char * const scif0_groups[] = {
+ "scif0_data",
+ "scif0_clk",
+ "scif0_ctrl",
+};
+
+static const char * const scif1_groups[] = {
+ /* suffix might be updated */
+ "scif1_data",
+ "scif1_clk",
+ "scif1_ctrl",
+ "scif1_data_x",
+ "scif1_clk_x",
+ "scif1_ctrl_x",
+};
+
+static const char * const scif3_groups[] = {
+ /* suffix might be updated */
+ "scif3_data",
+ "scif3_clk",
+ "scif3_ctrl",
+ "scif3_data_a",
+ "scif3_clk_a",
+ "scif3_ctrl_a",
+};
+
+static const char * const scif4_groups[] = {
+ "scif4_data",
+ "scif4_clk",
+ "scif4_ctrl",
+};
+
+static const char * const scif_clk_groups[] = {
+ "scif_clk",
+};
+
+static const char * const tpu_groups[] = {
+ /* suffix might be updated */
+ "tpu_to0",
+ "tpu_to0_a",
+ "tpu_to1",
+ "tpu_to1_a",
+ "tpu_to2",
+ "tpu_to2_a",
+ "tpu_to3",
+ "tpu_to3_a",
+};
+
+static const char * const tsn0_groups[] = {
+ "tsn0_link",
+ "tsn0_phy_int",
+ "tsn0_mdio",
+ "tsn0_rgmii",
+ "tsn0_txcrefclk",
+ "tsn0_avtp_pps",
+ "tsn0_avtp_capture",
+ "tsn0_avtp_match",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(avb0),
+ SH_PFC_FUNCTION(avb1),
+ SH_PFC_FUNCTION(avb2),
+
+ SH_PFC_FUNCTION(canfd0),
+ SH_PFC_FUNCTION(canfd1),
+ SH_PFC_FUNCTION(canfd2),
+ SH_PFC_FUNCTION(canfd3),
+ SH_PFC_FUNCTION(canfd4),
+ SH_PFC_FUNCTION(canfd5),
+ SH_PFC_FUNCTION(canfd6),
+ SH_PFC_FUNCTION(canfd7),
+ SH_PFC_FUNCTION(can_clk),
+
+ SH_PFC_FUNCTION(hscif0),
+ SH_PFC_FUNCTION(hscif1),
+ SH_PFC_FUNCTION(hscif2),
+ SH_PFC_FUNCTION(hscif3),
+
+ SH_PFC_FUNCTION(i2c0),
+ SH_PFC_FUNCTION(i2c1),
+ SH_PFC_FUNCTION(i2c2),
+ SH_PFC_FUNCTION(i2c3),
+ SH_PFC_FUNCTION(i2c4),
+ SH_PFC_FUNCTION(i2c5),
+
+ SH_PFC_FUNCTION(mmc),
+
+ SH_PFC_FUNCTION(msiof0),
+ SH_PFC_FUNCTION(msiof1),
+ SH_PFC_FUNCTION(msiof2),
+ SH_PFC_FUNCTION(msiof3),
+ SH_PFC_FUNCTION(msiof4),
+ SH_PFC_FUNCTION(msiof5),
+
+ SH_PFC_FUNCTION(pcie),
+
+ SH_PFC_FUNCTION(pwm0),
+ SH_PFC_FUNCTION(pwm1),
+ SH_PFC_FUNCTION(pwm2),
+ SH_PFC_FUNCTION(pwm3),
+ SH_PFC_FUNCTION(pwm4),
+ SH_PFC_FUNCTION(pwm5),
+ SH_PFC_FUNCTION(pwm6),
+ SH_PFC_FUNCTION(pwm7),
+ SH_PFC_FUNCTION(pwm8),
+ SH_PFC_FUNCTION(pwm9),
+
+ SH_PFC_FUNCTION(qspi0),
+ SH_PFC_FUNCTION(qspi1),
+
+ SH_PFC_FUNCTION(scif0),
+ SH_PFC_FUNCTION(scif1),
+ SH_PFC_FUNCTION(scif3),
+ SH_PFC_FUNCTION(scif4),
+ SH_PFC_FUNCTION(scif_clk),
+
+ SH_PFC_FUNCTION(tpu),
+
+ SH_PFC_FUNCTION(tsn0),
+};
+
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
+#define F_(x, y) FN_##y
+#define FM(x) FN_##x
+ { PINMUX_CFG_REG_VAR("GPSR0", 0xE6050040, 32,
+ GROUP(-13, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP0_31_19 RESERVED */
+ GP_0_18_FN, GPSR0_18,
+ GP_0_17_FN, GPSR0_17,
+ GP_0_16_FN, GPSR0_16,
+ GP_0_15_FN, GPSR0_15,
+ GP_0_14_FN, GPSR0_14,
+ GP_0_13_FN, GPSR0_13,
+ GP_0_12_FN, GPSR0_12,
+ GP_0_11_FN, GPSR0_11,
+ GP_0_10_FN, GPSR0_10,
+ GP_0_9_FN, GPSR0_9,
+ GP_0_8_FN, GPSR0_8,
+ GP_0_7_FN, GPSR0_7,
+ GP_0_6_FN, GPSR0_6,
+ GP_0_5_FN, GPSR0_5,
+ GP_0_4_FN, GPSR0_4,
+ GP_0_3_FN, GPSR0_3,
+ GP_0_2_FN, GPSR0_2,
+ GP_0_1_FN, GPSR0_1,
+ GP_0_0_FN, GPSR0_0, ))
+ },
+ { PINMUX_CFG_REG("GPSR1", 0xE6050840, 32, 1, GROUP(
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_1_28_FN, GPSR1_28,
+ GP_1_27_FN, GPSR1_27,
+ GP_1_26_FN, GPSR1_26,
+ GP_1_25_FN, GPSR1_25,
+ GP_1_24_FN, GPSR1_24,
+ GP_1_23_FN, GPSR1_23,
+ GP_1_22_FN, GPSR1_22,
+ GP_1_21_FN, GPSR1_21,
+ GP_1_20_FN, GPSR1_20,
+ GP_1_19_FN, GPSR1_19,
+ GP_1_18_FN, GPSR1_18,
+ GP_1_17_FN, GPSR1_17,
+ GP_1_16_FN, GPSR1_16,
+ GP_1_15_FN, GPSR1_15,
+ GP_1_14_FN, GPSR1_14,
+ GP_1_13_FN, GPSR1_13,
+ GP_1_12_FN, GPSR1_12,
+ GP_1_11_FN, GPSR1_11,
+ GP_1_10_FN, GPSR1_10,
+ GP_1_9_FN, GPSR1_9,
+ GP_1_8_FN, GPSR1_8,
+ GP_1_7_FN, GPSR1_7,
+ GP_1_6_FN, GPSR1_6,
+ GP_1_5_FN, GPSR1_5,
+ GP_1_4_FN, GPSR1_4,
+ GP_1_3_FN, GPSR1_3,
+ GP_1_2_FN, GPSR1_2,
+ GP_1_1_FN, GPSR1_1,
+ GP_1_0_FN, GPSR1_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR2", 0xE6058040, 32,
+ GROUP(-12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP2_31_20 RESERVED */
+ GP_2_19_FN, GPSR2_19,
+ GP_2_18_FN, GPSR2_18,
+ GP_2_17_FN, GPSR2_17,
+ GP_2_16_FN, GPSR2_16,
+ GP_2_15_FN, GPSR2_15,
+ GP_2_14_FN, GPSR2_14,
+ GP_2_13_FN, GPSR2_13,
+ GP_2_12_FN, GPSR2_12,
+ GP_2_11_FN, GPSR2_11,
+ GP_2_10_FN, GPSR2_10,
+ GP_2_9_FN, GPSR2_9,
+ GP_2_8_FN, GPSR2_8,
+ GP_2_7_FN, GPSR2_7,
+ GP_2_6_FN, GPSR2_6,
+ GP_2_5_FN, GPSR2_5,
+ GP_2_4_FN, GPSR2_4,
+ GP_2_3_FN, GPSR2_3,
+ GP_2_2_FN, GPSR2_2,
+ GP_2_1_FN, GPSR2_1,
+ GP_2_0_FN, GPSR2_0, ))
+ },
+ { PINMUX_CFG_REG("GPSR3", 0xE6058840, 32, 1, GROUP(
+ 0, 0,
+ 0, 0,
+ GP_3_29_FN, GPSR3_29,
+ GP_3_28_FN, GPSR3_28,
+ GP_3_27_FN, GPSR3_27,
+ GP_3_26_FN, GPSR3_26,
+ GP_3_25_FN, GPSR3_25,
+ GP_3_24_FN, GPSR3_24,
+ GP_3_23_FN, GPSR3_23,
+ GP_3_22_FN, GPSR3_22,
+ GP_3_21_FN, GPSR3_21,
+ GP_3_20_FN, GPSR3_20,
+ GP_3_19_FN, GPSR3_19,
+ GP_3_18_FN, GPSR3_18,
+ GP_3_17_FN, GPSR3_17,
+ GP_3_16_FN, GPSR3_16,
+ GP_3_15_FN, GPSR3_15,
+ GP_3_14_FN, GPSR3_14,
+ GP_3_13_FN, GPSR3_13,
+ GP_3_12_FN, GPSR3_12,
+ GP_3_11_FN, GPSR3_11,
+ GP_3_10_FN, GPSR3_10,
+ GP_3_9_FN, GPSR3_9,
+ GP_3_8_FN, GPSR3_8,
+ GP_3_7_FN, GPSR3_7,
+ GP_3_6_FN, GPSR3_6,
+ GP_3_5_FN, GPSR3_5,
+ GP_3_4_FN, GPSR3_4,
+ GP_3_3_FN, GPSR3_3,
+ GP_3_2_FN, GPSR3_2,
+ GP_3_1_FN, GPSR3_1,
+ GP_3_0_FN, GPSR3_0, ))
+ },
+ { PINMUX_CFG_REG("GPSR4", 0xE6060040, 32, 1, GROUP(
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_4_24_FN, GPSR4_24,
+ GP_4_23_FN, GPSR4_23,
+ GP_4_22_FN, GPSR4_22,
+ GP_4_21_FN, GPSR4_21,
+ GP_4_20_FN, GPSR4_20,
+ GP_4_19_FN, GPSR4_19,
+ GP_4_18_FN, GPSR4_18,
+ GP_4_17_FN, GPSR4_17,
+ GP_4_16_FN, GPSR4_16,
+ GP_4_15_FN, GPSR4_15,
+ GP_4_14_FN, GPSR4_14,
+ GP_4_13_FN, GPSR4_13,
+ GP_4_12_FN, GPSR4_12,
+ GP_4_11_FN, GPSR4_11,
+ GP_4_10_FN, GPSR4_10,
+ GP_4_9_FN, GPSR4_9,
+ GP_4_8_FN, GPSR4_8,
+ GP_4_7_FN, GPSR4_7,
+ GP_4_6_FN, GPSR4_6,
+ GP_4_5_FN, GPSR4_5,
+ GP_4_4_FN, GPSR4_4,
+ GP_4_3_FN, GPSR4_3,
+ GP_4_2_FN, GPSR4_2,
+ GP_4_1_FN, GPSR4_1,
+ GP_4_0_FN, GPSR4_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR5", 0xE6060840, 32,
+ GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP5_31_21 RESERVED */
+ GP_5_20_FN, GPSR5_20,
+ GP_5_19_FN, GPSR5_19,
+ GP_5_18_FN, GPSR5_18,
+ GP_5_17_FN, GPSR5_17,
+ GP_5_16_FN, GPSR5_16,
+ GP_5_15_FN, GPSR5_15,
+ GP_5_14_FN, GPSR5_14,
+ GP_5_13_FN, GPSR5_13,
+ GP_5_12_FN, GPSR5_12,
+ GP_5_11_FN, GPSR5_11,
+ GP_5_10_FN, GPSR5_10,
+ GP_5_9_FN, GPSR5_9,
+ GP_5_8_FN, GPSR5_8,
+ GP_5_7_FN, GPSR5_7,
+ GP_5_6_FN, GPSR5_6,
+ GP_5_5_FN, GPSR5_5,
+ GP_5_4_FN, GPSR5_4,
+ GP_5_3_FN, GPSR5_3,
+ GP_5_2_FN, GPSR5_2,
+ GP_5_1_FN, GPSR5_1,
+ GP_5_0_FN, GPSR5_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR6", 0xE6061040, 32,
+ GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP6_31_21 RESERVED */
+ GP_6_20_FN, GPSR6_20,
+ GP_6_19_FN, GPSR6_19,
+ GP_6_18_FN, GPSR6_18,
+ GP_6_17_FN, GPSR6_17,
+ GP_6_16_FN, GPSR6_16,
+ GP_6_15_FN, GPSR6_15,
+ GP_6_14_FN, GPSR6_14,
+ GP_6_13_FN, GPSR6_13,
+ GP_6_12_FN, GPSR6_12,
+ GP_6_11_FN, GPSR6_11,
+ GP_6_10_FN, GPSR6_10,
+ GP_6_9_FN, GPSR6_9,
+ GP_6_8_FN, GPSR6_8,
+ GP_6_7_FN, GPSR6_7,
+ GP_6_6_FN, GPSR6_6,
+ GP_6_5_FN, GPSR6_5,
+ GP_6_4_FN, GPSR6_4,
+ GP_6_3_FN, GPSR6_3,
+ GP_6_2_FN, GPSR6_2,
+ GP_6_1_FN, GPSR6_1,
+ GP_6_0_FN, GPSR6_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR7", 0xE6061840, 32,
+ GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP7_31_21 RESERVED */
+ GP_7_20_FN, GPSR7_20,
+ GP_7_19_FN, GPSR7_19,
+ GP_7_18_FN, GPSR7_18,
+ GP_7_17_FN, GPSR7_17,
+ GP_7_16_FN, GPSR7_16,
+ GP_7_15_FN, GPSR7_15,
+ GP_7_14_FN, GPSR7_14,
+ GP_7_13_FN, GPSR7_13,
+ GP_7_12_FN, GPSR7_12,
+ GP_7_11_FN, GPSR7_11,
+ GP_7_10_FN, GPSR7_10,
+ GP_7_9_FN, GPSR7_9,
+ GP_7_8_FN, GPSR7_8,
+ GP_7_7_FN, GPSR7_7,
+ GP_7_6_FN, GPSR7_6,
+ GP_7_5_FN, GPSR7_5,
+ GP_7_4_FN, GPSR7_4,
+ GP_7_3_FN, GPSR7_3,
+ GP_7_2_FN, GPSR7_2,
+ GP_7_1_FN, GPSR7_1,
+ GP_7_0_FN, GPSR7_0, ))
+ },
+ { PINMUX_CFG_REG_VAR("GPSR8", 0xE6068040, 32,
+ GROUP(-18, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* GP8_31_14 RESERVED */
+ GP_8_13_FN, GPSR8_13,
+ GP_8_12_FN, GPSR8_12,
+ GP_8_11_FN, GPSR8_11,
+ GP_8_10_FN, GPSR8_10,
+ GP_8_9_FN, GPSR8_9,
+ GP_8_8_FN, GPSR8_8,
+ GP_8_7_FN, GPSR8_7,
+ GP_8_6_FN, GPSR8_6,
+ GP_8_5_FN, GPSR8_5,
+ GP_8_4_FN, GPSR8_4,
+ GP_8_3_FN, GPSR8_3,
+ GP_8_2_FN, GPSR8_2,
+ GP_8_1_FN, GPSR8_1,
+ GP_8_0_FN, GPSR8_0, ))
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG("IP0SR0", 0xE6050060, 32, 4, GROUP(
+ IP0SR0_31_28
+ IP0SR0_27_24
+ IP0SR0_23_20
+ IP0SR0_19_16
+ IP0SR0_15_12
+ IP0SR0_11_8
+ IP0SR0_7_4
+ IP0SR0_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR0", 0xE6050064, 32, 4, GROUP(
+ IP1SR0_31_28
+ IP1SR0_27_24
+ IP1SR0_23_20
+ IP1SR0_19_16
+ IP1SR0_15_12
+ IP1SR0_11_8
+ IP1SR0_7_4
+ IP1SR0_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP2SR0", 0xE6050068, 32,
+ GROUP(-20, 4, 4, 4),
+ GROUP(
+ /* IP2SR0_31_12 RESERVED */
+ IP2SR0_11_8
+ IP2SR0_7_4
+ IP2SR0_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR1", 0xE6050860, 32, 4, GROUP(
+ IP0SR1_31_28
+ IP0SR1_27_24
+ IP0SR1_23_20
+ IP0SR1_19_16
+ IP0SR1_15_12
+ IP0SR1_11_8
+ IP0SR1_7_4
+ IP0SR1_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR1", 0xE6050864, 32, 4, GROUP(
+ IP1SR1_31_28
+ IP1SR1_27_24
+ IP1SR1_23_20
+ IP1SR1_19_16
+ IP1SR1_15_12
+ IP1SR1_11_8
+ IP1SR1_7_4
+ IP1SR1_3_0))
+ },
+ { PINMUX_CFG_REG("IP2SR1", 0xE6050868, 32, 4, GROUP(
+ IP2SR1_31_28
+ IP2SR1_27_24
+ IP2SR1_23_20
+ IP2SR1_19_16
+ IP2SR1_15_12
+ IP2SR1_11_8
+ IP2SR1_7_4
+ IP2SR1_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP3SR1", 0xE605086C, 32,
+ GROUP(-12, 4, 4, 4, 4, 4),
+ GROUP(
+ /* IP3SR1_31_20 RESERVED */
+ IP3SR1_19_16
+ IP3SR1_15_12
+ IP3SR1_11_8
+ IP3SR1_7_4
+ IP3SR1_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR2", 0xE6058060, 32, 4, GROUP(
+ IP0SR2_31_28
+ IP0SR2_27_24
+ IP0SR2_23_20
+ IP0SR2_19_16
+ IP0SR2_15_12
+ IP0SR2_11_8
+ IP0SR2_7_4
+ IP0SR2_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR2", 0xE6058064, 32, 4, GROUP(
+ IP1SR2_31_28
+ IP1SR2_27_24
+ IP1SR2_23_20
+ IP1SR2_19_16
+ IP1SR2_15_12
+ IP1SR2_11_8
+ IP1SR2_7_4
+ IP1SR2_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP2SR2", 0xE6058068, 32,
+ GROUP(-16, 4, 4, 4, 4),
+ GROUP(
+ /* IP2SR2_31_16 RESERVED */
+ IP2SR2_15_12
+ IP2SR2_11_8
+ IP2SR2_7_4
+ IP2SR2_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR3", 0xE6058860, 32, 4, GROUP(
+ IP0SR3_31_28
+ IP0SR3_27_24
+ IP0SR3_23_20
+ IP0SR3_19_16
+ IP0SR3_15_12
+ IP0SR3_11_8
+ IP0SR3_7_4
+ IP0SR3_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR3", 0xE6058864, 32, 4, GROUP(
+ IP1SR3_31_28
+ IP1SR3_27_24
+ IP1SR3_23_20
+ IP1SR3_19_16
+ IP1SR3_15_12
+ IP1SR3_11_8
+ IP1SR3_7_4
+ IP1SR3_3_0))
+ },
+ { PINMUX_CFG_REG("IP2SR3", 0xE6058868, 32, 4, GROUP(
+ IP2SR3_31_28
+ IP2SR3_27_24
+ IP2SR3_23_20
+ IP2SR3_19_16
+ IP2SR3_15_12
+ IP2SR3_11_8
+ IP2SR3_7_4
+ IP2SR3_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP3SR3", 0xE605886C, 32,
+ GROUP(-8, 4, 4, 4, 4, 4, 4),
+ GROUP(
+ /* IP3SR3_31_24 RESERVED */
+ IP3SR3_23_20
+ IP3SR3_19_16
+ IP3SR3_15_12
+ IP3SR3_11_8
+ IP3SR3_7_4
+ IP3SR3_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR6", 0xE6061060, 32, 4, GROUP(
+ IP0SR6_31_28
+ IP0SR6_27_24
+ IP0SR6_23_20
+ IP0SR6_19_16
+ IP0SR6_15_12
+ IP0SR6_11_8
+ IP0SR6_7_4
+ IP0SR6_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR6", 0xE6061064, 32, 4, GROUP(
+ IP1SR6_31_28
+ IP1SR6_27_24
+ IP1SR6_23_20
+ IP1SR6_19_16
+ IP1SR6_15_12
+ IP1SR6_11_8
+ IP1SR6_7_4
+ IP1SR6_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP2SR6", 0xE6061068, 32,
+ GROUP(-12, 4, 4, 4, 4, 4),
+ GROUP(
+ /* IP2SR6_31_20 RESERVED */
+ IP2SR6_19_16
+ IP2SR6_15_12
+ IP2SR6_11_8
+ IP2SR6_7_4
+ IP2SR6_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR7", 0xE6061860, 32, 4, GROUP(
+ IP0SR7_31_28
+ IP0SR7_27_24
+ IP0SR7_23_20
+ IP0SR7_19_16
+ IP0SR7_15_12
+ IP0SR7_11_8
+ IP0SR7_7_4
+ IP0SR7_3_0))
+ },
+ { PINMUX_CFG_REG("IP1SR7", 0xE6061864, 32, 4, GROUP(
+ IP1SR7_31_28
+ IP1SR7_27_24
+ IP1SR7_23_20
+ IP1SR7_19_16
+ IP1SR7_15_12
+ IP1SR7_11_8
+ IP1SR7_7_4
+ IP1SR7_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP2SR7", 0xE6061868, 32,
+ GROUP(-12, 4, 4, 4, 4, 4),
+ GROUP(
+ /* IP2SR7_31_20 RESERVED */
+ IP2SR7_19_16
+ IP2SR7_15_12
+ IP2SR7_11_8
+ IP2SR7_7_4
+ IP2SR7_3_0))
+ },
+ { PINMUX_CFG_REG("IP0SR8", 0xE6068060, 32, 4, GROUP(
+ IP0SR8_31_28
+ IP0SR8_27_24
+ IP0SR8_23_20
+ IP0SR8_19_16
+ IP0SR8_15_12
+ IP0SR8_11_8
+ IP0SR8_7_4
+ IP0SR8_3_0))
+ },
+ { PINMUX_CFG_REG_VAR("IP1SR8", 0xE6068064, 32,
+ GROUP(-8, 4, 4, 4, 4, 4, 4),
+ GROUP(
+ /* IP1SR8_31_24 RESERVED */
+ IP1SR8_23_20
+ IP1SR8_19_16
+ IP1SR8_15_12
+ IP1SR8_11_8
+ IP1SR8_7_4
+ IP1SR8_3_0))
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG_VAR("MOD_SEL4", 0xE6060100, 32,
+ GROUP(-12, 1, 1, -2, 1, 1, -1, 1, -2, 1, 1, -2, 1,
+ -2, 1, 1, -1),
+ GROUP(
+ /* RESERVED 31-20 */
+ MOD_SEL4_19
+ MOD_SEL4_18
+ /* RESERVED 17-16 */
+ MOD_SEL4_15
+ MOD_SEL4_14
+ /* RESERVED 13 */
+ MOD_SEL4_12
+ /* RESERVED 11-10 */
+ MOD_SEL4_9
+ MOD_SEL4_8
+ /* RESERVED 7-6 */
+ MOD_SEL4_5
+ /* RESERVED 4-3 */
+ MOD_SEL4_2
+ MOD_SEL4_1
+ /* RESERVED 0 */
+ ))
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL5", 0xE6060900, 32,
+ GROUP(-12, 1, -2, 1, 1, -2, 1, 1, -2, 1, -1,
+ 1, 1, -2, 1, -1, 1),
+ GROUP(
+ /* RESERVED 31-20 */
+ MOD_SEL5_19
+ /* RESERVED 18-17 */
+ MOD_SEL5_16
+ MOD_SEL5_15
+ /* RESERVED 14-13 */
+ MOD_SEL5_12
+ MOD_SEL5_11
+ /* RESERVED 10-9 */
+ MOD_SEL5_8
+ /* RESERVED 7 */
+ MOD_SEL5_6
+ MOD_SEL5_5
+ /* RESERVED 4-3 */
+ MOD_SEL5_2
+ /* RESERVED 1 */
+ MOD_SEL5_0))
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL6", 0xE6061100, 32,
+ GROUP(-13, 1, -1, 1, -2, 1, 1,
+ -1, 1, -2, 1, 1, 1, -2, 1, 1, -1),
+ GROUP(
+ /* RESERVED 31-19 */
+ MOD_SEL6_18
+ /* RESERVED 17 */
+ MOD_SEL6_16
+ /* RESERVED 15-14 */
+ MOD_SEL6_13
+ MOD_SEL6_12
+ /* RESERVED 11 */
+ MOD_SEL6_10
+ /* RESERVED 9-8 */
+ MOD_SEL6_7
+ MOD_SEL6_6
+ MOD_SEL6_5
+ /* RESERVED 4-3 */
+ MOD_SEL6_2
+ MOD_SEL6_1
+ /* RESERVED 0 */
+ ))
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL7", 0xE6061900, 32,
+ GROUP(-15, 1, 1, -1, 1, -1, 1, 1, -2, 1, 1,
+ -2, 1, 1, -1, 1),
+ GROUP(
+ /* RESERVED 31-17 */
+ MOD_SEL7_16
+ MOD_SEL7_15
+ /* RESERVED 14 */
+ MOD_SEL7_13
+ /* RESERVED 12 */
+ MOD_SEL7_11
+ MOD_SEL7_10
+ /* RESERVED 9-8 */
+ MOD_SEL7_7
+ MOD_SEL7_6
+ /* RESERVED 5-4 */
+ MOD_SEL7_3
+ MOD_SEL7_2
+ /* RESERVED 1 */
+ MOD_SEL7_0))
+ },
+ { PINMUX_CFG_REG_VAR("MOD_SEL8", 0xE6068100, 32,
+ GROUP(-20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+ GROUP(
+ /* RESERVED 31-12 */
+ MOD_SEL8_11
+ MOD_SEL8_10
+ MOD_SEL8_9
+ MOD_SEL8_8
+ MOD_SEL8_7
+ MOD_SEL8_6
+ MOD_SEL8_5
+ MOD_SEL8_4
+ MOD_SEL8_3
+ MOD_SEL8_2
+ MOD_SEL8_1
+ MOD_SEL8_0))
+ },
+ { },
+};
+
+static const struct pinmux_drive_reg pinmux_drive_regs[] = {
+ { PINMUX_DRIVE_REG("DRV0CTRL0", 0xE6050080) {
+ { RCAR_GP_PIN(0, 7), 28, 3 }, /* MSIOF5_SS2 */
+ { RCAR_GP_PIN(0, 6), 24, 3 }, /* IRQ0 */
+ { RCAR_GP_PIN(0, 5), 20, 3 }, /* IRQ1 */
+ { RCAR_GP_PIN(0, 4), 16, 3 }, /* IRQ2 */
+ { RCAR_GP_PIN(0, 3), 12, 3 }, /* IRQ3 */
+ { RCAR_GP_PIN(0, 2), 8, 3 }, /* GP0_02 */
+ { RCAR_GP_PIN(0, 1), 4, 3 }, /* GP0_01 */
+ { RCAR_GP_PIN(0, 0), 0, 3 }, /* GP0_00 */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL0", 0xE6050084) {
+ { RCAR_GP_PIN(0, 15), 28, 3 }, /* MSIOF2_SYNC */
+ { RCAR_GP_PIN(0, 14), 24, 3 }, /* MSIOF2_SS1 */
+ { RCAR_GP_PIN(0, 13), 20, 3 }, /* MSIOF2_SS2 */
+ { RCAR_GP_PIN(0, 12), 16, 3 }, /* MSIOF5_RXD */
+ { RCAR_GP_PIN(0, 11), 12, 3 }, /* MSIOF5_SCK */
+ { RCAR_GP_PIN(0, 10), 8, 3 }, /* MSIOF5_TXD */
+ { RCAR_GP_PIN(0, 9), 4, 3 }, /* MSIOF5_SYNC */
+ { RCAR_GP_PIN(0, 8), 0, 3 }, /* MSIOF5_SS1 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL0", 0xE6050088) {
+ { RCAR_GP_PIN(0, 18), 8, 3 }, /* MSIOF2_RXD */
+ { RCAR_GP_PIN(0, 17), 4, 3 }, /* MSIOF2_SCK */
+ { RCAR_GP_PIN(0, 16), 0, 3 }, /* MSIOF2_TXD */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL1", 0xE6050880) {
+ { RCAR_GP_PIN(1, 7), 28, 3 }, /* MSIOF0_SS1 */
+ { RCAR_GP_PIN(1, 6), 24, 3 }, /* MSIOF0_SS2 */
+ { RCAR_GP_PIN(1, 5), 20, 3 }, /* MSIOF1_RXD */
+ { RCAR_GP_PIN(1, 4), 16, 3 }, /* MSIOF1_TXD */
+ { RCAR_GP_PIN(1, 3), 12, 3 }, /* MSIOF1_SCK */
+ { RCAR_GP_PIN(1, 2), 8, 3 }, /* MSIOF1_SYNC */
+ { RCAR_GP_PIN(1, 1), 4, 3 }, /* MSIOF1_SS1 */
+ { RCAR_GP_PIN(1, 0), 0, 3 }, /* MSIOF1_SS2 */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL1", 0xE6050884) {
+ { RCAR_GP_PIN(1, 15), 28, 3 }, /* HSCK0 */
+ { RCAR_GP_PIN(1, 14), 24, 3 }, /* HRTS0_N */
+ { RCAR_GP_PIN(1, 13), 20, 3 }, /* HCTS0_N */
+ { RCAR_GP_PIN(1, 12), 16, 3 }, /* HTX0 */
+ { RCAR_GP_PIN(1, 11), 12, 3 }, /* MSIOF0_RXD */
+ { RCAR_GP_PIN(1, 10), 8, 3 }, /* MSIOF0_SCK */
+ { RCAR_GP_PIN(1, 9), 4, 3 }, /* MSIOF0_TXD */
+ { RCAR_GP_PIN(1, 8), 0, 3 }, /* MSIOF0_SYNC */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL1", 0xE6050888) {
+ { RCAR_GP_PIN(1, 23), 28, 3 }, /* GP1_23 */
+ { RCAR_GP_PIN(1, 22), 24, 3 }, /* AUDIO_CLKIN */
+ { RCAR_GP_PIN(1, 21), 20, 3 }, /* AUDIO_CLKOUT */
+ { RCAR_GP_PIN(1, 20), 16, 3 }, /* SSI_SD */
+ { RCAR_GP_PIN(1, 19), 12, 3 }, /* SSI_WS */
+ { RCAR_GP_PIN(1, 18), 8, 3 }, /* SSI_SCK */
+ { RCAR_GP_PIN(1, 17), 4, 3 }, /* SCIF_CLK */
+ { RCAR_GP_PIN(1, 16), 0, 3 }, /* HRX0 */
+ } },
+ { PINMUX_DRIVE_REG("DRV3CTRL1", 0xE605088C) {
+ { RCAR_GP_PIN(1, 28), 16, 3 }, /* HTX3 */
+ { RCAR_GP_PIN(1, 27), 12, 3 }, /* HCTS3_N */
+ { RCAR_GP_PIN(1, 26), 8, 3 }, /* HRTS3_N */
+ { RCAR_GP_PIN(1, 25), 4, 3 }, /* HSCK3 */
+ { RCAR_GP_PIN(1, 24), 0, 3 }, /* HRX3 */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL2", 0xE6058080) {
+ { RCAR_GP_PIN(2, 7), 28, 3 }, /* TPU0TO1 */
+ { RCAR_GP_PIN(2, 6), 24, 3 }, /* FXR_TXDB */
+ { RCAR_GP_PIN(2, 5), 20, 3 }, /* FXR_TXENB_N */
+ { RCAR_GP_PIN(2, 4), 16, 3 }, /* RXDB_EXTFXR */
+ { RCAR_GP_PIN(2, 3), 12, 3 }, /* CLK_EXTFXR */
+ { RCAR_GP_PIN(2, 2), 8, 3 }, /* RXDA_EXTFXR */
+ { RCAR_GP_PIN(2, 1), 4, 3 }, /* FXR_TXENA_N */
+ { RCAR_GP_PIN(2, 0), 0, 3 }, /* FXR_TXDA */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL2", 0xE6058084) {
+ { RCAR_GP_PIN(2, 15), 28, 3 }, /* CANFD3_RX */
+ { RCAR_GP_PIN(2, 14), 24, 3 }, /* CANFD3_TX */
+ { RCAR_GP_PIN(2, 13), 20, 3 }, /* CANFD2_RX */
+ { RCAR_GP_PIN(2, 12), 16, 3 }, /* CANFD2_TX */
+ { RCAR_GP_PIN(2, 11), 12, 3 }, /* CANFD0_RX */
+ { RCAR_GP_PIN(2, 10), 8, 3 }, /* CANFD0_TX */
+ { RCAR_GP_PIN(2, 9), 4, 3 }, /* CAN_CLK */
+ { RCAR_GP_PIN(2, 8), 0, 3 }, /* TPU0TO0 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL2", 0xE6058088) {
+ { RCAR_GP_PIN(2, 19), 12, 3 }, /* CANFD7_RX */
+ { RCAR_GP_PIN(2, 18), 8, 3 }, /* CANFD7_TX */
+ { RCAR_GP_PIN(2, 17), 4, 3 }, /* CANFD4_RX */
+ { RCAR_GP_PIN(2, 16), 0, 3 }, /* CANFD4_TX */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL3", 0xE6058880) {
+ { RCAR_GP_PIN(3, 7), 28, 3 }, /* MMC_D4 */
+ { RCAR_GP_PIN(3, 6), 24, 3 }, /* MMC_D5 */
+ { RCAR_GP_PIN(3, 5), 20, 3 }, /* MMC_SD_D3 */
+ { RCAR_GP_PIN(3, 4), 16, 3 }, /* MMC_DS */
+ { RCAR_GP_PIN(3, 3), 12, 3 }, /* MMC_SD_CLK */
+ { RCAR_GP_PIN(3, 2), 8, 3 }, /* MMC_SD_D2 */
+ { RCAR_GP_PIN(3, 1), 4, 3 }, /* MMC_SD_D0 */
+ { RCAR_GP_PIN(3, 0), 0, 3 }, /* MMC_SD_D1 */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL3", 0xE6058884) {
+ { RCAR_GP_PIN(3, 15), 28, 2 }, /* QSPI0_SSL */
+ { RCAR_GP_PIN(3, 14), 24, 2 }, /* IPC_CLKOUT */
+ { RCAR_GP_PIN(3, 13), 20, 2 }, /* IPC_CLKIN */
+ { RCAR_GP_PIN(3, 12), 16, 3 }, /* SD_WP */
+ { RCAR_GP_PIN(3, 11), 12, 3 }, /* SD_CD */
+ { RCAR_GP_PIN(3, 10), 8, 3 }, /* MMC_SD_CMD */
+ { RCAR_GP_PIN(3, 9), 4, 3 }, /* MMC_D6*/
+ { RCAR_GP_PIN(3, 8), 0, 3 }, /* MMC_D7 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL3", 0xE6058888) {
+ { RCAR_GP_PIN(3, 23), 28, 2 }, /* QSPI1_MISO_IO1 */
+ { RCAR_GP_PIN(3, 22), 24, 2 }, /* QSPI1_SPCLK */
+ { RCAR_GP_PIN(3, 21), 20, 2 }, /* QSPI1_MOSI_IO0 */
+ { RCAR_GP_PIN(3, 20), 16, 2 }, /* QSPI0_SPCLK */
+ { RCAR_GP_PIN(3, 19), 12, 2 }, /* QSPI0_MOSI_IO0 */
+ { RCAR_GP_PIN(3, 18), 8, 2 }, /* QSPI0_MISO_IO1 */
+ { RCAR_GP_PIN(3, 17), 4, 2 }, /* QSPI0_IO2 */
+ { RCAR_GP_PIN(3, 16), 0, 2 }, /* QSPI0_IO3 */
+ } },
+ { PINMUX_DRIVE_REG("DRV3CTRL3", 0xE605888C) {
+ { RCAR_GP_PIN(3, 29), 20, 2 }, /* RPC_INT_N */
+ { RCAR_GP_PIN(3, 28), 16, 2 }, /* RPC_WP_N */
+ { RCAR_GP_PIN(3, 27), 12, 2 }, /* RPC_RESET_N */
+ { RCAR_GP_PIN(3, 26), 8, 2 }, /* QSPI1_IO3 */
+ { RCAR_GP_PIN(3, 25), 4, 2 }, /* QSPI1_SSL */
+ { RCAR_GP_PIN(3, 24), 0, 2 }, /* QSPI1_IO2 */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL4", 0xE6060080) {
+ { RCAR_GP_PIN(4, 7), 28, 3 }, /* TSN0_RX_CTL */
+ { RCAR_GP_PIN(4, 6), 24, 3 }, /* TSN0_AVTP_CAPTURE */
+ { RCAR_GP_PIN(4, 5), 20, 3 }, /* TSN0_AVTP_MATCH */
+ { RCAR_GP_PIN(4, 4), 16, 3 }, /* TSN0_LINK */
+ { RCAR_GP_PIN(4, 3), 12, 3 }, /* TSN0_PHY_INT */
+ { RCAR_GP_PIN(4, 2), 8, 3 }, /* TSN0_AVTP_PPS1 */
+ { RCAR_GP_PIN(4, 1), 4, 3 }, /* TSN0_MDC */
+ { RCAR_GP_PIN(4, 0), 0, 3 }, /* TSN0_MDIO */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL4", 0xE6060084) {
+ { RCAR_GP_PIN(4, 15), 28, 3 }, /* TSN0_TD0 */
+ { RCAR_GP_PIN(4, 14), 24, 3 }, /* TSN0_TD1 */
+ { RCAR_GP_PIN(4, 13), 20, 3 }, /* TSN0_RD1 */
+ { RCAR_GP_PIN(4, 12), 16, 3 }, /* TSN0_TXC */
+ { RCAR_GP_PIN(4, 11), 12, 3 }, /* TSN0_RXC */
+ { RCAR_GP_PIN(4, 10), 8, 3 }, /* TSN0_RD0 */
+ { RCAR_GP_PIN(4, 9), 4, 3 }, /* TSN0_TX_CTL */
+ { RCAR_GP_PIN(4, 8), 0, 3 }, /* TSN0_AVTP_PPS0 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL4", 0xE6060088) {
+ { RCAR_GP_PIN(4, 23), 28, 3 }, /* AVS0 */
+ { RCAR_GP_PIN(4, 22), 24, 3 }, /* PCIE1_CLKREQ_N */
+ { RCAR_GP_PIN(4, 21), 20, 3 }, /* PCIE0_CLKREQ_N */
+ { RCAR_GP_PIN(4, 20), 16, 3 }, /* TSN0_TXCREFCLK */
+ { RCAR_GP_PIN(4, 19), 12, 3 }, /* TSN0_TD2 */
+ { RCAR_GP_PIN(4, 18), 8, 3 }, /* TSN0_TD3 */
+ { RCAR_GP_PIN(4, 17), 4, 3 }, /* TSN0_RD2 */
+ { RCAR_GP_PIN(4, 16), 0, 3 }, /* TSN0_RD3 */
+ } },
+ { PINMUX_DRIVE_REG("DRV3CTRL4", 0xE606008C) {
+ { RCAR_GP_PIN(4, 24), 0, 3 }, /* AVS1 */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL5", 0xE6060880) {
+ { RCAR_GP_PIN(5, 7), 28, 3 }, /* AVB2_TXCREFCLK */
+ { RCAR_GP_PIN(5, 6), 24, 3 }, /* AVB2_MDC */
+ { RCAR_GP_PIN(5, 5), 20, 3 }, /* AVB2_MAGIC */
+ { RCAR_GP_PIN(5, 4), 16, 3 }, /* AVB2_PHY_INT */
+ { RCAR_GP_PIN(5, 3), 12, 3 }, /* AVB2_LINK */
+ { RCAR_GP_PIN(5, 2), 8, 3 }, /* AVB2_AVTP_MATCH */
+ { RCAR_GP_PIN(5, 1), 4, 3 }, /* AVB2_AVTP_CAPTURE */
+ { RCAR_GP_PIN(5, 0), 0, 3 }, /* AVB2_AVTP_PPS */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL5", 0xE6060884) {
+ { RCAR_GP_PIN(5, 15), 28, 3 }, /* AVB2_TD0 */
+ { RCAR_GP_PIN(5, 14), 24, 3 }, /* AVB2_RD1 */
+ { RCAR_GP_PIN(5, 13), 20, 3 }, /* AVB2_RD2 */
+ { RCAR_GP_PIN(5, 12), 16, 3 }, /* AVB2_TD1 */
+ { RCAR_GP_PIN(5, 11), 12, 3 }, /* AVB2_TD2 */
+ { RCAR_GP_PIN(5, 10), 8, 3 }, /* AVB2_MDIO */
+ { RCAR_GP_PIN(5, 9), 4, 3 }, /* AVB2_RD3 */
+ { RCAR_GP_PIN(5, 8), 0, 3 }, /* AVB2_TD3 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL5", 0xE6060888) {
+ { RCAR_GP_PIN(5, 20), 16, 3 }, /* AVB2_RX_CTL */
+ { RCAR_GP_PIN(5, 19), 12, 3 }, /* AVB2_TX_CTL */
+ { RCAR_GP_PIN(5, 18), 8, 3 }, /* AVB2_RXC */
+ { RCAR_GP_PIN(5, 17), 4, 3 }, /* AVB2_RD0 */
+ { RCAR_GP_PIN(5, 16), 0, 3 }, /* AVB2_TXC */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL6", 0xE6061080) {
+ { RCAR_GP_PIN(6, 7), 28, 3 }, /* AVB1_TX_CTL */
+ { RCAR_GP_PIN(6, 6), 24, 3 }, /* AVB1_TXC */
+ { RCAR_GP_PIN(6, 5), 20, 3 }, /* AVB1_AVTP_MATCH */
+ { RCAR_GP_PIN(6, 4), 16, 3 }, /* AVB1_LINK */
+ { RCAR_GP_PIN(6, 3), 12, 3 }, /* AVB1_PHY_INT */
+ { RCAR_GP_PIN(6, 2), 8, 3 }, /* AVB1_MDC */
+ { RCAR_GP_PIN(6, 1), 4, 3 }, /* AVB1_MAGIC */
+ { RCAR_GP_PIN(6, 0), 0, 3 }, /* AVB1_MDIO */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL6", 0xE6061084) {
+ { RCAR_GP_PIN(6, 15), 28, 3 }, /* AVB1_RD0 */
+ { RCAR_GP_PIN(6, 14), 24, 3 }, /* AVB1_RD1 */
+ { RCAR_GP_PIN(6, 13), 20, 3 }, /* AVB1_TD0 */
+ { RCAR_GP_PIN(6, 12), 16, 3 }, /* AVB1_TD1 */
+ { RCAR_GP_PIN(6, 11), 12, 3 }, /* AVB1_AVTP_CAPTURE */
+ { RCAR_GP_PIN(6, 10), 8, 3 }, /* AVB1_AVTP_PPS */
+ { RCAR_GP_PIN(6, 9), 4, 3 }, /* AVB1_RX_CTL */
+ { RCAR_GP_PIN(6, 8), 0, 3 }, /* AVB1_RXC */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL6", 0xE6061088) {
+ { RCAR_GP_PIN(6, 20), 16, 3 }, /* AVB1_TXCREFCLK */
+ { RCAR_GP_PIN(6, 19), 12, 3 }, /* AVB1_RD3 */
+ { RCAR_GP_PIN(6, 18), 8, 3 }, /* AVB1_TD3 */
+ { RCAR_GP_PIN(6, 17), 4, 3 }, /* AVB1_RD2 */
+ { RCAR_GP_PIN(6, 16), 0, 3 }, /* AVB1_TD2 */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL7", 0xE6061880) {
+ { RCAR_GP_PIN(7, 7), 28, 3 }, /* AVB0_TD1 */
+ { RCAR_GP_PIN(7, 6), 24, 3 }, /* AVB0_TD2 */
+ { RCAR_GP_PIN(7, 5), 20, 3 }, /* AVB0_PHY_INT */
+ { RCAR_GP_PIN(7, 4), 16, 3 }, /* AVB0_LINK */
+ { RCAR_GP_PIN(7, 3), 12, 3 }, /* AVB0_TD3 */
+ { RCAR_GP_PIN(7, 2), 8, 3 }, /* AVB0_AVTP_MATCH */
+ { RCAR_GP_PIN(7, 1), 4, 3 }, /* AVB0_AVTP_CAPTURE */
+ { RCAR_GP_PIN(7, 0), 0, 3 }, /* AVB0_AVTP_PPS */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL7", 0xE6061884) {
+ { RCAR_GP_PIN(7, 15), 28, 3 }, /* AVB0_TXC */
+ { RCAR_GP_PIN(7, 14), 24, 3 }, /* AVB0_MDIO */
+ { RCAR_GP_PIN(7, 13), 20, 3 }, /* AVB0_MDC */
+ { RCAR_GP_PIN(7, 12), 16, 3 }, /* AVB0_RD2 */
+ { RCAR_GP_PIN(7, 11), 12, 3 }, /* AVB0_TD0 */
+ { RCAR_GP_PIN(7, 10), 8, 3 }, /* AVB0_MAGIC */
+ { RCAR_GP_PIN(7, 9), 4, 3 }, /* AVB0_TXCREFCLK */
+ { RCAR_GP_PIN(7, 8), 0, 3 }, /* AVB0_RD3 */
+ } },
+ { PINMUX_DRIVE_REG("DRV2CTRL7", 0xE6061888) {
+ { RCAR_GP_PIN(7, 20), 16, 3 }, /* AVB0_RX_CTL */
+ { RCAR_GP_PIN(7, 19), 12, 3 }, /* AVB0_RXC */
+ { RCAR_GP_PIN(7, 18), 8, 3 }, /* AVB0_RD0 */
+ { RCAR_GP_PIN(7, 17), 4, 3 }, /* AVB0_RD1 */
+ { RCAR_GP_PIN(7, 16), 0, 3 }, /* AVB0_TX_CTL */
+ } },
+ { PINMUX_DRIVE_REG("DRV0CTRL8", 0xE6068080) {
+ { RCAR_GP_PIN(8, 7), 28, 3 }, /* SDA3 */
+ { RCAR_GP_PIN(8, 6), 24, 3 }, /* SCL3 */
+ { RCAR_GP_PIN(8, 5), 20, 3 }, /* SDA2 */
+ { RCAR_GP_PIN(8, 4), 16, 3 }, /* SCL2 */
+ { RCAR_GP_PIN(8, 3), 12, 3 }, /* SDA1 */
+ { RCAR_GP_PIN(8, 2), 8, 3 }, /* SCL1 */
+ { RCAR_GP_PIN(8, 1), 4, 3 }, /* SDA0 */
+ { RCAR_GP_PIN(8, 0), 0, 3 }, /* SCL0 */
+ } },
+ { PINMUX_DRIVE_REG("DRV1CTRL8", 0xE6068084) {
+ { RCAR_GP_PIN(8, 13), 20, 3 }, /* GP8_13 */
+ { RCAR_GP_PIN(8, 12), 16, 3 }, /* GP8_12 */
+ { RCAR_GP_PIN(8, 11), 12, 3 }, /* SDA5 */
+ { RCAR_GP_PIN(8, 10), 8, 3 }, /* SCL5 */
+ { RCAR_GP_PIN(8, 9), 4, 3 }, /* SDA4 */
+ { RCAR_GP_PIN(8, 8), 0, 3 }, /* SCL4 */
+ } },
+ { },
+};
+
+enum ioctrl_regs {
+ POC0,
+ POC1,
+ POC3,
+ POC4,
+ POC5,
+ POC6,
+ POC7,
+ POC8,
+};
+
+static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = {
+ [POC0] = { 0xE60500A0, },
+ [POC1] = { 0xE60508A0, },
+ [POC3] = { 0xE60588A0, },
+ [POC4] = { 0xE60600A0, },
+ [POC5] = { 0xE60608A0, },
+ [POC6] = { 0xE60610A0, },
+ [POC7] = { 0xE60618A0, },
+ [POC8] = { 0xE60680A0, },
+ { /* sentinel */ },
+};
+
+static int r8a779g0_pin_to_pocctrl(unsigned int pin, u32 *pocctrl)
+{
+ int bit = pin & 0x1f;
+
+ *pocctrl = pinmux_ioctrl_regs[POC0].reg;
+ if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 18))
+ return bit;
+
+ *pocctrl = pinmux_ioctrl_regs[POC1].reg;
+ if (pin >= RCAR_GP_PIN(1, 0) && pin <= RCAR_GP_PIN(1, 22))
+ return bit;
+
+ *pocctrl = pinmux_ioctrl_regs[POC3].reg;
+ if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 12))
+ return bit;
+
+ *pocctrl = pinmux_ioctrl_regs[POC8].reg;
+ if (pin >= RCAR_GP_PIN(8, 0) && pin <= RCAR_GP_PIN(8, 13))
+ return bit;
+
+ return -EINVAL;
+}
+
+static const struct pinmux_bias_reg pinmux_bias_regs[] = {
+ { PINMUX_BIAS_REG("PUEN0", 0xE60500C0, "PUD0", 0xE60500E0) {
+ [ 0] = RCAR_GP_PIN(0, 0), /* GP0_00 */
+ [ 1] = RCAR_GP_PIN(0, 1), /* GP0_01 */
+ [ 2] = RCAR_GP_PIN(0, 2), /* GP0_02 */
+ [ 3] = RCAR_GP_PIN(0, 3), /* IRQ3 */
+ [ 4] = RCAR_GP_PIN(0, 4), /* IRQ2 */
+ [ 5] = RCAR_GP_PIN(0, 5), /* IRQ1 */
+ [ 6] = RCAR_GP_PIN(0, 6), /* IRQ0 */
+ [ 7] = RCAR_GP_PIN(0, 7), /* MSIOF5_SS2 */
+ [ 8] = RCAR_GP_PIN(0, 8), /* MSIOF5_SS1 */
+ [ 9] = RCAR_GP_PIN(0, 9), /* MSIOF5_SYNC */
+ [10] = RCAR_GP_PIN(0, 10), /* MSIOF5_TXD */
+ [11] = RCAR_GP_PIN(0, 11), /* MSIOF5_SCK */
+ [12] = RCAR_GP_PIN(0, 12), /* MSIOF5_RXD */
+ [13] = RCAR_GP_PIN(0, 13), /* MSIOF2_SS2 */
+ [14] = RCAR_GP_PIN(0, 14), /* MSIOF2_SS1 */
+ [15] = RCAR_GP_PIN(0, 15), /* MSIOF2_SYNC */
+ [16] = RCAR_GP_PIN(0, 16), /* MSIOF2_TXD */
+ [17] = RCAR_GP_PIN(0, 17), /* MSIOF2_SCK */
+ [18] = RCAR_GP_PIN(0, 18), /* MSIOF2_RXD */
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN1", 0xE60508C0, "PUD1", 0xE60508E0) {
+ [ 0] = RCAR_GP_PIN(1, 0), /* MSIOF1_SS2 */
+ [ 1] = RCAR_GP_PIN(1, 1), /* MSIOF1_SS1 */
+ [ 2] = RCAR_GP_PIN(1, 2), /* MSIOF1_SYNC */
+ [ 3] = RCAR_GP_PIN(1, 3), /* MSIOF1_SCK */
+ [ 4] = RCAR_GP_PIN(1, 4), /* MSIOF1_TXD */
+ [ 5] = RCAR_GP_PIN(1, 5), /* MSIOF1_RXD */
+ [ 6] = RCAR_GP_PIN(1, 6), /* MSIOF0_SS2 */
+ [ 7] = RCAR_GP_PIN(1, 7), /* MSIOF0_SS1 */
+ [ 8] = RCAR_GP_PIN(1, 8), /* MSIOF0_SYNC */
+ [ 9] = RCAR_GP_PIN(1, 9), /* MSIOF0_TXD */
+ [10] = RCAR_GP_PIN(1, 10), /* MSIOF0_SCK */
+ [11] = RCAR_GP_PIN(1, 11), /* MSIOF0_RXD */
+ [12] = RCAR_GP_PIN(1, 12), /* HTX0 */
+ [13] = RCAR_GP_PIN(1, 13), /* HCTS0_N */
+ [14] = RCAR_GP_PIN(1, 14), /* HRTS0_N */
+ [15] = RCAR_GP_PIN(1, 15), /* HSCK0 */
+ [16] = RCAR_GP_PIN(1, 16), /* HRX0 */
+ [17] = RCAR_GP_PIN(1, 17), /* SCIF_CLK */
+ [18] = RCAR_GP_PIN(1, 18), /* SSI_SCK */
+ [19] = RCAR_GP_PIN(1, 19), /* SSI_WS */
+ [20] = RCAR_GP_PIN(1, 20), /* SSI_SD */
+ [21] = RCAR_GP_PIN(1, 21), /* AUDIO_CLKOUT */
+ [22] = RCAR_GP_PIN(1, 22), /* AUDIO_CLKIN */
+ [23] = RCAR_GP_PIN(1, 23), /* GP1_23 */
+ [24] = RCAR_GP_PIN(1, 24), /* HRX3 */
+ [25] = RCAR_GP_PIN(1, 25), /* HSCK3 */
+ [26] = RCAR_GP_PIN(1, 26), /* HRTS3_N */
+ [27] = RCAR_GP_PIN(1, 27), /* HCTS3_N */
+ [28] = RCAR_GP_PIN(1, 28), /* HTX3 */
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN2", 0xE60580C0, "PUD2", 0xE60580E0) {
+ [ 0] = RCAR_GP_PIN(2, 0), /* FXR_TXDA */
+ [ 1] = RCAR_GP_PIN(2, 1), /* FXR_TXENA_N */
+ [ 2] = RCAR_GP_PIN(2, 2), /* RXDA_EXTFXR */
+ [ 3] = RCAR_GP_PIN(2, 3), /* CLK_EXTFXR */
+ [ 4] = RCAR_GP_PIN(2, 4), /* RXDB_EXTFXR */
+ [ 5] = RCAR_GP_PIN(2, 5), /* FXR_TXENB_N */
+ [ 6] = RCAR_GP_PIN(2, 6), /* FXR_TXDB */
+ [ 7] = RCAR_GP_PIN(2, 7), /* TPU0TO1 */
+ [ 8] = RCAR_GP_PIN(2, 8), /* TPU0TO0 */
+ [ 9] = RCAR_GP_PIN(2, 9), /* CAN_CLK */
+ [10] = RCAR_GP_PIN(2, 10), /* CANFD0_TX */
+ [11] = RCAR_GP_PIN(2, 11), /* CANFD0_RX */
+ [12] = RCAR_GP_PIN(2, 12), /* CANFD2_TX */
+ [13] = RCAR_GP_PIN(2, 13), /* CANFD2_RX */
+ [14] = RCAR_GP_PIN(2, 14), /* CANFD3_TX */
+ [15] = RCAR_GP_PIN(2, 15), /* CANFD3_RX */
+ [16] = RCAR_GP_PIN(2, 16), /* CANFD4_TX */
+ [17] = RCAR_GP_PIN(2, 17), /* CANFD4_RX */
+ [18] = RCAR_GP_PIN(2, 18), /* CANFD7_TX */
+ [19] = RCAR_GP_PIN(2, 19), /* CANFD7_RX */
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN3", 0xE60588C0, "PUD3", 0xE60588E0) {
+ [ 0] = RCAR_GP_PIN(3, 0), /* MMC_SD_D1 */
+ [ 1] = RCAR_GP_PIN(3, 1), /* MMC_SD_D0 */
+ [ 2] = RCAR_GP_PIN(3, 2), /* MMC_SD_D2 */
+ [ 3] = RCAR_GP_PIN(3, 3), /* MMC_SD_CLK */
+ [ 4] = RCAR_GP_PIN(3, 4), /* MMC_DS */
+ [ 5] = RCAR_GP_PIN(3, 5), /* MMC_SD_D3 */
+ [ 6] = RCAR_GP_PIN(3, 6), /* MMC_D5 */
+ [ 7] = RCAR_GP_PIN(3, 7), /* MMC_D4 */
+ [ 8] = RCAR_GP_PIN(3, 8), /* MMC_D7 */
+ [ 9] = RCAR_GP_PIN(3, 9), /* MMC_D6 */
+ [10] = RCAR_GP_PIN(3, 10), /* MMC_SD_CMD */
+ [11] = RCAR_GP_PIN(3, 11), /* SD_CD */
+ [12] = RCAR_GP_PIN(3, 12), /* SD_WP */
+ [13] = RCAR_GP_PIN(3, 13), /* IPC_CLKIN */
+ [14] = RCAR_GP_PIN(3, 14), /* IPC_CLKOUT */
+ [15] = RCAR_GP_PIN(3, 15), /* QSPI0_SSL */
+ [16] = RCAR_GP_PIN(3, 16), /* QSPI0_IO3 */
+ [17] = RCAR_GP_PIN(3, 17), /* QSPI0_IO2 */
+ [18] = RCAR_GP_PIN(3, 18), /* QSPI0_MISO_IO1 */
+ [19] = RCAR_GP_PIN(3, 19), /* QSPI0_MOSI_IO0 */
+ [20] = RCAR_GP_PIN(3, 20), /* QSPI0_SPCLK */
+ [21] = RCAR_GP_PIN(3, 21), /* QSPI1_MOSI_IO0 */
+ [22] = RCAR_GP_PIN(3, 22), /* QSPI1_SPCLK */
+ [23] = RCAR_GP_PIN(3, 23), /* QSPI1_MISO_IO1 */
+ [24] = RCAR_GP_PIN(3, 24), /* QSPI1_IO2 */
+ [25] = RCAR_GP_PIN(3, 25), /* QSPI1_SSL */
+ [26] = RCAR_GP_PIN(3, 26), /* QSPI1_IO3 */
+ [27] = RCAR_GP_PIN(3, 27), /* RPC_RESET_N */
+ [28] = RCAR_GP_PIN(3, 28), /* RPC_WP_N */
+ [29] = RCAR_GP_PIN(3, 29), /* RPC_INT_N */
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN4", 0xE60600C0, "PUD4", 0xE60600E0) {
+ [ 0] = RCAR_GP_PIN(4, 0), /* TSN0_MDIO */
+ [ 1] = RCAR_GP_PIN(4, 1), /* TSN0_MDC */
+ [ 2] = RCAR_GP_PIN(4, 2), /* TSN0_AVTP_PPS1 */
+ [ 3] = RCAR_GP_PIN(4, 3), /* TSN0_PHY_INT */
+ [ 4] = RCAR_GP_PIN(4, 4), /* TSN0_LINK */
+ [ 5] = RCAR_GP_PIN(4, 5), /* TSN0_AVTP_MATCH */
+ [ 6] = RCAR_GP_PIN(4, 6), /* TSN0_AVTP_CAPTURE */
+ [ 7] = RCAR_GP_PIN(4, 7), /* TSN0_RX_CTL */
+ [ 8] = RCAR_GP_PIN(4, 8), /* TSN0_AVTP_PPS0 */
+ [ 9] = RCAR_GP_PIN(4, 9), /* TSN0_TX_CTL */
+ [10] = RCAR_GP_PIN(4, 10), /* TSN0_RD0 */
+ [11] = RCAR_GP_PIN(4, 11), /* TSN0_RXC */
+ [12] = RCAR_GP_PIN(4, 12), /* TSN0_TXC */
+ [13] = RCAR_GP_PIN(4, 13), /* TSN0_RD1 */
+ [14] = RCAR_GP_PIN(4, 14), /* TSN0_TD1 */
+ [15] = RCAR_GP_PIN(4, 15), /* TSN0_TD0 */
+ [16] = RCAR_GP_PIN(4, 16), /* TSN0_RD3 */
+ [17] = RCAR_GP_PIN(4, 17), /* TSN0_RD2 */
+ [18] = RCAR_GP_PIN(4, 18), /* TSN0_TD3 */
+ [19] = RCAR_GP_PIN(4, 19), /* TSN0_TD2 */
+ [20] = RCAR_GP_PIN(4, 20), /* TSN0_TXCREFCLK */
+ [21] = RCAR_GP_PIN(4, 21), /* PCIE0_CLKREQ_N */
+ [22] = RCAR_GP_PIN(4, 22), /* PCIE1_CLKREQ_N */
+ [23] = RCAR_GP_PIN(4, 23), /* AVS0 */
+ [24] = RCAR_GP_PIN(4, 24), /* AVS1 */
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN5", 0xE60608C0, "PUD5", 0xE60608E0) {
+ [ 0] = RCAR_GP_PIN(5, 0), /* AVB2_AVTP_PPS */
+ [ 1] = RCAR_GP_PIN(5, 1), /* AVB0_AVTP_CAPTURE */
+ [ 2] = RCAR_GP_PIN(5, 2), /* AVB2_AVTP_MATCH */
+ [ 3] = RCAR_GP_PIN(5, 3), /* AVB2_LINK */
+ [ 4] = RCAR_GP_PIN(5, 4), /* AVB2_PHY_INT */
+ [ 5] = RCAR_GP_PIN(5, 5), /* AVB2_MAGIC */
+ [ 6] = RCAR_GP_PIN(5, 6), /* AVB2_MDC */
+ [ 7] = RCAR_GP_PIN(5, 7), /* AVB2_TXCREFCLK */
+ [ 8] = RCAR_GP_PIN(5, 8), /* AVB2_TD3 */
+ [ 9] = RCAR_GP_PIN(5, 9), /* AVB2_RD3 */
+ [10] = RCAR_GP_PIN(5, 10), /* AVB2_MDIO */
+ [11] = RCAR_GP_PIN(5, 11), /* AVB2_TD2 */
+ [12] = RCAR_GP_PIN(5, 12), /* AVB2_TD1 */
+ [13] = RCAR_GP_PIN(5, 13), /* AVB2_RD2 */
+ [14] = RCAR_GP_PIN(5, 14), /* AVB2_RD1 */
+ [15] = RCAR_GP_PIN(5, 15), /* AVB2_TD0 */
+ [16] = RCAR_GP_PIN(5, 16), /* AVB2_TXC */
+ [17] = RCAR_GP_PIN(5, 17), /* AVB2_RD0 */
+ [18] = RCAR_GP_PIN(5, 18), /* AVB2_RXC */
+ [19] = RCAR_GP_PIN(5, 19), /* AVB2_TX_CTL */
+ [20] = RCAR_GP_PIN(5, 20), /* AVB2_RX_CTL */
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN6", 0xE60610C0, "PUD6", 0xE60610E0) {
+ [ 0] = RCAR_GP_PIN(6, 0), /* AVB1_MDIO */
+ [ 1] = RCAR_GP_PIN(6, 1), /* AVB1_MAGIC */
+ [ 2] = RCAR_GP_PIN(6, 2), /* AVB1_MDC */
+ [ 3] = RCAR_GP_PIN(6, 3), /* AVB1_PHY_INT */
+ [ 4] = RCAR_GP_PIN(6, 4), /* AVB1_LINK */
+ [ 5] = RCAR_GP_PIN(6, 5), /* AVB1_AVTP_MATCH */
+ [ 6] = RCAR_GP_PIN(6, 6), /* AVB1_TXC */
+ [ 7] = RCAR_GP_PIN(6, 7), /* AVB1_TX_CTL */
+ [ 8] = RCAR_GP_PIN(6, 8), /* AVB1_RXC */
+ [ 9] = RCAR_GP_PIN(6, 9), /* AVB1_RX_CTL */
+ [10] = RCAR_GP_PIN(6, 10), /* AVB1_AVTP_PPS */
+ [11] = RCAR_GP_PIN(6, 11), /* AVB1_AVTP_CAPTURE */
+ [12] = RCAR_GP_PIN(6, 12), /* AVB1_TD1 */
+ [13] = RCAR_GP_PIN(6, 13), /* AVB1_TD0 */
+ [14] = RCAR_GP_PIN(6, 14), /* AVB1_RD1*/
+ [15] = RCAR_GP_PIN(6, 15), /* AVB1_RD0 */
+ [16] = RCAR_GP_PIN(6, 16), /* AVB1_TD2 */
+ [17] = RCAR_GP_PIN(6, 17), /* AVB1_RD2 */
+ [18] = RCAR_GP_PIN(6, 18), /* AVB1_TD3 */
+ [19] = RCAR_GP_PIN(6, 19), /* AVB1_RD3 */
+ [20] = RCAR_GP_PIN(6, 20), /* AVB1_TXCREFCLK */
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN7", 0xE60618C0, "PUD7", 0xE60618E0) {
+ [ 0] = RCAR_GP_PIN(7, 0), /* AVB0_AVTP_PPS */
+ [ 1] = RCAR_GP_PIN(7, 1), /* AVB0_AVTP_CAPTURE */
+ [ 2] = RCAR_GP_PIN(7, 2), /* AVB0_AVTP_MATCH */
+ [ 3] = RCAR_GP_PIN(7, 3), /* AVB0_TD3 */
+ [ 4] = RCAR_GP_PIN(7, 4), /* AVB0_LINK */
+ [ 5] = RCAR_GP_PIN(7, 5), /* AVB0_PHY_INT */
+ [ 6] = RCAR_GP_PIN(7, 6), /* AVB0_TD2 */
+ [ 7] = RCAR_GP_PIN(7, 7), /* AVB0_TD1 */
+ [ 8] = RCAR_GP_PIN(7, 8), /* AVB0_RD3 */
+ [ 9] = RCAR_GP_PIN(7, 9), /* AVB0_TXCREFCLK */
+ [10] = RCAR_GP_PIN(7, 10), /* AVB0_MAGIC */
+ [11] = RCAR_GP_PIN(7, 11), /* AVB0_TD0 */
+ [12] = RCAR_GP_PIN(7, 12), /* AVB0_RD2 */
+ [13] = RCAR_GP_PIN(7, 13), /* AVB0_MDC */
+ [14] = RCAR_GP_PIN(7, 14), /* AVB0_MDIO */
+ [15] = RCAR_GP_PIN(7, 15), /* AVB0_TXC */
+ [16] = RCAR_GP_PIN(7, 16), /* AVB0_TX_CTL */
+ [17] = RCAR_GP_PIN(7, 17), /* AVB0_RD1 */
+ [18] = RCAR_GP_PIN(7, 18), /* AVB0_RD0 */
+ [19] = RCAR_GP_PIN(7, 19), /* AVB0_RXC */
+ [20] = RCAR_GP_PIN(7, 20), /* AVB0_RX_CTL */
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { PINMUX_BIAS_REG("PUEN8", 0xE60680C0, "PUD8", 0xE60680E0) {
+ [ 0] = RCAR_GP_PIN(8, 0), /* SCL0 */
+ [ 1] = RCAR_GP_PIN(8, 1), /* SDA0 */
+ [ 2] = RCAR_GP_PIN(8, 2), /* SCL1 */
+ [ 3] = RCAR_GP_PIN(8, 3), /* SDA1 */
+ [ 4] = RCAR_GP_PIN(8, 4), /* SCL2 */
+ [ 5] = RCAR_GP_PIN(8, 5), /* SDA2 */
+ [ 6] = RCAR_GP_PIN(8, 6), /* SCL3 */
+ [ 7] = RCAR_GP_PIN(8, 7), /* SDA3 */
+ [ 8] = RCAR_GP_PIN(8, 8), /* SCL4 */
+ [ 9] = RCAR_GP_PIN(8, 9), /* SDA4 */
+ [10] = RCAR_GP_PIN(8, 10), /* SCL5 */
+ [11] = RCAR_GP_PIN(8, 11), /* SDA5 */
+ [12] = RCAR_GP_PIN(8, 12), /* GP8_12 */
+ [13] = RCAR_GP_PIN(8, 13), /* GP8_13 */
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
+ } },
+ { /* sentinel */ },
+};
+
+static const struct sh_pfc_soc_operations r8a779g0_pin_ops = {
+ .pin_to_pocctrl = r8a779g0_pin_to_pocctrl,
+ .get_bias = rcar_pinmux_get_bias,
+ .set_bias = rcar_pinmux_set_bias,
+};
+
+const struct sh_pfc_soc_info r8a779g0_pinmux_info = {
+ .name = "r8a779g0_pfc",
+ .ops = &r8a779g0_pin_ops,
+ .unlock_reg = 0x1ff, /* PMMRn mask */
+
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .pins = pinmux_pins,
+ .nr_pins = ARRAY_SIZE(pinmux_pins),
+ .groups = pinmux_groups,
+ .nr_groups = ARRAY_SIZE(pinmux_groups),
+ .functions = pinmux_functions,
+ .nr_functions = ARRAY_SIZE(pinmux_functions),
+
+ .cfg_regs = pinmux_config_regs,
+ .drive_regs = pinmux_drive_regs,
+ .bias_regs = pinmux_bias_regs,
+ .ioctrl_regs = pinmux_ioctrl_regs,
+
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
+};
diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c
index 8f7f9a74b45..f6e8dd93374 100644
--- a/drivers/pinctrl/renesas/pfc.c
+++ b/drivers/pinctrl/renesas/pfc.c
@@ -43,6 +43,8 @@ enum sh_pfc_model {
SH_PFC_R8A77990,
SH_PFC_R8A77995,
SH_PFC_R8A779A0,
+ SH_PFC_R8A779F0,
+ SH_PFC_R8A779G0,
};
struct sh_pfc_pin_config {
@@ -810,6 +812,8 @@ static int sh_pfc_pinconf_set(struct sh_pfc_pinctrl *pmx, unsigned _pin,
void __iomem *pocctrl;
u32 addr, val;
int bit, ret;
+ int idx = sh_pfc_get_pin_index(pfc, _pin);
+ const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
if (!sh_pfc_pinconf_validate(pfc, _pin, param))
return -ENOTSUPP;
@@ -842,13 +846,13 @@ static int sh_pfc_pinconf_set(struct sh_pfc_pinctrl *pmx, unsigned _pin,
return bit;
}
- if (arg != 1800 && arg != 3300)
+ if (arg != 1800 && arg != 2500 && arg != 3300)
return -EINVAL;
pocctrl = (void __iomem *)(uintptr_t)addr;
val = sh_pfc_read_raw_reg(pocctrl, 32);
- if (arg == 3300)
+ if (arg == ((pin->configs & SH_PFC_PIN_VOLTAGE_18_25) ? 2500 : 3300))
val |= BIT(bit);
else
val &= ~BIT(bit);
@@ -1025,6 +1029,14 @@ static int sh_pfc_pinctrl_probe(struct udevice *dev)
if (model == SH_PFC_R8A779A0)
priv->pfc.info = &r8a779a0_pinmux_info;
#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A779F0
+ if (model == SH_PFC_R8A779F0)
+ priv->pfc.info = &r8a779f0_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A779G0
+ if (model == SH_PFC_R8A779G0)
+ priv->pfc.info = &r8a779g0_pinmux_info;
+#endif
priv->pmx.pfc = &priv->pfc;
sh_pfc_init_ranges(&priv->pfc);
@@ -1142,6 +1154,18 @@ static const struct udevice_id sh_pfc_pinctrl_ids[] = {
.data = SH_PFC_R8A779A0,
},
#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A779F0
+ {
+ .compatible = "renesas,pfc-r8a779f0",
+ .data = SH_PFC_R8A779F0,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A779G0
+ {
+ .compatible = "renesas,pfc-r8a779g0",
+ .data = SH_PFC_R8A779G0,
+ },
+#endif
{ },
};
diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h
index 0ab743e80d5..f35fd3379a9 100644
--- a/drivers/pinctrl/renesas/sh_pfc.h
+++ b/drivers/pinctrl/renesas/sh_pfc.h
@@ -31,11 +31,14 @@ enum {
#define SH_PFC_PIN_VOLTAGE_18_33 (0 << 6)
#define SH_PFC_PIN_VOLTAGE_25_33 (1 << 6)
+#define SH_PFC_PIN_VOLTAGE_18_25 (2 << 6)
#define SH_PFC_PIN_CFG_IO_VOLTAGE_18_33 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
SH_PFC_PIN_VOLTAGE_18_33)
#define SH_PFC_PIN_CFG_IO_VOLTAGE_25_33 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
SH_PFC_PIN_VOLTAGE_25_33)
+#define SH_PFC_PIN_CFG_IO_VOLTAGE_18_25 (SH_PFC_PIN_CFG_IO_VOLTAGE | \
+ SH_PFC_PIN_VOLTAGE_18_25)
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
@@ -309,6 +312,8 @@ extern const struct sh_pfc_soc_info r8a77980_pinmux_info;
extern const struct sh_pfc_soc_info r8a77990_pinmux_info;
extern const struct sh_pfc_soc_info r8a77995_pinmux_info;
extern const struct sh_pfc_soc_info r8a779a0_pinmux_info;
+extern const struct sh_pfc_soc_info r8a779f0_pinmux_info;
+extern const struct sh_pfc_soc_info r8a779g0_pinmux_info;
/* -----------------------------------------------------------------------------
* Helper macros to create pin and port lists
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 90461ae8819..c91f650b043 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -15,5 +15,6 @@ obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
+obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
index 935aed9efc6..314edb5a606 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3568.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
@@ -13,6 +13,12 @@
#include "pinctrl-rockchip.h"
static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
+ MR_PMUGRF(RK_GPIO0, RK_PB7, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(1, 0, 0)), /* PWM0 IO mux selection M0 */
+ MR_PMUGRF(RK_GPIO0, RK_PC7, RK_FUNC_2, 0x0110, RK_GENMASK_VAL(1, 0, 1)), /* PWM0 IO mux selection M1 */
+ MR_PMUGRF(RK_GPIO0, RK_PC0, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(3, 2, 0)), /* PWM1 IO mux selection M0 */
+ MR_PMUGRF(RK_GPIO0, RK_PB5, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(3, 2, 1)), /* PWM1 IO mux selection M1 */
+ MR_PMUGRF(RK_GPIO0, RK_PC1, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(5, 4, 0)), /* PWM2 IO mux selection M0 */
+ MR_PMUGRF(RK_GPIO0, RK_PB6, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(5, 4, 1)), /* PWM2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)), /* CAN0 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)), /* CAN0 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)), /* CAN1 IO mux selection M0 */
@@ -33,30 +39,22 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)), /* I2C4 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)), /* I2C5 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)), /* I2C5 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)), /* PWM4 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)), /* PWM4 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)), /* PWM5 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)), /* PWM5 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)), /* PWM6 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)), /* PWM6 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)), /* PWM7 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)), /* PWM7 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_5, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO1, RK_PD6, RK_FUNC_4, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PB5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO4, RK_PC0, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PC0, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO4, RK_PC6, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)), /* SDMMC2 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)), /* SDMMC2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)), /* SPI0 IO mux selection M0 */
@@ -68,7 +66,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)), /* SPI3 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)), /* SPI3 IO mux selection M1 */
MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)), /* UART1 IO mux selection M0 */
- MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)), /* UART2 IO mux selection M0 */
MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)), /* UART2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)), /* UART3 IO mux selection M0 */
@@ -81,7 +79,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)), /* UART6 IO mux selection M1 */
MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)), /* UART7 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)), /* UART7 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
+ MR_TOPGRF(RK_GPIO4, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)), /* UART8 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)), /* UART8 IO mux selection M1 */
MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)), /* UART9 IO mux selection M0 */
@@ -94,8 +92,11 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)), /* I2S2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)), /* I2S3 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)), /* I2S3 IO mux selection M1 */
- MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)), /* PDM IO mux selection M0 */
- MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)), /* PDM IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO1, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO4, RK_PA0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 2)), /* PDM IO mux selection M2 */
MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)), /* PCIE20 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)), /* PCIE20 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)), /* PCIE20 IO mux selection M2 */
@@ -237,6 +238,15 @@ static int rk3568_set_pull(struct rockchip_pin_bank *bank,
return ret;
}
+ /*
+ * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
+ * where that pull up value becomes 3.
+ */
+ if (bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
+ if (ret == 1)
+ ret = 3;
+ }
+
/* enable the write to the equivalent lower bits */
data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3588.c b/drivers/pinctrl/rockchip/pinctrl-rk3588.c
new file mode 100644
index 00000000000..548cf09bcca
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3588.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+#include <dt-bindings/pinctrl/rockchip.h>
+
+static int rk3588_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+ struct regmap *regmap;
+ int iomux_num = (pin / 8);
+ int reg, ret, mask;
+ u8 bit;
+ u32 data;
+
+ debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
+
+ regmap = priv->regmap_base;
+ reg = bank->iomux[iomux_num].offset;
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ mask = 0xf;
+
+ if (bank->bank_num == 0) {
+ if (pin >= RK_PB4 && pin <= RK_PD7) {
+ if (mux < 8) {
+ reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+ ret = regmap_write(regmap, reg, data);
+ } else {
+ u32 reg0 = 0;
+
+ reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */
+ data = (mask << (bit + 16));
+ data |= 8 << bit;
+ ret = regmap_write(regmap, reg0, data);
+
+ reg0 = reg + 0x8000; /* BUS_IOC_BASE */
+ data = (mask << (bit + 16));
+ data |= mux << bit;
+ regmap = priv->regmap_base;
+ regmap_write(regmap, reg0, data);
+ }
+ } else {
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+ ret = regmap_write(regmap, reg, data);
+ }
+ return ret;
+ } else if (bank->bank_num > 0) {
+ reg += 0x8000; /* BUS_IOC_BASE */
+ }
+
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+
+ return regmap_write(regmap, reg, data);
+}
+
+#define RK3588_PMU1_IOC_REG (0x0000)
+#define RK3588_PMU2_IOC_REG (0x4000)
+#define RK3588_BUS_IOC_REG (0x8000)
+#define RK3588_VCCIO1_4_IOC_REG (0x9000)
+#define RK3588_VCCIO3_5_IOC_REG (0xA000)
+#define RK3588_VCCIO2_IOC_REG (0xB000)
+#define RK3588_VCCIO6_IOC_REG (0xC000)
+#define RK3588_EMMC_IOC_REG (0xD000)
+
+static const u32 rk3588_ds_regs[][2] = {
+ {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010},
+ {RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014},
+ {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018},
+ {RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014},
+ {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018},
+ {RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C},
+ {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020},
+ {RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024},
+ {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020},
+ {RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024},
+ {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028},
+ {RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C},
+ {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030},
+ {RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034},
+ {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038},
+ {RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C},
+ {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040},
+ {RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044},
+ {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048},
+ {RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C},
+ {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050},
+ {RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054},
+ {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058},
+ {RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C},
+ {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060},
+ {RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064},
+ {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068},
+ {RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C},
+ {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070},
+ {RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074},
+ {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078},
+ {RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C},
+ {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080},
+ {RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084},
+ {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088},
+ {RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C},
+ {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090},
+ {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090},
+ {RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094},
+ {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098},
+ {RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C},
+};
+
+static const u32 rk3588_p_regs[][2] = {
+ {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020},
+ {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024},
+ {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028},
+ {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C},
+ {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030},
+ {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110},
+ {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114},
+ {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118},
+ {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C},
+ {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120},
+ {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120},
+ {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124},
+ {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128},
+ {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C},
+ {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130},
+ {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134},
+ {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138},
+ {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C},
+ {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140},
+ {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144},
+ {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148},
+ {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148},
+ {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C},
+};
+
+static const u32 rk3588_smt_regs[][2] = {
+ {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030},
+ {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034},
+ {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040},
+ {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044},
+ {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048},
+ {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210},
+ {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214},
+ {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218},
+ {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C},
+ {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220},
+ {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220},
+ {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224},
+ {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228},
+ {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C},
+ {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230},
+ {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234},
+ {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238},
+ {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C},
+ {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240},
+ {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244},
+ {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248},
+ {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248},
+ {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C},
+};
+
+#define RK3588_PULL_BITS_PER_PIN 2
+#define RK3588_PULL_PINS_PER_REG 8
+
+static void rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *info = bank->priv;
+ u8 bank_num = bank->bank_num;
+ u32 pin = bank_num * 32 + pin_num;
+ int i;
+
+ for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) {
+ if (pin >= rk3588_p_regs[i][0]) {
+ *reg = rk3588_p_regs[i][1];
+ break;
+ }
+ }
+
+ assert(i >= 0);
+
+ *regmap = info->regmap_base;
+ *bit = pin_num % RK3588_PULL_PINS_PER_REG;
+ *bit *= RK3588_PULL_BITS_PER_PIN;
+}
+
+#define RK3588_DRV_BITS_PER_PIN 4
+#define RK3588_DRV_PINS_PER_REG 4
+
+static void rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *info = bank->priv;
+ u8 bank_num = bank->bank_num;
+ u32 pin = bank_num * 32 + pin_num;
+ int i;
+
+ for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) {
+ if (pin >= rk3588_ds_regs[i][0]) {
+ *reg = rk3588_ds_regs[i][1];
+ break;
+ }
+ }
+
+ assert(i >= 0);
+
+ *regmap = info->regmap_base;
+ *bit = pin_num % RK3588_DRV_PINS_PER_REG;
+ *bit *= RK3588_DRV_BITS_PER_PIN;
+}
+
+#define RK3588_SMT_BITS_PER_PIN 1
+#define RK3588_SMT_PINS_PER_REG 8
+
+static int rk3588_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *info = bank->priv;
+ u8 bank_num = bank->bank_num;
+ u32 pin = bank_num * 32 + pin_num;
+ int i;
+
+ for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) {
+ if (pin >= rk3588_smt_regs[i][0]) {
+ *reg = rk3588_smt_regs[i][1];
+ break;
+ }
+ }
+
+ assert(i >= 0);
+
+ *regmap = info->regmap_base;
+ *bit = pin_num % RK3588_SMT_PINS_PER_REG;
+ *bit *= RK3588_SMT_BITS_PER_PIN;
+
+ return 0;
+}
+
+static int rk3588_set_pull(struct rockchip_pin_bank *bank,
+ int pin_num, int pull)
+{
+ struct regmap *regmap;
+ int reg, translated_pull;
+ u8 bit, type;
+ u32 data;
+
+ rk3588_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+ type = bank->pull_type[pin_num / 8];
+ translated_pull = rockchip_translate_pull_value(type, pull);
+ if (translated_pull < 0) {
+ debug("unsupported pull setting %d\n", pull);
+ return -EINVAL;
+ }
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (translated_pull << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static int rk3588_set_drive(struct rockchip_pin_bank *bank,
+ int pin_num, int strength)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data;
+ u8 bit;
+
+ rk3588_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3588_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (strength << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static int rk3588_set_schmitt(struct rockchip_pin_bank *bank,
+ int pin_num, int enable)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data;
+ u8 bit;
+
+ rk3588_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3588_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (enable << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static struct rockchip_pin_bank rk3588_pin_banks[] = {
+ RK3588_PIN_BANK_FLAGS(0, 32, "gpio0",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(1, 32, "gpio1",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(2, 32, "gpio2",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(3, 32, "gpio3",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(4, 32, "gpio4",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+};
+
+static const struct rockchip_pin_ctrl rk3588_pin_ctrl = {
+ .pin_banks = rk3588_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3588_pin_banks),
+ .nr_pins = 160,
+ .set_mux = rk3588_set_mux,
+ .set_pull = rk3588_set_pull,
+ .set_drive = rk3588_set_drive,
+ .set_schmitt = rk3588_set_schmitt,
+};
+
+static const struct udevice_id rk3588_pinctrl_ids[] = {
+ {
+ .compatible = "rockchip,rk3588-pinctrl",
+ .data = (ulong)&rk3588_pin_ctrl
+ },
+ { }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3588) = {
+ .name = "rockchip_rk3588_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = rk3588_pinctrl_ids,
+ .priv_auto = sizeof(struct rockchip_pinctrl_priv),
+ .ops = &rockchip_pinctrl_ops,
+#if CONFIG_IS_ENABLED(OF_REAL)
+ .bind = dm_scan_fdt_dev,
+#endif
+ .probe = rockchip_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
index 8dfaba5c74d..df7bc684d29 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
@@ -9,6 +9,171 @@
#include <linux/bitops.h>
#include <linux/types.h>
+#define RK_GPIO0_A0 0
+#define RK_GPIO0_A1 1
+#define RK_GPIO0_A2 2
+#define RK_GPIO0_A3 3
+#define RK_GPIO0_A4 4
+#define RK_GPIO0_A5 5
+#define RK_GPIO0_A6 6
+#define RK_GPIO0_A7 7
+#define RK_GPIO0_B0 8
+#define RK_GPIO0_B1 9
+#define RK_GPIO0_B2 10
+#define RK_GPIO0_B3 11
+#define RK_GPIO0_B4 12
+#define RK_GPIO0_B5 13
+#define RK_GPIO0_B6 14
+#define RK_GPIO0_B7 15
+#define RK_GPIO0_C0 16
+#define RK_GPIO0_C1 17
+#define RK_GPIO0_C2 18
+#define RK_GPIO0_C3 19
+#define RK_GPIO0_C4 20
+#define RK_GPIO0_C5 21
+#define RK_GPIO0_C6 22
+#define RK_GPIO0_C7 23
+#define RK_GPIO0_D0 24
+#define RK_GPIO0_D1 25
+#define RK_GPIO0_D2 26
+#define RK_GPIO0_D3 27
+#define RK_GPIO0_D4 28
+#define RK_GPIO0_D5 29
+#define RK_GPIO0_D6 30
+#define RK_GPIO0_D7 31
+
+#define RK_GPIO1_A0 32
+#define RK_GPIO1_A1 33
+#define RK_GPIO1_A2 34
+#define RK_GPIO1_A3 35
+#define RK_GPIO1_A4 36
+#define RK_GPIO1_A5 37
+#define RK_GPIO1_A6 38
+#define RK_GPIO1_A7 39
+#define RK_GPIO1_B0 40
+#define RK_GPIO1_B1 41
+#define RK_GPIO1_B2 42
+#define RK_GPIO1_B3 43
+#define RK_GPIO1_B4 44
+#define RK_GPIO1_B5 45
+#define RK_GPIO1_B6 46
+#define RK_GPIO1_B7 47
+#define RK_GPIO1_C0 48
+#define RK_GPIO1_C1 49
+#define RK_GPIO1_C2 50
+#define RK_GPIO1_C3 51
+#define RK_GPIO1_C4 52
+#define RK_GPIO1_C5 53
+#define RK_GPIO1_C6 54
+#define RK_GPIO1_C7 55
+#define RK_GPIO1_D0 56
+#define RK_GPIO1_D1 57
+#define RK_GPIO1_D2 58
+#define RK_GPIO1_D3 59
+#define RK_GPIO1_D4 60
+#define RK_GPIO1_D5 61
+#define RK_GPIO1_D6 62
+#define RK_GPIO1_D7 63
+
+#define RK_GPIO2_A0 64
+#define RK_GPIO2_A1 65
+#define RK_GPIO2_A2 66
+#define RK_GPIO2_A3 67
+#define RK_GPIO2_A4 68
+#define RK_GPIO2_A5 69
+#define RK_GPIO2_A6 70
+#define RK_GPIO2_A7 71
+#define RK_GPIO2_B0 72
+#define RK_GPIO2_B1 73
+#define RK_GPIO2_B2 74
+#define RK_GPIO2_B3 75
+#define RK_GPIO2_B4 76
+#define RK_GPIO2_B5 77
+#define RK_GPIO2_B6 78
+#define RK_GPIO2_B7 79
+#define RK_GPIO2_C0 80
+#define RK_GPIO2_C1 81
+#define RK_GPIO2_C2 82
+#define RK_GPIO2_C3 83
+#define RK_GPIO2_C4 84
+#define RK_GPIO2_C5 85
+#define RK_GPIO2_C6 86
+#define RK_GPIO2_C7 87
+#define RK_GPIO2_D0 88
+#define RK_GPIO2_D1 89
+#define RK_GPIO2_D2 90
+#define RK_GPIO2_D3 91
+#define RK_GPIO2_D4 92
+#define RK_GPIO2_D5 93
+#define RK_GPIO2_D6 94
+#define RK_GPIO2_D7 95
+
+#define RK_GPIO3_A0 96
+#define RK_GPIO3_A1 97
+#define RK_GPIO3_A2 98
+#define RK_GPIO3_A3 99
+#define RK_GPIO3_A4 100
+#define RK_GPIO3_A5 101
+#define RK_GPIO3_A6 102
+#define RK_GPIO3_A7 103
+#define RK_GPIO3_B0 104
+#define RK_GPIO3_B1 105
+#define RK_GPIO3_B2 106
+#define RK_GPIO3_B3 107
+#define RK_GPIO3_B4 108
+#define RK_GPIO3_B5 109
+#define RK_GPIO3_B6 110
+#define RK_GPIO3_B7 111
+#define RK_GPIO3_C0 112
+#define RK_GPIO3_C1 113
+#define RK_GPIO3_C2 114
+#define RK_GPIO3_C3 115
+#define RK_GPIO3_C4 116
+#define RK_GPIO3_C5 117
+#define RK_GPIO3_C6 118
+#define RK_GPIO3_C7 119
+#define RK_GPIO3_D0 120
+#define RK_GPIO3_D1 121
+#define RK_GPIO3_D2 122
+#define RK_GPIO3_D3 123
+#define RK_GPIO3_D4 124
+#define RK_GPIO3_D5 125
+#define RK_GPIO3_D6 126
+#define RK_GPIO3_D7 127
+
+#define RK_GPIO4_A0 128
+#define RK_GPIO4_A1 129
+#define RK_GPIO4_A2 130
+#define RK_GPIO4_A3 131
+#define RK_GPIO4_A4 132
+#define RK_GPIO4_A5 133
+#define RK_GPIO4_A6 134
+#define RK_GPIO4_A7 135
+#define RK_GPIO4_B0 136
+#define RK_GPIO4_B1 137
+#define RK_GPIO4_B2 138
+#define RK_GPIO4_B3 139
+#define RK_GPIO4_B4 140
+#define RK_GPIO4_B5 141
+#define RK_GPIO4_B6 142
+#define RK_GPIO4_B7 143
+#define RK_GPIO4_C0 144
+#define RK_GPIO4_C1 145
+#define RK_GPIO4_C2 146
+#define RK_GPIO4_C3 147
+#define RK_GPIO4_C4 148
+#define RK_GPIO4_C5 149
+#define RK_GPIO4_C6 150
+#define RK_GPIO4_C7 151
+#define RK_GPIO4_D0 152
+#define RK_GPIO4_D1 153
+#define RK_GPIO4_D2 154
+#define RK_GPIO4_D3 155
+#define RK_GPIO4_D4 156
+#define RK_GPIO4_D5 157
+#define RK_GPIO4_D6 158
+#define RK_GPIO4_D7 159
+
#define RK_GENMASK_VAL(h, l, v) \
(GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l))))
@@ -180,6 +345,25 @@ struct rockchip_pin_bank {
}, \
}
+#define PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(id, pins, label, iom0, iom1, \
+ iom2, iom3, pull0, pull1, \
+ pull2, pull3) \
+ { \
+ .bank_num = id, \
+ .nr_pins = pins, \
+ .name = label, \
+ .iomux = { \
+ { .type = iom0, .offset = -1 }, \
+ { .type = iom1, .offset = -1 }, \
+ { .type = iom2, .offset = -1 }, \
+ { .type = iom3, .offset = -1 }, \
+ }, \
+ .pull_type[0] = pull0, \
+ .pull_type[1] = pull1, \
+ .pull_type[2] = pull2, \
+ .pull_type[3] = pull3, \
+ }
+
#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \
drv2, drv3, pull0, pull1, \
pull2, pull3) \
@@ -274,6 +458,9 @@ struct rockchip_pin_bank {
#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
+#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P) \
+ PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P)
+
/**
* struct rockchip_mux_recalced_data: recalculate a pin iomux data.
* @num: bank number.
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
new file mode 100644
index 00000000000..1b859c863e2
--- /dev/null
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SPL_PINCTRL_STARFIVE
+ bool "Support Pinctrl driver for StarFive SoC in SPL"
+ depends on SPL_PINCTRL_FULL && STARFIVE_JH7110
+ help
+ Enable support pin control driver for StarFive SoC.
+
+config SPL_PINCTRL_STARFIVE_JH7110
+ bool "Support Pinctrl and GPIO driver for StarFive JH7110 SoC in SPL"
+ depends on SPL_PINCTRL_STARFIVE
+ help
+ Enable support pinctrl and gpio driver for StarFive JH7110 in SPL.
+
+config PINCTRL_STARFIVE
+ bool "Pinctrl driver for StarFive SoC"
+ depends on PINCTRL_FULL && STARFIVE_JH7110
+ help
+ Say yes here to support pin control on the StarFive RISC-V SoC.
+ This also provides an interface to the GPIO pins not used by other
+ peripherals supporting inputs, outputs, configuring pull-up/pull-down
+ and interrupts on input changes.
+
+config PINCTRL_STARFIVE_JH7110
+ bool "Pinctrl and GPIO driver for StarFive JH7110 SoC"
+ depends on PINCTRL_STARFIVE
+ help
+ This selects the pinctrl driver for JH7110 starfive.
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
new file mode 100644
index 00000000000..a4a12069b36
--- /dev/null
+++ b/drivers/pinctrl/starfive/Makefile
@@ -0,0 +1,6 @@
+
+# SPDX-License-Identifier: GPL-2.0
+# Core
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE) += pinctrl-starfive.o
+# SoC Drivers
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE_JH7110) += pinctrl-jh7110-sys.o pinctrl-jh7110-aon.o
diff --git a/drivers/pinctrl/starfive/pinctrl-jh7110-aon.c b/drivers/pinctrl/starfive/pinctrl-jh7110-aon.c
new file mode 100644
index 00000000000..2d739906e24
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-jh7110-aon.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Lee Kuan Lim <[email protected]>
+ * Author: Jianlong Huang <[email protected]>
+ */
+
+#include <dm/read.h>
+#include <dm/device_compat.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+#include "pinctrl-starfive.h"
+
+#define JH7110_AON_NGPIO 4
+#define JH7110_AON_GC_BASE 64
+
+/* registers */
+#define JH7110_AON_DOEN 0x0
+#define JH7110_AON_DOUT 0x4
+#define JH7110_AON_GPI 0x8
+#define JH7110_AON_GPIOIN 0x2c
+
+#define JH7110_AON_GPIOEN 0xc
+#define JH7110_AON_GPIOIS 0x10
+#define JH7110_AON_GPIOIC 0x14
+#define JH7110_AON_GPIOIBE 0x18
+#define JH7110_AON_GPIOIEV 0x1c
+#define JH7110_AON_GPIOIE 0x20
+#define JH7110_AON_GPIORIS 0x28
+#define JH7110_AON_GPIOMIS 0x28
+
+#define AON_GPO_PDA_0_5_CFG 0x30
+
+static int jh7110_aon_set_one_pin_mux(struct udevice *dev, unsigned int pin,
+ unsigned int din, u32 dout,
+ u32 doen, u32 func)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+ if (pin < priv->info->ngpios && func == 0)
+ starfive_set_gpiomux(dev, pin, din, dout, doen);
+
+ return 0;
+}
+
+static int jh7110_aon_get_padcfg_base(struct udevice *dev,
+ unsigned int pin)
+{
+ if (pin < PAD_GMAC0_MDC)
+ return AON_GPO_PDA_0_5_CFG;
+
+ return -1;
+}
+
+static void jh7110_aon_init_hw(struct udevice *dev)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+ /* mask all GPIO interrupts */
+ writel(0, priv->base + JH7110_AON_GPIOIE);
+ /* clear edge interrupt flags */
+ writel(0, priv->base + JH7110_AON_GPIOIC);
+ writel(0x0f, priv->base + JH7110_AON_GPIOIC);
+ /* enable GPIO interrupts */
+ writel(1, priv->base + JH7110_AON_GPIOEN);
+}
+
+const struct starfive_pinctrl_soc_info jh7110_aon_pinctrl_info = {
+ /* pin conf */
+ .set_one_pinmux = jh7110_aon_set_one_pin_mux,
+ .get_padcfg_base = jh7110_aon_get_padcfg_base,
+
+ /* gpio dout/doen/din/gpioinput register */
+ .dout_reg_base = JH7110_AON_DOUT,
+ .dout_mask = GENMASK(3, 0),
+ .doen_reg_base = JH7110_AON_DOEN,
+ .doen_mask = GENMASK(2, 0),
+ .gpi_reg_base = JH7110_AON_GPI,
+ .gpi_mask = GENMASK(3, 0),
+ .gpioin_reg_base = JH7110_AON_GPIOIN,
+
+ /* gpio */
+ .gpio_bank_name = "RGPIO",
+ .ngpios = JH7110_AON_NGPIO,
+ .gpio_init_hw = jh7110_aon_init_hw,
+};
+
+static int jh7110_aon_pinctrl_probe(struct udevice *dev)
+{
+ struct starfive_pinctrl_soc_info *info =
+ (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+
+ return starfive_pinctrl_probe(dev, info);
+}
+
+static const struct udevice_id jh7110_aon_pinctrl_ids[] = {
+ /* JH7110 aon pinctrl */
+ { .compatible = "starfive,jh7110-aon-pinctrl",
+ .data = (ulong)&jh7110_aon_pinctrl_info, },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(jh7110_aon_pinctrl) = {
+ .name = "jh7110-aon-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = jh7110_aon_pinctrl_ids,
+ .priv_auto = sizeof(struct starfive_pinctrl_priv),
+ .ops = &starfive_pinctrl_ops,
+ .probe = jh7110_aon_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c b/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
new file mode 100644
index 00000000000..dafba65eae1
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Lee Kuan Lim <[email protected]>
+ * Author: Jianlong Huang <[email protected]>
+ */
+
+#include <dm/read.h>
+#include <dm/device_compat.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+#include "pinctrl-starfive.h"
+
+#define JH7110_SYS_NGPIO 64
+#define JH7110_SYS_GC_BASE 0
+
+/* registers */
+#define JH7110_SYS_DOEN 0x000
+#define JH7110_SYS_DOUT 0x040
+#define JH7110_SYS_GPI 0x080
+#define JH7110_SYS_GPIOIN 0x118
+
+#define JH7110_SYS_GPIOEN 0x0dc
+#define JH7110_SYS_GPIOIS0 0x0e0
+#define JH7110_SYS_GPIOIS1 0x0e4
+#define JH7110_SYS_GPIOIC0 0x0e8
+#define JH7110_SYS_GPIOIC1 0x0ec
+#define JH7110_SYS_GPIOIBE0 0x0f0
+#define JH7110_SYS_GPIOIBE1 0x0f4
+#define JH7110_SYS_GPIOIEV0 0x0f8
+#define JH7110_SYS_GPIOIEV1 0x0fc
+#define JH7110_SYS_GPIOIE0 0x100
+#define JH7110_SYS_GPIOIE1 0x104
+#define JH7110_SYS_GPIORIS0 0x108
+#define JH7110_SYS_GPIORIS1 0x10c
+#define JH7110_SYS_GPIOMIS0 0x110
+#define JH7110_SYS_GPIOMIS1 0x114
+
+#define SYS_GPO_PDA_0_74_CFG 0x120
+#define SYS_GPO_PDA_89_94_CFG 0x284
+
+static const struct starfive_pinctrl_pin jh7110_sys_pins[] = {
+ STARFIVE_PINCTRL(PAD_GPIO0, "GPIO0"),
+ STARFIVE_PINCTRL(PAD_GPIO1, "GPIO1"),
+ STARFIVE_PINCTRL(PAD_GPIO2, "GPIO2"),
+ STARFIVE_PINCTRL(PAD_GPIO3, "GPIO3"),
+ STARFIVE_PINCTRL(PAD_GPIO4, "GPIO4"),
+ STARFIVE_PINCTRL(PAD_GPIO5, "GPIO5"),
+ STARFIVE_PINCTRL(PAD_GPIO6, "GPIO6"),
+ STARFIVE_PINCTRL(PAD_GPIO7, "GPIO7"),
+ STARFIVE_PINCTRL(PAD_GPIO8, "GPIO8"),
+ STARFIVE_PINCTRL(PAD_GPIO9, "GPIO9"),
+ STARFIVE_PINCTRL(PAD_GPIO10, "GPIO10"),
+ STARFIVE_PINCTRL(PAD_GPIO11, "GPIO11"),
+ STARFIVE_PINCTRL(PAD_GPIO12, "GPIO12"),
+ STARFIVE_PINCTRL(PAD_GPIO13, "GPIO13"),
+ STARFIVE_PINCTRL(PAD_GPIO14, "GPIO14"),
+ STARFIVE_PINCTRL(PAD_GPIO15, "GPIO15"),
+ STARFIVE_PINCTRL(PAD_GPIO16, "GPIO16"),
+ STARFIVE_PINCTRL(PAD_GPIO17, "GPIO17"),
+ STARFIVE_PINCTRL(PAD_GPIO18, "GPIO18"),
+ STARFIVE_PINCTRL(PAD_GPIO19, "GPIO19"),
+ STARFIVE_PINCTRL(PAD_GPIO20, "GPIO20"),
+ STARFIVE_PINCTRL(PAD_GPIO21, "GPIO21"),
+ STARFIVE_PINCTRL(PAD_GPIO22, "GPIO22"),
+ STARFIVE_PINCTRL(PAD_GPIO23, "GPIO23"),
+ STARFIVE_PINCTRL(PAD_GPIO24, "GPIO24"),
+ STARFIVE_PINCTRL(PAD_GPIO25, "GPIO25"),
+ STARFIVE_PINCTRL(PAD_GPIO26, "GPIO26"),
+ STARFIVE_PINCTRL(PAD_GPIO27, "GPIO27"),
+ STARFIVE_PINCTRL(PAD_GPIO28, "GPIO28"),
+ STARFIVE_PINCTRL(PAD_GPIO29, "GPIO29"),
+ STARFIVE_PINCTRL(PAD_GPIO30, "GPIO30"),
+ STARFIVE_PINCTRL(PAD_GPIO31, "GPIO31"),
+ STARFIVE_PINCTRL(PAD_GPIO32, "GPIO32"),
+ STARFIVE_PINCTRL(PAD_GPIO33, "GPIO33"),
+ STARFIVE_PINCTRL(PAD_GPIO34, "GPIO34"),
+ STARFIVE_PINCTRL(PAD_GPIO35, "GPIO35"),
+ STARFIVE_PINCTRL(PAD_GPIO36, "GPIO36"),
+ STARFIVE_PINCTRL(PAD_GPIO37, "GPIO37"),
+ STARFIVE_PINCTRL(PAD_GPIO38, "GPIO38"),
+ STARFIVE_PINCTRL(PAD_GPIO39, "GPIO39"),
+ STARFIVE_PINCTRL(PAD_GPIO40, "GPIO40"),
+ STARFIVE_PINCTRL(PAD_GPIO41, "GPIO41"),
+ STARFIVE_PINCTRL(PAD_GPIO42, "GPIO42"),
+ STARFIVE_PINCTRL(PAD_GPIO43, "GPIO43"),
+ STARFIVE_PINCTRL(PAD_GPIO44, "GPIO44"),
+ STARFIVE_PINCTRL(PAD_GPIO45, "GPIO45"),
+ STARFIVE_PINCTRL(PAD_GPIO46, "GPIO46"),
+ STARFIVE_PINCTRL(PAD_GPIO47, "GPIO47"),
+ STARFIVE_PINCTRL(PAD_GPIO48, "GPIO48"),
+ STARFIVE_PINCTRL(PAD_GPIO49, "GPIO49"),
+ STARFIVE_PINCTRL(PAD_GPIO50, "GPIO50"),
+ STARFIVE_PINCTRL(PAD_GPIO51, "GPIO51"),
+ STARFIVE_PINCTRL(PAD_GPIO52, "GPIO52"),
+ STARFIVE_PINCTRL(PAD_GPIO53, "GPIO53"),
+ STARFIVE_PINCTRL(PAD_GPIO54, "GPIO54"),
+ STARFIVE_PINCTRL(PAD_GPIO55, "GPIO55"),
+ STARFIVE_PINCTRL(PAD_GPIO56, "GPIO56"),
+ STARFIVE_PINCTRL(PAD_GPIO57, "GPIO57"),
+ STARFIVE_PINCTRL(PAD_GPIO58, "GPIO58"),
+ STARFIVE_PINCTRL(PAD_GPIO59, "GPIO59"),
+ STARFIVE_PINCTRL(PAD_GPIO60, "GPIO60"),
+ STARFIVE_PINCTRL(PAD_GPIO61, "GPIO61"),
+ STARFIVE_PINCTRL(PAD_GPIO62, "GPIO62"),
+ STARFIVE_PINCTRL(PAD_GPIO63, "GPIO63"),
+ STARFIVE_PINCTRL(PAD_SD0_CLK, "SD0_CLK"),
+ STARFIVE_PINCTRL(PAD_SD0_CMD, "SD0_CMD"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA0, "SD0_DATA0"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA1, "SD0_DATA1"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA2, "SD0_DATA2"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA3, "SD0_DATA3"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA4, "SD0_DATA4"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA5, "SD0_DATA5"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA6, "SD0_DATA6"),
+ STARFIVE_PINCTRL(PAD_SD0_DATA7, "SD0_DATA7"),
+ STARFIVE_PINCTRL(PAD_SD0_STRB, "SD0_STRB"),
+ STARFIVE_PINCTRL(PAD_GMAC1_MDC, "GMAC1_MDC"),
+ STARFIVE_PINCTRL(PAD_GMAC1_MDIO, "GMAC1_MDIO"),
+ STARFIVE_PINCTRL(PAD_GMAC1_RXD0, "GMAC1_RXD0"),
+ STARFIVE_PINCTRL(PAD_GMAC1_RXD1, "GMAC1_RXD1"),
+ STARFIVE_PINCTRL(PAD_GMAC1_RXD2, "GMAC1_RXD2"),
+ STARFIVE_PINCTRL(PAD_GMAC1_RXD3, "GMAC1_RXD3"),
+ STARFIVE_PINCTRL(PAD_GMAC1_RXDV, "GMAC1_RXDV"),
+ STARFIVE_PINCTRL(PAD_GMAC1_RXC, "GMAC1_RXC"),
+ STARFIVE_PINCTRL(PAD_GMAC1_TXD0, "GMAC1_TXD0"),
+ STARFIVE_PINCTRL(PAD_GMAC1_TXD1, "GMAC1_TXD1"),
+ STARFIVE_PINCTRL(PAD_GMAC1_TXD2, "GMAC1_TXD2"),
+ STARFIVE_PINCTRL(PAD_GMAC1_TXD3, "GMAC1_TXD3"),
+ STARFIVE_PINCTRL(PAD_GMAC1_TXEN, "GMAC1_TXEN"),
+ STARFIVE_PINCTRL(PAD_GMAC1_TXC, "GMAC1_TXC"),
+ STARFIVE_PINCTRL(PAD_QSPI_SCLK, "QSPI_SCLK"),
+ STARFIVE_PINCTRL(PAD_QSPI_CS0, "QSPI_CS0"),
+ STARFIVE_PINCTRL(PAD_QSPI_DATA0, "QSPI_DATA0"),
+ STARFIVE_PINCTRL(PAD_QSPI_DATA1, "QSPI_DATA1"),
+ STARFIVE_PINCTRL(PAD_QSPI_DATA2, "QSPI_DATA2"),
+ STARFIVE_PINCTRL(PAD_QSPI_DATA3, "QSPI_DATA3"),
+};
+
+struct jh7110_func_sel {
+ u16 offset;
+ u8 shift;
+ u8 max;
+};
+
+static const struct jh7110_func_sel
+ jh7110_sys_func_sel[ARRAY_SIZE(jh7110_sys_pins)] = {
+ [PAD_GMAC1_RXC] = { 0x29c, 0, 1 },
+ [PAD_GPIO10] = { 0x29c, 2, 3 },
+ [PAD_GPIO11] = { 0x29c, 5, 3 },
+ [PAD_GPIO12] = { 0x29c, 8, 3 },
+ [PAD_GPIO13] = { 0x29c, 11, 3 },
+ [PAD_GPIO14] = { 0x29c, 14, 3 },
+ [PAD_GPIO15] = { 0x29c, 17, 3 },
+ [PAD_GPIO16] = { 0x29c, 20, 3 },
+ [PAD_GPIO17] = { 0x29c, 23, 3 },
+ [PAD_GPIO18] = { 0x29c, 26, 3 },
+ [PAD_GPIO19] = { 0x29c, 29, 3 },
+
+ [PAD_GPIO20] = { 0x2a0, 0, 3 },
+ [PAD_GPIO21] = { 0x2a0, 3, 3 },
+ [PAD_GPIO22] = { 0x2a0, 6, 3 },
+ [PAD_GPIO23] = { 0x2a0, 9, 3 },
+ [PAD_GPIO24] = { 0x2a0, 12, 3 },
+ [PAD_GPIO25] = { 0x2a0, 15, 3 },
+ [PAD_GPIO26] = { 0x2a0, 18, 3 },
+ [PAD_GPIO27] = { 0x2a0, 21, 3 },
+ [PAD_GPIO28] = { 0x2a0, 24, 3 },
+ [PAD_GPIO29] = { 0x2a0, 27, 3 },
+
+ [PAD_GPIO30] = { 0x2a4, 0, 3 },
+ [PAD_GPIO31] = { 0x2a4, 3, 3 },
+ [PAD_GPIO32] = { 0x2a4, 6, 3 },
+ [PAD_GPIO33] = { 0x2a4, 9, 3 },
+ [PAD_GPIO34] = { 0x2a4, 12, 3 },
+ [PAD_GPIO35] = { 0x2a4, 15, 3 },
+ [PAD_GPIO36] = { 0x2a4, 17, 3 },
+ [PAD_GPIO37] = { 0x2a4, 20, 3 },
+ [PAD_GPIO38] = { 0x2a4, 23, 3 },
+ [PAD_GPIO39] = { 0x2a4, 26, 3 },
+ [PAD_GPIO40] = { 0x2a4, 29, 3 },
+
+ [PAD_GPIO41] = { 0x2a8, 0, 3 },
+ [PAD_GPIO42] = { 0x2a8, 3, 3 },
+ [PAD_GPIO43] = { 0x2a8, 6, 3 },
+ [PAD_GPIO44] = { 0x2a8, 9, 3 },
+ [PAD_GPIO45] = { 0x2a8, 12, 3 },
+ [PAD_GPIO46] = { 0x2a8, 15, 3 },
+ [PAD_GPIO47] = { 0x2a8, 18, 3 },
+ [PAD_GPIO48] = { 0x2a8, 21, 3 },
+ [PAD_GPIO49] = { 0x2a8, 24, 3 },
+ [PAD_GPIO50] = { 0x2a8, 27, 3 },
+ [PAD_GPIO51] = { 0x2a8, 30, 3 },
+
+ [PAD_GPIO52] = { 0x2ac, 0, 3 },
+ [PAD_GPIO53] = { 0x2ac, 2, 3 },
+ [PAD_GPIO54] = { 0x2ac, 4, 3 },
+ [PAD_GPIO55] = { 0x2ac, 6, 3 },
+ [PAD_GPIO56] = { 0x2ac, 9, 3 },
+ [PAD_GPIO57] = { 0x2ac, 12, 3 },
+ [PAD_GPIO58] = { 0x2ac, 15, 3 },
+ [PAD_GPIO59] = { 0x2ac, 18, 3 },
+ [PAD_GPIO60] = { 0x2ac, 21, 3 },
+ [PAD_GPIO61] = { 0x2ac, 24, 3 },
+ [PAD_GPIO62] = { 0x2ac, 27, 3 },
+ [PAD_GPIO63] = { 0x2ac, 30, 3 },
+
+ [PAD_GPIO6] = { 0x2b0, 0, 3 },
+ [PAD_GPIO7] = { 0x2b0, 2, 3 },
+ [PAD_GPIO8] = { 0x2b0, 5, 3 },
+ [PAD_GPIO9] = { 0x2b0, 8, 3 },
+};
+
+struct jh7110_vin_group_sel {
+ u16 offset;
+ u8 shift;
+ u8 group;
+};
+
+static const struct jh7110_vin_group_sel
+ jh7110_sys_vin_group_sel[ARRAY_SIZE(jh7110_sys_pins)] = {
+ [PAD_GPIO6] = { 0x2b4, 21, 0 },
+ [PAD_GPIO7] = { 0x2b4, 18, 0 },
+ [PAD_GPIO8] = { 0x2b4, 15, 0 },
+ [PAD_GPIO9] = { 0x2b0, 11, 0 },
+ [PAD_GPIO10] = { 0x2b0, 20, 0 },
+ [PAD_GPIO11] = { 0x2b0, 23, 0 },
+ [PAD_GPIO12] = { 0x2b0, 26, 0 },
+ [PAD_GPIO13] = { 0x2b0, 29, 0 },
+ [PAD_GPIO14] = { 0x2b4, 0, 0 },
+ [PAD_GPIO15] = { 0x2b4, 3, 0 },
+ [PAD_GPIO16] = { 0x2b4, 6, 0 },
+ [PAD_GPIO17] = { 0x2b4, 9, 0 },
+ [PAD_GPIO18] = { 0x2b4, 12, 0 },
+ [PAD_GPIO19] = { 0x2b0, 14, 0 },
+ [PAD_GPIO20] = { 0x2b0, 17, 0 },
+
+ [PAD_GPIO21] = { 0x2b4, 21, 1 },
+ [PAD_GPIO22] = { 0x2b4, 18, 1 },
+ [PAD_GPIO23] = { 0x2b4, 15, 1 },
+ [PAD_GPIO24] = { 0x2b0, 11, 1 },
+ [PAD_GPIO25] = { 0x2b0, 20, 1 },
+ [PAD_GPIO26] = { 0x2b0, 23, 1 },
+ [PAD_GPIO27] = { 0x2b0, 26, 1 },
+ [PAD_GPIO28] = { 0x2b0, 29, 1 },
+ [PAD_GPIO29] = { 0x2b4, 0, 1 },
+ [PAD_GPIO30] = { 0x2b4, 3, 1 },
+ [PAD_GPIO31] = { 0x2b4, 6, 1 },
+ [PAD_GPIO32] = { 0x2b4, 9, 1 },
+ [PAD_GPIO33] = { 0x2b4, 12, 1 },
+ [PAD_GPIO34] = { 0x2b0, 14, 1 },
+ [PAD_GPIO35] = { 0x2b0, 17, 1 },
+
+ [PAD_GPIO36] = { 0x2b4, 21, 2 },
+ [PAD_GPIO37] = { 0x2b4, 18, 2 },
+ [PAD_GPIO38] = { 0x2b4, 15, 2 },
+ [PAD_GPIO39] = { 0x2b0, 11, 2 },
+ [PAD_GPIO40] = { 0x2b0, 20, 2 },
+ [PAD_GPIO41] = { 0x2b0, 23, 2 },
+ [PAD_GPIO42] = { 0x2b0, 26, 2 },
+ [PAD_GPIO43] = { 0x2b0, 29, 2 },
+ [PAD_GPIO44] = { 0x2b4, 0, 2 },
+ [PAD_GPIO45] = { 0x2b4, 3, 2 },
+ [PAD_GPIO46] = { 0x2b4, 6, 2 },
+ [PAD_GPIO47] = { 0x2b4, 9, 2 },
+ [PAD_GPIO48] = { 0x2b4, 12, 2 },
+ [PAD_GPIO49] = { 0x2b0, 14, 2 },
+ [PAD_GPIO50] = { 0x2b0, 17, 2 },
+};
+
+static void jh7110_set_function(struct udevice *dev,
+ unsigned int pin, u32 func)
+{
+ const struct jh7110_func_sel *fs = &jh7110_sys_func_sel[pin];
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+ void __iomem *reg;
+ u32 mask;
+
+ if (!fs->offset)
+ return;
+
+ if (func > fs->max)
+ return;
+
+ reg = priv->base + fs->offset;
+ func = func << fs->shift;
+ mask = 0x3U << fs->shift;
+
+ func |= readl(reg) & ~mask;
+ writel(func, reg);
+}
+
+static void jh7110_set_vin_group(struct udevice *dev, unsigned int pin)
+{
+ const struct jh7110_vin_group_sel *gs =
+ &jh7110_sys_vin_group_sel[pin];
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+ void __iomem *reg;
+ u32 mask;
+ u32 grp;
+
+ if (!gs->offset)
+ return;
+
+ reg = priv->base + gs->offset;
+ grp = gs->group << gs->shift;
+ mask = 0x3U << gs->shift;
+
+ grp |= readl(reg) & ~mask;
+ writel(grp, reg);
+}
+
+static int jh7110_sys_set_one_pin_mux(struct udevice *dev, unsigned int pin,
+ unsigned int din, u32 dout, u32 doen, u32 func)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+ if (pin < priv->info->ngpios && func == 0)
+ starfive_set_gpiomux(dev, pin, din, dout, doen);
+
+ jh7110_set_function(dev, pin, func);
+
+ if (pin < priv->info->ngpios && func == 2)
+ jh7110_set_vin_group(dev, pin);
+
+ return 0;
+}
+
+static int jh7110_sys_get_padcfg_base(struct udevice *dev,
+ unsigned int pin)
+{
+ if (pin < PAD_GMAC1_MDC)
+ return SYS_GPO_PDA_0_74_CFG;
+ else if (pin > PAD_GMAC1_TXC && pin <= PAD_QSPI_DATA3)
+ return SYS_GPO_PDA_89_94_CFG;
+ else
+ return -1;
+}
+
+static void jh7110_sys_init_hw(struct udevice *dev)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+ /* mask all GPIO interrupts */
+ writel(0U, priv->base + JH7110_SYS_GPIOIE0);
+ writel(0U, priv->base + JH7110_SYS_GPIOIE1);
+ /* clear edge interrupt flags */
+ writel(~0U, priv->base + JH7110_SYS_GPIOIC0);
+ writel(~0U, priv->base + JH7110_SYS_GPIOIC1);
+ /* enable GPIO interrupts */
+ writel(1U, priv->base + JH7110_SYS_GPIOEN);
+}
+
+const struct starfive_pinctrl_soc_info jh7110_sys_pinctrl_info = {
+ /* pin conf */
+ .set_one_pinmux = jh7110_sys_set_one_pin_mux,
+ .get_padcfg_base = jh7110_sys_get_padcfg_base,
+
+ /* gpio dout/doen/din/gpioinput register */
+ .dout_reg_base = JH7110_SYS_DOUT,
+ .dout_mask = GENMASK(6, 0),
+ .doen_reg_base = JH7110_SYS_DOEN,
+ .doen_mask = GENMASK(5, 0),
+ .gpi_reg_base = JH7110_SYS_GPI,
+ .gpi_mask = GENMASK(6, 0),
+ .gpioin_reg_base = JH7110_SYS_GPIOIN,
+
+ /* gpio */
+ .gpio_bank_name = "GPIO",
+ .ngpios = JH7110_SYS_NGPIO,
+ .gpio_init_hw = jh7110_sys_init_hw,
+};
+
+static int jh7110_sys_pinctrl_probe(struct udevice *dev)
+{
+ struct starfive_pinctrl_soc_info *info =
+ (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+
+ return starfive_pinctrl_probe(dev, info);
+}
+
+static const struct udevice_id jh7110_sys_pinctrl_ids[] = {
+ /* JH7110 sys pinctrl */
+ { .compatible = "starfive,jh7110-sys-pinctrl",
+ .data = (ulong)&jh7110_sys_pinctrl_info, },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(jh7110_sys_pinctrl) = {
+ .name = "jh7110-sys-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = jh7110_sys_pinctrl_ids,
+ .priv_auto = sizeof(struct starfive_pinctrl_priv),
+ .ops = &starfive_pinctrl_ops,
+ .probe = jh7110_sys_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.c b/drivers/pinctrl/starfive/pinctrl-starfive.c
new file mode 100644
index 00000000000..9b09cc21cfa
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.c
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7100 SoC
+ *
+ * Copyright (C) 2022 Shanghai StarFive Technology Co., Ltd.
+ * Author: Lee Kuan Lim <[email protected]>
+ * Author: Jianlong Huang <[email protected]>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <asm-generic/gpio.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <dm/device_compat.h>
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+
+#include "pinctrl-starfive.h"
+
+/* pad control bits */
+#define STARFIVE_PADCFG_POS BIT(7)
+#define STARFIVE_PADCFG_SMT BIT(6)
+#define STARFIVE_PADCFG_SLEW BIT(5)
+#define STARFIVE_PADCFG_PD BIT(4)
+#define STARFIVE_PADCFG_PU BIT(3)
+#define STARFIVE_PADCFG_BIAS (STARFIVE_PADCFG_PD | STARFIVE_PADCFG_PU)
+#define STARFIVE_PADCFG_DS_MASK GENMASK(2, 1)
+#define STARFIVE_PADCFG_DS_2MA (0U << 1)
+#define STARFIVE_PADCFG_DS_4MA BIT(1)
+#define STARFIVE_PADCFG_DS_8MA (2U << 1)
+#define STARFIVE_PADCFG_DS_12MA (3U << 1)
+#define STARFIVE_PADCFG_IE BIT(0)
+#define GPIO_NUM_PER_WORD 32
+
+/*
+ * The packed pinmux values from the device tree look like this:
+ *
+ * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
+ * | din | dout | doen | function | pin |
+ */
+static unsigned int starfive_pinmux_din(u32 v)
+{
+ return (v & GENMASK(31, 24)) >> 24;
+}
+
+static u32 starfive_pinmux_dout(u32 v)
+{
+ return (v & GENMASK(23, 16)) >> 16;
+}
+
+static u32 starfive_pinmux_doen(u32 v)
+{
+ return (v & GENMASK(15, 10)) >> 10;
+}
+
+static u32 starfive_pinmux_function(u32 v)
+{
+ return (v & GENMASK(9, 8)) >> 8;
+}
+
+static unsigned int starfive_pinmux_pin(u32 v)
+{
+ return v & GENMASK(7, 0);
+}
+
+void starfive_set_gpiomux(struct udevice *dev, unsigned int pin,
+ unsigned int din, u32 dout, u32 doen)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct starfive_pinctrl_soc_info *info = priv->info;
+
+ unsigned int offset = 4 * (pin / 4);
+ unsigned int shift = 8 * (pin % 4);
+ u32 dout_mask = info->dout_mask << shift;
+ u32 done_mask = info->doen_mask << shift;
+ u32 ival, imask;
+ void __iomem *reg_dout;
+ void __iomem *reg_doen;
+ void __iomem *reg_din;
+
+ reg_dout = priv->base + info->dout_reg_base + offset;
+ reg_doen = priv->base + info->doen_reg_base + offset;
+ dout <<= shift;
+ doen <<= shift;
+ if (din != GPI_NONE) {
+ unsigned int ioffset = 4 * (din / 4);
+ unsigned int ishift = 8 * (din % 4);
+
+ reg_din = priv->base + info->gpi_reg_base + ioffset;
+ ival = (pin + 2) << ishift;
+ imask = info->gpi_mask << ishift;
+ } else {
+ reg_din = NULL;
+ }
+
+ dout |= readl(reg_dout) & ~dout_mask;
+ writel(dout, reg_dout);
+ doen |= readl(reg_doen) & ~done_mask;
+ writel(doen, reg_doen);
+ if (reg_din) {
+ ival |= readl(reg_din) & ~imask;
+ writel(ival, reg_din);
+ }
+}
+
+static const struct pinconf_param starfive_pinconf_params[] = {
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+ { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+ { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+ { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+ { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
+ { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
+};
+
+static const u8 starfive_drive_strength_mA[4] = { 2, 4, 8, 12 };
+
+static u32 starfive_padcfg_ds_from_mA(u32 v)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (v <= starfive_drive_strength_mA[i])
+ break;
+ }
+ return i << 1;
+}
+
+static void starfive_padcfg_rmw(struct udevice *dev,
+ unsigned int pin, u32 mask, u32 value)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+ void __iomem *reg;
+ int padcfg_base;
+
+ if (!info->get_padcfg_base)
+ return;
+
+ padcfg_base = info->get_padcfg_base(dev, pin);
+ if (padcfg_base < 0)
+ return;
+
+ reg = priv->base + padcfg_base + 4 * pin;
+ value &= mask;
+
+ value |= readl(reg) & ~mask;
+ writel(value, reg);
+}
+
+static int starfive_pinconf_set(struct udevice *dev, unsigned int pin,
+ unsigned int param, unsigned int arg)
+{
+ u16 mask = 0;
+ u16 value = 0;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ mask |= STARFIVE_PADCFG_BIAS;
+ value &= ~STARFIVE_PADCFG_BIAS;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (arg == 0)
+ return -EINVAL;
+ mask |= STARFIVE_PADCFG_BIAS;
+ value = (value & ~STARFIVE_PADCFG_BIAS) | STARFIVE_PADCFG_PD;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (arg == 0)
+ return -EINVAL;
+ mask |= STARFIVE_PADCFG_BIAS;
+ value = (value & ~STARFIVE_PADCFG_BIAS) | STARFIVE_PADCFG_PU;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ mask |= STARFIVE_PADCFG_DS_MASK;
+ value = (value & ~STARFIVE_PADCFG_DS_MASK) |
+ starfive_padcfg_ds_from_mA(arg);
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ mask |= STARFIVE_PADCFG_IE;
+ if (arg)
+ value |= STARFIVE_PADCFG_IE;
+ else
+ value &= ~STARFIVE_PADCFG_IE;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ mask |= STARFIVE_PADCFG_SMT;
+ if (arg)
+ value |= STARFIVE_PADCFG_SMT;
+ else
+ value &= ~STARFIVE_PADCFG_SMT;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ mask |= STARFIVE_PADCFG_SLEW;
+ if (arg)
+ value |= STARFIVE_PADCFG_SLEW;
+ else
+ value &= ~STARFIVE_PADCFG_SLEW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ starfive_padcfg_rmw(dev, pin, mask, value);
+
+ return 0;
+}
+
+static int starfive_property_set(struct udevice *dev, u32 pinmux_group)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ if (info->set_one_pinmux)
+ info->set_one_pinmux(dev,
+ starfive_pinmux_pin(pinmux_group),
+ starfive_pinmux_din(pinmux_group),
+ starfive_pinmux_dout(pinmux_group),
+ starfive_pinmux_doen(pinmux_group),
+ starfive_pinmux_function(pinmux_group));
+
+ return starfive_pinmux_pin(pinmux_group);
+}
+
+const struct pinctrl_ops starfive_pinctrl_ops = {
+ .set_state = pinctrl_generic_set_state,
+ .pinconf_num_params = ARRAY_SIZE(starfive_pinconf_params),
+ .pinconf_params = starfive_pinconf_params,
+ .pinconf_set = starfive_pinconf_set,
+ .pinmux_property_set = starfive_property_set,
+};
+
+static int starfive_gpio_get_direction(struct udevice *dev, unsigned int off)
+{
+ struct udevice *pdev = dev->parent;
+ struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ unsigned int offset = 4 * (off / 4);
+ unsigned int shift = 8 * (off % 4);
+ u32 doen = readl(priv->base + info->doen_reg_base + offset);
+
+ doen = (doen >> shift) & info->doen_mask;
+
+ return doen == GPOEN_ENABLE ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int starfive_gpio_direction_input(struct udevice *dev, unsigned int off)
+{
+ struct udevice *pdev = dev->parent;
+ struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ /* enable input and schmitt trigger */
+ starfive_padcfg_rmw(pdev, off,
+ STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT,
+ STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT);
+
+ if (info->set_one_pinmux)
+ info->set_one_pinmux(pdev, off,
+ GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0);
+
+ return 0;
+}
+
+static int starfive_gpio_direction_output(struct udevice *dev,
+ unsigned int off, int val)
+{
+ struct udevice *pdev = dev->parent;
+ struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ if (info->set_one_pinmux)
+ info->set_one_pinmux(pdev, off,
+ GPI_NONE, val ? GPOUT_HIGH : GPOUT_LOW,
+ GPOEN_ENABLE, 0);
+
+ /* disable input, schmitt trigger and bias */
+ starfive_padcfg_rmw(pdev, off,
+ STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT
+ | STARFIVE_PADCFG_BIAS,
+ 0);
+
+ return 0;
+}
+
+static int starfive_gpio_get_value(struct udevice *dev, unsigned int off)
+{
+ struct udevice *pdev = dev->parent;
+ struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ void __iomem *reg = priv->base + info->gpioin_reg_base
+ + 4 * (off / GPIO_NUM_PER_WORD);
+
+ return !!(readl(reg) & BIT(off % GPIO_NUM_PER_WORD));
+}
+
+static int starfive_gpio_set_value(struct udevice *dev,
+ unsigned int off, int val)
+{
+ struct udevice *pdev = dev->parent;
+ struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ unsigned int offset = 4 * (off / 4);
+ unsigned int shift = 8 * (off % 4);
+ void __iomem *reg_dout = priv->base + info->dout_reg_base + offset;
+ u32 dout = (val ? GPOUT_HIGH : GPOUT_LOW) << shift;
+ u32 mask = info->dout_mask << shift;
+
+ dout |= readl(reg_dout) & ~mask;
+ writel(dout, reg_dout);
+
+ return 0;
+}
+
+static int starfive_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv;
+ struct udevice *pdev = dev->parent;
+ struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+ struct starfive_pinctrl_soc_info *info = priv->info;
+
+ uc_priv = dev_get_uclass_priv(dev);
+ uc_priv->bank_name = info->gpio_bank_name;
+ uc_priv->gpio_count = info->ngpios;
+
+ if (!info->gpio_init_hw)
+ return -ENXIO;
+
+ info->gpio_init_hw(pdev);
+
+ return 0;
+}
+
+static const struct dm_gpio_ops starfive_gpio_ops = {
+ .get_function = starfive_gpio_get_direction,
+ .direction_input = starfive_gpio_direction_input,
+ .direction_output = starfive_gpio_direction_output,
+ .get_value = starfive_gpio_get_value,
+ .set_value = starfive_gpio_set_value,
+};
+
+static struct driver starfive_gpio_driver = {
+ .name = "starfive_gpio",
+ .id = UCLASS_GPIO,
+ .probe = starfive_gpio_probe,
+ .ops = &starfive_gpio_ops,
+};
+
+static int starfive_gpiochip_register(struct udevice *parent)
+{
+ struct uclass_driver *drv;
+ struct udevice *dev;
+ int ret;
+ ofnode node;
+
+ drv = lists_uclass_lookup(UCLASS_GPIO);
+ if (!drv)
+ return -ENOENT;
+
+ node = dev_ofnode(parent);
+ ret = device_bind_with_driver_data(parent, &starfive_gpio_driver,
+ "starfive_gpio", 0, node, &dev);
+
+ return (ret == 0) ? 0 : ret;
+}
+
+int starfive_pinctrl_probe(struct udevice *dev,
+ const struct starfive_pinctrl_soc_info *info)
+{
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ /* Bind pinctrl_info from .data to priv */
+ priv->info =
+ (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+
+ if (!priv->info)
+ return -EINVAL;
+
+ priv->base = dev_read_addr_ptr(dev);
+ if (!priv->base)
+ return -EINVAL;
+
+ /* gpiochip register */
+ ret = starfive_gpiochip_register(dev);
+
+ return (ret == 0) ? 0 : ret;
+}
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.h b/drivers/pinctrl/starfive/pinctrl-starfive.h
new file mode 100644
index 00000000000..5721c3c36e4
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Pinctrl / GPIO driver for StarFive SoC
+ *
+ * Copyright (C) 2022 Shanghai StarFive Technology Co., Ltd.
+ * Author: Lee Kuan Lim <[email protected]>
+ * Author: Jianlong Huang <[email protected]>
+ */
+
+#define STARFIVE_PINCTRL(a, b) { .number = a, .name = b }
+
+extern const struct pinctrl_ops starfive_pinctrl_ops;
+
+struct starfive_pinctrl_pin {
+ unsigned int number;
+ const char *name;
+};
+
+struct starfive_pinctrl_soc_info {
+ /* pinctrl */
+ int (*set_one_pinmux)(struct udevice *dev, unsigned int pin,
+ unsigned int din, u32 dout, u32 doen, u32 func);
+ int (*get_padcfg_base)(struct udevice *dev,
+ unsigned int pin);
+
+ /* gpio dout/doen/din/gpioinput register */
+ unsigned int dout_reg_base;
+ unsigned int dout_mask;
+ unsigned int doen_reg_base;
+ unsigned int doen_mask;
+ unsigned int gpi_reg_base;
+ unsigned int gpi_mask;
+ unsigned int gpioin_reg_base;
+
+ /* gpio */
+ const char *gpio_bank_name;
+ int ngpios;
+ void (*gpio_init_hw)(struct udevice *dev);
+};
+
+/*
+ * struct starfive_pinctrl_priv - private data for Starfive pinctrl driver
+ *
+ * @padctl_base: base address of the pinctrl device
+ * @info: SoC specific data & function
+ */
+struct starfive_pinctrl_priv {
+ void __iomem *base;
+ struct starfive_pinctrl_soc_info *info;
+};
+
+void starfive_set_gpiomux(struct udevice *dev, unsigned int pin,
+ unsigned int din, u32 dout, u32 doen);
+int starfive_pinctrl_probe(struct udevice *dev,
+ const struct starfive_pinctrl_soc_info *info);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index c4fbda7a925..e5102180902 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -269,6 +269,7 @@ static const struct sunxi_pinctrl_function sun4i_a10_pinctrl_functions[] = {
#endif
{ "mmc2", 3 }, /* PC6-PC15 */
{ "mmc3", 2 }, /* PI4-PI9 */
+ { "nand0", 2 }, /* PC0-PC24 */
{ "spi0", 3 }, /* PC0-PC2, PC23 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 4 }, /* PF2-PF4 */
@@ -293,6 +294,7 @@ static const struct sunxi_pinctrl_function sun5i_a13_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG3-PG8 */
{ "mmc2", 3 }, /* PC6-PC15 */
+ { "nand0", 2 }, /* PC0-PC19 */
{ "spi0", 3 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 4 }, /* PF2-PF4 */
@@ -319,6 +321,7 @@ static const struct sunxi_pinctrl_function sun6i_a31_pinctrl_functions[] = {
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC6-PC15, PC24 */
{ "mmc3", 4 }, /* PC6-PC15, PC24 */
+ { "nand0", 2 }, /* PC0-PC26 */
{ "spi0", 3 }, /* PC0-PC2, PC27 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -363,6 +366,7 @@ static const struct sunxi_pinctrl_function sun7i_a20_pinctrl_functions[] = {
{ "mmc1", 4 }, /* PG0-PG5 */
#endif
{ "mmc2", 3 }, /* PC5-PC15, PC24 */
+ { "nand0", 2 }, /* PC0-PC24 */
{ "spi0", 3 }, /* PC0-PC2, PC23 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 4 }, /* PF2-PF4 */
@@ -386,6 +390,7 @@ static const struct sunxi_pinctrl_function sun8i_a23_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC5-PC16 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "spi0", 3 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -424,6 +429,7 @@ static const struct sunxi_pinctrl_function sun8i_a33_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC5-PC16 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "spi0", 3 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -450,6 +456,7 @@ static const struct sunxi_pinctrl_function sun8i_a83t_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC5-PC16 */
+ { "nand0", 2 }, /* PC0-PC18 */
{ "spi0", 3 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -491,6 +498,7 @@ static const struct sunxi_pinctrl_function sun8i_h3_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC5-PC16 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "spi0", 3 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -557,6 +565,7 @@ static const struct sunxi_pinctrl_function sun9i_a80_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC6-PC16 */
+ { "nand0", 2 }, /* PC0-PC18 */
{ "spi0", 3 }, /* PC0-PC2, PC19 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 4 }, /* PF2-PF4 */
@@ -597,6 +606,7 @@ static const struct sunxi_pinctrl_function sun50i_a64_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC1-PC16 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "pwm", 2 }, /* PD22 */
{ "spi0", 4 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
@@ -639,6 +649,7 @@ static const struct sunxi_pinctrl_function sun50i_h5_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC1-PC16 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "spi0", 3 }, /* PC0-PC3 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -665,6 +676,7 @@ static const struct sunxi_pinctrl_function sun50i_h6_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC1-PC14 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "spi0", 4 }, /* PC0-PC7 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
@@ -703,6 +715,7 @@ static const struct sunxi_pinctrl_function sun50i_h616_pinctrl_functions[] = {
{ "mmc0", 2 }, /* PF0-PF5 */
{ "mmc1", 2 }, /* PG0-PG5 */
{ "mmc2", 3 }, /* PC0-PC16 */
+ { "nand0", 2 }, /* PC0-PC16 */
{ "spi0", 4 }, /* PC0-PC7, PC15-PC16 */
#if IS_ENABLED(CONFIG_UART0_PORT_F)
{ "uart0", 3 }, /* PF2-PF4 */
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index c346d035072..eb5aa38c1cc 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -57,6 +57,13 @@ config SPL_REGULATOR_AXP
Enable support in SPL for the regulators (DCDCs, LDOs) in the
X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
+config REGULATOR_AXP_USB_POWER
+ bool "Enable driver for X-Powers AXP PMIC USB power supply"
+ depends on DM_REGULATOR && PMIC_AXP
+ help
+ Enable support for reading the USB power supply status from
+ X-Powers AXP2xx and AXP8xx PMICs.
+
config DM_REGULATOR_BD71837
bool "Enable Driver Model for ROHM BD71837/BD71847 regulators"
depends on DM_REGULATOR && DM_PMIC_BD71837
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 2d97e1033a8..d9e0cd5949c 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o
obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o
obj-$(CONFIG_$(SPL_)REGULATOR_AXP) += axp_regulator.o
+obj-$(CONFIG_$(SPL_)REGULATOR_AXP_USB_POWER) += axp_usb_power.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_DA9063) += da9063.o
obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
obj-$(CONFIG_DM_REGULATOR_NPCM8XX) += npcm8xx_regulator.o
diff --git a/drivers/power/regulator/axp_usb_power.c b/drivers/power/regulator/axp_usb_power.c
new file mode 100644
index 00000000000..f32fb6a92dc
--- /dev/null
+++ b/drivers/power/regulator/axp_usb_power.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <dm/device.h>
+#include <errno.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#define AXP_POWER_STATUS 0x00
+#define AXP_POWER_STATUS_VBUS_PRESENT BIT(5)
+
+static int axp_usb_power_get_enable(struct udevice *dev)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, AXP_POWER_STATUS);
+ if (ret < 0)
+ return ret;
+
+ return !!(ret & AXP_POWER_STATUS_VBUS_PRESENT);
+}
+
+static const struct dm_regulator_ops axp_usb_power_ops = {
+ .get_enable = axp_usb_power_get_enable,
+};
+
+static int axp_usb_power_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ uc_plat->type = REGULATOR_TYPE_FIXED;
+
+ return 0;
+}
+
+static const struct udevice_id axp_usb_power_ids[] = {
+ { .compatible = "x-powers,axp202-usb-power-supply" },
+ { .compatible = "x-powers,axp221-usb-power-supply" },
+ { .compatible = "x-powers,axp223-usb-power-supply" },
+ { .compatible = "x-powers,axp813-usb-power-supply" },
+ { }
+};
+
+U_BOOT_DRIVER(axp_usb_power) = {
+ .name = "axp_usb_power",
+ .id = UCLASS_REGULATOR,
+ .of_match = axp_usb_power_ids,
+ .probe = axp_usb_power_probe,
+ .ops = &axp_usb_power_ops,
+};
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index e085119963b..1acf212f87c 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -112,3 +112,4 @@ source "drivers/ram/rockchip/Kconfig"
source "drivers/ram/sifive/Kconfig"
source "drivers/ram/stm32mp1/Kconfig"
source "drivers/ram/octeon/Kconfig"
+source "drivers/ram/starfive/Kconfig"
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 83948e2c43e..2b9429cfee9 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -20,5 +20,7 @@ obj-$(CONFIG_K3_DDRSS) += k3-ddrss/
obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o
obj-$(CONFIG_RAM_SIFIVE) += sifive/
-
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
+endif
obj-$(CONFIG_ARCH_OCTEON) += octeon/
diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c
index 4453c247b29..b8338f84a3d 100644
--- a/drivers/ram/k3-am654-ddrss.c
+++ b/drivers/ram/k3-am654-ddrss.c
@@ -13,11 +13,14 @@
#include <ram.h>
#include <asm/io.h>
#include <power-domain.h>
-#include <asm/arch/sys_proto.h>
#include <dm/device_compat.h>
#include <power/regulator.h>
#include "k3-am654-ddrss.h"
+void sdelay(unsigned long loops);
+u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
+ u32 bound);
+
#define LDELAY 10000
/* DDRSS PHY configuration register fixed values */
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index b1fea04e84a..89932452520 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -2749,6 +2749,8 @@ static u64 dram_detect_cap(struct dram_info *dram,
/* detect cs1 row */
sdram_detect_cs1_row(cap_info, params->base.dramtype);
+ sdram_detect_high_row(cap_info);
+
/* detect die bw */
sdram_detect_dbw(cap_info, params->base.dramtype);
@@ -2954,7 +2956,7 @@ static int sdram_init(struct dram_info *dram,
params->ch[ch].cap_info.rank = rank;
}
-#if defined(CONFIG_RAM_RK3399_LPDDR4)
+#if defined(CONFIG_RAM_ROCKCHIP_LPDDR4)
/* LPDDR4 needs to be trained at 400MHz */
lpddr4_set_rate(dram, params, 0);
params->base.ddr_freq = dfs_cfgs_lpddr4[0].base.ddr_freq / MHz;
diff --git a/drivers/ram/starfive/Kconfig b/drivers/ram/starfive/Kconfig
new file mode 100644
index 00000000000..80c790066f0
--- /dev/null
+++ b/drivers/ram/starfive/Kconfig
@@ -0,0 +1,5 @@
+config SPL_STARFIVE_DDR
+ bool "StarFive DDR driver in SPL"
+ depends on SPL_RAM && STARFIVE_JH7110
+ help
+ This enables DDR support for the platforms based on StarFive JH7110 SoC.
diff --git a/drivers/ram/starfive/Makefile b/drivers/ram/starfive/Makefile
new file mode 100644
index 00000000000..1df42c377bd
--- /dev/null
+++ b/drivers/ram/starfive/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2022 StarFive, Inc
+#
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_STARFIVE_DDR) += ddrphy_start.o
+obj-$(CONFIG_SPL_STARFIVE_DDR) += ddrphy_train.o
+obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive_ddr.o
+obj-$(CONFIG_SPL_STARFIVE_DDR) += ddrphy_utils.o
+obj-$(CONFIG_SPL_STARFIVE_DDR) += ddrcsr_boot.o
+endif \ No newline at end of file
diff --git a/drivers/ram/starfive/ddrcsr_boot.c b/drivers/ram/starfive/ddrcsr_boot.c
new file mode 100644
index 00000000000..f2dd55f74a0
--- /dev/null
+++ b/drivers/ram/starfive/ddrcsr_boot.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang<[email protected]>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/regs.h>
+#include <linux/delay.h>
+#include <wait_bit.h>
+
+#include "starfive_ddr.h"
+
+#define REGOFFSET(offset) ((offset) / 4)
+
+static const struct ddr_reg_cfg ddr_csr_cfg[] = {
+ {0x0, 0x0, 0x00000001, REGSETALL},
+ {0xf00, 0x0, 0x40001030, (OFFSET_SEL | F_SET | REG4G | REG8G)},
+ {0xf00, 0x0, 0x40001030, (OFFSET_SEL | F_SET | REG2G)},
+ {0xf04, 0x0, 0x00000001, (OFFSET_SEL | F_SET | REG4G | REG8G)},
+ {0xf04, 0x0, 0x00800001, (OFFSET_SEL | F_SET | REG2G)},
+ {0xf10, 0x0, 0x00400000, (OFFSET_SEL | REGSETALL)},
+ {0xf14, 0x0, 0x043fffff, (OFFSET_SEL | REGSETALL)},
+ {0xf18, 0x0, 0x00000000, (OFFSET_SEL | REGSETALL)},
+ {0xf30, 0x0, 0x1f000041, (OFFSET_SEL | REGSETALL)},
+ {0xf34, 0x0, 0x1f000041, (OFFSET_SEL | F_SET | REG4G | REG8G)},
+ {0x110, 0x0, 0xc0000001, (OFFSET_SEL | REGSETALL)},
+ {0x114, 0x0, 0xffffffff, (OFFSET_SEL | REGSETALL)},
+ {0x10c, 0x0, 0x00000505, REGSETALL},
+ {0x11c, 0x0, 0x00000000, REGSETALL},
+ {0x500, 0x0, 0x00000201, REGSETALL},
+ {0x514, 0x0, 0x00000100, REGSETALL},
+ {0x6a8, 0x0, 0x00040000, REGSETALL},
+ {0xea8, 0x0, 0x00040000, REGSETALL},
+ {0x504, 0x0, 0x40000000, REGSETALL}
+};
+
+static const struct ddr_reg_cfg ddr_csr_cfg1[] = {
+ {0x310, 0x0, 0x00020000, REGSETALL},
+ {0x310, 0x0, 0x00020001, REGSETALL},
+ {0x600, 0x0, 0x002e0176, REGSETALL},
+ {0x604, 0x0, 0x002e0176, REGSETALL},
+ {0x608, 0x0, 0x001700bb, REGSETALL},
+ {0x60c, 0x0, 0x000b005d, REGSETALL},
+ {0x610, 0x0, 0x0005002e, REGSETALL},
+ {0x614, 0x0, 0x00020017, REGSETALL},
+ {0x618, 0x0, 0x00020017, REGSETALL},
+ {0x61c, 0x0, 0x00020017, REGSETALL},
+ {0x678, 0x0, 0x00000019, REGSETALL},
+ {0x100, 0x0, 0x000000f8, REGSETALL},
+ {0x620, 0x0, 0x03030404, REGSETALL},
+ {0x624, 0x0, 0x04030505, REGSETALL},
+ {0x628, 0x0, 0x07030884, REGSETALL},
+ {0x62c, 0x0, 0x13150401, REGSETALL},
+ {0x630, 0x0, 0x17150604, REGSETALL},
+ {0x634, 0x0, 0x00110000, REGSETALL},
+ {0x638, 0x0, 0x200a0a08, REGSETALL},
+ {0x63c, 0x0, 0x1730f803, REGSETALL},
+ {0x640, 0x0, 0x000a0c00, REGSETALL},
+ {0x644, 0x0, 0xa005000a, REGSETALL},
+ {0x648, 0x0, 0x00000000, REGSETALL},
+ {0x64c, 0x0, 0x00081306, REGSETALL},
+ {0x650, 0x0, 0x04070304, REGSETALL},
+ {0x654, 0x0, 0x00000404, REGSETALL},
+ {0x658, 0x0, 0x00000060, REGSETALL},
+ {0x65c, 0x0, 0x00030008, REGSETALL},
+ {0x660, 0x0, 0x00000000, REGSETALL},
+ {0x680, 0x0, 0x00000603, REGSETALL},
+ {0x684, 0x0, 0x01000202, REGSETALL},
+ {0x688, 0x0, 0x0413040d, REGSETALL},
+ {0x68c, 0x0, 0x20002420, REGSETALL},
+ {0x690, 0x0, 0x00140000, REGSETALL},
+ {0x69c, 0x0, 0x01240074, REGSETALL},
+ {0x6a0, 0x0, 0x00000000, REGSETALL},
+ {0x6a4, 0x0, 0x20240c00, REGSETALL},
+ {0x6a8, 0x0, 0x00040000, REGSETALL},
+ {0x4, 0x0, 0x30010006, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10010006, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x30020000, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10020000, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x30030031, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10030031, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x300b0033, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x100b0033, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x30160016, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10160016, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x10, 0x0, 0x00000010, REGSETALL},
+ {0x14, 0x0, 0x00000001, REGSETALL},
+};
+
+static const struct ddr_reg_cfg ddr_csr_cfg2[] = {
+ {0xb8, 0xf0ffffff, 0x3000000, REGCLRSETALL},
+ {0x84, 0xFEFFFFFF, 0x0, REGCLRSETALL},
+ {0xb0, 0xFFFEFFFF, 0x0, REGCLRSETALL},
+ {0xb0, 0xFEFFFFFF, 0x0, REGCLRSETALL},
+ {0xb4, 0xffffffff, 0x1, REGCLRSETALL},
+ {0x248, 0xffffffff, 0x3000000, REGCLRSETALL},
+ {0x24c, 0xffffffff, 0x300, REGCLRSETALL},
+ {0x24c, 0xffffffff, 0x3000000, REGCLRSETALL},
+ {0xb0, 0xffffffff, 0x100, REGCLRSETALL},
+ {0xb8, 0xFFF0FFFF, 0x30000, REGCLRSETALL},
+ {0x84, 0xFFFEFFFF, 0x0, REGCLRSETALL},
+ {0xac, 0xFFFEFFFF, 0x0, REGCLRSETALL},
+ {0xac, 0xFEFFFFFF, 0x0, REGCLRSETALL},
+ {0xb0, 0xffffffff, 0x1, REGCLRSETALL},
+ {0x248, 0xffffffff, 0x30000, REGCLRSETALL},
+ {0x24c, 0xffffffff, 0x3, REGCLRSETALL},
+ {0x24c, 0xffffffff, 0x30000, REGCLRSETALL},
+ {0x250, 0xffffffff, 0x3000000, REGCLRSETALL},
+ {0x254, 0xffffffff, 0x3000000, REGCLRSETALL},
+ {0x258, 0xffffffff, 0x3000000, REGCLRSETALL},
+ {0xac, 0xffffffff, 0x100, REGCLRSETALL},
+ {0x10c, 0xFFFFF0FF, 0x300, REGCLRSETALL},
+ {0x110, 0xFFFFFEFF, 0x0, REGCLRSETALL},
+ {0x11c, 0xFFFEFFFF, 0x0, REGCLRSETALL},
+ {0x11c, 0xFEFFFFFF, 0x0, REGCLRSETALL},
+ {0x120, 0xffffffff, 0x100, REGCLRSETALL},
+ {0x2d0, 0xffffffff, 0x300, REGCLRSETALL},
+ {0x2dc, 0xffffffff, 0x300, REGCLRSETALL},
+ {0x2e8, 0xffffffff, 0x300, REGCLRSETALL},
+};
+
+static const struct ddr_reg_cfg ddr_csr_cfg3[] = {
+ {0x100, 0x0, 0x000000e0, REGSETALL},
+ {0x620, 0x0, 0x04041417, REGSETALL},
+ {0x624, 0x0, 0x09110609, REGSETALL},
+ {0x628, 0x0, 0x442d0994, REGSETALL},
+ {0x62c, 0x0, 0x271e102b, REGSETALL},
+ {0x630, 0x0, 0x291b140a, REGSETALL},
+ {0x634, 0x0, 0x001c0000, REGSETALL},
+ {0x638, 0x0, 0x200f0f08, REGSETALL},
+ {0x63c, 0x0, 0x29420a06, REGSETALL},
+ {0x640, 0x0, 0x019e1fc1, REGSETALL},
+ {0x644, 0x0, 0x10cb0196, REGSETALL},
+ {0x648, 0x0, 0x00000000, REGSETALL},
+ {0x64c, 0x0, 0x00082714, REGSETALL},
+ {0x650, 0x0, 0x16442f0d, REGSETALL},
+ {0x654, 0x0, 0x00001916, REGSETALL},
+ {0x658, 0x0, 0x00000060, REGSETALL},
+ {0x65c, 0x0, 0x00600020, REGSETALL},
+ {0x660, 0x0, 0x00000000, REGSETALL},
+ {0x680, 0x0, 0x0c00040f, REGSETALL},
+ {0x684, 0x0, 0x03000604, REGSETALL},
+ {0x688, 0x0, 0x0515040d, REGSETALL},
+ {0x68c, 0x0, 0x20002c20, REGSETALL},
+ {0x690, 0x0, 0x00140000, REGSETALL},
+ {0x69c, 0x0, 0x01240074, REGSETALL},
+ {0x6a0, 0x0, 0x00000000, REGSETALL},
+ {0x6a4, 0x0, 0x202c0c00, REGSETALL},
+ {0x6a8, 0x0, 0x00040000, REGSETALL},
+ {0x4, 0x0, 0x30010036, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10010036, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x3002001b, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10010036, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x30030031, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10030031, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x300b0066, (F_SET | REG4G)},
+ {0x4, 0x0, 0x300b0036, (F_SET | REG8G)},
+ {0x4, 0x0, 0x100b0066, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x4, 0x0, 0x30160016, (F_SET | REG4G | REG8G)},
+ {0x4, 0x0, 0x10160016, (F_SET | REG2G)},
+ {0xc, 0x0, 0x00000002, REGSETALL},
+ {0x410, 0x0, 0x00101010, REGSETALL},
+ {0x420, 0x0, 0x0c181006, REGSETALL},
+ {0x424, 0x0, 0x20200820, REGSETALL},
+ {0x428, 0x0, 0x80000020, REGSETALL},
+ {0x0, 0x0, 0x00000001, REGSETALL},
+ {0x108, 0x0, 0x00003000, REGSETALL},
+ {0x704, 0x0, 0x00000007, REGSETALL | OFFSET_SEL},
+ {0x330, 0x0, 0x09313fff, (F_SET | REG4G | REG8G)},
+ {0x330, 0x0, 0x09311fff, (F_SET | REG2G)},
+ {0x508, 0x0, 0x00000033, (F_SET | REG4G | REG8G)},
+ {0x508, 0x0, 0x00000013, (F_SET | REG2G)},
+ {0x324, 0x0, 0x00002000, REGSETALL},
+ {0x104, 0x0, 0x90000000, REGSETALL},
+ {0x510, 0x0, 0x00000100, REGSETALL},
+ {0x514, 0x0, 0x00000000, REGSETALL},
+ {0x700, 0x0, 0x00000003, REGSETALL | OFFSET_SEL},
+ {0x514, 0x0, 0x00000600, REGSETALL},
+ {0x20, 0x0, 0x00000001, REGSETALL},
+};
+
+static void ddr_csr_set(u32 *csrreg, u32 *secreg, const struct ddr_reg_cfg *data,
+ u32 len, u32 mask)
+{
+ u32 *addr;
+ u32 i;
+
+ for (i = 0; i < len; i++) {
+ if (!(data[i].flag & mask))
+ continue;
+
+ if (data[i].flag & OFFSET_SEL)
+ addr = secreg + REGOFFSET(data[i].offset);
+ else
+ addr = csrreg + REGOFFSET(data[i].offset);
+
+ if (data[i].flag & F_CLRSET)
+ DDR_REG_TRIGGER(addr, data[i].mask, data[i].val);
+ else
+ out_le32(addr, data[i].val);
+ }
+}
+
+void ddrcsr_boot(u32 *csrreg, u32 *secreg, u32 *phyreg, enum ddr_size_t size)
+{
+ u32 len;
+ u32 val;
+ u32 mask;
+ int ret;
+
+ switch (size) {
+ case DDR_SIZE_2G:
+ mask = REG2G;
+ break;
+
+ case DDR_SIZE_4G:
+ mask = REG4G;
+ break;
+
+ case DDR_SIZE_8G:
+ mask = REG8G;
+ break;
+
+ case DDR_SIZE_16G:
+ default:
+ return;
+ };
+
+ len = ARRAY_SIZE(ddr_csr_cfg);
+ ddr_csr_set(csrreg, secreg, ddr_csr_cfg, len, mask);
+
+ ret = wait_for_bit_le32(csrreg + REGOFFSET(0x504), BIT(31),
+ true, 1000, false);
+ if (ret)
+ return;
+
+ out_le32(csrreg + REGOFFSET(0x504), 0x0);
+ out_le32(csrreg + REGOFFSET(0x50c), 0x0);
+ udelay(300);
+ out_le32(csrreg + REGOFFSET(0x50c), 0x1);
+ mdelay(3);
+
+ switch (size) {
+ case DDR_SIZE_2G:
+ out_le32(csrreg + REGOFFSET(0x10), 0x1c);
+ break;
+
+ case DDR_SIZE_8G:
+ case DDR_SIZE_4G:
+ out_le32(csrreg + REGOFFSET(0x10), 0x3c);
+ break;
+
+ case DDR_SIZE_16G:
+ default:
+ break;
+ };
+
+ out_le32(csrreg + REGOFFSET(0x14), 0x1);
+ udelay(4);
+
+ len = ARRAY_SIZE(ddr_csr_cfg1);
+ ddr_csr_set(csrreg, secreg, ddr_csr_cfg1, len, mask);
+
+ udelay(4);
+ out_le32(csrreg + REGOFFSET(0x10), 0x11);
+ out_le32(csrreg + REGOFFSET(0x14), 0x1);
+
+ switch (size) {
+ case DDR_SIZE_4G:
+ case DDR_SIZE_8G:
+ out_le32(csrreg + REGOFFSET(0x10), 0x20);
+ out_le32(csrreg + REGOFFSET(0x14), 0x1);
+ udelay(4);
+ out_le32(csrreg + REGOFFSET(0x10), 0x21);
+ out_le32(csrreg + REGOFFSET(0x14), 0x1);
+ break;
+
+ case DDR_SIZE_2G:
+ case DDR_SIZE_16G:
+ default:
+ break;
+ };
+
+ out_le32(csrreg + REGOFFSET(0x514), 0x0);
+ ret = wait_for_bit_le32(csrreg + REGOFFSET(0x518), BIT(1),
+ true, 1000, false);
+ if (ret)
+ return;
+
+ val = in_le32(csrreg + REGOFFSET(0x518));
+ while ((val & 0x2) != 0x0) {
+ val = in_le32(phyreg + 1);
+
+ if ((val & 0x20) == 0x20) {
+ switch (val & 0x1f) {
+ case 0: /* ddrc_clock=12M */
+ DDR_REG_SET(BUS, DDR_BUS_OSC_DIV2);
+ break;
+ case 1: /* ddrc_clock=200M */
+ DDR_REG_SET(BUS, DDR_BUS_PLL1_DIV8);
+ break;
+ case 2: /* ddrc_clock=800M */
+ DDR_REG_SET(BUS, DDR_BUS_PLL1_DIV2);
+ break;
+ default:
+ break;
+ };
+
+ out_le32(phyreg + 2, 0x1);
+ ret = wait_for_bit_le32(phyreg + 2, BIT(0), false, 1000, false);
+ if (ret)
+ return;
+ }
+
+ udelay(1);
+ val = in_le32(csrreg + REGOFFSET(0x518));
+ };
+
+ val = in_le32(phyreg + 2048 + 83);
+ val = in_le32(phyreg + 2048 + 84);
+ out_le32(phyreg + 2048 + 84, val & 0xF8000000);
+
+ len = ARRAY_SIZE(ddr_csr_cfg2);
+ ddr_csr_set(phyreg + PHY_BASE_ADDR, secreg, ddr_csr_cfg2, len, mask);
+
+ len = ARRAY_SIZE(ddr_csr_cfg3);
+ ddr_csr_set(csrreg, secreg, ddr_csr_cfg3, len, mask);
+}
diff --git a/drivers/ram/starfive/ddrphy_start.c b/drivers/ram/starfive/ddrphy_start.c
new file mode 100644
index 00000000000..479b6ef1041
--- /dev/null
+++ b/drivers/ram/starfive/ddrphy_start.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang<[email protected]>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include "starfive_ddr.h"
+
+static const struct ddr_reg_cfg ddr_start_cfg[] = {
+ {89, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {78, 0xfffffcff, 0x0, (OFFSET_SEL | REGCLRSETALL)},
+ {345, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {334, 0xfffffcff, 0x0, (OFFSET_SEL | REGCLRSETALL)},
+ {601, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {590, 0xfffffcff, 0x0, (OFFSET_SEL | REGCLRSETALL)},
+ {857, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {846, 0xfffffcff, 0x0, (OFFSET_SEL | REGCLRSETALL)},
+ {1793, 0xfffffeff, 0x0, (OFFSET_SEL | REGCLRSETALL)},
+ {1793, 0xfffcffff, 0x0, (OFFSET_SEL | REGCLRSETALL)},
+ {125, 0xfff0ffff, 0x00010000, (OFFSET_SEL | REGCLRSETALL)},
+ {102, 0xfffffffc, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {105, 0xffffffe0, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {92, 0xfffffffe, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {94, 0xffffe0ff, 0x00000200, (OFFSET_SEL | REGCLRSETALL)},
+ {96, 0xfffff0ff, 0x00000400, (OFFSET_SEL | REGCLRSETALL)},
+ {89, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {381, 0xfff0ffff, 0x00010000, (OFFSET_SEL | REGCLRSETALL)},
+ {358, 0xfffffffc, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {361, 0xffffffe0, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {348, 0xfffffffe, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {350, 0xffffe0ff, 0x00000200, (OFFSET_SEL | REGCLRSETALL)},
+ {352, 0xfffff0ff, 0x00000400, (OFFSET_SEL | REGCLRSETALL)},
+ {345, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {637, 0xfff0ffff, 0x00010000, (OFFSET_SEL | REGCLRSETALL)},
+ {614, 0xfffffffc, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {617, 0xffffffe0, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {604, 0xfffffffe, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {606, 0xffffe0ff, 0x00000200, (OFFSET_SEL | REGCLRSETALL)},
+ {608, 0xfffff0ff, 0x00000400, (OFFSET_SEL | REGCLRSETALL)},
+ {601, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {893, 0xfff0ffff, 0x00010000, (OFFSET_SEL | REGCLRSETALL)},
+ {870, 0xfffffffc, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {873, 0xffffffe0, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {860, 0xfffffffe, 0x00000001, (OFFSET_SEL | REGCLRSETALL)},
+ {862, 0xffffe0ff, 0x00000200, (OFFSET_SEL | REGCLRSETALL)},
+ {864, 0xfffff0ff, 0x00000400, (OFFSET_SEL | REGCLRSETALL)},
+ {857, 0xffffff00, 0x00000051, (OFFSET_SEL | REGCLRSETALL)},
+ {1895, 0xffffe000, 0x00001342, (OFFSET_SEL | REGCLRSETALL)},
+ {1835, 0xfffff0ff, 0x00000200, (OFFSET_SEL | REGCLRSETALL)},
+ {1793, 0xfffffeff, 0x00000100, (OFFSET_SEL | REGCLRSETALL)},
+ {62, 0xfffffeff, 0x0, REGCLRSETALL},
+ {66, 0xfffffeff, 0x0, REGCLRSETALL},
+ {166, 0xffffff80, 0x00000001, REGCLRSETALL},
+ {62, 0xfff0ffff, 0x00010000, REGCLRSETALL},
+ {62, 0xf0ffffff, 0x01000000, REGCLRSETALL},
+ {166, 0xffff80ff, 0x00000100, REGCLRSETALL},
+ {179, 0xff80ffff, 0x00010000, REGCLRSETALL},
+ {67, 0xffe0ffff, 0x00010000, REGCLRSETALL},
+ {67, 0xe0ffffff, 0x01000000, REGCLRSETALL},
+ {179, 0x80ffffff, 0x01000000, REGCLRSETALL},
+ {166, 0xff80ffff, 0x00010000, REGCLRSETALL},
+ {62, 0xfff0ffff, 0x00010000, REGCLRSETALL},
+ {62, 0xf0ffffff, 0x01000000, REGCLRSETALL},
+ {166, 0x80ffffff, 0x01000000, REGCLRSETALL},
+ {182, 0xff80ffff, 0x00010000, REGCLRSETALL},
+ {67, 0xffe0ffff, 0x00010000, REGCLRSETALL},
+ {67, 0xe0ffffff, 0x01000000, REGCLRSETALL},
+ {182, 0x80ffffff, 0x01000000, REGCLRSETALL},
+ {167, 0xffffff80, 0x00000017, REGCLRSETALL},
+ {62, 0xfff0ffff, 0x00010000, REGCLRSETALL},
+ {62, 0xf0ffffff, 0x01000000, REGCLRSETALL},
+ {167, 0xffff80ff, 0x00001700, REGCLRSETALL},
+ {185, 0xff80ffff, 0x00200000, REGCLRSETALL},
+ {67, 0xffe0ffff, 0x00010000, REGCLRSETALL},
+ {67, 0xe0ffffff, 0x01000000, REGCLRSETALL},
+ {185, 0x80ffffff, 0x20000000, REGCLRSETALL},
+ {10, 0xffffffe0, 0x00000002, REGCLRSETALL},
+ {0, 0xfffffffe, 0x00000001, REGCLRSETALL},
+ {11, 0xfffffff0, 0x00000005, (F_CLRSET | REG2G)},
+ {247, 0xffffffff, 0x00000008, REGCLRSETALL},
+ {249, 0xffffffff, 0x00000800, REGCLRSETALL},
+ {252, 0xffffffff, 0x00000008, REGCLRSETALL},
+ {254, 0xffffffff, 0x00000800, REGCLRSETALL},
+ {281, 0xffffffff, 0x33000000, REGCLRSETALL},
+ {305, 0xffffffff, 0x33000000, REGCLRSETALL},
+ {329, 0xffffffff, 0x33000000, REGCLRSETALL},
+ {353, 0xffffffff, 0x33000000, REGCLRSETALL},
+ {289, 0xffffffff, 0x36000000, (F_CLRSET | REG8G)},
+ {313, 0xffffffff, 0x36000000, (F_CLRSET | REG8G)},
+ {337, 0xffffffff, 0x36000000, (F_CLRSET | REG8G)},
+ {361, 0xffffffff, 0x36000000, (F_CLRSET | REG8G)},
+ {289, 0xffffffff, 0x66000000, (F_CLRSET | REG2G | REG4G)},
+ {313, 0xffffffff, 0x66000000, (F_CLRSET | REG2G | REG4G)},
+ {337, 0xffffffff, 0x66000000, (F_CLRSET | REG2G | REG4G)},
+ {361, 0xffffffff, 0x66000000, (F_CLRSET | REG2G | REG4G)},
+ {282, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {306, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {330, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {354, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {290, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {314, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {338, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {362, 0xffffffff, 0x00160000, REGCLRSETALL},
+ {282, 0xffffff00, 0x17, REGCLRSETALL},
+ {306, 0xffffff00, 0x17, REGCLRSETALL},
+ {330, 0xffffff00, 0x17, REGCLRSETALL},
+ {354, 0xffffff00, 0x17, REGCLRSETALL},
+ {290, 0xffffff00, 0x17, REGCLRSETALL},
+ {314, 0xffffff00, 0x17, REGCLRSETALL},
+ {338, 0xffffff00, 0x17, REGCLRSETALL},
+ {362, 0xffffff00, 0x17, REGCLRSETALL},
+ {282, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {306, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {330, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {354, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {290, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {314, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {338, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {362, 0xffff00ff, 0x2000, REGCLRSETALL},
+ {65, 0xffffffff, 0x00000100, (OFFSET_SEL | REGCLRSETALL)},
+ {321, 0xffffffff, 0x00000100, (OFFSET_SEL | REGCLRSETALL)},
+ {577, 0xffffffff, 0x00000100, (OFFSET_SEL | REGCLRSETALL)},
+ {833, 0xffffffff, 0x00000100, (OFFSET_SEL | REGCLRSETALL)},
+ {96, 0x0, 0x300, (OFFSET_SEL | REGADDSETALL)},
+ {352, 0x0, 0x300, (OFFSET_SEL | REGADDSETALL)},
+ {608, 0x0, 0x300, (OFFSET_SEL | REGADDSETALL)},
+ {864, 0x0, 0x300, (OFFSET_SEL | REGADDSETALL)},
+ {96, 0xff00ffff, 0x00120000, (OFFSET_SEL | REGCLRSETALL)},
+ {352, 0xff00ffff, 0x00120000, (OFFSET_SEL | REGCLRSETALL)},
+ {608, 0xff00ffff, 0x00120000, (OFFSET_SEL | REGCLRSETALL)},
+ {864, 0xff00ffff, 0x00120000, (OFFSET_SEL | REGCLRSETALL)},
+ {33, 0xffffff00, 0x0040, (OFFSET_SEL | REGCLRSETALL)},
+ {289, 0xffffff00, 0x0040, (OFFSET_SEL | REGCLRSETALL)},
+ {545, 0xffffff00, 0x0040, (OFFSET_SEL | REGCLRSETALL)},
+ {801, 0xffffff00, 0x0040, (OFFSET_SEL | REGCLRSETALL)},
+ {1038, 0xfcffffff, 0x03000000, (OFFSET_SEL | REGCLRSETALL)},
+ {1294, 0xfcffffff, 0x03000000, (OFFSET_SEL | REGCLRSETALL)},
+ {1550, 0xfcffffff, 0x03000000, (OFFSET_SEL | REGCLRSETALL)},
+ {83, 0xffc0ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {339, 0xffc0ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {595, 0xffc0ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {851, 0xffc0ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {1062, 0xf800ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {1318, 0xf800ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {1574, 0xf800ffff, 0x70000, (OFFSET_SEL | REGCLRSETALL)},
+ {1892, 0xfffc0000, 0x15547, (OFFSET_SEL | REGCLRSETALL)},
+ {1893, 0xfffc0000, 0x7, (OFFSET_SEL | REGCLRSETALL)},
+ {1852, 0xffffe000, 0x07a, (OFFSET_SEL | REGCLRSETALL)},
+ {1853, 0xffffffff, 0x0100, (OFFSET_SEL | REGCLRSETALL)},
+ {1822, 0xffffffff, 0xFF, (OFFSET_SEL | REGCLRSETALL)},
+ {1896, 0xfffffc00, 0x03d5, (OFFSET_SEL | REGCLRSETALL)},
+ {91, 0xfc00ffff, 0x03d50000, (OFFSET_SEL | REGCLRSETALL)},
+ {347, 0xfc00ffff, 0x03d50000, (OFFSET_SEL | REGCLRSETALL)},
+ {603, 0xfc00ffff, 0x03d50000, (OFFSET_SEL | REGCLRSETALL)},
+ {859, 0xfc00ffff, 0x03d50000, (OFFSET_SEL | REGCLRSETALL)},
+ {1912, 0x0, 0xcc3bfc7, (OFFSET_SEL | REGSETALL)},
+ {1913, 0x0, 0xff8f, (OFFSET_SEL | REGSETALL)},
+ {1914, 0x0, 0x33f07ff, (OFFSET_SEL | REGSETALL)},
+ {1915, 0x0, 0xc3c37ff, (OFFSET_SEL | REGSETALL)},
+ {1916, 0x0, 0x1fffff10, (OFFSET_SEL | REGSETALL)},
+ {1917, 0x0, 0x230070, (OFFSET_SEL | REGSETALL)},
+ {1918, 0x0, 0x3ff7ffff, (OFFSET_SEL | REG4G | REG2G | F_SET)},
+ {1918, 0x0, 0x3ff7ffff, (OFFSET_SEL | REG8G | F_SET)},
+ {1919, 0x0, 0xe10, (OFFSET_SEL | REGSETALL)},
+ {1920, 0x0, 0x1fffffff, (OFFSET_SEL | REGSETALL)},
+ {1921, 0x0, 0x188411, (OFFSET_SEL | REGSETALL)},
+ {1922, 0x0, 0x1fffffff, (OFFSET_SEL | REGSETALL)},
+ {1923, 0x0, 0x180400, (OFFSET_SEL | REGSETALL)},
+ {1924, 0x0, 0x1fffffff, (OFFSET_SEL | REGSETALL)},
+ {1925, 0x0, 0x180400, (OFFSET_SEL | REGSETALL)},
+ {1926, 0x0, 0x1fffffcf, (OFFSET_SEL | REGSETALL)},
+ {1927, 0x0, 0x188400, (OFFSET_SEL | REGSETALL)},
+ {1928, 0x0, 0x1fffffff, (OFFSET_SEL | REGSETALL)},
+ {1929, 0x0, 0x4188411, (OFFSET_SEL | REGSETALL)},
+ {1837, 0x0, 0x24410, (OFFSET_SEL | REGSETALL)},
+ {1840, 0x0, 0x24410, (OFFSET_SEL | REGSETALL)},
+ {1842, 0x0, 0x2ffff, (OFFSET_SEL | REGSETALL)},
+ {76, 0xff0000f8, 0x00ff8f07, (OFFSET_SEL | REGCLRSETALL)},
+ {332, 0xff0000f8, 0x00ff8f07, (OFFSET_SEL | REGCLRSETALL)},
+ {588, 0xff0000f8, 0x00ff8f07, (OFFSET_SEL | REGCLRSETALL)},
+ {844, 0xff0000f8, 0x00ff8f07, (OFFSET_SEL | REGCLRSETALL)},
+ {77, 0xffff0000, 0xff8f, (OFFSET_SEL | REGCLRSETALL)},
+ {333, 0xffff0000, 0xff8f, (OFFSET_SEL | REGCLRSETALL)},
+ {589, 0xffff0000, 0xff8f, (OFFSET_SEL | REGCLRSETALL)},
+ {845, 0xffff0000, 0xff8f, (OFFSET_SEL | REGCLRSETALL)},
+ {1062, 0xffffff00, 0xff, (OFFSET_SEL | REG4G | REG2G | F_CLRSET)},
+ {1318, 0xffffff00, 0xff, (OFFSET_SEL | REG4G | REG2G | F_CLRSET)},
+ {1574, 0xffffff00, 0xff, (OFFSET_SEL | REG4G | REG2G | F_CLRSET)},
+ {1062, 0xffffff00, 0xfb, (OFFSET_SEL | REG8G | F_CLRSET)},
+ {1318, 0xffffff00, 0xfb, (OFFSET_SEL | REG8G | F_CLRSET)},
+ {1574, 0xffffff00, 0xfb, (OFFSET_SEL | REG8G | F_CLRSET)},
+ {1028, 0xffffffff, 0x1000000, (OFFSET_SEL | REGCLRSETALL)},
+ {1284, 0xffffffff, 0x1000000, (OFFSET_SEL | REGCLRSETALL)},
+ {1540, 0xffffffff, 0x1000000, (OFFSET_SEL | REGCLRSETALL)},
+ {1848, 0x0, 0x3cf07f8, (OFFSET_SEL | REGSETALL)},
+ {1849, 0x0, 0x3f, (OFFSET_SEL | REGSETALL)},
+ {1850, 0x0, 0x1fffff, (OFFSET_SEL | REGSETALL)},
+ {1851, 0x0, 0x060000, (OFFSET_SEL | REGSETALL)},
+ {130, 0x0000ffff, 0xffff0000, (OFFSET_SEL | REGCLRSETALL)},
+ {386, 0x0000ffff, 0xffff0000, (OFFSET_SEL | REGCLRSETALL)},
+ {642, 0x0000ffff, 0xffff0000, (OFFSET_SEL | REGCLRSETALL)},
+ {898, 0x0000ffff, 0xffff0000, (OFFSET_SEL | REGCLRSETALL)},
+ {131, 0xfffffff0, 0xf, (OFFSET_SEL | REGCLRSETALL)},
+ {387, 0xfffffff0, 0xf, (OFFSET_SEL | REGCLRSETALL)},
+ {643, 0xfffffff0, 0xf, (OFFSET_SEL | REGCLRSETALL)},
+ {899, 0xfffffff0, 0xf, (OFFSET_SEL | REGCLRSETALL)},
+ {29, 0xc0ffffff, 0x10000000, (OFFSET_SEL | REGCLRSETALL)},
+ {285, 0xc0ffffff, 0x10000000, (OFFSET_SEL | REGCLRSETALL)},
+ {541, 0xc0ffffff, 0x10000000, (OFFSET_SEL | REGCLRSETALL)},
+ {797, 0xc0ffffff, 0x10000000, (OFFSET_SEL | REGCLRSETALL)},
+ {30, 0xffffffff, 0x00080000, (OFFSET_SEL | REGCLRSETALL)},
+ {286, 0xffffffff, 0x00080000, (OFFSET_SEL | REGCLRSETALL)},
+ {542, 0xffffffff, 0x00080000, (OFFSET_SEL | REGCLRSETALL)},
+ {798, 0xffffffff, 0x00080000, (OFFSET_SEL | REGCLRSETALL)},
+ {31, 0xffffffc0, 0x00000010, (OFFSET_SEL | REGCLRSETALL)},
+ {287, 0xffffffc0, 0x00000010, (OFFSET_SEL | REGCLRSETALL)},
+ {543, 0xffffffc0, 0x00000010, (OFFSET_SEL | REGCLRSETALL)},
+ {799, 0xffffffc0, 0x00000010, (OFFSET_SEL | REGCLRSETALL)},
+ {1071, 0xfffffff0, 0x00000008, (OFFSET_SEL | REGCLRSETALL)},
+ {1327, 0xfffffff0, 0x00000008, (OFFSET_SEL | REGCLRSETALL)},
+ {1583, 0xfffffff0, 0x00000008, (OFFSET_SEL | REGCLRSETALL)},
+ {1808, 0xfffffff0, 0x00000008, (OFFSET_SEL | REGCLRSETALL)},
+ {1896, 0xfff0ffff, 0x00080000, (OFFSET_SEL | REGCLRSETALL)},
+};
+
+void ddr_reg_set(u32 *reg, const struct ddr_reg_cfg *data,
+ u32 len, u32 mask)
+{
+ u32 *addr;
+ u32 i;
+
+ for (i = 0; i < len; i++) {
+ if (!(data[i].flag & mask))
+ continue;
+
+ if (data[i].flag & OFFSET_SEL)
+ addr = reg + PHY_AC_BASE_ADDR + data[i].offset;
+ else
+ addr = reg + PHY_BASE_ADDR + data[i].offset;
+
+ if (data[i].flag & F_CLRSET)
+ DDR_REG_TRIGGER(addr, data[i].mask, data[i].val);
+ else if (data[i].flag & F_SET)
+ out_le32(addr, data[i].val);
+ else
+ out_le32(addr, in_le32(addr) + data[i].val);
+ }
+}
+
+void ddr_phy_start(u32 *phyreg, enum ddr_size_t size)
+{
+ u32 len;
+ u32 mask;
+
+ switch (size) {
+ case DDR_SIZE_2G:
+ mask = REG2G;
+ break;
+
+ case DDR_SIZE_4G:
+ mask = REG4G;
+ break;
+
+ case DDR_SIZE_8G:
+ mask = REG8G;
+ break;
+
+ case DDR_SIZE_16G:
+ default:
+ return;
+ };
+
+ len = ARRAY_SIZE(ddr_start_cfg);
+ ddr_reg_set(phyreg, ddr_start_cfg, len, mask);
+ out_le32(phyreg, 0x01);
+}
diff --git a/drivers/ram/starfive/ddrphy_train.c b/drivers/ram/starfive/ddrphy_train.c
new file mode 100644
index 00000000000..0740f49be5b
--- /dev/null
+++ b/drivers/ram/starfive/ddrphy_train.c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang<[email protected]>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+static const u32 ddr_train_data[] = {
+ 0xb00,
+ 0x101,
+ 0x640000,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1,
+ 0x7,
+ 0x10002,
+ 0x300080f,
+ 0x1,
+ 0x5,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1010000,
+ 0x280a0000,
+ 0x0,
+ 0x1,
+ 0x3200000f,
+ 0x0,
+ 0x0,
+ 0x10102,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0xaa,
+ 0x55,
+ 0xb5,
+ 0x4a,
+ 0x56,
+ 0xa9,
+ 0xa9,
+ 0xb5,
+ 0x1000000,
+ 0x1000000,
+ 0x0,
+ 0xf0f0000,
+ 0x14,
+ 0x7d0,
+ 0x300,
+ 0x0,
+ 0x0,
+ 0x1000000,
+ 0x10101,
+ 0x0,
+ 0x30000,
+ 0x100,
+ 0x170f,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0xa140a01,
+ 0x204010a,
+ 0x2080510,
+ 0x40400,
+ 0x1000101,
+ 0x10100,
+ 0x2040f00,
+ 0x34000000,
+ 0x0,
+ 0x0,
+ 0x1000000,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x10100,
+ 0x80101,
+ 0x2000200,
+ 0x1000100,
+ 0x1000000,
+ 0x2000200,
+ 0x200,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0xe000004,
+ 0xc0d100f,
+ 0xa09080b,
+ 0x2010000,
+ 0x80103,
+ 0x200,
+ 0x0,
+ 0xf000000,
+ 0x4,
+ 0xa,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x30100,
+ 0x1010001,
+ 0x10200,
+ 0x4000103,
+ 0x1050001,
+ 0x10600,
+ 0x107,
+ 0x0,
+ 0x0,
+ 0x10001,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x10000,
+ 0x4,
+ 0x0,
+ 0x10000,
+ 0x0,
+ 0x3c0003,
+ 0x80100a0,
+ 0x16,
+ 0x2c,
+ 0x33,
+ 0x20043,
+ 0x2000200,
+ 0x4,
+ 0x60c,
+ 0xa1400,
+ 0x280000,
+ 0x6,
+ 0x46,
+ 0x70,
+ 0x610,
+ 0x12b,
+ 0x4001035,
+ 0x1010404,
+ 0x1e01,
+ 0x1e001e,
+ 0x1000100,
+ 0x100,
+ 0x0,
+ 0x5060403,
+ 0x1011108,
+ 0x1010101,
+ 0xf0a0a,
+ 0x0,
+ 0x0,
+ 0x4000000,
+ 0x4021008,
+ 0x4020206,
+ 0xc0034,
+ 0x100038,
+ 0x17003f,
+ 0x10001,
+ 0x10001,
+ 0x10005,
+ 0x20064,
+ 0x100010b,
+ 0x60006,
+ 0x650100,
+ 0x1000065,
+ 0x10c010c,
+ 0x1e1a1e1a,
+ 0x1011e1a,
+ 0xa070601,
+ 0xa07060d,
+ 0x100b080d,
+ 0xc00f,
+ 0xc01000,
+ 0xc01000,
+ 0x21000,
+ 0x120005,
+ 0x190064,
+ 0x10b,
+ 0x1100,
+ 0x1e1a0056,
+ 0x6000101,
+ 0x130204,
+ 0x1e1a0058,
+ 0x1000101,
+ 0x230408,
+ 0x1e1a005e,
+ 0x9000101,
+ 0x610,
+ 0x4040800,
+ 0x40100,
+ 0x3000277,
+ 0xa032001,
+ 0xa0a,
+ 0x80908,
+ 0x901,
+ 0x1100315c,
+ 0xa062002,
+ 0xa0a,
+ 0x141708,
+ 0x150d,
+ 0x2d00838e,
+ 0xf102004,
+ 0xf0b,
+ 0x8c,
+ 0x578,
+ 0xc20,
+ 0x7940,
+ 0x206a,
+ 0x14424,
+ 0x730006,
+ 0x3030133,
+ 0x4,
+ 0x0,
+ 0x4,
+ 0x1,
+ 0x5,
+ 0x2,
+ 0x6,
+ 0x50,
+ 0x1,
+ 0x5,
+ 0x28,
+ 0x73,
+ 0xd6,
+ 0x1,
+ 0x5,
+ 0x6b,
+ 0x1000133,
+ 0x140040,
+ 0x10001,
+ 0x1900040,
+ 0x1000c,
+ 0x42b0040,
+ 0x320,
+ 0x360014,
+ 0x1010101,
+ 0x2020101,
+ 0x8080404,
+ 0x67676767,
+ 0x67676767,
+ 0x67676767,
+ 0x67676767,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x5500,
+ 0x5a00,
+ 0x55003c,
+ 0x0,
+ 0x3c00005a,
+ 0x5500,
+ 0x5a00,
+ 0x55003c,
+ 0x0,
+ 0x3c00005a,
+ 0x18171615,
+ 0x14131211,
+ 0x7060504,
+ 0x3020100,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1000000,
+ 0x4020201,
+ 0x80804,
+ 0x0,
+ 0x4,
+ 0x0,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x14,
+ 0x9,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x34,
+ 0x1b,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x4,
+ 0x0,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x14,
+ 0x9,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x34,
+ 0x1b,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x4,
+ 0x0,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x14,
+ 0x9,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x34,
+ 0x1b,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x4,
+ 0x0,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x14,
+ 0x9,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+ 0x0,
+ 0x34,
+ 0x1b,
+ 0x31,
+ 0x31,
+ 0x0,
+ 0x0,
+ 0x4d4d,
+};
+
+void ddr_phy_train(u32 *phyreg)
+{
+ u32 i, len;
+
+ len = ARRAY_SIZE(ddr_train_data);
+ for (i = 0; i < len; i++)
+ out_le32(phyreg + i, ddr_train_data[i]);
+}
diff --git a/drivers/ram/starfive/ddrphy_utils.c b/drivers/ram/starfive/ddrphy_utils.c
new file mode 100644
index 00000000000..1c9fe0a7846
--- /dev/null
+++ b/drivers/ram/starfive/ddrphy_utils.c
@@ -0,0 +1,1955 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang<[email protected]>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+static const u32 ddr_phy_data[] = {
+ 0x4f0,
+ 0x0,
+ 0x1030200,
+ 0x0,
+ 0x0,
+ 0x3000000,
+ 0x1000001,
+ 0x3000400,
+ 0x1000001,
+ 0x0,
+ 0x0,
+ 0x1000001,
+ 0x0,
+ 0xc00004,
+ 0xcc0008,
+ 0x660601,
+ 0x3,
+ 0x0,
+ 0x1,
+ 0xaaaa,
+ 0x5555,
+ 0xb5b5,
+ 0x4a4a,
+ 0x5656,
+ 0xa9a9,
+ 0xa9a9,
+ 0xb5b5,
+ 0x0,
+ 0x0,
+ 0x8000000,
+ 0x4000008,
+ 0x408,
+ 0xe4e400,
+ 0x71020,
+ 0xc0020,
+ 0x620,
+ 0x100,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x5555,
+ 0x1000100,
+ 0x800180,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4,
+ 0x20,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x7ff0000,
+ 0x20008008,
+ 0x810,
+ 0x40100,
+ 0x0,
+ 0x1880c01,
+ 0x2003880c,
+ 0x20000125,
+ 0x7ff0200,
+ 0x101,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x20000,
+ 0x51515052,
+ 0x31c06000,
+ 0x11f0004,
+ 0xc0c001,
+ 0x3000000,
+ 0x30202,
+ 0x42100010,
+ 0x10c053e,
+ 0xf0c20,
+ 0x1000140,
+ 0xa30120,
+ 0xc00,
+ 0x210,
+ 0x200,
+ 0x2800000,
+ 0x80800101,
+ 0x3,
+ 0x76543210,
+ 0x8,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x280,
+ 0x8000,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x6e0080,
+ 0x1a00003,
+ 0x0,
+ 0x30000,
+ 0x80200,
+ 0x0,
+ 0x20202020,
+ 0x20202020,
+ 0x2020,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4f0,
+ 0x0,
+ 0x1030200,
+ 0x0,
+ 0x0,
+ 0x3000000,
+ 0x1000001,
+ 0x3000400,
+ 0x1000001,
+ 0x0,
+ 0x0,
+ 0x1000001,
+ 0x0,
+ 0xc00004,
+ 0xcc0008,
+ 0x660601,
+ 0x3,
+ 0x0,
+ 0x1,
+ 0xaaaa,
+ 0x5555,
+ 0xb5b5,
+ 0x4a4a,
+ 0x5656,
+ 0xa9a9,
+ 0xa9a9,
+ 0xb5b5,
+ 0x0,
+ 0x0,
+ 0x8000000,
+ 0x4000008,
+ 0x408,
+ 0xe4e400,
+ 0x71020,
+ 0xc0020,
+ 0x620,
+ 0x100,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x5555,
+ 0x1000100,
+ 0x800180,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4,
+ 0x20,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x7ff0000,
+ 0x20008008,
+ 0x810,
+ 0x40100,
+ 0x0,
+ 0x1880c01,
+ 0x2003880c,
+ 0x20000125,
+ 0x7ff0200,
+ 0x101,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x20000,
+ 0x51515052,
+ 0x31c06000,
+ 0x11f0004,
+ 0xc0c001,
+ 0x3000000,
+ 0x30202,
+ 0x42100010,
+ 0x10c053e,
+ 0xf0c20,
+ 0x1000140,
+ 0xa30120,
+ 0xc00,
+ 0x210,
+ 0x200,
+ 0x2800000,
+ 0x80800101,
+ 0x3,
+ 0x76543210,
+ 0x8,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x280,
+ 0x8000,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x6e0080,
+ 0x1a00003,
+ 0x0,
+ 0x30000,
+ 0x80200,
+ 0x0,
+ 0x20202020,
+ 0x20202020,
+ 0x2020,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4f0,
+ 0x0,
+ 0x1030200,
+ 0x0,
+ 0x0,
+ 0x3000000,
+ 0x1000001,
+ 0x3000400,
+ 0x1000001,
+ 0x0,
+ 0x0,
+ 0x1000001,
+ 0x0,
+ 0xc00004,
+ 0xcc0008,
+ 0x660601,
+ 0x3,
+ 0x0,
+ 0x1,
+ 0xaaaa,
+ 0x5555,
+ 0xb5b5,
+ 0x4a4a,
+ 0x5656,
+ 0xa9a9,
+ 0xa9a9,
+ 0xb5b5,
+ 0x0,
+ 0x0,
+ 0x8000000,
+ 0x4000008,
+ 0x408,
+ 0xe4e400,
+ 0x71020,
+ 0xc0020,
+ 0x620,
+ 0x100,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x5555,
+ 0x1000100,
+ 0x800180,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4,
+ 0x20,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x7ff0000,
+ 0x20008008,
+ 0x810,
+ 0x40100,
+ 0x0,
+ 0x1880c01,
+ 0x2003880c,
+ 0x20000125,
+ 0x7ff0200,
+ 0x101,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x20000,
+ 0x51515052,
+ 0x31c06000,
+ 0x11f0004,
+ 0xc0c001,
+ 0x3000000,
+ 0x30202,
+ 0x42100010,
+ 0x10c053e,
+ 0xf0c20,
+ 0x1000140,
+ 0xa30120,
+ 0xc00,
+ 0x210,
+ 0x200,
+ 0x2800000,
+ 0x80800101,
+ 0x3,
+ 0x76543210,
+ 0x8,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x280,
+ 0x8000,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x6e0080,
+ 0x1a00003,
+ 0x0,
+ 0x30000,
+ 0x80200,
+ 0x0,
+ 0x20202020,
+ 0x20202020,
+ 0x2020,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4f0,
+ 0x0,
+ 0x1030200,
+ 0x0,
+ 0x0,
+ 0x3000000,
+ 0x1000001,
+ 0x3000400,
+ 0x1000001,
+ 0x0,
+ 0x0,
+ 0x1000001,
+ 0x0,
+ 0xc00004,
+ 0xcc0008,
+ 0x660601,
+ 0x3,
+ 0x0,
+ 0x1,
+ 0xaaaa,
+ 0x5555,
+ 0xb5b5,
+ 0x4a4a,
+ 0x5656,
+ 0xa9a9,
+ 0xa9a9,
+ 0xb5b5,
+ 0x0,
+ 0x0,
+ 0x8000000,
+ 0x4000008,
+ 0x408,
+ 0xe4e400,
+ 0x71020,
+ 0xc0020,
+ 0x620,
+ 0x100,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x55555555,
+ 0xaaaaaaaa,
+ 0x5555,
+ 0x1000100,
+ 0x800180,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4,
+ 0x20,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x7ff0000,
+ 0x20008008,
+ 0x810,
+ 0x40100,
+ 0x0,
+ 0x1880c01,
+ 0x2003880c,
+ 0x20000125,
+ 0x7ff0200,
+ 0x101,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x20000,
+ 0x51515052,
+ 0x31c06000,
+ 0x11f0004,
+ 0xc0c001,
+ 0x3000000,
+ 0x30202,
+ 0x42100010,
+ 0x10c053e,
+ 0xf0c20,
+ 0x1000140,
+ 0xa30120,
+ 0xc00,
+ 0x210,
+ 0x200,
+ 0x2800000,
+ 0x80800101,
+ 0x3,
+ 0x76543210,
+ 0x8,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x2800280,
+ 0x280,
+ 0x8000,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x800080,
+ 0x6e0080,
+ 0x1a00003,
+ 0x0,
+ 0x30000,
+ 0x80200,
+ 0x0,
+ 0x20202020,
+ 0x20202020,
+ 0x2020,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x100,
+ 0x200,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x400000,
+ 0x80,
+ 0xdcba98,
+ 0x3000000,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x2a,
+ 0x15,
+ 0x15,
+ 0x2a,
+ 0x33,
+ 0xc,
+ 0xc,
+ 0x33,
+ 0xa418820,
+ 0x3f0000,
+ 0x13f,
+ 0x20202000,
+ 0x202020,
+ 0x20008008,
+ 0x810,
+ 0x0,
+ 0x255,
+ 0x30000,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x42080010,
+ 0x33e,
+ 0x1010002,
+ 0x80,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x100,
+ 0x200,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x400000,
+ 0x80,
+ 0xdcba98,
+ 0x3000000,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x2a,
+ 0x15,
+ 0x15,
+ 0x2a,
+ 0x33,
+ 0xc,
+ 0xc,
+ 0x33,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x20202000,
+ 0x202020,
+ 0x20008008,
+ 0x810,
+ 0x0,
+ 0x255,
+ 0x30000,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x42080010,
+ 0x33e,
+ 0x1010002,
+ 0x80,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x100,
+ 0x200,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x400000,
+ 0x80,
+ 0xdcba98,
+ 0x3000000,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x2a,
+ 0x15,
+ 0x15,
+ 0x2a,
+ 0x33,
+ 0xc,
+ 0xc,
+ 0x33,
+ 0x0,
+ 0x10000000,
+ 0x0,
+ 0x20202000,
+ 0x202020,
+ 0x20008008,
+ 0x810,
+ 0x0,
+ 0x255,
+ 0x30000,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x42080010,
+ 0x33e,
+ 0x1010002,
+ 0x80,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x100,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x50000,
+ 0x4000000,
+ 0x55,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0xf0001,
+ 0x280040,
+ 0x5002,
+ 0x10101,
+ 0x8008,
+ 0x81020,
+ 0x0,
+ 0x0,
+ 0x1000000,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x64,
+ 0x0,
+ 0x0,
+ 0x1010000,
+ 0x2020101,
+ 0x4040202,
+ 0x8080404,
+ 0xf0f0808,
+ 0xf0f0f0f,
+ 0x20200f0f,
+ 0x1b428000,
+ 0x4,
+ 0x1010000,
+ 0x1070501,
+ 0x54,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x4410,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x64,
+ 0x0,
+ 0x108,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x3000000,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x4102035,
+ 0x41020,
+ 0x1c98c98,
+ 0x3f400000,
+ 0x3f3f1f3f,
+ 0x1f3f3f1f,
+ 0x1f3f3f,
+ 0x0,
+ 0x0,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x76543210,
+ 0x6010198,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x40700,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x2,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1142,
+ 0x3020100,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x3000300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x300,
+ 0x2,
+ 0x4011,
+ 0x4011,
+ 0x40,
+ 0x40,
+ 0x4011,
+ 0x1fff00,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x4011,
+ 0x1004011,
+ 0x200400,
+
+};
+
+void ddr_phy_util(u32 *phyreg)
+{
+ u32 i, len;
+
+ len = ARRAY_SIZE(ddr_phy_data);
+ for (i = 1792; i < len; i++)
+ out_le32(phyreg + i, ddr_phy_data[i]);
+
+ for (i = 0; i < 1792; i++)
+ out_le32(phyreg + i, ddr_phy_data[i]);
+}
diff --git a/drivers/ram/starfive/starfive_ddr.c b/drivers/ram/starfive/starfive_ddr.c
new file mode 100644
index 00000000000..553f2ce6f44
--- /dev/null
+++ b/drivers/ram/starfive/starfive_ddr.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang<[email protected]>
+ */
+
+#include <common.h>
+#include <asm/arch/regs.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <linux/bitops.h>
+#include <linux/sizes.h>
+#include <linux/delay.h>
+#include <ram.h>
+#include <reset.h>
+
+#include "starfive_ddr.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct starfive_ddr_priv {
+ struct udevice *dev;
+ struct ram_info info;
+ void __iomem *ctrlreg;
+ void __iomem *phyreg;
+ struct reset_ctl_bulk rst;
+ struct clk clk;
+ u32 fre;
+};
+
+static int starfive_ddr_setup(struct udevice *dev, struct starfive_ddr_priv *priv)
+{
+ enum ddr_size_t size;
+
+ switch (priv->info.size) {
+ case SZ_2G:
+ size = DDR_SIZE_2G;
+ break;
+
+ case SZ_4G:
+ size = DDR_SIZE_4G;
+ break;
+
+ case 0x200000000:
+ size = DDR_SIZE_8G;
+ break;
+
+ case 0x400000000:
+ default:
+ pr_err("unsupport size %lx\n", priv->info.size);
+ return -EINVAL;
+ }
+
+ ddr_phy_train(priv->phyreg + (PHY_BASE_ADDR << 2));
+ ddr_phy_util(priv->phyreg + (PHY_AC_BASE_ADDR << 2));
+ ddr_phy_start(priv->phyreg, size);
+
+ DDR_REG_SET(BUS, DDR_BUS_OSC_DIV2);
+ ddrcsr_boot(priv->ctrlreg, priv->ctrlreg + SEC_CTRL_ADDR,
+ priv->phyreg, size);
+
+ return 0;
+}
+
+static int starfive_ddr_probe(struct udevice *dev)
+{
+ struct starfive_ddr_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ u64 rate;
+ int ret;
+
+ /* Read memory base and size from DT */
+ fdtdec_setup_mem_size_base();
+ priv->info.base = gd->ram_base;
+ priv->info.size = gd->ram_size;
+
+ priv->dev = dev;
+ addr = dev_read_addr_index(dev, 0);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->ctrlreg = (void __iomem *)addr;
+ addr = dev_read_addr_index(dev, 1);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->phyreg = (void __iomem *)addr;
+ ret = dev_read_u32(dev, "clock-frequency", &priv->fre);
+ if (ret)
+ return ret;
+
+ switch (priv->fre) {
+ case 2133:
+ rate = 1066000000;
+ break;
+
+ case 2800:
+ rate = 1400000000;
+ break;
+
+ default:
+ pr_err("Unknown DDR frequency %d\n", priv->fre);
+ return -EINVAL;
+ };
+
+ ret = reset_get_bulk(dev, &priv->rst);
+ if (ret)
+ return ret;
+
+ ret = reset_deassert_bulk(&priv->rst);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret)
+ goto err_free_reset;
+
+ ret = clk_set_rate(&priv->clk, rate);
+ if (ret < 0)
+ goto err_free_reset;
+
+ ret = starfive_ddr_setup(dev, priv);
+ printf("DDR version: dc2e84f0.\n");
+
+ return ret;
+
+err_free_reset:
+ reset_release_bulk(&priv->rst);
+
+ return ret;
+}
+
+static int starfive_ddr_get_info(struct udevice *dev, struct ram_info *info)
+{
+ struct starfive_ddr_priv *priv = dev_get_priv(dev);
+
+ *info = priv->info;
+
+ return 0;
+}
+
+static struct ram_ops starfive_ddr_ops = {
+ .get_info = starfive_ddr_get_info,
+};
+
+static const struct udevice_id starfive_ddr_ids[] = {
+ { .compatible = "starfive,jh7110-dmc" },
+ { }
+};
+
+U_BOOT_DRIVER(starfive_ddr) = {
+ .name = "starfive_ddr",
+ .id = UCLASS_RAM,
+ .of_match = starfive_ddr_ids,
+ .ops = &starfive_ddr_ops,
+ .probe = starfive_ddr_probe,
+ .priv_auto = sizeof(struct starfive_ddr_priv),
+};
diff --git a/drivers/ram/starfive/starfive_ddr.h b/drivers/ram/starfive/starfive_ddr.h
new file mode 100644
index 00000000000..d0ec1c1da80
--- /dev/null
+++ b/drivers/ram/starfive/starfive_ddr.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang<[email protected]>
+ */
+
+#ifndef __STARFIVE_DDR_H__
+#define __STARFIVE_DDR_H__
+
+#define SEC_CTRL_ADDR 0x1000
+#define PHY_BASE_ADDR 0x800
+#define PHY_AC_BASE_ADDR 0x1000
+
+#define DDR_BUS_MASK GENMASK(29, 24)
+#define DDR_AXI_MASK BIT(31)
+#define DDR_BUS_OFFSET 0xAC
+#define DDR_AXI_OFFSET 0xB0
+
+#define DDR_BUS_OSC_DIV2 0
+#define DDR_BUS_PLL1_DIV2 1
+#define DDR_BUS_PLL1_DIV4 2
+#define DDR_BUS_PLL1_DIV8 3
+#define DDR_AXI_DISABLE 0
+#define DDR_AXI_ENABLE 1
+
+#define OFFSET_SEL BIT(31)
+#define REG2G BIT(30)
+#define REG4G BIT(29)
+#define REG8G BIT(28)
+#define F_ADDSET BIT(2)
+#define F_SET BIT(1)
+#define F_CLRSET BIT(0)
+#define REGALL (REG2G | REG4G | REG8G)
+#define REGSETALL (F_SET | REGALL)
+#define REGCLRSETALL (F_CLRSET | REGALL)
+#define REGADDSETALL (F_ADDSET | REGALL)
+
+struct ddr_reg_cfg {
+ u32 offset;
+ u32 mask;
+ u32 val;
+ u32 flag;
+};
+
+enum ddr_size_t {
+ DDR_SIZE_2G,
+ DDR_SIZE_4G,
+ DDR_SIZE_8G,
+ DDR_SIZE_16G,
+};
+
+void ddr_phy_train(u32 *phyreg);
+void ddr_phy_util(u32 *phyreg);
+void ddr_phy_start(u32 *phyreg, enum ddr_size_t size);
+void ddrcsr_boot(u32 *csrreg, u32 *secreg, u32 *phyreg, enum ddr_size_t size);
+
+#define DDR_REG_TRIGGER(addr, mask, value) \
+ out_le32((addr), (in_le32(addr) & (mask)) | (value))
+
+#define DDR_REG_SET(type, val) \
+ clrsetbits_le32(JH7110_SYS_CRG + DDR_##type##_OFFSET, \
+ DDR_##type##_MASK, \
+ ((val) << __ffs(DDR_##type##_MASK)) & DDR_##type##_MASK)
+
+#endif /*__STARFIVE_DDR_H__*/
diff --git a/drivers/ram/stm32mp1/stm32mp1_interactive.c b/drivers/ram/stm32mp1/stm32mp1_interactive.c
index f0fe7e61e33..2c19847c663 100644
--- a/drivers/ram/stm32mp1/stm32mp1_interactive.c
+++ b/drivers/ram/stm32mp1/stm32mp1_interactive.c
@@ -391,7 +391,7 @@ bool stm32mp1_ddr_interactive(void *priv,
if (next_step < 0)
return false;
- if (step < 0 || step > ARRAY_SIZE(step_str)) {
+ if (step < 0 || step >= ARRAY_SIZE(step_str)) {
printf("** step %d ** INVALID\n", step);
return false;
}
diff --git a/drivers/remoteproc/ti_k3_arm64_rproc.c b/drivers/remoteproc/ti_k3_arm64_rproc.c
index 1f2415dc1a6..99f11000dfb 100644
--- a/drivers/remoteproc/ti_k3_arm64_rproc.c
+++ b/drivers/remoteproc/ti_k3_arm64_rproc.c
@@ -36,6 +36,8 @@
* @gtc_base: Timer base address.
*/
struct k3_arm64_privdata {
+ bool has_cluster_node;
+ struct power_domain cluster_pwrdmn;
struct power_domain rproc_pwrdmn;
struct power_domain gtc_pwrdmn;
struct reset_ctl rproc_rst;
@@ -55,6 +57,7 @@ struct k3_arm64_privdata {
static int k3_arm64_load(struct udevice *dev, ulong addr, ulong size)
{
struct k3_arm64_privdata *rproc = dev_get_priv(dev);
+ ulong gtc_rate;
int ret;
dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size);
@@ -64,26 +67,10 @@ static int k3_arm64_load(struct udevice *dev, ulong addr, ulong size)
if (ret)
return ret;
- return ti_sci_proc_set_config(&rproc->tsp, addr, 0, 0);
-}
-
-/**
- * k3_arm64_start() - Start the remote processor
- * @dev: rproc device pointer
- *
- * Return: 0 if all went ok, else return appropriate error
- */
-static int k3_arm64_start(struct udevice *dev)
-{
- struct k3_arm64_privdata *rproc = dev_get_priv(dev);
- ulong gtc_rate;
- int ret;
-
- dev_dbg(dev, "%s\n", __func__);
-
ret = power_domain_on(&rproc->gtc_pwrdmn);
if (ret) {
- dev_err(dev, "power_domain_on() failed: %d\n", ret);
+ dev_err(dev, "power_domain_on(&rproc->gtc_pwrdmn) failed: %d\n",
+ ret);
return ret;
}
@@ -100,9 +87,36 @@ static int k3_arm64_start(struct udevice *dev)
* assigned-clock-rates during the device probe. So no need to
* set the frequency again here.
*/
+ if (rproc->has_cluster_node) {
+ ret = power_domain_on(&rproc->cluster_pwrdmn);
+ if (ret) {
+ dev_err(dev,
+ "power_domain_on(&rproc->cluster_pwrdmn) failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return ti_sci_proc_set_config(&rproc->tsp, addr, 0, 0);
+}
+
+/**
+ * k3_arm64_start() - Start the remote processor
+ * @dev: rproc device pointer
+ *
+ * Return: 0 if all went ok, else return appropriate error
+ */
+static int k3_arm64_start(struct udevice *dev)
+{
+ struct k3_arm64_privdata *rproc = dev_get_priv(dev);
+ int ret;
+
+ dev_dbg(dev, "%s\n", __func__);
ret = power_domain_on(&rproc->rproc_pwrdmn);
if (ret) {
- dev_err(dev, "power_domain_on() failed: %d\n", ret);
+ dev_err(dev,
+ "power_domain_on(&rproc->rproc_pwrdmn) failed: %d\n",
+ ret);
return ret;
}
@@ -166,9 +180,17 @@ static int k3_arm64_of_to_priv(struct udevice *dev,
dev_dbg(dev, "%s\n", __func__);
+ /* Cluster needs to be powered on if firewalls are being configured */
+ rproc->has_cluster_node = true;
+ ret = power_domain_get_by_index(dev, &rproc->cluster_pwrdmn, 2);
+ if (ret) {
+ dev_dbg(dev, "warning: power_domain_get_cluster() failed: %d\n", ret);
+ rproc->has_cluster_node = false;
+ }
+
ret = power_domain_get_by_index(dev, &rproc->rproc_pwrdmn, 1);
if (ret) {
- dev_err(dev, "power_domain_get() failed: %d\n", ret);
+ dev_err(dev, "power_domain_get_rproc() failed: %d\n", ret);
return ret;
}
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index e4039d74744..73bbd306925 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -172,6 +172,22 @@ config RESET_SIFIVE
different hw blocks like DDR, gemgxl. With this driver we leverage
U-Boot's reset framework to reset these hardware blocks.
+config RESET_JH7110
+ bool "Reset driver for StarFive JH7110 SoC"
+ depends on DM_RESET && STARFIVE_JH7110
+ default y
+ help
+ Support for reset controller on StarFive
+ JH7110 SoCs.
+
+config SPL_RESET_JH7110
+ bool "SPL Reset driver for StarFive JH7110 SoC"
+ depends on SPL && STARFIVE_JH7110
+ default y
+ help
+ Support for reset controller on StarFive
+ JH7110 SoCs in SPL.
+
config RESET_SYSCON
bool "Enable generic syscon reset driver support"
depends on DM_RESET
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 6c8b45ecbab..68012681809 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
obj-$(CONFIG_RESET_DRA7) += reset-dra7.o
obj-$(CONFIG_RESET_AT91) += reset-at91.o
+obj-$(CONFIG_$(SPL_TPL_)RESET_JH7110) += reset-jh7110.o
diff --git a/drivers/reset/reset-jh7110.c b/drivers/reset/reset-jh7110.c
new file mode 100644
index 00000000000..d6bdf6bb00c
--- /dev/null
+++ b/drivers/reset/reset-jh7110.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Author: Yanhong Wang <[email protected]>
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/ofnode.h>
+#include <dt-bindings/reset/starfive,jh7110-crg.h>
+#include <errno.h>
+#include <linux/iopoll.h>
+#include <reset-uclass.h>
+
+struct jh7110_reset_priv {
+ void __iomem *reg;
+ u32 assert;
+ u32 status;
+ u32 resets;
+};
+
+struct reset_info {
+ const char *compat;
+ const u32 nr_resets;
+ const u32 assert_offset;
+ const u32 status_offset;
+};
+
+static const struct reset_info jh7110_rst_info[] = {
+ {
+ .compat = "starfive,jh7110-syscrg",
+ .nr_resets = JH7110_SYSRST_END,
+ .assert_offset = 0x2F8,
+ .status_offset = 0x308,
+ },
+ {
+ .compat = "starfive,jh7110-aoncrg",
+ .nr_resets = JH7110_AONRST_END,
+ .assert_offset = 0x38,
+ .status_offset = 0x3C,
+ },
+ {
+ .compat = "starfive,jh7110-stgcrg",
+ .nr_resets = JH7110_STGRST_END,
+ .assert_offset = 0x74,
+ .status_offset = 0x78,
+ }
+};
+
+static const struct reset_info *jh7110_reset_get_cfg(const char *compat)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(jh7110_rst_info); i++)
+ if (!strcmp(compat, jh7110_rst_info[i].compat))
+ return &jh7110_rst_info[i];
+
+ return NULL;
+}
+
+static int jh7110_reset_trigger(struct jh7110_reset_priv *priv,
+ unsigned long id, bool assert)
+{
+ ulong group;
+ u32 mask, value, done = 0;
+ ulong addr;
+
+ group = id / 32;
+ mask = BIT(id % 32);
+
+ if (!assert)
+ done ^= mask;
+
+ addr = (ulong)priv->reg + priv->assert + group * sizeof(u32);
+ value = readl((ulong *)addr);
+
+ if (assert)
+ value |= mask;
+ else
+ value &= ~mask;
+
+ writel(value, (ulong *)addr);
+ addr = (ulong)priv->reg + priv->status + group * sizeof(u32);
+
+ return readl_poll_timeout((ulong *)addr, value,
+ (value & mask) == done, 1000);
+}
+
+static int jh7110_reset_assert(struct reset_ctl *rst)
+{
+ struct jh7110_reset_priv *priv = dev_get_priv(rst->dev);
+
+ jh7110_reset_trigger(priv, rst->id, true);
+
+ return 0;
+}
+
+static int jh7110_reset_deassert(struct reset_ctl *rst)
+{
+ struct jh7110_reset_priv *priv = dev_get_priv(rst->dev);
+
+ jh7110_reset_trigger(priv, rst->id, false);
+
+ return 0;
+}
+
+static int jh7110_reset_free(struct reset_ctl *rst)
+{
+ return 0;
+}
+
+static int jh7110_reset_request(struct reset_ctl *rst)
+{
+ struct jh7110_reset_priv *priv = dev_get_priv(rst->dev);
+
+ if (rst->id >= priv->resets)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int jh7110_reset_probe(struct udevice *dev)
+{
+ struct jh7110_reset_priv *priv = dev_get_priv(dev);
+ const struct reset_info *cfg;
+ const char *compat;
+
+ compat = ofnode_get_property(dev_ofnode(dev), "compatible", NULL);
+ if (!compat)
+ return -EINVAL;
+
+ cfg = jh7110_reset_get_cfg(compat);
+ if (!cfg)
+ return -EINVAL;
+
+ priv->assert = cfg->assert_offset;
+ priv->status = cfg->status_offset;
+ priv->resets = cfg->nr_resets;
+ priv->reg = (void __iomem *)dev_read_addr_index(dev, 0);
+
+ return 0;
+}
+
+const struct reset_ops jh7110_reset_reset_ops = {
+ .rfree = jh7110_reset_free,
+ .request = jh7110_reset_request,
+ .rst_assert = jh7110_reset_assert,
+ .rst_deassert = jh7110_reset_deassert,
+};
+
+U_BOOT_DRIVER(jh7110_reset) = {
+ .name = "jh7110_reset",
+ .id = UCLASS_RESET,
+ .ops = &jh7110_reset_reset_ops,
+ .probe = jh7110_reset_probe,
+ .priv_auto = sizeof(struct jh7110_reset_priv),
+};
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
index 5dcf68176af..5deb5db5b71 100644
--- a/drivers/rng/Kconfig
+++ b/drivers/rng/Kconfig
@@ -58,8 +58,9 @@ config RNG_ROCKCHIP
bool "Enable random number generator for rockchip crypto rng"
depends on ARCH_ROCKCHIP && DM_RNG
help
- Enable random number generator for rockchip.This driver is
- support rng module of crypto v1 and crypto v2.
+ Enable random number generator for rockchip. This driver
+ supports the rng module of crypto v1, crypto v2, and the
+ trng module of the rk3588 series.
config RNG_IPROC200
bool "Broadcom iProc RNG200 random number generator"
diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c
index 800150f1147..705b424cf3d 100644
--- a/drivers/rng/rockchip_rng.c
+++ b/drivers/rng/rockchip_rng.c
@@ -43,9 +43,41 @@
#define CRYPTO_V2_RNG_DOUT_0 0x0410
/* end of CRYPTO V2 register define */
+/* start of TRNG V1 register define */
+#define TRNG_V1_CTRL 0x0000
+#define TRNG_V1_CTRL_NOP _SBF(0, 0x00)
+#define TRNG_V1_CTRL_RAND _SBF(0, 0x01)
+#define TRNG_V1_CTRL_SEED _SBF(0, 0x02)
+
+#define TRNG_V1_MODE 0x0008
+#define TRNG_V1_MODE_128_BIT _SBF(3, 0x00)
+#define TRNG_V1_MODE_256_BIT _SBF(3, 0x01)
+
+#define TRNG_V1_IE 0x0010
+#define TRNG_V1_IE_GLBL_EN BIT(31)
+#define TRNG_V1_IE_SEED_DONE_EN BIT(1)
+#define TRNG_V1_IE_RAND_RDY_EN BIT(0)
+
+#define TRNG_V1_ISTAT 0x0014
+#define TRNG_V1_ISTAT_RAND_RDY BIT(0)
+
+/* RAND0 ~ RAND7 */
+#define TRNG_V1_RAND0 0x0020
+#define TRNG_V1_RAND7 0x003C
+
+#define TRNG_V1_AUTO_RQSTS 0x0060
+
+#define TRNG_V1_VERSION 0x00F0
+#define TRNG_v1_VERSION_CODE 0x46BC
+/* end of TRNG V1 register define */
+
#define RK_RNG_TIME_OUT 50000 /* max 50ms */
+#define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos))
+#define trng_read(pdata, pos) readl((pdata)->base + (pos))
+
struct rk_rng_soc_data {
+ int (*rk_rng_init)(struct udevice *dev);
int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
};
@@ -75,7 +107,7 @@ static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size)
return 0;
}
-static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len)
+static int rk_cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
u32 reg = 0;
@@ -106,7 +138,7 @@ exit:
return 0;
}
-static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len)
+static int rk_cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
u32 reg = 0;
@@ -140,6 +172,63 @@ exit:
return retval;
}
+static int rk_trngv1_init(struct udevice *dev)
+{
+ u32 status, version;
+ u32 auto_reseed_cnt = 1000;
+ struct rk_rng_plat *pdata = dev_get_priv(dev);
+
+ version = trng_read(pdata, TRNG_V1_VERSION);
+ if (version != TRNG_v1_VERSION_CODE) {
+ printf("wrong trng version, expected = %08x, actual = %08x",
+ TRNG_V1_VERSION, version);
+ return -EFAULT;
+ }
+
+ /* wait in case of RND_RDY triggered at firs power on */
+ readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, status,
+ (status & TRNG_V1_ISTAT_RAND_RDY),
+ RK_RNG_TIME_OUT);
+
+ /* clear RAND_RDY flag for first power on */
+ trng_write(pdata, TRNG_V1_ISTAT, status);
+
+ /* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
+ trng_write(pdata, TRNG_V1_AUTO_RQSTS, auto_reseed_cnt);
+
+ return 0;
+}
+
+static int rk_trngv1_rng_read(struct udevice *dev, void *data, size_t len)
+{
+ struct rk_rng_plat *pdata = dev_get_priv(dev);
+ u32 reg = 0;
+ int retval;
+
+ if (len > RK_HW_RNG_MAX)
+ return -EINVAL;
+
+ trng_write(pdata, TRNG_V1_MODE, TRNG_V1_MODE_256_BIT);
+ trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_RAND);
+
+ retval = readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, reg,
+ (reg & TRNG_V1_ISTAT_RAND_RDY),
+ RK_RNG_TIME_OUT);
+ /* clear ISTAT */
+ trng_write(pdata, TRNG_V1_ISTAT, reg);
+
+ if (retval)
+ goto exit;
+
+ rk_rng_read_regs(pdata->base + TRNG_V1_RAND0, data, len);
+
+exit:
+ /* close TRNG */
+ trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
+
+ return retval;
+}
+
static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
{
unsigned char *buf = data;
@@ -184,18 +273,27 @@ static int rockchip_rng_of_to_plat(struct udevice *dev)
static int rockchip_rng_probe(struct udevice *dev)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
+ int ret = 0;
pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
- return 0;
+ if (pdata->soc_data->rk_rng_init)
+ ret = pdata->soc_data->rk_rng_init(dev);
+
+ return ret;
}
-static const struct rk_rng_soc_data rk_rng_v1_soc_data = {
- .rk_rng_read = rk_v1_rng_read,
+static const struct rk_rng_soc_data rk_cryptov1_soc_data = {
+ .rk_rng_read = rk_cryptov1_rng_read,
+};
+
+static const struct rk_rng_soc_data rk_cryptov2_soc_data = {
+ .rk_rng_read = rk_cryptov2_rng_read,
};
-static const struct rk_rng_soc_data rk_rng_v2_soc_data = {
- .rk_rng_read = rk_v2_rng_read,
+static const struct rk_rng_soc_data rk_trngv1_soc_data = {
+ .rk_rng_init = rk_trngv1_init,
+ .rk_rng_read = rk_trngv1_rng_read,
};
static const struct dm_rng_ops rockchip_rng_ops = {
@@ -205,11 +303,15 @@ static const struct dm_rng_ops rockchip_rng_ops = {
static const struct udevice_id rockchip_rng_match[] = {
{
.compatible = "rockchip,cryptov1-rng",
- .data = (ulong)&rk_rng_v1_soc_data,
+ .data = (ulong)&rk_cryptov1_soc_data,
},
{
.compatible = "rockchip,cryptov2-rng",
- .data = (ulong)&rk_rng_v2_soc_data,
+ .data = (ulong)&rk_cryptov2_soc_data,
+ },
+ {
+ .compatible = "rockchip,trngv1",
+ .data = (ulong)&rk_trngv1_soc_data,
},
{},
};
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index ad484ce8e88..a8014129d33 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -26,7 +26,7 @@ config SCSI_AHCI_PLAT
This is deprecated. An AHCI driver should be provided instead.
config SYS_SCSI_MAX_SCSI_ID
- int "Maximum supporedt SCSI ID"
+ int "Maximum supported SCSI ID"
default 1
help
Sets the maximum number of SCSI IDs to scan when looking for devices.
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 10d07daf277..7faf6784442 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -946,6 +946,8 @@ config MSM_SERIAL
config MSM_GENI_SERIAL
bool "Qualcomm on-chip GENI UART"
+ select MISC
+ imply QCOM_GENI_SE
help
Support UART based on Generic Interface (GENI) Serial Engine (SE),
used on Qualcomm Snapdragon SoCs. Should support all qualcomm SOCs
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 77d3f373721..067fae26145 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -31,7 +31,7 @@ static const unsigned long baudrate_table[] = CFG_SYS_BAUDRATE_TABLE;
static int serial_check_stdout(const void *blob, struct udevice **devp)
{
int node = -1;
- const char *str, *p, *name;
+ const char *str, *p;
int namelen;
/* Check for a chosen console */
@@ -39,20 +39,16 @@ static int serial_check_stdout(const void *blob, struct udevice **devp)
if (str) {
p = strchr(str, ':');
namelen = p ? p - str : strlen(str);
+ /*
+ * This also deals with things like
+ *
+ * stdout-path = "serial0:115200n8";
+ *
+ * since fdt_path_offset_namelen() treats a str not
+ * beginning with '/' as an alias and thus applies
+ * fdt_get_alias_namelen() to it.
+ */
node = fdt_path_offset_namelen(blob, str, namelen);
-
- if (node < 0) {
- /*
- * Deal with things like
- * stdout-path = "serial0:115200n8";
- *
- * We need to look up the alias and then follow it to
- * the correct node.
- */
- name = fdt_get_alias_namelen(blob, str, namelen);
- if (name)
- node = fdt_path_offset(blob, name);
- }
}
if (node < 0)
diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c
index b8d6a81b650..d82760c7f10 100644
--- a/drivers/serial/serial_mpc8xx.c
+++ b/drivers/serial/serial_mpc8xx.c
@@ -83,15 +83,18 @@ static int serial_mpc8xx_probe(struct udevice *dev)
immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
smc_t __iomem *sp;
smc_uart_t __iomem *up;
+ u16 smc_rpbase;
cpm8xx_t __iomem *cp = &(im->im_cpm);
struct serialbuffer __iomem *rtx;
/* initialize pointers to SMC */
sp = cp->cp_smc + SMC_INDEX;
- up = (smc_uart_t __iomem *)&cp->cp_dparam[PROFF_SMC];
- /* Disable relocation */
- out_be16(&up->smc_rpbase, 0);
+ up = (smc_uart_t __iomem *)&cp->cp_dpmem[PROFF_SMC];
+
+ smc_rpbase = in_be16(&up->smc_rpbase);
+ if (smc_rpbase)
+ up = (smc_uart_t __iomem *)&cp->cp_dpmem[smc_rpbase];
/* Disable transmitter/receiver. */
clrbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
@@ -154,15 +157,12 @@ static int serial_mpc8xx_probe(struct udevice *dev)
out_be16(&up->smc_maxidl, CONFIG_SYS_MAXIDLE);
out_be32(&rtx->rxindex, 0);
- /* Initialize Tx/Rx parameters. */
- while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */
- ;
-
- out_be16(&cp->cp_cpcr,
- mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG);
-
- while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */
- ;
+ out_be32(&up->smc_rstate, 0);
+ out_be32(&up->smc_tstate, 0);
+ out_be16(&up->smc_rbptr, CPM_SERIAL_BASE);
+ out_be16(&up->smc_tbptr, CPM_SERIAL_BASE + sizeof(cbd_t));
+ out_be16(&up->smc_brkcr, 1);
+ out_be16(&up->smc_brkec, 0);
/* Enable transmitter/receiver. */
setbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c
index 3943ca43e49..78fd9389c03 100644
--- a/drivers/serial/serial_msm_geni.c
+++ b/drivers/serial/serial_msm_geni.c
@@ -11,15 +11,10 @@
#include <clk.h>
#include <common.h>
#include <dm.h>
-#include <dm/pinctrl.h>
#include <errno.h>
-#include <linux/compiler.h>
-#include <log.h>
#include <linux/delay.h>
-#include <malloc.h>
+#include <misc.h>
#include <serial.h>
-#include <watchdog.h>
-#include <linux/bug.h>
#define UART_OVERSAMPLING 32
#define STALE_TIMEOUT 160
@@ -116,6 +111,10 @@
#define TX_FIFO_DEPTH_MSK (GENMASK(21, 16))
#define TX_FIFO_DEPTH_SHFT 16
+/* GENI SE QUP Registers */
+#define QUP_HW_VER_REG 0x4
+#define QUP_SE_VERSION_2_5 0x20050000
+
/*
* Predefined packing configuration of the serial engine (CFG0, CFG1 regs)
* for uart mode.
@@ -133,11 +132,12 @@ DECLARE_GLOBAL_DATA_PTR;
struct msm_serial_data {
phys_addr_t base;
u32 baud;
+ u32 oversampling;
};
unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
- 32000000, 48000000, 64000000, 80000000,
- 96000000, 100000000};
+ 32000000, 48000000, 64000000, 80000000,
+ 96000000, 100000000};
/**
* get_clk_cfg() - Get clock rate to apply on clock supplier.
@@ -166,8 +166,7 @@ static int get_clk_cfg(unsigned long clk_freq)
*
* Return: frequency, supported by clock supplier, multiple of clk_freq.
*/
-static int get_clk_div_rate(u32 baud,
- u64 sampling_rate, u32 *clk_div)
+static int get_clk_div_rate(u32 baud, u64 sampling_rate, u32 *clk_div)
{
unsigned long ser_clk;
unsigned long desired_clk;
@@ -189,7 +188,7 @@ static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate)
struct clk *clk;
int ret;
- clk = devm_clk_get(dev, "se-clk");
+ clk = devm_clk_get(dev, NULL);
if (!clk)
return -EINVAL;
@@ -234,7 +233,7 @@ static inline u32 geni_se_get_tx_fifo_width(long base)
}
static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div,
- int baud)
+ int baud)
{
u32 s_clk_cfg = 0;
@@ -245,15 +244,15 @@ static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div,
writel(s_clk_cfg, base_address + GENI_SER_S_CLK_CFG);
}
-int msm_serial_setbrg(struct udevice *dev, int baud)
+static int msm_serial_setbrg(struct udevice *dev, int baud)
{
struct msm_serial_data *priv = dev_get_priv(dev);
+ u64 clk_rate;
+ u32 clk_div;
priv->baud = baud;
- u32 clk_div;
- u64 clk_rate;
- clk_rate = get_clk_div_rate(baud, UART_OVERSAMPLING, &clk_div);
+ clk_rate = get_clk_div_rate(baud, priv->oversampling, &clk_div);
geni_serial_set_clock_rate(dev, clk_rate);
geni_serial_baud(priv->base, clk_div, baud);
@@ -274,7 +273,7 @@ int msm_serial_setbrg(struct udevice *dev, int baud)
* reached.
*/
static bool qcom_geni_serial_poll_bit(const struct udevice *dev, int offset,
- int field, bool set)
+ int field, bool set)
{
u32 reg;
struct msm_serial_data *priv = dev_get_priv(dev);
@@ -487,6 +486,31 @@ static const struct dm_serial_ops msm_serial_ops = {
.setbrg = msm_serial_setbrg,
};
+static void geni_set_oversampling(struct udevice *dev)
+{
+ struct msm_serial_data *priv = dev_get_priv(dev);
+ struct udevice *parent_dev = dev_get_parent(dev);
+ u32 geni_se_version;
+ int ret;
+
+ priv->oversampling = UART_OVERSAMPLING;
+
+ /*
+ * It could happen that GENI SE IP is missing in the board's device
+ * tree or GENI UART node is a direct child of SoC device tree node.
+ */
+ if (device_get_uclass_id(parent_dev) != UCLASS_MISC)
+ return;
+
+ ret = misc_read(parent_dev, QUP_HW_VER_REG,
+ &geni_se_version, sizeof(geni_se_version));
+ if (ret != sizeof(geni_se_version))
+ return;
+
+ if (geni_se_version >= QUP_SE_VERSION_2_5)
+ priv->oversampling /= 2;
+}
+
static inline void geni_serial_init(struct udevice *dev)
{
struct msm_serial_data *priv = dev_get_priv(dev);
@@ -530,6 +554,8 @@ static int msm_serial_probe(struct udevice *dev)
{
struct msm_serial_data *priv = dev_get_priv(dev);
+ geni_set_oversampling(dev);
+
/* No need to reinitialize the UART after relocation */
if (gd->flags & GD_FLG_RELOC)
return 0;
@@ -554,7 +580,9 @@ static int msm_serial_ofdata_to_platdata(struct udevice *dev)
}
static const struct udevice_id msm_serial_ids[] = {
- {.compatible = "qcom,msm-geni-uart"}, {}};
+ { .compatible = "qcom,geni-debug-uart" },
+ { }
+};
U_BOOT_DRIVER(serial_msm_geni) = {
.name = "serial_msm_geni",
@@ -564,6 +592,7 @@ U_BOOT_DRIVER(serial_msm_geni) = {
.priv_auto = sizeof(struct msm_serial_data),
.probe = msm_serial_probe,
.ops = &msm_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
};
#ifdef CONFIG_DEBUG_UART_MSM_GENI
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index e08bdcadc9c..20cda5dbe27 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -57,6 +57,9 @@ static void sh_serial_init_generic(struct uart_port *port)
#if defined(CONFIG_RZA1)
sci_out(port, SCSPTR, 0x0003);
#endif
+
+ if (port->type == PORT_HSCIF)
+ sci_out(port, HSSRR, HSSRR_SRE | HSSRR_SRCYC8);
}
static void
@@ -205,6 +208,7 @@ static const struct udevice_id sh_serial_id[] ={
{.compatible = "renesas,sci", .data = PORT_SCI},
{.compatible = "renesas,scif", .data = PORT_SCIF},
{.compatible = "renesas,scifa", .data = PORT_SCIFA},
+ {.compatible = "renesas,hscif", .data = PORT_HSCIF},
{}
};
@@ -257,6 +261,8 @@ U_BOOT_DRIVER(serial_sh) = {
#define SCIF_BASE_PORT PORT_SCIFA
#elif defined(CFG_SCI)
#define SCIF_BASE_PORT PORT_SCI
+#elif defined(CFG_HSCIF)
+ #define SCIF_BASE_PORT PORT_HSCIF
#else
#define SCIF_BASE_PORT PORT_SCIF
#endif
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index eb8523dde55..149ec1fe739 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -89,7 +89,7 @@ struct uart_port {
# define SCSPTR7 0xe800a820 /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ORER 0x0001 /* overrun error bit */
-#elif defined(CONFIG_RCAR_GEN2) || defined(CONFIG_RCAR_GEN3) || \
+#elif defined(CONFIG_RCAR_GEN2) || defined(CONFIG_RCAR_64) || \
defined(CONFIG_R7S72100)
# if defined(CFG_SCIF_A)
# define SCIF_ORER 0x0200
@@ -213,6 +213,10 @@ struct uart_port {
#define SCFCR_TCRST 0x4000
#define SCFCR_MCE 0x0008
+/* HSSRR */
+#define HSSRR_SRE BIT(15)
+#define HSSRR_SRCYC8 0x0007
+
#define SCI_MAJOR 204
#define SCI_MINOR_START 8
@@ -242,7 +246,8 @@ struct uart_port {
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
static inline unsigned int sci_##name##_in(struct uart_port *port) {\
- if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\
+ if (port->type == PORT_SCIF || port->type == PORT_SCIFB ||\
+ port->type == PORT_HSCIF) {\
SCI_IN(scif_size, scif_offset)\
} else { /* PORT_SCI or PORT_SCIFA */\
SCI_IN(sci_size, sci_offset);\
@@ -250,7 +255,8 @@ struct uart_port {
}\
static inline void sci_##name##_out(struct uart_port *port,\
unsigned int value) {\
- if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\
+ if (port->type == PORT_SCIF || port->type == PORT_SCIFB ||\
+ port->type == PORT_HSCIF) {\
SCI_OUT(scif_size, scif_offset, value)\
} else { /* PORT_SCI or PORT_SCIFA */\
SCI_OUT(sci_size, sci_offset, value);\
@@ -375,6 +381,7 @@ SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
SCIF_FNS(DL, 0, 0, 0x30, 16)
SCIF_FNS(CKS, 0, 0, 0x34, 16)
+SCIF_FNS(HSSRR, 0, 0, 0x40, 16) /* HSCIF only */
#if defined(CFG_SCIF_A)
SCIF_FNS(SCLSR, 0, 0, 0x14, 16)
#else
@@ -414,7 +421,9 @@ SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
#endif
SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
#endif
-SCIF_FNS(DL, 0, 0, 0x0, 0) /* dummy */
+SCIF_FNS(DL, 0, 0, 0x30, 16)
+SCIF_FNS(CKS, 0, 0, 0x34, 16)
+SCIF_FNS(HSSRR, 0, 0, 0x40, 16) /* HSCIF only */
#endif
#define sci_in(port, reg) sci_##reg##_in(port)
#define sci_out(port, reg, value) sci_##reg##_out(port, value)
@@ -485,11 +494,20 @@ static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
#elif defined(CONFIG_RCAR_GEN2)
#define DL_VALUE(bps, clk) (clk / bps / 16) /* External Clock */
- #if defined(CFG_SCIF_A)
+ #if defined(CFG_SCIF_A) || defined(CFG_HSCIF)
#define SCBRR_VALUE(bps, clk) (clk / bps / 16 - 1) /* Internal Clock */
#else
#define SCBRR_VALUE(bps, clk) (clk / bps / 32 - 1) /* Internal Clock */
#endif
+#elif defined(CONFIG_RCAR_64)
+static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
+{
+ if (port->type == PORT_SCIF)
+ return (clk + 16 * bps) / (32 * bps) - 1;
+ else /* PORT_HSCIF */
+ return clk / bps / 8 / 2 - 1; /* Internal Clock, Sampling rate = 8 */
+}
+#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
#else /* Generic SH */
#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
#endif
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index acf555baaec..85dac9de78a 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -10,7 +10,7 @@ config SOC_DEVICE
specific device variant in use.
config SOC_DEVICE_TI_K3
- depends on SOC_DEVICE
+ depends on SOC_DEVICE && ARCH_K3
bool "Enable SoC Device ID driver for TI K3 SoCs"
help
This allows Texas Instruments Keystone 3 SoCs to identify
diff --git a/drivers/soc/soc_ti_k3.c b/drivers/soc/soc_ti_k3.c
index 8af0ac70519..b720131ae5d 100644
--- a/drivers/soc/soc_ti_k3.c
+++ b/drivers/soc/soc_ti_k3.c
@@ -8,21 +8,9 @@
#include <dm.h>
#include <soc.h>
+#include <asm/arch/hardware.h>
#include <asm/io.h>
-#define AM65X 0xbb5a
-#define J721E 0xbb64
-#define J7200 0xbb6d
-#define AM64X 0xbb38
-#define J721S2 0xbb75
-#define AM62X 0xbb7e
-#define AM62AX 0xbb8d
-
-#define JTAG_ID_VARIANT_SHIFT 28
-#define JTAG_ID_VARIANT_MASK (0xf << 28)
-#define JTAG_ID_PARTNO_SHIFT 12
-#define JTAG_ID_PARTNO_MASK (0xffff << 12)
-
struct soc_ti_k3_plat {
const char *family;
const char *revision;
@@ -36,25 +24,25 @@ static const char *get_family_string(u32 idreg)
soc = (idreg & JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
switch (soc) {
- case AM65X:
+ case JTAG_ID_PARTNO_AM65X:
family = "AM65X";
break;
- case J721E:
+ case JTAG_ID_PARTNO_J721E:
family = "J721E";
break;
- case J7200:
+ case JTAG_ID_PARTNO_J7200:
family = "J7200";
break;
- case AM64X:
+ case JTAG_ID_PARTNO_AM64X:
family = "AM64X";
break;
- case J721S2:
+ case JTAG_ID_PARTNO_J721S2:
family = "J721S2";
break;
- case AM62X:
+ case JTAG_ID_PARTNO_AM62X:
family = "AM62X";
break;
- case AM62AX:
+ case JTAG_ID_PARTNO_AM62AX:
family = "AM62AX";
break;
default:
@@ -81,13 +69,13 @@ static const char *get_rev_string(u32 idreg)
soc = (idreg & JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
switch (soc) {
- case J721E:
- if (rev > ARRAY_SIZE(j721e_rev_string_map))
+ case JTAG_ID_PARTNO_J721E:
+ if (rev >= ARRAY_SIZE(j721e_rev_string_map))
goto bail;
return j721e_rev_string_map[rev];
default:
- if (rev > ARRAY_SIZE(typical_rev_string_map))
+ if (rev >= ARRAY_SIZE(typical_rev_string_map))
goto bail;
return typical_rev_string_map[rev];
};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index cdd2304aeb1..4f435fd2681 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -381,7 +381,7 @@ config SPI_QUP
config RENESAS_RPC_SPI
bool "Renesas RPC SPI driver"
- depends on RCAR_GEN3 || RZA1
+ depends on RCAR_64 || RZA1
imply SPI_FLASH_BAR
help
Enable the Renesas RPC SPI driver, used to access SPI NOR flash
@@ -573,6 +573,7 @@ endif # if DM_SPI
config FSL_ESPI
bool "Freescale eSPI driver"
+ depends on MPC85xx
imply SPI_FLASH_BAR
help
Enable the Freescale eSPI driver. This driver can be used to
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index c7f10c50132..f931e4cf3e2 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -312,13 +312,12 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi,
* which is unsupported on some flash devices during register
* reads, prefer STIG mode for such small reads.
*/
- if (!op->addr.nbytes ||
- op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
+ if (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
mode = CQSPI_STIG_READ;
else
mode = CQSPI_READ;
} else {
- if (!op->addr.nbytes || !op->data.buf.out)
+ if (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
mode = CQSPI_STIG_WRITE;
else
mode = CQSPI_WRITE;
@@ -362,8 +361,15 @@ static bool cadence_spi_mem_supports_op(struct spi_slave *slave,
{
bool all_true, all_false;
- all_true = op->cmd.dtr && op->addr.dtr && op->dummy.dtr &&
- op->data.dtr;
+ /*
+ * op->dummy.dtr is required for converting nbytes into ncycles.
+ * Also, don't check the dtr field of the op phase having zero nbytes.
+ */
+ all_true = op->cmd.dtr &&
+ (!op->addr.nbytes || op->addr.dtr) &&
+ (!op->dummy.nbytes || op->dummy.dtr) &&
+ (!op->data.nbytes || op->data.dtr);
+
all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
!op->data.dtr;
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index 21fe2e655c5..9ce2c0f254f 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -120,7 +120,16 @@ static int cadence_qspi_set_protocol(struct cadence_spi_priv *priv,
{
int ret;
- priv->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr;
+ /*
+ * For an op to be DTR, cmd phase along with every other non-empty
+ * phase should have dtr field set to 1. If an op phase has zero
+ * nbytes, ignore its dtr field; otherwise, check its dtr field.
+ * Also, dummy checks not performed here Since supports_op()
+ * already checks that all or none of the fields are DTR.
+ */
+ priv->dtr = op->cmd.dtr &&
+ (!op->addr.nbytes || op->addr.dtr) &&
+ (!op->data.nbytes || op->data.dtr);
ret = cadence_qspi_buswidth_to_inst_type(op->cmd.buswidth);
if (ret < 0)
@@ -367,6 +376,9 @@ int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg)
if (!cadence_qspi_wait_idle(reg_base))
return -EIO;
+ /* Flush the CMDCTRL reg after the execution */
+ writel(0, reg_base + CQSPI_REG_CMDCTRL);
+
return 0;
}
@@ -453,11 +465,6 @@ int cadence_qspi_apb_command_read(struct cadence_spi_priv *priv,
unsigned int dummy_clk;
u8 opcode;
- if (rxlen > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) {
- printf("QSPI: Invalid input arguments rxlen %u\n", rxlen);
- return -EINVAL;
- }
-
if (priv->dtr)
opcode = op->cmd.opcode >> 8;
else
@@ -540,26 +547,12 @@ int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv,
unsigned int reg = 0;
unsigned int wr_data;
unsigned int wr_len;
+ unsigned int dummy_clk;
unsigned int txlen = op->data.nbytes;
const void *txbuf = op->data.buf.out;
void *reg_base = priv->regbase;
- u32 addr;
u8 opcode;
- /* Reorder address to SPI bus order if only transferring address */
- if (!txlen) {
- addr = cpu_to_be32(op->addr.val);
- if (op->addr.nbytes == 3)
- addr >>= 8;
- txbuf = &addr;
- txlen = op->addr.nbytes;
- }
-
- if (txlen > CQSPI_STIG_DATA_LEN_MAX) {
- printf("QSPI: Invalid input arguments txlen %u\n", txlen);
- return -EINVAL;
- }
-
if (priv->dtr)
opcode = op->cmd.opcode >> 8;
else
@@ -567,6 +560,27 @@ int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv,
reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ /* setup ADDR BIT field */
+ if (op->addr.nbytes) {
+ writel(op->addr.val, priv->regbase + CQSPI_REG_CMDADDRESS);
+ /*
+ * address bytes are zero indexed
+ */
+ reg |= (((op->addr.nbytes - 1) &
+ CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
+ CQSPI_REG_CMDCTRL_ADD_BYTES_LSB);
+ reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+ }
+
+ /* Set up dummy cycles. */
+ dummy_clk = cadence_qspi_calc_dummy(op, priv->dtr);
+ if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
+ return -EOPNOTSUPP;
+
+ if (dummy_clk)
+ reg |= (dummy_clk & CQSPI_REG_CMDCTRL_DUMMY_MASK)
+ << CQSPI_REG_CMDCTRL_DUMMY_LSB;
+
if (txlen) {
/* writing data = yes */
reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c
index d84d7aea888..5c8d7609351 100644
--- a/drivers/spi/mpc8xx_spi.c
+++ b/drivers/spi/mpc8xx_spi.c
@@ -51,11 +51,13 @@ static int mpc8xx_spi_probe(struct udevice *dev)
{
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cp = &immr->im_cpm;
- spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI];
+ spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dpmem[PROFF_SPI];
+ u16 spi_rpbase;
cbd_t __iomem *tbdf, *rbdf;
- /* Disable relocation */
- out_be16(&spi->spi_rpbase, 0x1d80);
+ spi_rpbase = in_be16(&spi->spi_rpbase);
+ if (spi_rpbase)
+ spi = (spi_t __iomem *)&cp->cp_dpmem[spi_rpbase];
/* 1 */
/* Initialize the parameter ram.
diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c
index 6869d60d97b..78892173dc1 100644
--- a/drivers/spi/mpc8xxx_spi.c
+++ b/drivers/spi/mpc8xxx_spi.c
@@ -16,6 +16,7 @@
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <asm/arch/soc.h>
enum {
SPI_EV_NE = BIT(31 - 22), /* Receiver Not Empty */
@@ -30,6 +31,7 @@ enum {
SPI_MODE_REV = BIT(31 - 5), /* Reverse mode - MSB first */
SPI_MODE_MS = BIT(31 - 6), /* Always master */
SPI_MODE_EN = BIT(31 - 7), /* Enable interface */
+ SPI_MODE_OP = BIT(31 - 17), /* CPU Mode, QE otherwise */
SPI_MODE_LEN_MASK = 0xf00000,
SPI_MODE_LEN_SHIFT = 20,
@@ -89,6 +91,9 @@ static int mpc8xxx_spi_probe(struct udevice *dev)
*/
out_be32(&priv->spi->mode, SPI_MODE_REV | SPI_MODE_MS);
+ if (dev_get_driver_data(dev) == SOC_MPC832X)
+ setbits_be32(&priv->spi->mode, SPI_MODE_OP);
+
/* set len to 8 bits */
setbits_be32(&spi->mode, (8 - 1) << SPI_MODE_LEN_SHIFT);
@@ -130,6 +135,7 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
u32 tmpdin = 0, tmpdout = 0, n;
const u8 *cout = dout;
u8 *cin = din;
+ ulong type = dev_get_driver_data(bus);
debug("%s: slave %s:%u dout %08X din %08X bitlen %u\n", __func__,
bus->name, plat->cs, (uint)dout, (uint)din, bitlen);
@@ -157,6 +163,9 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
if (cout)
tmpdout = *cout++;
+ if (type == SOC_MPC832X)
+ tmpdout <<= 24;
+
/* Write the data out */
out_be32(&spi->tx, tmpdout);
@@ -179,6 +188,9 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
tmpdin = in_be32(&spi->rx);
setbits_be32(&spi->event, SPI_EV_NE);
+ if (type == SOC_MPC832X)
+ tmpdin >>= 16;
+
if (cin)
*cin++ = tmpdin;
@@ -271,6 +283,7 @@ static const struct dm_spi_ops mpc8xxx_spi_ops = {
static const struct udevice_id mpc8xxx_spi_ids[] = {
{ .compatible = "fsl,spi" },
+ { .compatible = "fsl,mpc832x-spi", .data = SOC_MPC832X },
{ }
};
diff --git a/drivers/spi/npcm_fiu_spi.c b/drivers/spi/npcm_fiu_spi.c
index 7000fe5860d..73c506442ae 100644
--- a/drivers/spi/npcm_fiu_spi.c
+++ b/drivers/spi/npcm_fiu_spi.c
@@ -11,6 +11,7 @@
#include <linux/bitfield.h>
#include <linux/log2.h>
#include <linux/iopoll.h>
+#include <power/regulator.h>
#define DW_SIZE 4
#define CHUNK_SIZE 16
@@ -34,6 +35,34 @@
#define UMA_CTS_RDYST BIT(24)
#define UMA_CTS_DEV_NUM_MASK GENMASK(9, 8)
+/* Direct Write Configuration Register */
+#define DWR_CFG_WBURST_MASK GENMASK(25, 24)
+#define DWR_CFG_ADDSIZ_MASK GENMASK(17, 16)
+#define DWR_CFG_ABPCK_MASK GENMASK(11, 10)
+#define DRW_CFG_DBPCK_MASK GENMASK(9, 8)
+#define DRW_CFG_WRCMD 2
+enum {
+ DWR_WBURST_1_BYTE,
+ DWR_WBURST_16_BYTE = 3,
+};
+
+enum {
+ DWR_ADDSIZ_24_BIT,
+ DWR_ADDSIZ_32_BIT,
+};
+
+enum {
+ DWR_ABPCK_BIT_PER_CLK,
+ DWR_ABPCK_2_BIT_PER_CLK,
+ DWR_ABPCK_4_BIT_PER_CLK,
+};
+
+enum {
+ DWR_DBPCK_BIT_PER_CLK,
+ DWR_DBPCK_2_BIT_PER_CLK,
+ DWR_DBPCK_4_BIT_PER_CLK,
+};
+
struct npcm_fiu_regs {
unsigned int drd_cfg;
unsigned int dwr_cfg;
@@ -67,19 +96,10 @@ struct npcm_fiu_regs {
struct npcm_fiu_priv {
struct npcm_fiu_regs *regs;
- struct clk clk;
};
static int npcm_fiu_spi_set_speed(struct udevice *bus, uint speed)
{
- struct npcm_fiu_priv *priv = dev_get_priv(bus);
- int ret;
-
- debug("%s: set speed %u\n", bus->name, speed);
- ret = clk_set_rate(&priv->clk, speed);
- if (ret < 0)
- return ret;
-
return 0;
}
@@ -349,13 +369,38 @@ static int npcm_fiu_exec_op(struct spi_slave *slave,
static int npcm_fiu_spi_probe(struct udevice *bus)
{
struct npcm_fiu_priv *priv = dev_get_priv(bus);
- int ret;
+ struct udevice *vqspi_supply;
+ int vqspi_uv;
priv->regs = (struct npcm_fiu_regs *)dev_read_addr_ptr(bus);
- ret = clk_get_by_index(bus, 0, &priv->clk);
- if (ret < 0)
- return ret;
+ if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ device_get_supply_regulator(bus, "vqspi-supply", &vqspi_supply);
+ vqspi_uv = dev_read_u32_default(bus, "vqspi-microvolt", 0);
+ /* Set IO voltage */
+ if (vqspi_supply && vqspi_uv)
+ regulator_set_value(vqspi_supply, vqspi_uv);
+ }
+
+ return 0;
+}
+
+static int npcm_fiu_spi_bind(struct udevice *bus)
+{
+ struct npcm_fiu_regs *regs;
+
+ if (dev_read_bool(bus, "nuvoton,spix-mode")) {
+ regs = dev_read_addr_ptr(bus);
+ if (!regs)
+ return -EINVAL;
+
+ /* Setup direct write cfg for SPIX */
+ writel(FIELD_PREP(DWR_CFG_WBURST_MASK, DWR_WBURST_16_BYTE) |
+ FIELD_PREP(DWR_CFG_ADDSIZ_MASK, DWR_ADDSIZ_24_BIT) |
+ FIELD_PREP(DWR_CFG_ABPCK_MASK, DWR_ABPCK_4_BIT_PER_CLK) |
+ FIELD_PREP(DRW_CFG_DBPCK_MASK, DWR_DBPCK_4_BIT_PER_CLK) |
+ DRW_CFG_WRCMD, &regs->dwr_cfg);
+ }
return 0;
}
@@ -384,4 +429,5 @@ U_BOOT_DRIVER(npcm_fiu_spi) = {
.ops = &npcm_fiu_spi_ops,
.priv_auto = sizeof(struct npcm_fiu_priv),
.probe = npcm_fiu_spi_probe,
+ .bind = npcm_fiu_spi_bind,
};
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 8e8995fc537..b7eca583595 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -181,8 +181,12 @@ bool spi_mem_dtr_supports_op(struct spi_slave *slave,
if (op->dummy.nbytes && op->dummy.buswidth == 8 && op->dummy.nbytes % 2)
return false;
- if (op->data.dir != SPI_MEM_NO_DATA &&
- op->dummy.buswidth == 8 && op->data.nbytes % 2)
+ /*
+ * Transactions of odd length do not make sense for 8D-8D-8D mode
+ * because a byte is transferred in just half a cycle.
+ */
+ if (op->data.dir != SPI_MEM_NO_DATA && op->data.dir != SPI_MEM_DATA_IN &&
+ op->data.buswidth == 8 && op->data.nbytes % 2)
return false;
return spi_mem_check_buswidth(slave, op);
diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
index ebf2903d3ea..e3633a52608 100644
--- a/drivers/spi/spi-sn-f-ospi.c
+++ b/drivers/spi/spi-sn-f-ospi.c
@@ -556,7 +556,7 @@ static bool f_ospi_supports_op(struct spi_slave *slave,
if (!f_ospi_supports_op_width(op))
return false;
- return true;
+ return spi_mem_default_supports_op(slave, op);
}
static int f_ospi_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op)
diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c
index 0cae3dfc778..0f5d0a30c39 100644
--- a/drivers/spi/spi-synquacer.c
+++ b/drivers/spi/spi-synquacer.c
@@ -186,7 +186,7 @@ static void synquacer_spi_config(struct udevice *dev, void *rx, const void *tx)
struct udevice *bus = dev->parent;
struct synquacer_spi_priv *priv = dev_get_priv(bus);
struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
- u32 val, div, bus_width;
+ u32 val, div, bus_width = 1;
int rwflag;
rwflag = (rx ? 1 : 0) | (tx ? 2 : 0);
@@ -211,6 +211,8 @@ static void synquacer_spi_config(struct udevice *dev, void *rx, const void *tx)
bus_width = 4;
else if (priv->mode & SPI_TX_OCTAL)
bus_width = 8;
+ else
+ log_warning("SPI mode not configured, setting to byte mode\n");
div = DIV_ROUND_UP(125000000, priv->speed);
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index 90c207d5184..eb52ff73b23 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -115,15 +115,8 @@ struct stm32_qspi_regs {
#define STM32_BUSY_TIMEOUT_US 100000
#define STM32_ABT_TIMEOUT_US 100000
-struct stm32_qspi_flash {
- u32 cr;
- u32 dcr;
- bool initialized;
-};
-
struct stm32_qspi_priv {
struct stm32_qspi_regs *regs;
- struct stm32_qspi_flash flash[STM32_QSPI_MAX_CHIP];
void __iomem *mm_base;
resource_size_t mm_size;
ulong clock_rate;
@@ -407,25 +400,11 @@ static int stm32_qspi_claim_bus(struct udevice *dev)
return -ENODEV;
if (priv->cs_used != slave_cs) {
- struct stm32_qspi_flash *flash = &priv->flash[slave_cs];
-
priv->cs_used = slave_cs;
- if (flash->initialized) {
- /* Set the configuration: speed + cs */
- writel(flash->cr, &priv->regs->cr);
- writel(flash->dcr, &priv->regs->dcr);
- } else {
- /* Set chip select */
- clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
- priv->cs_used ? STM32_QSPI_CR_FSEL : 0);
-
- /* Save the configuration: speed + cs */
- flash->cr = readl(&priv->regs->cr);
- flash->dcr = readl(&priv->regs->dcr);
-
- flash->initialized = true;
- }
+ /* Set chip select */
+ clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
+ priv->cs_used ? STM32_QSPI_CR_FSEL : 0);
}
setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
diff --git a/drivers/sysreset/sysreset_gpio.c b/drivers/sysreset/sysreset_gpio.c
index dfca10ccc8e..de42b593542 100644
--- a/drivers/sysreset/sysreset_gpio.c
+++ b/drivers/sysreset/sysreset_gpio.c
@@ -17,6 +17,7 @@ struct gpio_reboot_priv {
static int gpio_reboot_request(struct udevice *dev, enum sysreset_t type)
{
struct gpio_reboot_priv *priv = dev_get_priv(dev);
+ int ret;
/*
* When debug log is enabled please make sure that chars won't end up
@@ -26,7 +27,11 @@ static int gpio_reboot_request(struct udevice *dev, enum sysreset_t type)
debug("GPIO reset\n");
/* Writing 1 respects polarity (active high/low) based on gpio->flags */
- return dm_gpio_set_value(&priv->gpio, 1);
+ ret = dm_gpio_set_value(&priv->gpio, 1);
+ if (ret < 0)
+ return ret;
+
+ return -EINPROGRESS;
}
static struct sysreset_ops gpio_reboot_ops = {
diff --git a/drivers/sysreset/sysreset_psci.c b/drivers/sysreset/sysreset_psci.c
index 83ecbcb9d2c..a8a41528a84 100644
--- a/drivers/sysreset/sysreset_psci.c
+++ b/drivers/sysreset/sysreset_psci.c
@@ -9,6 +9,11 @@
#include <linux/errno.h>
#include <linux/psci.h>
+__weak int psci_sysreset_get_status(struct udevice *dev, char *buf, int size)
+{
+ return -EOPNOTSUPP;
+}
+
static int psci_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
switch (type) {
@@ -28,10 +33,12 @@ static int psci_sysreset_request(struct udevice *dev, enum sysreset_t type)
static struct sysreset_ops psci_sysreset_ops = {
.request = psci_sysreset_request,
+ .get_status = psci_sysreset_get_status,
};
U_BOOT_DRIVER(psci_sysreset) = {
.name = "psci-sysreset",
.id = UCLASS_SYSRESET,
.ops = &psci_sysreset_ops,
+ .flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
index 0ee286cbb34..3750c60b9b9 100644
--- a/drivers/sysreset/sysreset_sandbox.c
+++ b/drivers/sysreset/sysreset_sandbox.c
@@ -65,7 +65,6 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
if (!state->sysreset_allowed[type])
return -EACCES;
sandbox_exit();
- break;
case SYSRESET_POWER:
if (!state->sysreset_allowed[type])
return -EACCES;
diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
index 35e8542fa37..86219a9bb1a 100644
--- a/drivers/tee/sandbox.c
+++ b/drivers/tee/sandbox.c
@@ -119,6 +119,7 @@ static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params,
{
u32 res;
static bool enabled;
+ static bool provisioned;
switch (func) {
case PTA_CMD_ENABLE_SCP03:
@@ -130,12 +131,18 @@ static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params,
if (res)
return res;
- if (!enabled) {
+ /* If SCP03 was not enabled, enable it */
+ if (!enabled)
enabled = true;
- } else {
- }
- if (params[0].u.value.a)
+ /* If SCP03 was not provisioned, provision new keys */
+ if (params[0].u.value.a && !provisioned)
+ provisioned = true;
+
+ /*
+ * Either way, we asume both operations succeeded and that
+ * the communication channel has now been stablished
+ */
return TEE_SUCCESS;
default:
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 01ccc4bc178..7c5c1ab3de7 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -266,6 +266,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
default:
break;
}
+ break;
case SANDBOX_FLASH_EP_IN:
switch (info->phase) {
case SCSIPH_DATA:
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index 041ec3772aa..084cc16cc68 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -220,13 +220,9 @@ static int sandbox_hub_submit_control_msg(struct udevice *bus,
udev->status = 0;
udev->act_len = sizeof(*hubsts);
return 0;
+ }
}
- default:
- debug("%s: rx ctl requesttype=%x, request=%x\n",
- __func__, setup->requesttype,
- setup->request);
- break;
- }
+ break;
case USB_RT_PORT | USB_DIR_IN:
switch (setup->request) {
case USB_REQ_GET_STATUS: {
@@ -239,13 +235,12 @@ static int sandbox_hub_submit_control_msg(struct udevice *bus,
udev->status = 0;
udev->act_len = sizeof(*portsts);
return 0;
+ }
}
- }
- default:
- debug("%s: rx ctl requesttype=%x, request=%x\n",
- __func__, setup->requesttype, setup->request);
break;
}
+ debug("%s: rx ctl requesttype=%x, request=%x\n",
+ __func__, setup->requesttype, setup->request);
} else if (pipe == usb_sndctrlpipe(udev, 0)) {
switch (setup->requesttype) {
case USB_RT_PORT:
@@ -263,7 +258,7 @@ static int sandbox_hub_submit_control_msg(struct udevice *bus,
debug(" ** Invalid feature\n");
}
return ret;
- }
+ }
case USB_REQ_CLEAR_FEATURE: {
int port;
@@ -279,18 +274,11 @@ static int sandbox_hub_submit_control_msg(struct udevice *bus,
}
udev->status = 0;
return 0;
+ }
}
- default:
- debug("%s: tx ctl requesttype=%x, request=%x\n",
- __func__, setup->requesttype,
- setup->request);
- break;
- }
- default:
- debug("%s: tx ctl requesttype=%x, request=%x\n",
- __func__, setup->requesttype, setup->request);
- break;
}
+ debug("%s: tx ctl requesttype=%x, request=%x\n",
+ __func__, setup->requesttype, setup->request);
}
debug("pipe=%lx\n", pipe);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 2a309e624e1..04b85419931 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1068,7 +1068,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (!gadget_is_dualspeed(gadget) ||
gadget->speed >= USB_SPEED_SUPER)
break;
-
+ fallthrough;
case USB_DT_CONFIG:
value = config_desc(cdev, w_value);
if (value >= 0)
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 45f0504b6e8..f46829eb7ad 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -1117,7 +1117,7 @@ static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
{
struct fsg_lun *curlun = &common->luns[common->lun];
u8 *buf = (u8 *) bh->buf;
- u32 sd, sdinfo;
+ u32 sd, sdinfo = 0;
int valid;
/*
@@ -1145,7 +1145,6 @@ static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
if (!curlun) { /* Unsupported LUNs are okay */
common->bad_lun_okay = 1;
sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
- sdinfo = 0;
valid = 0;
} else {
sd = curlun->sense_data;
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index 9ea43f29cfb..4da5a160a09 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -865,6 +865,7 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image,
struct spl_image_info spl_image = {};
struct spl_boot_device bootdev = {};
spl_parse_image_header(&spl_image, &bootdev, header);
+ spl_board_prepare_for_boot();
jump_to_image_no_args(&spl_image);
#else
/* In U-Boot, allow jumps to scripts */
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 91633f013a5..fae20838c60 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -703,6 +703,10 @@ static int ehci_usb_probe(struct udevice *dev)
usb_internal_phy_clock_gate(priv->phy_addr, 1);
usb_phy_enable(ehci, priv->phy_addr);
#endif
+#else
+ ret = generic_setup_phy(dev, &priv->phy, 0);
+ if (ret)
+ goto err_regulator;
#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
@@ -725,12 +729,6 @@ static int ehci_usb_probe(struct udevice *dev)
mdelay(10);
-#if defined(CONFIG_PHY)
- ret = generic_setup_phy(dev, &priv->phy, 0);
- if (ret)
- goto err_regulator;
-#endif
-
hccr = (struct ehci_hccr *)((uintptr_t)&ehci->caplength);
hcor = (struct ehci_hcor *)((uintptr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 60f4a4bf9cc..fcc0e85d2e6 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -466,6 +466,17 @@ config VIDEO_BCM2835
that same resolution (or as near as possible) and 32bpp depth, so
that U-Boot can access it with full colour depth.
+config VIDEO_LCD_ENDEAVORU
+ tristate "Endeavoru 720x1280 DSI video mode panel"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for the IPS-LCD panel
+ module for HTC One X. Driver supports a family of panels,
+ made at least by 3 vendors (Sharp, Sony and AUO), but set up
+ using the same DSI command sequence. The panel has a 720x1280
+ resolution and uses 24 bit RGB per pixel.
+
config VIDEO_LCD_ORISETECH_OTM8009A
bool "OTM8009A DSI LCD panel support"
select VIDEO_MIPI_DSI
@@ -480,6 +491,24 @@ config VIDEO_LCD_RAYDIUM_RM68200
Say Y here if you want to enable support for Raydium RM68200
720x1280 DSI video mode panel.
+config VIDEO_LCD_RENESAS_R61307
+ tristate "Renesas R61307 DSI video mode panel"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for KOE tx13d100vm0eaa
+ IPS-LCD module with Renesas R69328 IC. The panel has a 1024x768
+ resolution and uses 24 bit RGB per pixel.
+
+config VIDEO_LCD_RENESAS_R69328
+ tristate "Renesas R69328 720x1280 DSI video mode panel"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for JDI dx12d100vm0eaa
+ IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280
+ resolution and uses 24 bit RGB per pixel.
+
config VIDEO_LCD_SSD2828
bool "SSD2828 bridge chip"
---help---
@@ -606,6 +635,15 @@ config ATMEL_HLCD
help
HLCDC supports video output to an attached LCD panel.
+config BACKLIGHT_LM3533
+ bool "Backlight Driver for LM3533"
+ depends on BACKLIGHT
+ select DM_I2C
+ help
+ Say Y to enable the backlight driver for National Semiconductor / TI
+ LM3533 Lighting Power chip. Only Bank A is supported as for now.
+ Supported backlight level range is from 2 to 255 with step of 1.
+
source "drivers/video/ti/Kconfig"
source "drivers/video/exynos/Kconfig"
@@ -668,15 +706,6 @@ source "drivers/video/stm32/Kconfig"
source "drivers/video/tidss/Kconfig"
-config VIDEO_TEGRA20
- bool "Enable LCD support on Tegra20"
- depends on OF_CONTROL
- help
- Tegra20 supports video output to an attached LCD panel as well as
- other options such as HDMI. Only the LCD is supported in U-Boot.
- This option enables this support which can be used on devices which
- have an LCD display connected.
-
config VIDEO_TEGRA124
bool "Enable video support on Tegra124"
help
@@ -687,6 +716,8 @@ config VIDEO_TEGRA124
source "drivers/video/bridge/Kconfig"
+source "drivers/video/tegra20/Kconfig"
+
source "drivers/video/imx/Kconfig"
config VIDEO_MXS
@@ -893,7 +924,7 @@ endif # SPLASH_SCREEN
config VIDEO_BMP_GZIP
bool "Gzip compressed BMP image support"
- depends on CMD_BMP || SPLASH_SCREEN
+ depends on BMP || SPLASH_SCREEN
help
If this option is set, additionally to standard BMP
images, gzipped BMP images can be displayed via the
@@ -930,4 +961,225 @@ config BMP_32BPP
endif # VIDEO
+config SPL_VIDEO
+ bool "Enable driver model support for LCD/video"
+ depends on SPL_DM
+ help
+ The video subsystem adds a small amount of overhead to the image.
+ If this is acceptable and you have a need to use video drivers in
+ SPL, enable this option. It might provide a cleaner interface to
+ setting up video within SPL, and allows the same drivers to be
+ used as U-Boot proper.
+
+if SPL_VIDEO
+source "drivers/video/tidss/Kconfig"
+
+config SPL_VIDEO_LOGO
+ bool "Show the U-Boot logo on the display at SPL"
+ default y if !SPL_SPLASH_SCREEN
+ select SPL_VIDEO_BMP_RLE8
+ help
+ This enables showing the U-Boot logo on the display when a video
+ device is probed. It appears at the top right. The logo itself is at
+ tools/logos/u-boot_logo.bmp and looks best when the display has a
+ black background.
+
+config SPL_SPLASH_SCREEN
+ bool "Show a splash-screen image at SPL"
+ help
+ If this option is set, the environment is checked for a variable
+ "splashimage" at spl stage.
+
+config SPL_SYS_WHITE_ON_BLACK
+ bool "Display console as white on a black background at SPL"
+ help
+ Normally the display is black on a white background, Enable this
+ option to invert this, i.e. white on a black background at spl stage.
+ This can be better in low-light situations or to reduce eye strain in
+ some cases.
+
+config SPL_VIDEO_PCI_DEFAULT_FB_SIZE
+ hex "Default framebuffer size to use if no drivers request it at SPL"
+ default 0x1000000 if X86 && PCI
+ default 0 if !(X86 && PCI)
+ help
+ Generally, video drivers request the amount of memory they need for
+ the frame buffer when they are bound, by setting the size field in
+ struct video_uc_plat. That memory is then reserved for use after
+ relocation. But PCI drivers cannot be bound before relocation unless
+ they are mentioned in the devicetree.
+
+ With this value set appropriately, it is possible for PCI video
+ devices to have a framebuffer allocated by U-Boot.
+
+ Note: the framebuffer needs to be large enough to store all pixels at
+ maximum resolution. For example, at 1920 x 1200 with 32 bits per
+ pixel, 2560 * 1600 * 32 / 8 = 0xfa0000 bytes are needed.
+
+config SPL_CONSOLE_SCROLL_LINES
+ int "Number of lines to scroll the console by at SPL"
+ default 1
+ help
+ When the console need to be scrolled, this is the number of
+ lines to scroll by. It defaults to 1. Increasing this makes the
+ console jump but can help speed up operation when scrolling
+ is slow.
+
+config SPL_CONSOLE_NORMAL
+ bool "Support a simple text console at SPL"
+ default y
+ help
+ Support drawing text on the frame buffer console so that it can be
+ used as a console. Rotation is not supported by this driver (see
+ CONFIG_CONSOLE_ROTATION for that). A built-in 8x16 font is used
+ for the display.
+
+config SPL_BACKLIGHT
+ bool "Enable panel backlight uclass support at SPL"
+ default y
+ help
+ This provides backlight uclass driver that enables basic panel
+ backlight support.
+
+config SPL_PANEL
+ bool "Enable panel uclass support at SPL"
+ default y
+ help
+ This provides panel uclass driver that enables basic panel support.
+
+config SPL_SIMPLE_PANEL
+ bool "Enable simple panel support at SPL"
+ depends on SPL_PANEL && SPL_BACKLIGHT && SPL_DM_GPIO
+ default y
+ help
+ This turns on a simple panel driver that enables a compatible
+ video panel.
+
+config SPL_SYS_WHITE_ON_BLACK
+ bool "Display console as white on a black background at SPL"
+ help
+ Normally the display is black on a white background, Enable this
+ option to invert this, i.e. white on a black background at spl stage.
+ This can be better in low-light situations or to reduce eye strain in
+ some cases.
+
+if SPL_SPLASH_SCREEN
+
+config SPL_SPLASH_SCREEN_ALIGN
+ bool "Allow positioning the splash image anywhere on the display at SPL"
+ help
+ If this option is set the splash image can be freely positioned
+ on the screen only at SPL. Environment variable "splashpos" specifies
+ the position as "x,y". If a positive number is given it is used as
+ number of pixel from left/top. If a negative number is given it
+ is used as number of pixel from right/bottom.
+
+config SPL_SPLASH_SOURCE
+ bool "Control the source of the splash image at SPL"
+ help
+ Use the splash_source.c library. This library provides facilities to
+ declare board specific splash image locations, routines for loading
+ splash image from supported locations, and a way of controlling the
+ selected splash location using the "splashsource" environment
+ variable.
+
+ This CONFIG works as follows:
+
+ - If splashsource is set to a supported location name as defined by
+ board code, use that splash location.
+ - If splashsource is undefined, use the first splash location as
+ default.
+ - If splashsource is set to an unsupported value, do not load a splash
+ screen.
+
+ A splash source location can describe either storage with raw data, a
+ storage formatted with a file system or a FIT image. In case of a
+ filesystem, the splash screen data is loaded as a file. The name of
+ the splash screen file can be controlled with the environment variable
+ "splashfile".
+
+ To enable loading the splash image from a FIT image, CONFIG_FIT must
+ be enabled. The FIT image has to start at the 'offset' field address
+ in the selected splash location. The name of splash image within the
+ FIT shall be specified by the environment variable "splashfile".
+
+ In case the environment variable "splashfile" is not defined the
+ default name 'splash.bmp' will be used.
+
+endif # SPL_SPLASH_SCREEN
+
+config SPL_VIDEO_BMP_GZIP
+ bool "Gzip compressed BMP image support at SPL"
+ depends on SPL_SPLASH_SCREEN || SPL_BMP
+ help
+ If this option is set, additionally to standard BMP
+ images, gzipped BMP images can be displayed via the
+ splashscreen supportat SPL stage.
+
+config SPL_VIDEO_LOGO_MAX_SIZE
+ hex "Maximum size of the bitmap logo in bytes at SPL"
+ default 0x100000
+ help
+ Sets the maximum uncompressed size of the logo. This is needed when
+ decompressing a BMP file using the gzip algorithm, since it cannot
+ read the size from the bitmap header.
+
+config SPL_VIDEO_BMP_RLE8
+ bool "Run length encoded BMP image (RLE8) support at SPL"
+ help
+ If this option is set, the 8-bit RLE compressed BMP images
+ is supported.
+
+config SPL_BMP_16BPP
+ bool "16-bit-per-pixel BMP image support at SPL"
+ help
+ Support display of bitmaps file with 16-bit-per-pixel
+
+config SPL_BMP_24BPP
+ bool "24-bit-per-pixel BMP image support at SPL"
+ help
+ Support display of bitmaps file with 24-bit-per-pixel.
+
+config SPL_BMP_32BPP
+ bool "32-bit-per-pixel BMP image support at SPL"
+ help
+ Support display of bitmaps file with 32-bit-per-pixel.
+
+config SPL_VIDEO_BPP8
+ bool "Support 8-bit-per-pixel displays at SPL"
+ default y
+ help
+ Support drawing text and bitmaps onto a 8-bit-per-pixel display.
+ Enabling this will include code to support this display. Without
+ this option, such displays will not be supported and console output
+ will be empty.
+
+config SPL_VIDEO_BPP16
+ bool "Support 16-bit-per-pixel displays at SPL"
+ default y
+ help
+ Support drawing text and bitmaps onto a 16-bit-per-pixel display.
+ Enabling this will include code to support this display. Without
+ this option, such displays will not be supported and console output
+ will be empty.
+
+config SPL_VIDEO_BPP32
+ bool "Support 32-bit-per-pixel displays at SPL"
+ default y
+ help
+ Support drawing text and bitmaps onto a 32-bit-per-pixel display.
+ Enabling this will include code to support this display. Without
+ this option, such displays will not be supported and console output
+ will be empty.
+
+config SPL_HIDE_LOGO_VERSION
+ bool "Hide the version information on the splash screen at SPL"
+ help
+ Normally the U-Boot version string is shown on the display when the
+ splash screen is enabled. This information is not otherwise visible
+ since video starts up after U-Boot has displayed the initial banner.
+
+ Enable this option to hide this information.
+endif
+
endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index cb3f3736459..9a53cd14187 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -4,12 +4,12 @@
# Wolfgang Denk, DENX Software Engineering, [email protected].
ifdef CONFIG_DM
-obj-$(CONFIG_BACKLIGHT) += backlight-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)BACKLIGHT) += backlight-uclass.o
obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o
-obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o
+obj-$(CONFIG_$(SPL_TPL_)CONSOLE_NORMAL) += console_normal.o
obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o
-ifdef CONFIG_CONSOLE_NORMAL
+ifdef CONFIG_$(SPL_TPL_)CONSOLE_NORMAL
obj-y += console_core.o
else ifdef CONFIG_CONSOLE_ROTATION
obj-y += console_core.o
@@ -18,21 +18,22 @@ obj-$(CONFIG_CONSOLE_ROTATION) += console_core.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/
obj-$(CONFIG_DISPLAY) += display-uclass.o
obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o
-obj-$(CONFIG_VIDEO) += video-uclass.o vidconsole-uclass.o
-obj-$(CONFIG_VIDEO) += video_bmp.o
-obj-$(CONFIG_PANEL) += panel-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video-uclass.o vidconsole-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video_bmp.o
+obj-$(CONFIG_$(SPL_TPL_)PANEL) += panel-uclass.o
obj-$(CONFIG_PANEL_HX8238D) += hx8238d.o
-obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o
+obj-$(CONFIG_$(SPL_TPL_)SIMPLE_PANEL) += simple_panel.o
obj-$(CONFIG_VIDEO_LOGO) += u_boot_logo.o
endif
+obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o
obj-${CONFIG_EXYNOS_FB} += exynos/
obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/
obj-${CONFIG_VIDEO_STM32} += stm32/
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
-obj-${CONFIG_VIDEO_TIDSS} += tidss/
+obj-${CONFIG_$(SPL_)VIDEO_TIDSS} += tidss/
obj-y += ti/
obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o
@@ -52,9 +53,12 @@ obj-$(CONFIG_VIDEO_EFI) += efi.o
obj-$(CONFIG_VIDEO_IPUV3) += imx/
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
+obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o
obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o
+obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o
+obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o
obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o
@@ -67,10 +71,10 @@ obj-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
obj-$(CONFIG_VIDEO_DSI_HOST_SANDBOX) += sandbox_dsi_host.o
obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
-obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o
obj-$(CONFIG_VIDEO_VESA) += vesa.o
obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp_dpsub.o
obj-y += bridge/
obj-y += sunxi/
+obj-y += tegra20/
diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig
index 765f7380b89..2311ca2d1a5 100644
--- a/drivers/video/bridge/Kconfig
+++ b/drivers/video/bridge/Kconfig
@@ -33,3 +33,10 @@ config VIDEO_BRIDGE_ANALOGIX_ANX6345
help
The Analogix ANX6345 is RGB-to-DP converter. It enables an eDP LCD
panel to be connected to an parallel LCD interface.
+
+config VIDEO_BRIDGE_SOLOMON_SSD2825
+ bool "Solomon SSD2825 bridge driver"
+ depends on PANEL && DM_GPIO
+ select VIDEO_MIPI_DSI
+ help
+ Solomon SSD2824 SPI RGB-DSI bridge driver wrapped into panel uClass.
diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile
index 45e54ac1768..22625c8bc67 100644
--- a/drivers/video/bridge/Makefile
+++ b/drivers/video/bridge/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o
obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o
obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o
obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o
+obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o
diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c
new file mode 100644
index 00000000000..cea20dcffa5
--- /dev/null
+++ b/drivers/video/bridge/ssd2825.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <backlight.h>
+#include <panel.h>
+#include <spi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <asm/gpio.h>
+
+#define SSD2825_DEVICE_ID_REG 0xB0
+#define SSD2825_RGB_INTERFACE_CTRL_REG_1 0xB1
+#define SSD2825_RGB_INTERFACE_CTRL_REG_2 0xB2
+#define SSD2825_RGB_INTERFACE_CTRL_REG_3 0xB3
+#define SSD2825_RGB_INTERFACE_CTRL_REG_4 0xB4
+#define SSD2825_RGB_INTERFACE_CTRL_REG_5 0xB5
+#define SSD2825_RGB_INTERFACE_CTRL_REG_6 0xB6
+#define SSD2825_NON_BURST BIT(2)
+#define SSD2825_BURST BIT(3)
+#define SSD2825_PCKL_HIGH BIT(13)
+#define SSD2825_HSYNC_HIGH BIT(14)
+#define SSD2825_VSYNC_HIGH BIT(15)
+#define SSD2825_CONFIGURATION_REG 0xB7
+#define SSD2825_CONF_REG_HS BIT(0)
+#define SSD2825_CONF_REG_CKE BIT(1)
+#define SSD2825_CONF_REG_SLP BIT(2)
+#define SSD2825_CONF_REG_VEN BIT(3)
+#define SSD2825_CONF_REG_HCLK BIT(4)
+#define SSD2825_CONF_REG_CSS BIT(5)
+#define SSD2825_CONF_REG_DCS BIT(6)
+#define SSD2825_CONF_REG_REN BIT(7)
+#define SSD2825_CONF_REG_ECD BIT(8)
+#define SSD2825_CONF_REG_EOT BIT(9)
+#define SSD2825_CONF_REG_LPE BIT(10)
+#define SSD2825_VC_CTRL_REG 0xB8
+#define SSD2825_PLL_CTRL_REG 0xB9
+#define SSD2825_PLL_CONFIGURATION_REG 0xBA
+#define SSD2825_CLOCK_CTRL_REG 0xBB
+#define SSD2825_PACKET_SIZE_CTRL_REG_1 0xBC
+#define SSD2825_PACKET_SIZE_CTRL_REG_2 0xBD
+#define SSD2825_PACKET_SIZE_CTRL_REG_3 0xBE
+#define SSD2825_PACKET_DROP_REG 0xBF
+#define SSD2825_OPERATION_CTRL_REG 0xC0
+#define SSD2825_MAX_RETURN_SIZE_REG 0xC1
+#define SSD2825_RETURN_DATA_COUNT_REG 0xC2
+#define SSD2825_ACK_RESPONSE_REG 0xC3
+#define SSD2825_LINE_CTRL_REG 0xC4
+#define SSD2825_INTERRUPT_CTRL_REG 0xC5
+#define SSD2825_INTERRUPT_STATUS_REG 0xC6
+#define SSD2825_ERROR_STATUS_REG 0xC7
+#define SSD2825_DATA_FORMAT_REG 0xC8
+#define SSD2825_DELAY_ADJ_REG_1 0xC9
+#define SSD2825_DELAY_ADJ_REG_2 0xCA
+#define SSD2825_DELAY_ADJ_REG_3 0xCB
+#define SSD2825_DELAY_ADJ_REG_4 0xCC
+#define SSD2825_DELAY_ADJ_REG_5 0xCD
+#define SSD2825_DELAY_ADJ_REG_6 0xCE
+#define SSD2825_HS_TX_TIMER_REG_1 0xCF
+#define SSD2825_HS_TX_TIMER_REG_2 0xD0
+#define SSD2825_LP_RX_TIMER_REG_1 0xD1
+#define SSD2825_LP_RX_TIMER_REG_2 0xD2
+#define SSD2825_TE_STATUS_REG 0xD3
+#define SSD2825_SPI_READ_REG 0xD4
+#define SSD2825_PLL_LOCK_REG 0xD5
+#define SSD2825_TEST_REG 0xD6
+#define SSD2825_TE_COUNT_REG 0xD7
+#define SSD2825_ANALOG_CTRL_REG_1 0xD8
+#define SSD2825_ANALOG_CTRL_REG_2 0xD9
+#define SSD2825_ANALOG_CTRL_REG_3 0xDA
+#define SSD2825_ANALOG_CTRL_REG_4 0xDB
+#define SSD2825_INTERRUPT_OUT_CTRL_REG 0xDC
+#define SSD2825_RGB_INTERFACE_CTRL_REG_7 0xDD
+#define SSD2825_LANE_CONFIGURATION_REG 0xDE
+#define SSD2825_DELAY_ADJ_REG_7 0xDF
+#define SSD2825_INPUT_PIN_CTRL_REG_1 0xE0
+#define SSD2825_INPUT_PIN_CTRL_REG_2 0xE1
+#define SSD2825_BIDIR_PIN_CTRL_REG_1 0xE2
+#define SSD2825_BIDIR_PIN_CTRL_REG_2 0xE3
+#define SSD2825_BIDIR_PIN_CTRL_REG_3 0xE4
+#define SSD2825_BIDIR_PIN_CTRL_REG_4 0xE5
+#define SSD2825_BIDIR_PIN_CTRL_REG_5 0xE6
+#define SSD2825_BIDIR_PIN_CTRL_REG_6 0xE7
+#define SSD2825_BIDIR_PIN_CTRL_REG_7 0xE8
+#define SSD2825_CABC_BRIGHTNESS_CTRL_REG_1 0xE9
+#define SSD2825_CABC_BRIGHTNESS_CTRL_REG_2 0xEA
+#define SSD2825_CABC_BRIGHTNESS_STATUS_REG 0xEB
+#define SSD2825_READ_REG 0xFF
+#define SSD2825_SPI_READ_REG_RESET 0xFA
+
+#define SSD2825_CMD_MASK 0x00
+#define SSD2825_DAT_MASK 0x01
+
+#define SSD2825_CMD_SEND BIT(0)
+#define SSD2825_DAT_SEND BIT(1)
+#define SSD2825_DSI_SEND BIT(2)
+
+#define SSD2828_LP_CLOCK_DIVIDER(n) (((n) - 1) & 0x3F)
+#define SSD2825_LP_MIN_CLK 5000 /* KHz */
+#define SSD2825_REF_MIN_CLK 2000 /* KHz */
+
+struct ssd2825_bridge_priv {
+ struct mipi_dsi_host host;
+ struct mipi_dsi_device device;
+
+ struct udevice *panel;
+ struct display_timing timing;
+
+ struct gpio_desc power_gpio;
+ struct gpio_desc reset_gpio;
+
+ struct clk *tx_clk;
+
+ u32 pll_freq_kbps; /* PLL in kbps */
+};
+
+static int ssd2825_spi_write(struct udevice *dev, int reg,
+ const void *buf, int flags)
+{
+ u8 command[2];
+
+ if (flags & SSD2825_CMD_SEND) {
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = reg;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+ }
+
+ if (flags & SSD2825_DAT_SEND) {
+ u16 data = *(u16 *)buf;
+ u8 cmd1, cmd2;
+
+ /* send low byte first and then high byte */
+ cmd1 = (data & 0x00FF);
+ cmd2 = (data & 0xFF00) >> 8;
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = cmd1;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = cmd2;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+ }
+
+ if (flags & SSD2825_DSI_SEND) {
+ u16 data = *(u16 *)buf;
+ data &= 0x00FF;
+
+ debug("%s: dsi command (0x%x)\n",
+ __func__, data);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = data;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+ }
+
+ return 0;
+}
+
+static int ssd2825_spi_read(struct udevice *dev, int reg,
+ void *data, int flags)
+{
+ u8 command[2];
+
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = SSD2825_SPI_READ_REG;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = SSD2825_SPI_READ_REG_RESET;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = 0;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = reg;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = SSD2825_SPI_READ_REG_RESET;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ dm_spi_xfer(dev, 16, NULL,
+ (u8 *)data, SPI_XFER_ONCE);
+
+ return 0;
+}
+
+static void ssd2825_write_register(struct udevice *dev, u8 reg,
+ u16 command)
+{
+ ssd2825_spi_write(dev, reg, &command,
+ SSD2825_CMD_SEND |
+ SSD2825_DAT_SEND);
+}
+
+static void ssd2825_write_dsi(struct udevice *dev, const u8 *command,
+ int len)
+{
+ int i;
+
+ ssd2825_spi_write(dev, SSD2825_PACKET_SIZE_CTRL_REG_1, &len,
+ SSD2825_CMD_SEND | SSD2825_DAT_SEND);
+
+ ssd2825_spi_write(dev, SSD2825_PACKET_DROP_REG, NULL,
+ SSD2825_CMD_SEND);
+
+ for (i = 0; i < len; i++)
+ ssd2825_spi_write(dev, 0, &command[i], SSD2825_DSI_SEND);
+}
+
+static ssize_t ssd2825_bridge_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct udevice *dev = (struct udevice *)host->dev;
+ u8 buf = *(u8 *)msg->tx_buf;
+ u16 config;
+ int ret;
+
+ ret = ssd2825_spi_read(dev, SSD2825_CONFIGURATION_REG,
+ &config, 0);
+ if (ret)
+ return ret;
+
+ switch (msg->type) {
+ case MIPI_DSI_DCS_SHORT_WRITE:
+ case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+ case MIPI_DSI_DCS_LONG_WRITE:
+ config |= SSD2825_CONF_REG_DCS;
+ break;
+ case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
+ case MIPI_DSI_GENERIC_LONG_WRITE:
+ config &= ~SSD2825_CONF_REG_DCS;
+ break;
+ default:
+ return 0;
+ }
+
+ ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG, config);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+ ssd2825_write_dsi(dev, msg->tx_buf, msg->tx_len);
+
+ if (buf == MIPI_DCS_SET_DISPLAY_ON) {
+ ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG,
+ SSD2825_CONF_REG_HS | SSD2825_CONF_REG_VEN |
+ SSD2825_CONF_REG_DCS | SSD2825_CONF_REG_ECD |
+ SSD2825_CONF_REG_EOT);
+ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+ }
+
+ return 0;
+}
+
+static const struct mipi_dsi_host_ops ssd2825_bridge_host_ops = {
+ .transfer = ssd2825_bridge_transfer,
+};
+
+/*
+ * PLL configuration register settings.
+ *
+ * See the "PLL Configuration Register Description" in the SSD2825 datasheet.
+ */
+static u16 construct_pll_config(struct ssd2825_bridge_priv *priv,
+ u32 desired_pll_freq_kbps, u32 reference_freq_khz)
+{
+ u32 div_factor = 1, mul_factor, fr = 0;
+
+ while (reference_freq_khz / (div_factor + 1) >= SSD2825_REF_MIN_CLK)
+ div_factor++;
+ if (div_factor > 31)
+ div_factor = 31;
+
+ mul_factor = DIV_ROUND_UP(desired_pll_freq_kbps * div_factor,
+ reference_freq_khz);
+
+ priv->pll_freq_kbps = reference_freq_khz * mul_factor / div_factor;
+
+ if (priv->pll_freq_kbps >= 501000)
+ fr = 3;
+ else if (priv->pll_freq_kbps >= 251000)
+ fr = 2;
+ else if (priv->pll_freq_kbps >= 126000)
+ fr = 1;
+
+ return (fr << 14) | (div_factor << 8) | mul_factor;
+}
+
+static void ssd2825_setup_pll(struct udevice *dev)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct display_timing *dt = &priv->timing;
+ u16 pll_config, lp_div;
+ u32 pclk_mult, tx_freq_khz, pd_lines;
+
+ tx_freq_khz = clk_get_rate(priv->tx_clk) / 1000;
+ pd_lines = mipi_dsi_pixel_format_to_bpp(device->format);
+ pclk_mult = pd_lines / device->lanes + 1;
+
+ pll_config = construct_pll_config(priv, pclk_mult *
+ dt->pixelclock.typ / 1000,
+ tx_freq_khz);
+
+ lp_div = priv->pll_freq_kbps / (SSD2825_LP_MIN_CLK * 8);
+
+ /* Disable PLL */
+ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0000);
+ ssd2825_write_register(dev, SSD2825_LINE_CTRL_REG, 0x0001);
+
+ /* Set delays */
+ ssd2825_write_register(dev, SSD2825_DELAY_ADJ_REG_1, 0x2103);
+
+ /* Set PLL coeficients */
+ ssd2825_write_register(dev, SSD2825_PLL_CONFIGURATION_REG, pll_config);
+
+ /* Clock Control Register */
+ ssd2825_write_register(dev, SSD2825_CLOCK_CTRL_REG,
+ SSD2828_LP_CLOCK_DIVIDER(lp_div));
+
+ /* Enable PLL */
+ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+}
+
+static int ssd2825_bridge_enable_panel(struct udevice *dev)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct display_timing *dt = &priv->timing;
+ int ret;
+
+ ret = clk_prepare_enable(priv->tx_clk);
+ if (ret) {
+ log_err("error enabling tx_clk (%d)\n", ret);
+ return ret;
+ }
+
+ ret = dm_gpio_set_value(&priv->power_gpio, 1);
+ if (ret) {
+ log_err("error changing power-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(10);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(10);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(10);
+
+ /* Perform panel HW setup */
+ ret = panel_enable_backlight(priv->panel);
+ if (ret)
+ return ret;
+
+ /* Perform SW reset */
+ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100);
+
+ /* Set panel timings */
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_1,
+ dt->vsync_len.typ << 8 | dt->hsync_len.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_2,
+ (dt->vsync_len.typ + dt->vback_porch.typ) << 8 |
+ (dt->hsync_len.typ + dt->hback_porch.typ));
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_3,
+ dt->vfront_porch.typ << 8 | dt->hfront_porch.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_4,
+ dt->hactive.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_5,
+ dt->vactive.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_6,
+ SSD2825_HSYNC_HIGH | SSD2825_VSYNC_HIGH |
+ SSD2825_PCKL_HIGH | SSD2825_NON_BURST |
+ (3 - device->format));
+ ssd2825_write_register(dev, SSD2825_LANE_CONFIGURATION_REG,
+ device->lanes - 1);
+ ssd2825_write_register(dev, SSD2825_TEST_REG, 0x0004);
+
+ /* Call PLL configuration */
+ ssd2825_setup_pll(dev);
+
+ mdelay(10);
+
+ /* Initial DSI configuration register set */
+ ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG,
+ SSD2825_CONF_REG_CKE | SSD2825_CONF_REG_DCS |
+ SSD2825_CONF_REG_ECD | SSD2825_CONF_REG_EOT);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+
+ /* Set up SW panel configuration */
+ ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ssd2825_bridge_set_panel(struct udevice *dev, int percent)
+{
+ return 0;
+}
+
+static int ssd2825_bridge_panel_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+
+ memcpy(timing, &priv->timing, sizeof(*timing));
+
+ return 0;
+}
+
+static int ssd2825_bridge_probe(struct udevice *dev)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+ struct spi_slave *slave = dev_get_parent_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct mipi_dsi_panel_plat *mipi_plat;
+ int ret;
+
+ ret = spi_claim_bus(slave);
+ if (ret) {
+ log_err("SPI bus allocation failed (%d)\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev,
+ "panel", &priv->panel);
+ if (ret) {
+ log_err("cannot get panel: ret=%d\n", ret);
+ return ret;
+ }
+
+ panel_get_display_timing(priv->panel, &priv->timing);
+
+ mipi_plat = dev_get_plat(priv->panel);
+ mipi_plat->device = device;
+
+ priv->host.dev = (struct device *)dev;
+ priv->host.ops = &ssd2825_bridge_host_ops;
+
+ device->host = &priv->host;
+ device->lanes = mipi_plat->lanes;
+ device->format = mipi_plat->format;
+ device->mode_flags = mipi_plat->mode_flags;
+
+ /* get panel gpios */
+ ret = gpio_request_by_name(dev, "power-gpios", 0,
+ &priv->power_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode power-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode reset-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ /* get clk */
+ priv->tx_clk = devm_clk_get(dev, "tx_clk");
+ if (IS_ERR(priv->tx_clk)) {
+ log_err("cannot get tx_clk: %ld\n", PTR_ERR(priv->tx_clk));
+ return PTR_ERR(priv->tx_clk);
+ }
+
+ return 0;
+}
+
+static const struct panel_ops ssd2825_bridge_ops = {
+ .enable_backlight = ssd2825_bridge_enable_panel,
+ .set_backlight = ssd2825_bridge_set_panel,
+ .get_display_timing = ssd2825_bridge_panel_timings,
+};
+
+static const struct udevice_id ssd2825_bridge_ids[] = {
+ { .compatible = "solomon,ssd2825" },
+ { }
+};
+
+U_BOOT_DRIVER(ssd2825) = {
+ .name = "ssd2825",
+ .id = UCLASS_PANEL,
+ .of_match = ssd2825_bridge_ids,
+ .ops = &ssd2825_bridge_ops,
+ .probe = ssd2825_bridge_probe,
+ .priv_auto = sizeof(struct ssd2825_bridge_priv),
+};
diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c
index d4f79c656a9..1f93b1b85fa 100644
--- a/drivers/video/console_core.c
+++ b/drivers/video/console_core.c
@@ -46,11 +46,11 @@ static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata
int check_bpix_support(int bpix)
{
- if (bpix == VIDEO_BPP8 && IS_ENABLED(CONFIG_VIDEO_BPP8))
+ if (bpix == VIDEO_BPP8 && CONFIG_IS_ENABLED(VIDEO_BPP8))
return 0;
- else if (bpix == VIDEO_BPP16 && IS_ENABLED(CONFIG_VIDEO_BPP16))
+ else if (bpix == VIDEO_BPP16 && CONFIG_IS_ENABLED(VIDEO_BPP16))
return 0;
- else if (bpix == VIDEO_BPP32 && IS_ENABLED(CONFIG_VIDEO_BPP32))
+ else if (bpix == VIDEO_BPP32 && CONFIG_IS_ENABLED(VIDEO_BPP32))
return 0;
else
return -ENOSYS;
diff --git a/drivers/video/dw_mipi_dsi.c b/drivers/video/dw_mipi_dsi.c
index 6d9c5a94761..a4606923ffc 100644
--- a/drivers/video/dw_mipi_dsi.c
+++ b/drivers/video/dw_mipi_dsi.c
@@ -806,6 +806,15 @@ static int dw_mipi_dsi_init(struct udevice *dev,
return -EINVAL;
}
+ /*
+ * The Rockchip based devices don't have px_clk, so simply move
+ * on.
+ */
+ if (IS_ENABLED(CONFIG_DISPLAY_ROCKCHIP_DW_MIPI)) {
+ dw_mipi_dsi_bridge_set(dsi, timings);
+ return 0;
+ }
+
ret = clk_get_by_name(device->dev, "px_clk", &clk);
if (ret) {
dev_err(device->dev, "peripheral clock get error %d\n", ret);
diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c
new file mode 100644
index 00000000000..79a272128b8
--- /dev/null
+++ b/drivers/video/endeavoru-panel.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+struct endeavoru_panel_priv {
+ struct udevice *vdd;
+ struct udevice *vddio;
+
+ struct udevice *backlight;
+
+ struct gpio_desc reset_gpio;
+};
+
+static struct display_timing default_timing = {
+ .pixelclock.typ = 63200000,
+ .hactive.typ = 720,
+ .hfront_porch.typ = 55,
+ .hback_porch.typ = 29,
+ .hsync_len.typ = 16,
+ .vactive.typ = 1280,
+ .vfront_porch.typ = 2,
+ .vback_porch.typ = 1,
+ .vsync_len.typ = 1,
+};
+
+static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data)
+{
+ mipi_dsi_dcs_write(dsi, cmd, &data, 1);
+}
+
+/*
+ * This panel is not able to auto-increment all cmd addresses so for some of
+ * them, we need to send them one by one...
+ */
+#define dcs_write_seq(dsi, cmd, seq...) \
+({ \
+ static const u8 d[] = { seq }; \
+ unsigned int i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(d) ; i++) \
+ dcs_write_one(dsi, cmd + i, d[i]); \
+})
+
+static int endeavoru_panel_enable_backlight(struct udevice *dev)
+{
+ struct endeavoru_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = regulator_set_enable_if_allowed(priv->vddio, 1);
+ if (ret) {
+ log_err("error enabling iovcc-supply (%d)\n", ret);
+ return ret;
+ }
+ mdelay(1);
+
+ ret = regulator_set_enable_if_allowed(priv->vdd, 1);
+ if (ret) {
+ log_err("error enabling vcc-supply (%d)\n", ret);
+ return ret;
+ }
+ mdelay(20);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(2);
+
+ /* Reset panel */
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(1);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(25);
+
+ return 0;
+}
+
+static int endeavoru_panel_set_backlight(struct udevice *dev, int percent)
+{
+ struct endeavoru_panel_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *dsi = plat->device;
+ int ret;
+
+ dcs_write_one(dsi, 0xc2, 0x08);
+
+ /* color enhancement 2.2 */
+ dcs_write_one(dsi, 0xff, 0x03);
+ dcs_write_one(dsi, 0xfe, 0x08);
+ dcs_write_one(dsi, 0x18, 0x00);
+ dcs_write_one(dsi, 0x19, 0x00);
+ dcs_write_one(dsi, 0x1a, 0x00);
+ dcs_write_one(dsi, 0x25, 0x26);
+
+ dcs_write_seq(dsi, 0x00, 0x00, 0x05, 0x10, 0x17,
+ 0x22, 0x26, 0x29, 0x29, 0x26, 0x23,
+ 0x17, 0x12, 0x06, 0x02, 0x01, 0x00);
+
+ dcs_write_one(dsi, 0xfb, 0x01);
+ dcs_write_one(dsi, 0xff, 0x00);
+ dcs_write_one(dsi, 0xfe, 0x01);
+
+ mipi_dsi_dcs_exit_sleep_mode(dsi);
+
+ mdelay(105);
+
+ dcs_write_one(dsi, 0x35, 0x00);
+
+ /* PWM frequency adjust */
+ dcs_write_one(dsi, 0xff, 0x04);
+ dcs_write_one(dsi, 0x0a, 0x07);
+ dcs_write_one(dsi, 0x09, 0x20);
+ dcs_write_one(dsi, 0xff, 0x00);
+
+ dcs_write_one(dsi, 0xff, 0xee);
+ dcs_write_one(dsi, 0x12, 0x50);
+ dcs_write_one(dsi, 0x13, 0x02);
+ dcs_write_one(dsi, 0x6a, 0x60);
+ dcs_write_one(dsi, 0xfb, 0x01);
+ dcs_write_one(dsi, 0xff, 0x00);
+
+ mipi_dsi_dcs_set_display_on(dsi);
+
+ mdelay(42);
+
+ dcs_write_one(dsi, 0xba, 0x01);
+
+ dcs_write_one(dsi, 0x53, 0x24);
+ dcs_write_one(dsi, 0x55, 0x80);
+ dcs_write_one(dsi, 0x5e, 0x06);
+
+ ret = backlight_enable(priv->backlight);
+ if (ret)
+ return ret;
+
+ /* Set backlight */
+ dcs_write_one(dsi, 0x51, 0x96);
+
+ ret = backlight_set_brightness(priv->backlight, percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int endeavoru_panel_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ memcpy(timing, &default_timing, sizeof(*timing));
+ return 0;
+}
+
+static int endeavoru_panel_of_to_plat(struct udevice *dev)
+{
+ struct endeavoru_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret) {
+ log_err("cannot get backlight: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "vdd-supply", &priv->vdd);
+ if (ret) {
+ log_err("cannot get vdd-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "vddio-supply", &priv->vddio);
+ if (ret) {
+ log_err("cannot get vddio-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode reser-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int endeavoru_panel_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ /* fill characteristics of DSI data link */
+ plat->lanes = 2;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO;
+
+ return 0;
+}
+
+static const struct panel_ops endeavoru_panel_ops = {
+ .enable_backlight = endeavoru_panel_enable_backlight,
+ .set_backlight = endeavoru_panel_set_backlight,
+ .get_display_timing = endeavoru_panel_timings,
+};
+
+static const struct udevice_id endeavoru_panel_ids[] = {
+ { .compatible = "htc,edge-panel" },
+ { }
+};
+
+U_BOOT_DRIVER(endeavoru_panel) = {
+ .name = "endeavoru_panel",
+ .id = UCLASS_PANEL,
+ .of_match = endeavoru_panel_ids,
+ .ops = &endeavoru_panel_ops,
+ .of_to_plat = endeavoru_panel_of_to_plat,
+ .probe = endeavoru_panel_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct endeavoru_panel_priv),
+};
diff --git a/drivers/video/lm3533_backlight.c b/drivers/video/lm3533_backlight.c
new file mode 100644
index 00000000000..00297a09b7f
--- /dev/null
+++ b/drivers/video/lm3533_backlight.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT
+
+#include <backlight.h>
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <asm/gpio.h>
+
+#define LM3533_BL_MIN_BRIGHTNESS 0x02
+#define LM3533_BL_MAX_BRIGHTNESS 0xFF
+
+#define LM3533_SINK_OUTPUT_CONFIG_1 0x10
+#define LM3533_CONTROL_BANK_A_PWM 0x14
+#define LM3533_CONTROL_BANK_AB_BRIGHTNESS 0x1A
+#define LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT 0x1F
+#define LM3533_CONTROL_BANK_ENABLE 0x27
+#define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C
+#define LM3533_BRIGHTNESS_REGISTER_A 0x40
+
+struct lm3533_backlight_priv {
+ struct gpio_desc enable_gpio;
+ u32 def_bl_lvl;
+};
+
+static int lm3533_backlight_enable(struct udevice *dev)
+{
+ struct lm3533_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ dm_gpio_set_value(&priv->enable_gpio, 1);
+ mdelay(5);
+
+ /* HVLED 1 & 2 are controlled by Bank A */
+ ret = dm_i2c_reg_write(dev, LM3533_SINK_OUTPUT_CONFIG_1, 0x00);
+ if (ret)
+ return ret;
+
+ /* PWM input is disabled for CABC */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_PWM, 0x00);
+ if (ret)
+ return ret;
+
+ /* Linear & Control Bank A is configured for register Current control */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS, 0x02);
+ if (ret)
+ return ret;
+
+ /* Full-Scale Current (20.2mA) */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT, 0x13);
+ if (ret)
+ return ret;
+
+ /* Control Bank A is enable */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_ENABLE, 0x01);
+ if (ret)
+ return ret;
+
+ ret = dm_i2c_reg_write(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, 0x0A);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lm3533_backlight_set_brightness(struct udevice *dev, int percent)
+{
+ struct lm3533_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (percent == BACKLIGHT_DEFAULT)
+ percent = priv->def_bl_lvl;
+
+ if (percent < LM3533_BL_MIN_BRIGHTNESS)
+ percent = LM3533_BL_MIN_BRIGHTNESS;
+
+ if (percent > LM3533_BL_MAX_BRIGHTNESS)
+ percent = LM3533_BL_MAX_BRIGHTNESS;
+
+ /* Set brightness level */
+ ret = dm_i2c_reg_write(dev, LM3533_BRIGHTNESS_REGISTER_A,
+ percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lm3533_backlight_probe(struct udevice *dev)
+{
+ struct lm3533_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
+ return -EPROTONOSUPPORT;
+
+ ret = gpio_request_by_name(dev, "enable-gpios", 0,
+ &priv->enable_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("Could not decode enable-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ priv->def_bl_lvl = dev_read_u32_default(dev, "default-brightness-level",
+ LM3533_BL_MAX_BRIGHTNESS);
+
+ return 0;
+}
+
+static const struct backlight_ops lm3533_backlight_ops = {
+ .enable = lm3533_backlight_enable,
+ .set_brightness = lm3533_backlight_set_brightness,
+};
+
+static const struct udevice_id lm3533_backlight_ids[] = {
+ { .compatible = "ti,lm3533" },
+ { }
+};
+
+U_BOOT_DRIVER(lm3533_backlight) = {
+ .name = "lm3533_backlight",
+ .id = UCLASS_PANEL_BACKLIGHT,
+ .of_match = lm3533_backlight_ids,
+ .probe = lm3533_backlight_probe,
+ .ops = &lm3533_backlight_ops,
+ .priv_auto = sizeof(struct lm3533_backlight_priv),
+};
diff --git a/drivers/video/orisetech_otm8009a.c b/drivers/video/orisetech_otm8009a.c
index 95738e34bf6..848f174b6e4 100644
--- a/drivers/video/orisetech_otm8009a.c
+++ b/drivers/video/orisetech_otm8009a.c
@@ -300,7 +300,7 @@ static int otm8009a_panel_of_to_plat(struct udevice *dev)
struct otm8009a_panel_priv *priv = dev_get_priv(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
ret = device_get_supply_regulator(dev, "power-supply",
&priv->reg);
if (ret && ret != -ENOENT) {
@@ -326,7 +326,7 @@ static int otm8009a_panel_probe(struct udevice *dev)
struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->reg) {
dev_dbg(dev, "enable regulator '%s'\n", priv->reg->name);
ret = regulator_set_enable(priv->reg, true);
if (ret)
diff --git a/drivers/video/raydium-rm68200.c b/drivers/video/raydium-rm68200.c
index 373668d28bf..f1fce55a2cb 100644
--- a/drivers/video/raydium-rm68200.c
+++ b/drivers/video/raydium-rm68200.c
@@ -266,7 +266,7 @@ static int rm68200_panel_of_to_plat(struct udevice *dev)
struct rm68200_panel_priv *priv = dev_get_priv(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
ret = device_get_supply_regulator(dev, "power-supply",
&priv->reg);
if (ret && ret != -ENOENT) {
@@ -299,7 +299,7 @@ static int rm68200_panel_probe(struct udevice *dev)
struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->reg) {
ret = regulator_set_enable(priv->reg, true);
if (ret)
return ret;
diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c
new file mode 100644
index 00000000000..426fdc6224a
--- /dev/null
+++ b/drivers/video/renesas-r61307.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Renesas R61307 panel driver
+ *
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+/*
+ * The datasheet is not publicly available, all values are
+ * taken from the downstream. If you have access to datasheets,
+ * corrections are welcome.
+ */
+
+#define R61307_MACP 0xB0 /* Manufacturer CMD Protect */
+
+#define R61307_INVERSION 0xC1
+#define R61307_GAMMA_SET_A 0xC8 /* Gamma Setting A */
+#define R61307_GAMMA_SET_B 0xC9 /* Gamma Setting B */
+#define R61307_GAMMA_SET_C 0xCA /* Gamma Setting C */
+#define R61307_CONTRAST_SET 0xCC
+
+struct renesas_r61307_priv {
+ struct udevice *vcc;
+ struct udevice *iovcc;
+
+ struct udevice *backlight;
+
+ struct gpio_desc reset_gpio;
+
+ bool dig_cont_adj;
+ bool inversion;
+ u32 gamma;
+};
+
+static const u8 macp_on[] = {
+ R61307_MACP, 0x03
+};
+
+static const u8 macp_off[] = {
+ R61307_MACP, 0x04
+};
+
+static const u8 address_mode[] = {
+ MIPI_DCS_SET_ADDRESS_MODE
+};
+
+static const u8 contrast_setting[] = {
+ R61307_CONTRAST_SET,
+ 0xdc, 0xb4, 0xff
+};
+
+static const u8 column_inversion[] = {
+ R61307_INVERSION,
+ 0x00, 0x50, 0x03, 0x22,
+ 0x16, 0x06, 0x60, 0x11
+};
+
+static const u8 line_inversion[] = {
+ R61307_INVERSION,
+ 0x00, 0x10, 0x03, 0x22,
+ 0x16, 0x06, 0x60, 0x01
+};
+
+static const u8 gamma_setting[][25] = {
+ {},
+ {
+ R61307_GAMMA_SET_A,
+ 0x00, 0x06, 0x0a, 0x0f,
+ 0x14, 0x1f, 0x1f, 0x17,
+ 0x12, 0x0c, 0x09, 0x06,
+ 0x00, 0x06, 0x0a, 0x0f,
+ 0x14, 0x1f, 0x1f, 0x17,
+ 0x12, 0x0c, 0x09, 0x06
+ },
+ {
+ R61307_GAMMA_SET_A,
+ 0x00, 0x05, 0x0b, 0x0f,
+ 0x11, 0x1d, 0x20, 0x18,
+ 0x18, 0x09, 0x07, 0x06,
+ 0x00, 0x05, 0x0b, 0x0f,
+ 0x11, 0x1d, 0x20, 0x18,
+ 0x18, 0x09, 0x07, 0x06
+ },
+ {
+ R61307_GAMMA_SET_A,
+ 0x0b, 0x0d, 0x10, 0x14,
+ 0x13, 0x1d, 0x20, 0x18,
+ 0x12, 0x09, 0x07, 0x06,
+ 0x0a, 0x0c, 0x10, 0x14,
+ 0x13, 0x1d, 0x20, 0x18,
+ 0x12, 0x09, 0x07, 0x06
+ },
+};
+
+static struct display_timing default_timing = {
+ .pixelclock.typ = 62000000,
+ .hactive.typ = 768,
+ .hfront_porch.typ = 116,
+ .hback_porch.typ = 81,
+ .hsync_len.typ = 5,
+ .vactive.typ = 1024,
+ .vfront_porch.typ = 24,
+ .vback_porch.typ = 8,
+ .vsync_len.typ = 2,
+};
+
+static int renesas_r61307_enable_backlight(struct udevice *dev)
+{
+ struct renesas_r61307_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = regulator_set_enable_if_allowed(priv->vcc, 1);
+ if (ret) {
+ log_err("enabling vcc-supply failed (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = regulator_set_enable_if_allowed(priv->iovcc, 1);
+ if (ret) {
+ log_err("enabling iovcc-supply failed (%d)\n", ret);
+ return ret;
+ }
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("changing reset-gpio failed (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("changing reset-gpio failed (%d)\n", ret);
+ return ret;
+ }
+
+ mdelay(5);
+
+ return 0;
+}
+
+static int renesas_r61307_set_backlight(struct udevice *dev, int percent)
+{
+ struct renesas_r61307_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *dsi = plat->device;
+ int ret;
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ log_err("failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(80);
+
+ mipi_dsi_dcs_write_buffer(dsi, address_mode,
+ sizeof(address_mode));
+
+ mdelay(20);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
+ if (ret < 0) {
+ log_err("failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ /* MACP Off */
+ mipi_dsi_generic_write(dsi, macp_off, sizeof(macp_off));
+
+ if (priv->dig_cont_adj)
+ mipi_dsi_generic_write(dsi, contrast_setting,
+ sizeof(contrast_setting));
+
+ if (priv->gamma)
+ mipi_dsi_generic_write(dsi, gamma_setting[priv->gamma],
+ sizeof(gamma_setting[priv->gamma]));
+
+ if (priv->inversion)
+ mipi_dsi_generic_write(dsi, column_inversion,
+ sizeof(column_inversion));
+ else
+ mipi_dsi_generic_write(dsi, line_inversion,
+ sizeof(line_inversion));
+
+ /* MACP On */
+ mipi_dsi_generic_write(dsi, macp_on, sizeof(macp_on));
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ log_err("failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(50);
+
+ ret = backlight_enable(priv->backlight);
+ if (ret)
+ return ret;
+
+ ret = backlight_set_brightness(priv->backlight, percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int renesas_r61307_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ memcpy(timing, &default_timing, sizeof(*timing));
+ return 0;
+}
+
+static int renesas_r61307_of_to_plat(struct udevice *dev)
+{
+ struct renesas_r61307_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret) {
+ log_err("Cannot get backlight: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "vcc-supply", &priv->vcc);
+ if (ret) {
+ log_err("Cannot get vcc-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "iovcc-supply", &priv->iovcc);
+ if (ret) {
+ log_err("Cannot get iovcc-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("Could not decode reser-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ priv->dig_cont_adj = dev_read_bool(dev, "renesas,contrast");
+ priv->inversion = dev_read_bool(dev, "renesas,inversion");
+ priv->gamma = dev_read_u32_default(dev, "renesas,gamma", 0);
+
+ return 0;
+}
+
+static int renesas_r61307_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ /* fill characteristics of DSI data link */
+ plat->lanes = 4;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO;
+
+ return 0;
+}
+
+static const struct panel_ops renesas_r61307_ops = {
+ .enable_backlight = renesas_r61307_enable_backlight,
+ .set_backlight = renesas_r61307_set_backlight,
+ .get_display_timing = renesas_r61307_timings,
+};
+
+static const struct udevice_id renesas_r61307_ids[] = {
+ { .compatible = "koe,tx13d100vm0eaa" },
+ { .compatible = "hitachi,tx13d100vm0eaa" },
+ { }
+};
+
+U_BOOT_DRIVER(renesas_r61307) = {
+ .name = "renesas_r61307",
+ .id = UCLASS_PANEL,
+ .of_match = renesas_r61307_ids,
+ .ops = &renesas_r61307_ops,
+ .of_to_plat = renesas_r61307_of_to_plat,
+ .probe = renesas_r61307_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct renesas_r61307_priv),
+};
diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c
new file mode 100644
index 00000000000..d2f71694681
--- /dev/null
+++ b/drivers/video/renesas-r69328.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Renesas R69328 panel driver
+ *
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+/*
+ * The datasheet is not publicly available, all values are
+ * taken from the downstream. If you have access to datasheets,
+ * corrections are welcome.
+ */
+
+#define R69328_MACP 0xB0 /* Manufacturer Command Access Protect */
+
+#define R69328_GAMMA_SET_A 0xC8 /* Gamma Setting A */
+#define R69328_GAMMA_SET_B 0xC9 /* Gamma Setting B */
+#define R69328_GAMMA_SET_C 0xCA /* Gamma Setting C */
+
+#define R69328_POWER_SET 0xD1
+
+struct renesas_r69328_priv {
+ struct udevice *backlight;
+
+ struct gpio_desc enable_gpio;
+ struct gpio_desc reset_gpio;
+};
+
+static const u8 address_mode[] = {
+ MIPI_DCS_SET_ADDRESS_MODE
+};
+
+#define dsi_generic_write_seq(dsi, cmd, seq...) do { \
+ static const u8 b[] = { cmd, seq }; \
+ int ret; \
+ ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+static struct display_timing default_timing = {
+ .pixelclock.typ = 68000000,
+ .hactive.typ = 720,
+ .hfront_porch.typ = 92,
+ .hback_porch.typ = 62,
+ .hsync_len.typ = 4,
+ .vactive.typ = 1280,
+ .vfront_porch.typ = 6,
+ .vback_porch.typ = 3,
+ .vsync_len.typ = 1,
+};
+
+static int renesas_r69328_enable_backlight(struct udevice *dev)
+{
+ struct renesas_r69328_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = dm_gpio_set_value(&priv->enable_gpio, 1);
+ if (ret) {
+ log_err("error changing enable-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ mdelay(5);
+
+ return 0;
+}
+
+static int renesas_r69328_set_backlight(struct udevice *dev, int percent)
+{
+ struct renesas_r69328_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *dsi = plat->device;
+ int ret;
+
+ mipi_dsi_dcs_write_buffer(dsi, address_mode,
+ sizeof(address_mode));
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
+ if (ret < 0) {
+ log_err("failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ log_err("failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(100);
+
+ /* MACP Off */
+ dsi_generic_write_seq(dsi, R69328_MACP, 0x04);
+
+ dsi_generic_write_seq(dsi, R69328_POWER_SET, 0x14,
+ 0x1d, 0x21, 0x67, 0x11, 0x9a);
+
+ dsi_generic_write_seq(dsi, R69328_GAMMA_SET_A, 0x00,
+ 0x1a, 0x20, 0x28, 0x25, 0x24,
+ 0x26, 0x15, 0x13, 0x11, 0x18,
+ 0x1e, 0x1c, 0x00, 0x00, 0x1a,
+ 0x20, 0x28, 0x25, 0x24, 0x26,
+ 0x15, 0x13, 0x11, 0x18, 0x1e,
+ 0x1c, 0x00);
+ dsi_generic_write_seq(dsi, R69328_GAMMA_SET_B, 0x00,
+ 0x1a, 0x20, 0x28, 0x25, 0x24,
+ 0x26, 0x15, 0x13, 0x11, 0x18,
+ 0x1e, 0x1c, 0x00, 0x00, 0x1a,
+ 0x20, 0x28, 0x25, 0x24, 0x26,
+ 0x15, 0x13, 0x11, 0x18, 0x1e,
+ 0x1c, 0x00);
+ dsi_generic_write_seq(dsi, R69328_GAMMA_SET_C, 0x00,
+ 0x1a, 0x20, 0x28, 0x25, 0x24,
+ 0x26, 0x15, 0x13, 0x11, 0x18,
+ 0x1e, 0x1c, 0x00, 0x00, 0x1a,
+ 0x20, 0x28, 0x25, 0x24, 0x26,
+ 0x15, 0x13, 0x11, 0x18, 0x1e,
+ 0x1c, 0x00);
+
+ /* MACP On */
+ dsi_generic_write_seq(dsi, R69328_MACP, 0x03);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ log_err("failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(50);
+
+ ret = backlight_enable(priv->backlight);
+ if (ret)
+ return ret;
+
+ ret = backlight_set_brightness(priv->backlight, percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int renesas_r69328_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ memcpy(timing, &default_timing, sizeof(*timing));
+ return 0;
+}
+
+static int renesas_r69328_of_to_plat(struct udevice *dev)
+{
+ struct renesas_r69328_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret) {
+ log_err("cannot get backlight: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "enable-gpios", 0,
+ &priv->enable_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode enable-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode reser-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int renesas_r69328_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ /* fill characteristics of DSI data link */
+ plat->lanes = 4;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO;
+
+ return 0;
+}
+
+static const struct panel_ops renesas_r69328_ops = {
+ .enable_backlight = renesas_r69328_enable_backlight,
+ .set_backlight = renesas_r69328_set_backlight,
+ .get_display_timing = renesas_r69328_timings,
+};
+
+static const struct udevice_id renesas_r69328_ids[] = {
+ { .compatible = "jdi,dx12d100vm0eaa" },
+ { }
+};
+
+U_BOOT_DRIVER(renesas_r69328) = {
+ .name = "renesas_r69328",
+ .id = UCLASS_PANEL,
+ .of_match = renesas_r69328_ids,
+ .ops = &renesas_r69328_ops,
+ .of_to_plat = renesas_r69328_of_to_plat,
+ .probe = renesas_r69328_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct renesas_r69328_priv),
+};
diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
index b03866347b0..01804dcb1cc 100644
--- a/drivers/video/rockchip/Kconfig
+++ b/drivers/video/rockchip/Kconfig
@@ -69,4 +69,12 @@ config DISPLAY_ROCKCHIP_MIPI
support. The mipi controller and dphy on rk3288& rk3399 support
16,18, 24 bits per pixel with up to 2k resolution ratio.
+config DISPLAY_ROCKCHIP_DW_MIPI
+ bool "Rockchip Designware MIPI"
+ depends on VIDEO_ROCKCHIP
+ select VIDEO_DW_MIPI_DSI
+ help
+ Select the Designware MIPI DSI controller in use on some Rockchip
+ SOCs.
+
endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 9aced5ef3f4..8128289cc82 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -15,4 +15,5 @@ obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
obj-mipi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_mipi.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o $(obj-mipi-y)
+obj-$(CONFIG_DISPLAY_ROCKCHIP_DW_MIPI) += dw_mipi_dsi_rockchip.o
endif
diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
new file mode 100644
index 00000000000..ca548a60b75
--- /dev/null
+++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author(s): Chris Morgan <[email protected]>
+ *
+ * This MIPI DSI controller driver is heavily based on the Linux Kernel
+ * driver from drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c and the
+ * U-Boot driver from drivers/video/stm32/stm32_dsi.c.
+ */
+
+#define LOG_CATEGORY UCLASS_VIDEO_BRIDGE
+
+#include <clk.h>
+#include <dm.h>
+#include <div64.h>
+#include <dsi_host.h>
+#include <generic-phy.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <phy-mipi-dphy.h>
+#include <reset.h>
+#include <video_bridge.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <linux/iopoll.h>
+
+#include <common.h>
+#include <log.h>
+#include <video.h>
+#include <asm/io.h>
+#include <dm/device-internal.h>
+#include <linux/bitops.h>
+
+#define USEC_PER_SEC 1000000L
+
+/*
+ * DSI wrapper registers & bit definitions
+ * Note: registers are named as in the Reference Manual
+ */
+#define DSI_WCR 0x0404 /* Wrapper Control Reg */
+#define WCR_DSIEN BIT(3) /* DSI ENable */
+
+#define DSI_PHY_TST_CTRL0 0xb4
+#define PHY_TESTCLK BIT(1)
+#define PHY_UNTESTCLK 0
+#define PHY_TESTCLR BIT(0)
+#define PHY_UNTESTCLR 0
+
+#define DSI_PHY_TST_CTRL1 0xb8
+#define PHY_TESTEN BIT(16)
+#define PHY_UNTESTEN 0
+#define PHY_TESTDOUT(n) (((n) & 0xff) << 8)
+#define PHY_TESTDIN(n) (((n) & 0xff) << 0)
+
+#define BYPASS_VCO_RANGE BIT(7)
+#define VCO_RANGE_CON_SEL(val) (((val) & 0x7) << 3)
+#define VCO_IN_CAP_CON_DEFAULT (0x0 << 1)
+#define VCO_IN_CAP_CON_LOW (0x1 << 1)
+#define VCO_IN_CAP_CON_HIGH (0x2 << 1)
+#define REF_BIAS_CUR_SEL BIT(0)
+
+#define CP_CURRENT_3UA 0x1
+#define CP_CURRENT_4_5UA 0x2
+#define CP_CURRENT_7_5UA 0x6
+#define CP_CURRENT_6UA 0x9
+#define CP_CURRENT_12UA 0xb
+#define CP_CURRENT_SEL(val) ((val) & 0xf)
+#define CP_PROGRAM_EN BIT(7)
+
+#define LPF_RESISTORS_15_5KOHM 0x1
+#define LPF_RESISTORS_13KOHM 0x2
+#define LPF_RESISTORS_11_5KOHM 0x4
+#define LPF_RESISTORS_10_5KOHM 0x8
+#define LPF_RESISTORS_8KOHM 0x10
+#define LPF_PROGRAM_EN BIT(6)
+#define LPF_RESISTORS_SEL(val) ((val) & 0x3f)
+
+#define HSFREQRANGE_SEL(val) (((val) & 0x3f) << 1)
+
+#define INPUT_DIVIDER(val) (((val) - 1) & 0x7f)
+#define LOW_PROGRAM_EN 0
+#define HIGH_PROGRAM_EN BIT(7)
+#define LOOP_DIV_LOW_SEL(val) (((val) - 1) & 0x1f)
+#define LOOP_DIV_HIGH_SEL(val) ((((val) - 1) >> 5) & 0xf)
+#define PLL_LOOP_DIV_EN BIT(5)
+#define PLL_INPUT_DIV_EN BIT(4)
+
+#define POWER_CONTROL BIT(6)
+#define INTERNAL_REG_CURRENT BIT(3)
+#define BIAS_BLOCK_ON BIT(2)
+#define BANDGAP_ON BIT(0)
+
+#define TER_RESISTOR_HIGH BIT(7)
+#define TER_RESISTOR_LOW 0
+#define LEVEL_SHIFTERS_ON BIT(6)
+#define TER_CAL_DONE BIT(5)
+#define SETRD_MAX (0x7 << 2)
+#define POWER_MANAGE BIT(1)
+#define TER_RESISTORS_ON BIT(0)
+
+#define BIASEXTR_SEL(val) ((val) & 0x7)
+#define BANDGAP_SEL(val) ((val) & 0x7)
+#define TLP_PROGRAM_EN BIT(7)
+#define THS_PRE_PROGRAM_EN BIT(7)
+#define THS_ZERO_PROGRAM_EN BIT(6)
+
+#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL 0x10
+#define PLL_CP_CONTROL_PLL_LOCK_BYPASS 0x11
+#define PLL_LPF_AND_CP_CONTROL 0x12
+#define PLL_INPUT_DIVIDER_RATIO 0x17
+#define PLL_LOOP_DIVIDER_RATIO 0x18
+#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL 0x19
+#define BANDGAP_AND_BIAS_CONTROL 0x20
+#define TERMINATION_RESISTER_CONTROL 0x21
+#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22
+#define HS_RX_CONTROL_OF_LANE_CLK 0x34
+#define HS_RX_CONTROL_OF_LANE_0 0x44
+#define HS_RX_CONTROL_OF_LANE_1 0x54
+#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL 0x60
+#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL 0x61
+#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL 0x62
+#define HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL 0x63
+#define HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL 0x64
+#define HS_TX_CLOCK_LANE_POST_TIME_CONTROL 0x65
+#define HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL 0x70
+#define HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL 0x71
+#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL 0x72
+#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL 0x73
+#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL 0x74
+#define HS_RX_DATA_LANE_THS_SETTLE_CONTROL 0x75
+#define HS_RX_CONTROL_OF_LANE_2 0x84
+#define HS_RX_CONTROL_OF_LANE_3 0x94
+
+#define RK3568_GRF_VO_CON2 0x0368
+#define RK3568_DSI0_SKEWCALHS (0x1f << 11)
+#define RK3568_DSI0_FORCETXSTOPMODE (0xf << 4)
+#define RK3568_DSI0_TURNDISABLE BIT(2)
+#define RK3568_DSI0_FORCERXMODE BIT(0)
+
+/*
+ * Note these registers do not appear in the datasheet, they are
+ * however present in the BSP driver which is where these values
+ * come from. Name GRF_VO_CON3 is assumed.
+ */
+#define RK3568_GRF_VO_CON3 0x36c
+#define RK3568_DSI1_SKEWCALHS (0x1f << 11)
+#define RK3568_DSI1_FORCETXSTOPMODE (0xf << 4)
+#define RK3568_DSI1_TURNDISABLE BIT(2)
+#define RK3568_DSI1_FORCERXMODE BIT(0)
+
+#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
+
+/* Timeout for regulator on/off, pll lock/unlock & fifo empty */
+#define TIMEOUT_US 200000
+
+enum {
+ BANDGAP_97_07,
+ BANDGAP_98_05,
+ BANDGAP_99_02,
+ BANDGAP_100_00,
+ BANDGAP_93_17,
+ BANDGAP_94_15,
+ BANDGAP_95_12,
+ BANDGAP_96_10,
+};
+
+enum {
+ BIASEXTR_87_1,
+ BIASEXTR_91_5,
+ BIASEXTR_95_9,
+ BIASEXTR_100,
+ BIASEXTR_105_94,
+ BIASEXTR_111_88,
+ BIASEXTR_118_8,
+ BIASEXTR_127_7,
+};
+
+struct rockchip_dw_dsi_chip_data {
+ u32 reg;
+
+ u32 lcdsel_grf_reg;
+ u32 lcdsel_big;
+ u32 lcdsel_lit;
+
+ u32 enable_grf_reg;
+ u32 enable;
+
+ u32 lanecfg1_grf_reg;
+ u32 lanecfg1;
+ u32 lanecfg2_grf_reg;
+ u32 lanecfg2;
+
+ unsigned int flags;
+ unsigned int max_data_lanes;
+};
+
+struct dw_rockchip_dsi_priv {
+ struct mipi_dsi_device device;
+ void __iomem *base;
+ struct udevice *panel;
+
+ /* Optional external dphy */
+ struct phy phy;
+ struct phy_configure_opts_mipi_dphy phy_opts;
+
+ struct clk *pclk;
+ struct clk *ref;
+ struct reset_ctl *rst;
+ unsigned int lane_mbps; /* per lane */
+ u16 input_div;
+ u16 feedback_div;
+ const struct rockchip_dw_dsi_chip_data *cdata;
+ struct udevice *dsi_host;
+};
+
+static inline void dsi_write(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 val)
+{
+ writel(val, dsi->base + reg);
+}
+
+static inline u32 dsi_read(struct dw_rockchip_dsi_priv *dsi, u32 reg)
+{
+ return readl(dsi->base + reg);
+}
+
+static inline void dsi_set(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 mask)
+{
+ dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);
+}
+
+static inline void dsi_clear(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 mask)
+{
+ dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);
+}
+
+static inline void dsi_update_bits(struct dw_rockchip_dsi_priv *dsi, u32 reg,
+ u32 mask, u32 val)
+{
+ dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);
+}
+
+static void dw_mipi_dsi_phy_write(struct dw_rockchip_dsi_priv *dsi,
+ u8 test_code,
+ u8 test_data)
+{
+ /*
+ * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
+ * is latched internally as the current test code. Test data is
+ * programmed internally by rising edge on TESTCLK.
+ */
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+
+ dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_TESTEN | PHY_TESTDOUT(0) |
+ PHY_TESTDIN(test_code));
+
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLK | PHY_UNTESTCLR);
+
+ dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_UNTESTEN | PHY_TESTDOUT(0) |
+ PHY_TESTDIN(test_data));
+
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+}
+
+struct dphy_pll_parameter_map {
+ unsigned int max_mbps;
+ u8 hsfreqrange;
+ u8 icpctrl;
+ u8 lpfctrl;
+};
+
+/* The table is based on 27MHz DPHY pll reference clock. */
+static const struct dphy_pll_parameter_map dppa_map[] = {
+ { 89, 0x00, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
+ { 99, 0x10, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
+ { 109, 0x20, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
+ { 129, 0x01, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+ { 139, 0x11, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+ { 149, 0x21, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+ { 169, 0x02, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
+ { 179, 0x12, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
+ { 199, 0x22, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
+ { 219, 0x03, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
+ { 239, 0x13, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
+ { 249, 0x23, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
+ { 269, 0x04, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
+ { 299, 0x14, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
+ { 329, 0x05, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+ { 359, 0x15, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+ { 399, 0x25, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+ { 449, 0x06, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 499, 0x16, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 549, 0x07, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
+ { 599, 0x17, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
+ { 649, 0x08, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 699, 0x18, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 749, 0x09, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 799, 0x19, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 849, 0x29, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 899, 0x39, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+ { 949, 0x0a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+ { 999, 0x1a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+ {1049, 0x2a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+ {1099, 0x3a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+ {1149, 0x0b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1199, 0x1b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1249, 0x2b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1299, 0x3b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1349, 0x0c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1399, 0x1c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1449, 0x2c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+ {1500, 0x3c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }
+};
+
+static int max_mbps_to_parameter(unsigned int max_mbps)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dppa_map); i++)
+ if (dppa_map[i].max_mbps >= max_mbps)
+ return i;
+
+ return -EINVAL;
+}
+
+/*
+ * ns2bc - Nanoseconds to byte clock cycles
+ */
+static inline unsigned int ns2bc(struct dw_rockchip_dsi_priv *dsi, int ns)
+{
+ return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000);
+}
+
+/*
+ * ns2ui - Nanoseconds to UI time periods
+ */
+static inline unsigned int ns2ui(struct dw_rockchip_dsi_priv *dsi, int ns)
+{
+ return DIV_ROUND_UP(ns * dsi->lane_mbps, 1000);
+}
+
+static int dsi_phy_init(void *priv_data)
+{
+ struct mipi_dsi_device *device = priv_data;
+ struct udevice *dev = device->dev;
+ struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
+ int ret, i, vco;
+
+ if (&dsi->phy) {
+ ret = generic_phy_configure(&dsi->phy, &dsi->phy_opts);
+ if (ret) {
+ dev_err(dsi->dsi_host,
+ "Configure external dphy fail %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = generic_phy_power_on(&dsi->phy);
+ if (ret) {
+ dev_err(dsi->dsi_host,
+ "Generic phy power on fail %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+ }
+
+ /*
+ * Get vco from frequency(lane_mbps)
+ * vco frequency table
+ * 000 - between 80 and 200 MHz
+ * 001 - between 200 and 300 MHz
+ * 010 - between 300 and 500 MHz
+ * 011 - between 500 and 700 MHz
+ * 100 - between 700 and 900 MHz
+ * 101 - between 900 and 1100 MHz
+ * 110 - between 1100 and 1300 MHz
+ * 111 - between 1300 and 1500 MHz
+ */
+ vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200;
+
+ i = max_mbps_to_parameter(dsi->lane_mbps);
+ if (i < 0) {
+ dev_err(dsi->dsi_host,
+ "failed to get parameter for %dmbps clock\n",
+ dsi->lane_mbps);
+ return i;
+ }
+
+ dw_mipi_dsi_phy_write(dsi, PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL,
+ BYPASS_VCO_RANGE |
+ VCO_RANGE_CON_SEL(vco) |
+ VCO_IN_CAP_CON_LOW |
+ REF_BIAS_CUR_SEL);
+
+ dw_mipi_dsi_phy_write(dsi, PLL_CP_CONTROL_PLL_LOCK_BYPASS,
+ CP_CURRENT_SEL(dppa_map[i].icpctrl));
+ dw_mipi_dsi_phy_write(dsi, PLL_LPF_AND_CP_CONTROL,
+ CP_PROGRAM_EN | LPF_PROGRAM_EN |
+ LPF_RESISTORS_SEL(dppa_map[i].lpfctrl));
+
+ dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
+ HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
+
+ dw_mipi_dsi_phy_write(dsi, PLL_INPUT_DIVIDER_RATIO,
+ INPUT_DIVIDER(dsi->input_div));
+ dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
+ LOOP_DIV_LOW_SEL(dsi->feedback_div) |
+ LOW_PROGRAM_EN);
+ /*
+ * We need set PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL immediately
+ * to make the configured LSB effective according to IP simulation
+ * and lab test results.
+ * Only in this way can we get correct mipi phy pll frequency.
+ */
+ dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
+ PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
+ dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
+ LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
+ HIGH_PROGRAM_EN);
+ dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
+ PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
+
+ dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
+ LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7));
+ dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
+ HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10));
+
+ dw_mipi_dsi_phy_write(dsi, BANDGAP_AND_BIAS_CONTROL,
+ POWER_CONTROL | INTERNAL_REG_CURRENT |
+ BIAS_BLOCK_ON | BANDGAP_ON);
+
+ dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
+ TER_RESISTOR_LOW | TER_CAL_DONE |
+ SETRD_MAX | TER_RESISTORS_ON);
+ dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
+ TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON |
+ SETRD_MAX | POWER_MANAGE |
+ TER_RESISTORS_ON);
+
+ dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL,
+ TLP_PROGRAM_EN | ns2bc(dsi, 500));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL,
+ THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL,
+ THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL,
+ THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL,
+ BIT(5) | ns2bc(dsi, 100));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_POST_TIME_CONTROL,
+ BIT(5) | (ns2bc(dsi, 60) + 7));
+
+ dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL,
+ TLP_PROGRAM_EN | ns2bc(dsi, 500));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL,
+ THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 20));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL,
+ THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL,
+ THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
+ dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL,
+ BIT(5) | ns2bc(dsi, 100));
+
+ return ret;
+}
+
+static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
+{
+ struct mipi_dsi_device *device = priv_data;
+ struct udevice *dev = device->dev;
+ struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
+
+ dev_dbg(dev, "Set mode %p enable %ld\n", dsi,
+ mode_flags & MIPI_DSI_MODE_VIDEO);
+
+ if (!dsi)
+ return;
+
+ /*
+ * DSI wrapper must be enabled in video mode & disabled in command mode.
+ * If wrapper is enabled in command mode, the display controller
+ * register access will hang. Note that this was carried over from the
+ * stm32 dsi driver and is unknown if necessary for Rockchip.
+ */
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO)
+ dsi_set(dsi, DSI_WCR, WCR_DSIEN);
+ else
+ dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
+}
+
+static int
+dw_mipi_dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
+ u32 lanes, u32 format, unsigned int *lane_mbps)
+{
+ struct mipi_dsi_device *device = priv_data;
+ struct udevice *dev = device->dev;
+ struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
+ int bpp;
+ unsigned long mpclk, tmp;
+ unsigned int target_mbps = 1000;
+ unsigned int max_mbps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps;
+ unsigned long best_freq = 0;
+ unsigned long fvco_min, fvco_max, fin, fout;
+ unsigned int min_prediv, max_prediv;
+ unsigned int _prediv, best_prediv;
+ unsigned long _fbdiv, best_fbdiv;
+ unsigned long min_delta = ULONG_MAX;
+ unsigned int pllref_clk;
+
+ bpp = mipi_dsi_pixel_format_to_bpp(format);
+ if (bpp < 0) {
+ dev_err(dsi->dsi_host,
+ "failed to get bpp for pixel format %d\n",
+ format);
+ return bpp;
+ }
+
+ mpclk = DIV_ROUND_UP(timings->pixelclock.typ, 1000);
+ if (mpclk) {
+ /* take 1 / 0.8, since mbps must big than bandwidth of RGB */
+ tmp = (mpclk * (bpp / lanes) * 10 / 8) / 1000;
+ if (tmp < max_mbps)
+ target_mbps = tmp;
+ else
+ dev_err(dsi->dsi_host,
+ "DPHY clock frequency is out of range\n");
+ }
+
+ /* for external phy only the mipi_dphy_config is necessary */
+ if (&dsi->phy) {
+ phy_mipi_dphy_get_default_config(timings->pixelclock.typ * 10 / 8,
+ bpp, lanes,
+ &dsi->phy_opts);
+ dsi->lane_mbps = target_mbps;
+ *lane_mbps = dsi->lane_mbps;
+
+ return 0;
+ }
+
+ pllref_clk = clk_get_rate(dsi->ref);
+ fout = target_mbps * USEC_PER_SEC;
+
+ /* constraint: 5Mhz <= Fref / N <= 40MHz */
+ min_prediv = DIV_ROUND_UP(fin, 40 * USEC_PER_SEC);
+ max_prediv = fin / (5 * USEC_PER_SEC);
+
+ /* constraint: 80MHz <= Fvco <= 1500Mhz */
+ fvco_min = 80 * USEC_PER_SEC;
+ fvco_max = 1500 * USEC_PER_SEC;
+
+ for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
+ u64 tmp;
+ u32 delta;
+ /* Fvco = Fref * M / N */
+ tmp = (u64)fout * _prediv;
+ do_div(tmp, fin);
+ _fbdiv = tmp;
+ /*
+ * Due to the use of a "by 2 pre-scaler," the range of the
+ * feedback multiplication value M is limited to even division
+ * numbers, and m must be greater than 6, not bigger than 512.
+ */
+ if (_fbdiv < 6 || _fbdiv > 512)
+ continue;
+
+ _fbdiv += _fbdiv % 2;
+
+ tmp = (u64)_fbdiv * fin;
+ do_div(tmp, _prediv);
+ if (tmp < fvco_min || tmp > fvco_max)
+ continue;
+
+ delta = abs(fout - tmp);
+ if (delta < min_delta) {
+ best_prediv = _prediv;
+ best_fbdiv = _fbdiv;
+ min_delta = delta;
+ best_freq = tmp;
+ }
+ }
+
+ if (best_freq) {
+ dsi->lane_mbps = DIV_ROUND_UP(best_freq, USEC_PER_SEC);
+ *lane_mbps = dsi->lane_mbps;
+ dsi->input_div = best_prediv;
+ dsi->feedback_div = best_fbdiv;
+ } else {
+ dev_err(dsi->dsi_host, "Can not find best_freq for DPHY\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+struct hstt {
+ unsigned int maxfreq;
+ struct mipi_dsi_phy_timing timing;
+};
+
+#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \
+{ \
+ .maxfreq = _maxfreq, \
+ .timing = { \
+ .clk_lp2hs = _c_lp2hs, \
+ .clk_hs2lp = _c_hs2lp, \
+ .data_lp2hs = _d_lp2hs, \
+ .data_hs2lp = _d_hs2lp, \
+ } \
+}
+
+/*
+ * Table A-3 High-Speed Transition Times
+ * (Note spacing is deliberate for readability).
+ */
+static struct hstt hstt_table[] = {
+ HSTT( 90, 32, 20, 26, 13),
+ HSTT( 100, 35, 23, 28, 14),
+ HSTT( 110, 32, 22, 26, 13),
+ HSTT( 130, 31, 20, 27, 13),
+ HSTT( 140, 33, 22, 26, 14),
+ HSTT( 150, 33, 21, 26, 14),
+ HSTT( 170, 32, 20, 27, 13),
+ HSTT( 180, 36, 23, 30, 15),
+ HSTT( 200, 40, 22, 33, 15),
+ HSTT( 220, 40, 22, 33, 15),
+ HSTT( 240, 44, 24, 36, 16),
+ HSTT( 250, 48, 24, 38, 17),
+ HSTT( 270, 48, 24, 38, 17),
+ HSTT( 300, 50, 27, 41, 18),
+ HSTT( 330, 56, 28, 45, 18),
+ HSTT( 360, 59, 28, 48, 19),
+ HSTT( 400, 61, 30, 50, 20),
+ HSTT( 450, 67, 31, 55, 21),
+ HSTT( 500, 73, 31, 59, 22),
+ HSTT( 550, 79, 36, 63, 24),
+ HSTT( 600, 83, 37, 68, 25),
+ HSTT( 650, 90, 38, 73, 27),
+ HSTT( 700, 95, 40, 77, 28),
+ HSTT( 750, 102, 40, 84, 28),
+ HSTT( 800, 106, 42, 87, 30),
+ HSTT( 850, 113, 44, 93, 31),
+ HSTT( 900, 118, 47, 98, 32),
+ HSTT( 950, 124, 47, 102, 34),
+ HSTT(1000, 130, 49, 107, 35),
+ HSTT(1050, 135, 51, 111, 37),
+ HSTT(1100, 139, 51, 114, 38),
+ HSTT(1150, 146, 54, 120, 40),
+ HSTT(1200, 153, 57, 125, 41),
+ HSTT(1250, 158, 58, 130, 42),
+ HSTT(1300, 163, 58, 135, 44),
+ HSTT(1350, 168, 60, 140, 45),
+ HSTT(1400, 172, 64, 144, 47),
+ HSTT(1450, 176, 65, 148, 48),
+ HSTT(1500, 181, 66, 153, 50)
+};
+
+static int dw_mipi_dsi_rockchip_get_timing(void *priv_data,
+ unsigned int lane_mbps,
+ struct mipi_dsi_phy_timing *timing)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hstt_table); i++)
+ if (lane_mbps < hstt_table[i].maxfreq)
+ break;
+
+ if (i == ARRAY_SIZE(hstt_table))
+ i--;
+
+ *timing = hstt_table[i].timing;
+
+ return 0;
+}
+
+static const struct mipi_dsi_phy_ops dsi_rockchip_phy_ops = {
+ .init = dsi_phy_init,
+ .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
+ .get_timing = dw_mipi_dsi_rockchip_get_timing,
+ .post_set_mode = dsi_phy_post_set_mode,
+};
+
+static int dw_mipi_dsi_rockchip_attach(struct udevice *dev)
+{
+ struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct mipi_dsi_panel_plat *mplat;
+ struct display_timing timings;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_PANEL, &priv->panel);
+ if (ret) {
+ dev_err(dev, "panel device error %d\n", ret);
+ return ret;
+ }
+
+ mplat = dev_get_plat(priv->panel);
+ mplat->device = &priv->device;
+ device->lanes = mplat->lanes;
+ device->format = mplat->format;
+ device->mode_flags = mplat->mode_flags;
+
+ ret = panel_get_display_timing(priv->panel, &timings);
+ if (ret) {
+ ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
+ 0, &timings);
+ if (ret) {
+ dev_err(dev, "decode display timing error %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
+ if (ret) {
+ dev_err(dev, "No video dsi host detected %d\n", ret);
+ return ret;
+ }
+
+ ret = dsi_host_init(priv->dsi_host, device, &timings, 4,
+ &dsi_rockchip_phy_ops);
+ if (ret) {
+ dev_err(dev, "failed to initialize mipi dsi host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dw_mipi_dsi_rockchip_set_bl(struct udevice *dev, int percent)
+{
+ struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ /*
+ * Allow backlight to be optional, since this driver may be
+ * used to simply detect a panel rather than bring one up.
+ */
+ ret = panel_enable_backlight(priv->panel);
+ if ((ret) && (ret != -ENOSYS)) {
+ dev_err(dev, "panel %s enable backlight error %d\n",
+ priv->panel->name, ret);
+ return ret;
+ }
+
+ ret = dsi_host_enable(priv->dsi_host);
+ if (ret) {
+ dev_err(dev, "failed to enable mipi dsi host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void dw_mipi_dsi_rockchip_config(struct dw_rockchip_dsi_priv *dsi)
+{
+ if (dsi->cdata->lanecfg1_grf_reg)
+ dsi_write(dsi, dsi->cdata->lanecfg1_grf_reg,
+ dsi->cdata->lanecfg1);
+
+ if (dsi->cdata->lanecfg2_grf_reg)
+ dsi_write(dsi, dsi->cdata->lanecfg2_grf_reg,
+ dsi->cdata->lanecfg2);
+
+ if (dsi->cdata->enable_grf_reg)
+ dsi_write(dsi, dsi->cdata->enable_grf_reg,
+ dsi->cdata->enable);
+}
+
+static int dw_mipi_dsi_rockchip_bind(struct udevice *dev)
+{
+ int ret;
+
+ ret = device_bind_driver_to_node(dev, "dw_mipi_dsi", "dsihost",
+ dev_ofnode(dev), NULL);
+ if (ret) {
+ dev_err(dev, "failed to bind driver to node\n");
+ return ret;
+ }
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static int dw_mipi_dsi_rockchip_probe(struct udevice *dev)
+{
+ struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ int ret, i;
+ const struct rockchip_dw_dsi_chip_data *cdata =
+ (const struct rockchip_dw_dsi_chip_data *)dev_get_driver_data(dev);
+
+ device->dev = dev;
+
+ priv->base = (void *)dev_read_addr(dev);
+ if ((fdt_addr_t)priv->base == FDT_ADDR_T_NONE) {
+ dev_err(dev, "dsi dt register address error\n");
+ return -EINVAL;
+ }
+
+ i = 0;
+ while (cdata[i].reg) {
+ if (cdata[i].reg == (fdt_addr_t)priv->base) {
+ priv->cdata = &cdata[i];
+ break;
+ }
+
+ i++;
+ }
+
+ if (!priv->cdata) {
+ dev_err(dev, "no dsi-config for %s node\n", dev->name);
+ return -EINVAL;
+ }
+
+ /*
+ * Get an optional external dphy. The external dphy stays as
+ * NULL if it's not initialized.
+ */
+ ret = generic_phy_get_by_name(dev, "dphy", &priv->phy);
+ if ((ret) && (ret != -ENODEV)) {
+ dev_err(dev, "failed to get mipi dphy: %d\n", ret);
+ return -EINVAL;
+ }
+
+ priv->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(priv->pclk)) {
+ dev_err(dev, "peripheral clock get error %d\n", ret);
+ return ret;
+ }
+
+ /* Get a ref clock only if not using an external phy. */
+ if (&priv->phy) {
+ dev_dbg(dev, "setting priv->ref to NULL\n");
+ priv->ref = NULL;
+
+ } else {
+ priv->ref = devm_clk_get(dev, "ref");
+ if (ret) {
+ dev_err(dev, "pll reference clock get error %d\n", ret);
+ return ret;
+ }
+ }
+
+ priv->rst = devm_reset_control_get_by_index(device->dev, 0);
+ if (IS_ERR(priv->rst)) {
+ dev_err(dev, "missing dsi hardware reset\n");
+ return ret;
+ }
+
+ /* Reset */
+ reset_deassert(priv->rst);
+
+ dw_mipi_dsi_rockchip_config(priv);
+
+ return 0;
+}
+
+struct video_bridge_ops dw_mipi_dsi_rockchip_ops = {
+ .attach = dw_mipi_dsi_rockchip_attach,
+ .set_backlight = dw_mipi_dsi_rockchip_set_bl,
+};
+
+static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = {
+ {
+ .reg = 0xfe060000,
+ .lanecfg1_grf_reg = RK3568_GRF_VO_CON2,
+ .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS |
+ RK3568_DSI0_FORCETXSTOPMODE |
+ RK3568_DSI0_TURNDISABLE |
+ RK3568_DSI0_FORCERXMODE),
+ .max_data_lanes = 4,
+ },
+ {
+ .reg = 0xfe070000,
+ .lanecfg1_grf_reg = RK3568_GRF_VO_CON3,
+ .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS |
+ RK3568_DSI1_FORCETXSTOPMODE |
+ RK3568_DSI1_TURNDISABLE |
+ RK3568_DSI1_FORCERXMODE),
+ .max_data_lanes = 4,
+ },
+ { /* sentinel */ }
+};
+
+static const struct udevice_id dw_mipi_dsi_rockchip_dt_ids[] = {
+ { .compatible = "rockchip,rk3568-mipi-dsi",
+ .data = (long)&rk3568_chip_data,
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(dw_mipi_dsi_rockchip) = {
+ .name = "dw-mipi-dsi-rockchip",
+ .id = UCLASS_VIDEO_BRIDGE,
+ .of_match = dw_mipi_dsi_rockchip_dt_ids,
+ .bind = dw_mipi_dsi_rockchip_bind,
+ .probe = dw_mipi_dsi_rockchip_probe,
+ .ops = &dw_mipi_dsi_rockchip_ops,
+ .priv_auto = sizeof(struct dw_rockchip_dsi_priv),
+};
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index bc98ab6875a..e21ac7e3036 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -307,7 +307,8 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
__func__, dev_read_name(dev));
return -EINVAL;
}
- if (strstr(compat, "edp")) {
+ if (strstr(compat, "edp") ||
+ strstr(compat, "rk3288-dp")) {
vop_id = VOP_MODE_EDP;
} else if (strstr(compat, "mipi")) {
vop_id = VOP_MODE_MIPI;
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c
index 91c91ee75d8..6a6473eb0e5 100644
--- a/drivers/video/simple_panel.c
+++ b/drivers/video/simple_panel.c
@@ -8,6 +8,7 @@
#include <backlight.h>
#include <dm.h>
#include <log.h>
+#include <mipi_dsi.h>
#include <panel.h>
#include <asm/gpio.h>
#include <power/regulator.h>
@@ -18,6 +19,19 @@ struct simple_panel_priv {
struct gpio_desc enable;
};
+/* List of supported DSI panels */
+enum {
+ PANEL_NON_DSI,
+ PANASONIC_VVX10F004B00,
+};
+
+static const struct mipi_dsi_panel_plat panasonic_vvx10f004b00 = {
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+};
+
static int simple_panel_enable_backlight(struct udevice *dev)
{
struct simple_panel_priv *priv = dev_get_priv(dev);
@@ -48,12 +62,21 @@ static int simple_panel_set_backlight(struct udevice *dev, int percent)
return 0;
}
+static int simple_panel_get_display_timing(struct udevice *dev,
+ struct display_timing *timings)
+{
+ const void *blob = gd->fdt_blob;
+
+ return fdtdec_decode_display_timing(blob, dev_of_offset(dev),
+ 0, timings);
+}
+
static int simple_panel_of_to_plat(struct udevice *dev)
{
struct simple_panel_priv *priv = dev_get_priv(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
"power-supply", &priv->reg);
if (ret) {
@@ -87,21 +110,34 @@ static int simple_panel_of_to_plat(struct udevice *dev)
static int simple_panel_probe(struct udevice *dev)
{
struct simple_panel_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ const u32 dsi_data = dev_get_driver_data(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->reg) {
debug("%s: Enable regulator '%s'\n", __func__, priv->reg->name);
ret = regulator_set_enable(priv->reg, true);
if (ret)
return ret;
}
+ switch (dsi_data) {
+ case PANASONIC_VVX10F004B00:
+ memcpy(plat, &panasonic_vvx10f004b00,
+ sizeof(panasonic_vvx10f004b00));
+ break;
+ case PANEL_NON_DSI:
+ default:
+ break;
+ }
+
return 0;
}
static const struct panel_ops simple_panel_ops = {
.enable_backlight = simple_panel_enable_backlight,
.set_backlight = simple_panel_set_backlight,
+ .get_display_timing = simple_panel_get_display_timing,
};
static const struct udevice_id simple_panel_ids[] = {
@@ -113,15 +149,18 @@ static const struct udevice_id simple_panel_ids[] = {
{ .compatible = "lg,lb070wv8" },
{ .compatible = "sharp,lq123p1jx31" },
{ .compatible = "boe,nv101wxmn51" },
+ { .compatible = "panasonic,vvx10f004b00",
+ .data = PANASONIC_VVX10F004B00 },
{ }
};
U_BOOT_DRIVER(simple_panel) = {
- .name = "simple_panel",
- .id = UCLASS_PANEL,
- .of_match = simple_panel_ids,
- .ops = &simple_panel_ops,
+ .name = "simple_panel",
+ .id = UCLASS_PANEL,
+ .of_match = simple_panel_ids,
+ .ops = &simple_panel_ops,
.of_to_plat = simple_panel_of_to_plat,
.probe = simple_panel_probe,
.priv_auto = sizeof(struct simple_panel_priv),
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
};
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 4f5d0989286..0324a050d03 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -5,21 +5,27 @@
* (C) Copyright 2017 Jernej Skrabec <[email protected]>
*/
+#include <clk.h>
#include <common.h>
#include <display.h>
#include <dm.h>
#include <dw_hdmi.h>
#include <edid.h>
#include <log.h>
+#include <reset.h>
#include <time.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/lcdc.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <power/regulator.h>
struct sunxi_dw_hdmi_priv {
struct dw_hdmi hdmi;
+ struct reset_ctl_bulk resets;
+ struct clk_bulk clocks;
+ struct udevice *hvcc;
};
struct sunxi_hdmi_phy {
@@ -329,6 +335,9 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
int ret;
+ if (priv->hvcc)
+ regulator_set_enable(priv->hvcc, true);
+
/* Set pll3 to 297 MHz */
clock_set_pll3(297000000);
@@ -336,14 +345,16 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
CCM_HDMI_CTRL_PLL3);
- /* Set ahb gating to pass */
- setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
+ /* This reset is referenced from the PHY devicetree node. */
setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI2);
- setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
- setbits_le32(&ccm->hdmi_slow_clk_cfg, CCM_HDMI_SLOW_CTRL_DDC_GATE);
- /* Clock on */
- setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
+ ret = reset_deassert_bulk(&priv->resets);
+ if (ret)
+ return ret;
+
+ ret = clk_enable_bulk(&priv->clocks);
+ if (ret)
+ return ret;
sunxi_dw_hdmi_phy_init(&priv->hdmi);
@@ -362,6 +373,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
{
struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
struct dw_hdmi *hdmi = &priv->hdmi;
+ int ret;
hdmi->ioaddr = (ulong)dev_read_addr(dev);
hdmi->i2c_clk_high = 0xd8;
@@ -369,6 +381,18 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
hdmi->reg_io_width = 1;
hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
+ ret = reset_get_bulk(dev, &priv->resets);
+ if (ret)
+ return ret;
+
+ ret = clk_get_bulk(dev, &priv->clocks);
+ if (ret)
+ return ret;
+
+ ret = device_get_supply_regulator(dev, "hvcc-supply", &priv->hvcc);
+ if (ret)
+ priv->hvcc = NULL;
+
return 0;
}
diff --git a/drivers/video/tdo-tl070wsh30.c b/drivers/video/tdo-tl070wsh30.c
index 7ad0af73f05..273672db024 100644
--- a/drivers/video/tdo-tl070wsh30.c
+++ b/drivers/video/tdo-tl070wsh30.c
@@ -75,7 +75,7 @@ static int tl070wsh30_panel_of_to_plat(struct udevice *dev)
struct tl070wsh30_panel_priv *priv = dev_get_priv(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
ret = device_get_supply_regulator(dev, "power-supply",
&priv->reg);
if (ret && ret != -ENOENT) {
@@ -108,7 +108,7 @@ static int tl070wsh30_panel_probe(struct udevice *dev)
struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
int ret;
- if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->reg) {
ret = regulator_set_enable(priv->reg, true);
if (ret)
return ret;
diff --git a/drivers/video/tegra20/Kconfig b/drivers/video/tegra20/Kconfig
new file mode 100644
index 00000000000..f5c4843e119
--- /dev/null
+++ b/drivers/video/tegra20/Kconfig
@@ -0,0 +1,24 @@
+config VIDEO_TEGRA20
+ bool "Enable Display Controller support on Tegra20 and Tegra 30"
+ depends on OF_CONTROL
+ help
+ T20/T30 support video output to an attached LCD panel as well as
+ other options such as HDMI. Only the LCD is supported in U-Boot.
+ This option enables this support which can be used on devices which
+ have an LCD display connected.
+
+config VIDEO_DSI_TEGRA30
+ bool "Enable Tegra 30 DSI support"
+ depends on PANEL && DM_GPIO
+ select VIDEO_TEGRA20
+ select VIDEO_MIPI_DSI
+ help
+ T30 has native support for DSI panels. This option enables support
+ for such panels which can be used on endeavoru and tf600t.
+
+config TEGRA_BACKLIGHT_PWM
+ bool "Enable Tegra DC PWM backlight support"
+ depends on BACKLIGHT
+ select VIDEO_TEGRA20
+ help
+ Tegra DC dependent backlight.
diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile
new file mode 100644
index 00000000000..f0b534c5794
--- /dev/null
+++ b/drivers/video/tegra20/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o
+obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o mipi-phy.o
+obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += tegra-pwm-backlight.o
diff --git a/drivers/video/tegra20/mipi-phy.c b/drivers/video/tegra20/mipi-phy.c
new file mode 100644
index 00000000000..c3ebc4074b5
--- /dev/null
+++ b/drivers/video/tegra20/mipi-phy.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ */
+
+#include <common.h>
+#include <linux/err.h>
+
+#include "mipi-phy.h"
+
+/*
+ * Default D-PHY timings based on MIPI D-PHY specification. Derived from the
+ * valid ranges specified in Section 6.9, Table 14, Page 40 of the D-PHY
+ * specification (v1.2) with minor adjustments.
+ */
+int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
+ unsigned long period)
+{
+ timing->clkmiss = 0;
+ timing->clkpost = 70 + 52 * period;
+ timing->clkpre = 8;
+ timing->clkprepare = 65;
+ timing->clksettle = 95;
+ timing->clktermen = 0;
+ timing->clktrail = 80;
+ timing->clkzero = 260;
+ timing->dtermen = 0;
+ timing->eot = 0;
+ timing->hsexit = 120;
+ timing->hsprepare = 65 + 5 * period;
+ timing->hszero = 145 + 5 * period;
+ timing->hssettle = 85 + 6 * period;
+ timing->hsskip = 40;
+
+ /*
+ * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40)
+ * contains this formula as:
+ *
+ * T_HS-TRAIL = max(n * 8 * period, 60 + n * 4 * period)
+ *
+ * where n = 1 for forward-direction HS mode and n = 4 for reverse-
+ * direction HS mode. There's only one setting and this function does
+ * not parameterize on anything other that period, so this code will
+ * assumes that reverse-direction HS mode is supported and uses n = 4.
+ */
+ timing->hstrail = max(4 * 8 * period, 60 + 4 * 4 * period);
+
+ timing->init = 100000;
+ timing->lpx = 60;
+ timing->taget = 5 * timing->lpx;
+ timing->tago = 4 * timing->lpx;
+ timing->tasure = 2 * timing->lpx;
+ timing->wakeup = 1000000;
+
+ return 0;
+}
+
+/*
+ * Validate D-PHY timing according to MIPI D-PHY specification
+ * (v1.2, Section 6.9 "Global Operation Timing Parameters").
+ */
+int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
+ unsigned long period)
+{
+ if (timing->clkmiss > 60)
+ return -EINVAL;
+
+ if (timing->clkpost < (60 + 52 * period))
+ return -EINVAL;
+
+ if (timing->clkpre < 8)
+ return -EINVAL;
+
+ if (timing->clkprepare < 38 || timing->clkprepare > 95)
+ return -EINVAL;
+
+ if (timing->clksettle < 95 || timing->clksettle > 300)
+ return -EINVAL;
+
+ if (timing->clktermen > 38)
+ return -EINVAL;
+
+ if (timing->clktrail < 60)
+ return -EINVAL;
+
+ if (timing->clkprepare + timing->clkzero < 300)
+ return -EINVAL;
+
+ if (timing->dtermen > 35 + 4 * period)
+ return -EINVAL;
+
+ if (timing->eot > 105 + 12 * period)
+ return -EINVAL;
+
+ if (timing->hsexit < 100)
+ return -EINVAL;
+
+ if (timing->hsprepare < 40 + 4 * period ||
+ timing->hsprepare > 85 + 6 * period)
+ return -EINVAL;
+
+ if (timing->hsprepare + timing->hszero < 145 + 10 * period)
+ return -EINVAL;
+
+ if ((timing->hssettle < 85 + 6 * period) ||
+ (timing->hssettle > 145 + 10 * period))
+ return -EINVAL;
+
+ if (timing->hsskip < 40 || timing->hsskip > 55 + 4 * period)
+ return -EINVAL;
+
+ if (timing->hstrail < max(8 * period, 60 + 4 * period))
+ return -EINVAL;
+
+ if (timing->init < 100000)
+ return -EINVAL;
+
+ if (timing->lpx < 50)
+ return -EINVAL;
+
+ if (timing->taget != 5 * timing->lpx)
+ return -EINVAL;
+
+ if (timing->tago != 4 * timing->lpx)
+ return -EINVAL;
+
+ if (timing->tasure < timing->lpx || timing->tasure > 2 * timing->lpx)
+ return -EINVAL;
+
+ if (timing->wakeup < 1000000)
+ return -EINVAL;
+
+ return 0;
+}
diff --git a/drivers/video/tegra20/mipi-phy.h b/drivers/video/tegra20/mipi-phy.h
new file mode 100644
index 00000000000..41889a75035
--- /dev/null
+++ b/drivers/video/tegra20/mipi-phy.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ */
+
+#ifndef DRM_TEGRA_MIPI_PHY_H
+#define DRM_TEGRA_MIPI_PHY_H
+
+/*
+ * D-PHY timing parameters
+ *
+ * A detailed description of these parameters can be found in the MIPI
+ * Alliance Specification for D-PHY, Section 5.9 "Global Operation Timing
+ * Parameters".
+ *
+ * All parameters are specified in nanoseconds.
+ */
+struct mipi_dphy_timing {
+ unsigned int clkmiss;
+ unsigned int clkpost;
+ unsigned int clkpre;
+ unsigned int clkprepare;
+ unsigned int clksettle;
+ unsigned int clktermen;
+ unsigned int clktrail;
+ unsigned int clkzero;
+ unsigned int dtermen;
+ unsigned int eot;
+ unsigned int hsexit;
+ unsigned int hsprepare;
+ unsigned int hszero;
+ unsigned int hssettle;
+ unsigned int hsskip;
+ unsigned int hstrail;
+ unsigned int init;
+ unsigned int lpx;
+ unsigned int taget;
+ unsigned int tago;
+ unsigned int tasure;
+ unsigned int wakeup;
+};
+
+int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
+ unsigned long period);
+int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
+ unsigned long period);
+
+#endif
diff --git a/drivers/video/tegra.c b/drivers/video/tegra20/tegra-dc.c
index 3f9fcd04036..f53ad463970 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra20/tegra-dc.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <backlight.h>
#include <dm.h>
#include <fdtdec.h>
#include <log.h>
@@ -33,20 +34,24 @@ struct tegra_lcd_priv {
enum video_log2_bpp log2_bpp; /* colour depth */
struct display_timing timing;
struct udevice *panel;
- struct disp_ctlr *disp; /* Display controller to use */
+ struct dc_ctlr *dc; /* Display controller regmap */
fdt_addr_t frame_buffer; /* Address of frame buffer */
unsigned pixel_clock; /* Pixel clock in Hz */
+ int dc_clk[2]; /* Contains clk and its parent */
+ bool rotation; /* 180 degree panel turn */
};
enum {
/* Maximum LCD size we support */
- LCD_MAX_WIDTH = 1366,
- LCD_MAX_HEIGHT = 768,
+ LCD_MAX_WIDTH = 1920,
+ LCD_MAX_HEIGHT = 1200,
LCD_MAX_LOG2_BPP = VIDEO_BPP16,
};
-static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win)
+static void update_window(struct tegra_lcd_priv *priv,
+ struct disp_ctl_win *win)
{
+ struct dc_ctlr *dc = priv->dc;
unsigned h_dda, v_dda;
unsigned long val;
@@ -87,6 +92,10 @@ static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win)
val = WIN_ENABLE;
if (win->bpp < 24)
val |= COLOR_EXPAND;
+
+ if (priv->rotation)
+ val |= H_DIRECTION | V_DIRECTION;
+
writel(val, &dc->win.win_opt);
writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr);
@@ -134,7 +143,7 @@ static int update_display_mode(struct dc_disp_reg *disp,
* the display clock (typically 600MHz) to the pixel clock. We round
* up or down as requried.
*/
- rate = clock_get_periph_rate(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL);
+ rate = clock_get_periph_rate(priv->dc_clk[0], priv->dc_clk[1]);
div = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2;
debug("Display clock %lu, divider %lu\n", rate, div);
@@ -223,8 +232,14 @@ static void rgb_enable(struct dc_com_reg *com)
static int setup_window(struct disp_ctl_win *win,
struct tegra_lcd_priv *priv)
{
- win->x = 0;
- win->y = 0;
+ if (priv->rotation) {
+ win->x = priv->width * 2;
+ win->y = priv->height;
+ } else {
+ win->x = 0;
+ win->y = 0;
+ }
+
win->w = priv->width;
win->h = priv->height;
win->out_x = 0;
@@ -268,32 +283,36 @@ static int tegra_display_probe(const void *blob, struct tegra_lcd_priv *priv,
void *default_lcd_base)
{
struct disp_ctl_win window;
- struct dc_ctlr *dc;
+ unsigned long rate = clock_get_rate(priv->dc_clk[1]);
priv->frame_buffer = (u32)default_lcd_base;
- dc = (struct dc_ctlr *)priv->disp;
+ /*
+ * We halve the rate if DISP1 paret is PLLD, since actual parent
+ * is plld_out0 which is PLLD divided by 2.
+ */
+ if (priv->dc_clk[1] == CLOCK_ID_DISPLAY)
+ rate /= 2;
/*
- * A header file for clock constants was NAKed upstream.
- * TODO: Put this into the FDT and fdt_lcd struct when we have clock
- * support there
+ * HOST1X is init by default at 150MHz with PLLC as parent
*/
- clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH,
- 144 * 1000000);
- clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL,
- 600 * 1000000);
- basic_init(&dc->cmd);
- basic_init_timer(&dc->disp);
- rgb_enable(&dc->com);
+ clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL,
+ 150 * 1000000);
+ clock_start_periph_pll(priv->dc_clk[0], priv->dc_clk[1],
+ rate);
+
+ basic_init(&priv->dc->cmd);
+ basic_init_timer(&priv->dc->disp);
+ rgb_enable(&priv->dc->com);
if (priv->pixel_clock)
- update_display_mode(&dc->disp, priv);
+ update_display_mode(&priv->dc->disp, priv);
if (setup_window(&window, priv))
return -1;
- update_window(dc, &window);
+ update_window(priv, &window);
return 0;
}
@@ -307,14 +326,19 @@ static int tegra_lcd_probe(struct udevice *dev)
int ret;
/* Initialize the Tegra display controller */
+#ifdef CONFIG_TEGRA20
funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT);
+#endif
+
if (tegra_display_probe(blob, priv, (void *)plat->base)) {
printf("%s: Failed to probe display driver\n", __func__);
return -1;
}
+#ifdef CONFIG_TEGRA20
pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM);
pinmux_tristate_disable(PMUX_PINGRP_GPU);
+#endif
ret = panel_enable_backlight(priv->panel);
if (ret) {
@@ -322,6 +346,12 @@ static int tegra_lcd_probe(struct udevice *dev)
return ret;
}
+ ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT);
+ if (ret) {
+ debug("%s: Cannot set backlight to default, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size,
DCACHE_WRITETHROUGH);
@@ -347,12 +377,21 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
int rgb;
int ret;
- priv->disp = dev_read_addr_ptr(dev);
- if (!priv->disp) {
+ priv->dc = (struct dc_ctlr *)dev_read_addr_ptr(dev);
+ if (!priv->dc) {
debug("%s: No display controller address\n", __func__);
return -EINVAL;
}
+ ret = clock_decode_pair(dev, priv->dc_clk);
+ if (ret < 0) {
+ debug("%s: Cannot decode clocks for '%s' (ret = %d)\n",
+ __func__, dev->name, ret);
+ return -EINVAL;
+ }
+
+ priv->rotation = dev_read_bool(dev, "nvidia,180-rotation");
+
rgb = fdt_subnode_offset(blob, node, "rgb");
if (rgb < 0) {
debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n",
@@ -360,18 +399,6 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
return -EINVAL;
}
- ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing);
- if (ret) {
- debug("%s: Cannot read display timing for '%s' (ret=%d)\n",
- __func__, dev->name, ret);
- return -EINVAL;
- }
- timing = &priv->timing;
- priv->width = timing->hactive.typ;
- priv->height = timing->vactive.typ;
- priv->pixel_clock = timing->pixelclock.typ;
- priv->log2_bpp = VIDEO_BPP16;
-
/*
* Sadly the panel phandle is in an rgb subnode so we cannot use
* uclass_get_device_by_phandle().
@@ -381,6 +408,7 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
debug("%s: Cannot find panel information\n", __func__);
return -EINVAL;
}
+
ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node,
&priv->panel);
if (ret) {
@@ -389,6 +417,30 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
return ret;
}
+ if (!strcmp(priv->panel->name, TEGRA_DSI_A) ||
+ !strcmp(priv->panel->name, TEGRA_DSI_B)) {
+ struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel);
+
+ dc_plat->dev = dev;
+ dc_plat->dc = priv->dc;
+ }
+
+ ret = panel_get_display_timing(priv->panel, &priv->timing);
+ if (ret) {
+ ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing);
+ if (ret) {
+ debug("%s: Cannot read display timing for '%s' (ret=%d)\n",
+ __func__, dev->name, ret);
+ return -EINVAL;
+ }
+ }
+
+ timing = &priv->timing;
+ priv->width = timing->hactive.typ;
+ priv->height = timing->vactive.typ;
+ priv->pixel_clock = timing->pixelclock.typ;
+ priv->log2_bpp = VIDEO_BPP16;
+
return 0;
}
@@ -414,6 +466,7 @@ static const struct video_ops tegra_lcd_ops = {
static const struct udevice_id tegra_lcd_ids[] = {
{ .compatible = "nvidia,tegra20-dc" },
+ { .compatible = "nvidia,tegra30-dc" },
{ }
};
diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c
new file mode 100644
index 00000000000..8c3404e085d
--- /dev/null
+++ b/drivers/video/tegra20/tegra-dsi.c
@@ -0,0 +1,864 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <backlight.h>
+#include <panel.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/display.h>
+#include <asm/arch-tegra30/dsi.h>
+
+#include "mipi-phy.h"
+
+#define USEC_PER_SEC 1000000L
+#define NSEC_PER_SEC 1000000000L
+
+struct tegra_dsi_priv {
+ struct mipi_dsi_host host;
+ struct mipi_dsi_device device;
+ struct mipi_dphy_timing dphy_timing;
+
+ struct udevice *panel;
+ struct display_timing timing;
+
+ struct dsi_ctlr *dsi;
+ struct udevice *avdd;
+
+ enum tegra_dsi_format format;
+
+ int dsi_clk;
+ int video_fifo_depth;
+ int host_fifo_depth;
+};
+
+static void tegra_dc_enable_controller(struct udevice *dev)
+{
+ struct tegra_dc_plat *dc_plat = dev_get_plat(dev);
+ struct dc_ctlr *dc = dc_plat->dc;
+ u32 value;
+
+ value = readl(&dc->disp.disp_win_opt);
+ value |= DSI_ENABLE;
+ writel(value, &dc->disp.disp_win_opt);
+
+ writel(GENERAL_UPDATE, &dc->cmd.state_ctrl);
+ writel(GENERAL_ACT_REQ, &dc->cmd.state_ctrl);
+}
+
+static const char * const error_report[16] = {
+ "SoT Error",
+ "SoT Sync Error",
+ "EoT Sync Error",
+ "Escape Mode Entry Command Error",
+ "Low-Power Transmit Sync Error",
+ "Peripheral Timeout Error",
+ "False Control Error",
+ "Contention Detected",
+ "ECC Error, single-bit",
+ "ECC Error, multi-bit",
+ "Checksum Error",
+ "DSI Data Type Not Recognized",
+ "DSI VC ID Invalid",
+ "Invalid Transmission Length",
+ "Reserved",
+ "DSI Protocol Violation",
+};
+
+static ssize_t tegra_dsi_read_response(struct dsi_misc_reg *misc,
+ const struct mipi_dsi_msg *msg,
+ size_t count)
+{
+ u8 *rx = msg->rx_buf;
+ unsigned int i, j, k;
+ size_t size = 0;
+ u16 errors;
+ u32 value;
+
+ /* read and parse packet header */
+ value = readl(&misc->dsi_rd_data);
+
+ switch (value & 0x3f) {
+ case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+ errors = (value >> 8) & 0xffff;
+ printf("%s: Acknowledge and error report: %04x\n",
+ __func__, errors);
+ for (i = 0; i < ARRAY_SIZE(error_report); i++)
+ if (errors & BIT(i))
+ printf("%s: %2u: %s\n", __func__, i,
+ error_report[i]);
+ break;
+
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+ rx[0] = (value >> 8) & 0xff;
+ size = 1;
+ break;
+
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+ rx[0] = (value >> 8) & 0xff;
+ rx[1] = (value >> 16) & 0xff;
+ size = 2;
+ break;
+
+ case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
+ size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
+ break;
+
+ case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
+ size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
+ break;
+
+ default:
+ printf("%s: unhandled response type: %02x\n",
+ __func__, value & 0x3f);
+ return -EPROTO;
+ }
+
+ size = min(size, msg->rx_len);
+
+ if (msg->rx_buf && size > 0) {
+ for (i = 0, j = 0; i < count - 1; i++, j += 4) {
+ u8 *rx = msg->rx_buf + j;
+
+ value = readl(&misc->dsi_rd_data);
+
+ for (k = 0; k < 4 && (j + k) < msg->rx_len; k++)
+ rx[j + k] = (value >> (k << 3)) & 0xff;
+ }
+ }
+
+ return size;
+}
+
+static int tegra_dsi_transmit(struct dsi_misc_reg *misc,
+ unsigned long timeout)
+{
+ writel(DSI_TRIGGER_HOST, &misc->dsi_trigger);
+
+ while (timeout--) {
+ u32 value = readl(&misc->dsi_trigger);
+
+ if ((value & DSI_TRIGGER_HOST) == 0)
+ return 0;
+
+ udelay(1000);
+ }
+
+ debug("timeout waiting for transmission to complete\n");
+ return -ETIMEDOUT;
+}
+
+static int tegra_dsi_wait_for_response(struct dsi_misc_reg *misc,
+ unsigned long timeout)
+{
+ while (timeout--) {
+ u32 value = readl(&misc->dsi_status);
+ u8 count = value & 0x1f;
+
+ if (count > 0)
+ return count;
+
+ udelay(1000);
+ }
+
+ debug("peripheral returned no data\n");
+ return -ETIMEDOUT;
+}
+
+static void tegra_dsi_writesl(struct dsi_misc_reg *misc,
+ const void *buffer, size_t size)
+{
+ const u8 *buf = buffer;
+ size_t i, j;
+ u32 value;
+
+ for (j = 0; j < size; j += 4) {
+ value = 0;
+
+ for (i = 0; i < 4 && j + i < size; i++)
+ value |= buf[j + i] << (i << 3);
+
+ writel(value, &misc->dsi_wr_data);
+ }
+}
+
+static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct udevice *dev = (struct udevice *)host->dev;
+ struct tegra_dsi_priv *priv = dev_get_priv(dev);
+ struct dsi_misc_reg *misc = &priv->dsi->misc;
+ struct mipi_dsi_packet packet;
+ const u8 *header;
+ size_t count;
+ ssize_t err;
+ u32 value;
+
+ err = mipi_dsi_create_packet(&packet, msg);
+ if (err < 0)
+ return err;
+
+ header = packet.header;
+
+ /* maximum FIFO depth is 1920 words */
+ if (packet.size > priv->video_fifo_depth * 4)
+ return -ENOSPC;
+
+ /* reset underflow/overflow flags */
+ value = readl(&misc->dsi_status);
+ if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) {
+ value = DSI_HOST_CONTROL_FIFO_RESET;
+ writel(value, &misc->host_dsi_ctrl);
+ udelay(10);
+ }
+
+ value = readl(&misc->dsi_pwr_ctrl);
+ value |= DSI_POWER_CONTROL_ENABLE;
+ writel(value, &misc->dsi_pwr_ctrl);
+
+ mdelay(5);
+
+ value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST |
+ DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
+
+ /*
+ * The host FIFO has a maximum of 64 words, so larger transmissions
+ * need to use the video FIFO.
+ */
+ if (packet.size > priv->host_fifo_depth * 4)
+ value |= DSI_HOST_CONTROL_FIFO_SEL;
+
+ writel(value, &misc->host_dsi_ctrl);
+
+ /*
+ * For reads and messages with explicitly requested ACK, generate a
+ * BTA sequence after the transmission of the packet.
+ */
+ if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
+ (msg->rx_buf && msg->rx_len > 0)) {
+ value = readl(&misc->host_dsi_ctrl);
+ value |= DSI_HOST_CONTROL_PKT_BTA;
+ writel(value, &misc->host_dsi_ctrl);
+ }
+
+ value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE;
+ writel(value, &misc->dsi_ctrl);
+
+ /* write packet header, ECC is generated by hardware */
+ value = header[2] << 16 | header[1] << 8 | header[0];
+ writel(value, &misc->dsi_wr_data);
+
+ /* write payload (if any) */
+ if (packet.payload_length > 0)
+ tegra_dsi_writesl(misc, packet.payload,
+ packet.payload_length);
+
+ err = tegra_dsi_transmit(misc, 250);
+ if (err < 0)
+ return err;
+
+ if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
+ (msg->rx_buf && msg->rx_len > 0)) {
+ err = tegra_dsi_wait_for_response(misc, 250);
+ if (err < 0)
+ return err;
+
+ count = err;
+
+ value = readl(&misc->dsi_rd_data);
+ switch (value) {
+ case 0x84:
+ debug("%s: ACK\n", __func__);
+ break;
+
+ case 0x87:
+ debug("%s: ESCAPE\n", __func__);
+ break;
+
+ default:
+ printf("%s: unknown status: %08x\n", __func__, value);
+ break;
+ }
+
+ if (count > 1) {
+ err = tegra_dsi_read_response(misc, msg, count);
+ if (err < 0) {
+ printf("%s: failed to parse response: %zd\n",
+ __func__, err);
+ } else {
+ /*
+ * For read commands, return the number of
+ * bytes returned by the peripheral.
+ */
+ count = err;
+ }
+ }
+ } else {
+ /*
+ * For write commands, we have transmitted the 4-byte header
+ * plus the variable-length payload.
+ */
+ count = 4 + packet.payload_length;
+ }
+
+ return count;
+}
+
+struct mipi_dsi_host_ops tegra_dsi_bridge_host_ops = {
+ .transfer = tegra_dsi_host_transfer,
+};
+
+#define PKT_ID0(id) ((((id) & 0x3f) << 3) | (1 << 9))
+#define PKT_LEN0(len) (((len) & 0x07) << 0)
+#define PKT_ID1(id) ((((id) & 0x3f) << 13) | (1 << 19))
+#define PKT_LEN1(len) (((len) & 0x07) << 10)
+#define PKT_ID2(id) ((((id) & 0x3f) << 23) | (1 << 29))
+#define PKT_LEN2(len) (((len) & 0x07) << 20)
+
+#define PKT_LP BIT(30)
+#define NUM_PKT_SEQ 12
+
+/*
+ * non-burst mode with sync pulses
+ */
+static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = {
+ [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+ PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+ PKT_LP,
+ [ 1] = 0,
+ [ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+ PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+ PKT_LP,
+ [ 3] = 0,
+ [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+ PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+ PKT_LP,
+ [ 5] = 0,
+ [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+ PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
+ [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
+ PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
+ PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
+ [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+ PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
+ PKT_LP,
+ [ 9] = 0,
+ [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
+ PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
+ [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
+ PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
+ PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
+};
+
+/*
+ * non-burst mode with sync events
+ */
+static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
+ [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
+ PKT_LP,
+ [ 1] = 0,
+ [ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
+ PKT_LP,
+ [ 3] = 0,
+ [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
+ PKT_LP,
+ [ 5] = 0,
+ [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
+ PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
+ [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
+ [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
+ PKT_LP,
+ [ 9] = 0,
+ [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
+ PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
+ PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
+ [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
+};
+
+static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = {
+ [ 0] = 0,
+ [ 1] = 0,
+ [ 2] = 0,
+ [ 3] = 0,
+ [ 4] = 0,
+ [ 5] = 0,
+ [ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP,
+ [ 7] = 0,
+ [ 8] = 0,
+ [ 9] = 0,
+ [10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP,
+ [11] = 0,
+};
+
+static void tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format,
+ unsigned int *mulp, unsigned int *divp)
+{
+ switch (format) {
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ case MIPI_DSI_FMT_RGB888:
+ *mulp = 3;
+ *divp = 1;
+ break;
+
+ case MIPI_DSI_FMT_RGB565:
+ *mulp = 2;
+ *divp = 1;
+ break;
+
+ case MIPI_DSI_FMT_RGB666:
+ *mulp = 9;
+ *divp = 4;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format,
+ enum tegra_dsi_format *fmt)
+{
+ switch (format) {
+ case MIPI_DSI_FMT_RGB888:
+ *fmt = TEGRA_DSI_FORMAT_24P;
+ break;
+
+ case MIPI_DSI_FMT_RGB666:
+ *fmt = TEGRA_DSI_FORMAT_18NP;
+ break;
+
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ *fmt = TEGRA_DSI_FORMAT_18P;
+ break;
+
+ case MIPI_DSI_FMT_RGB565:
+ *fmt = TEGRA_DSI_FORMAT_16P;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad)
+{
+ u32 value;
+
+ /* start calibration */
+ value = DSI_PAD_CONTROL_PAD_LPUPADJ(0x1) |
+ DSI_PAD_CONTROL_PAD_LPDNADJ(0x1) |
+ DSI_PAD_CONTROL_PAD_PREEMP_EN(0x1) |
+ DSI_PAD_CONTROL_PAD_SLEWDNADJ(0x6) |
+ DSI_PAD_CONTROL_PAD_SLEWUPADJ(0x6) |
+ DSI_PAD_CONTROL_PAD_PDIO(0) |
+ DSI_PAD_CONTROL_PAD_PDIO_CLK(0) |
+ DSI_PAD_CONTROL_PAD_PULLDN_ENAB(0);
+ writel(value, &pad->pad_ctrl);
+
+ clock_enable(PERIPH_ID_VI);
+ clock_enable(PERIPH_ID_CSI);
+ udelay(2);
+ reset_set_enable(PERIPH_ID_VI, 0);
+ reset_set_enable(PERIPH_ID_CSI, 0);
+
+ value = MIPI_CAL_TERMOSA(0x4);
+ writel(value, TEGRA_VI_BASE + (CSI_CILA_MIPI_CAL_CONFIG_0 << 2));
+
+ value = MIPI_CAL_TERMOSB(0x4);
+ writel(value, TEGRA_VI_BASE + (CSI_CILB_MIPI_CAL_CONFIG_0 << 2));
+
+ value = MIPI_CAL_HSPUOSD(0x3) | MIPI_CAL_HSPDOSD(0x4);
+ writel(value, TEGRA_VI_BASE + (CSI_DSI_MIPI_CAL_CONFIG << 2));
+
+ value = PAD_DRIV_DN_REF(0x5) | PAD_DRIV_UP_REF(0x7);
+ writel(value, TEGRA_VI_BASE + (CSI_MIPIBIAS_PAD_CONFIG << 2));
+
+ value = PAD_CIL_PDVREG(0x0);
+ writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2));
+}
+
+static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout,
+ unsigned long bclk,
+ unsigned int vrefresh)
+{
+ unsigned int timeout;
+ u32 value;
+
+ /* one frame high-speed transmission timeout */
+ timeout = (bclk / vrefresh) / 512;
+ value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
+ writel(value, &rtimeout->dsi_timeout_0);
+
+ /* 2 ms peripheral timeout for panel */
+ timeout = 2 * bclk / 512 * 1000;
+ value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
+ writel(value, &rtimeout->dsi_timeout_1);
+
+ value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
+ writel(value, &rtimeout->dsi_to_tally);
+}
+
+static void tegra_dsi_set_phy_timing(struct dsi_timing_reg *ptiming,
+ unsigned long period,
+ const struct mipi_dphy_timing *dphy_timing)
+{
+ u32 value;
+
+ value = DSI_TIMING_FIELD(dphy_timing->hsexit, period, 1) << 24 |
+ DSI_TIMING_FIELD(dphy_timing->hstrail, period, 0) << 16 |
+ DSI_TIMING_FIELD(dphy_timing->hszero, period, 3) << 8 |
+ DSI_TIMING_FIELD(dphy_timing->hsprepare, period, 1);
+ writel(value, &ptiming->dsi_phy_timing_0);
+
+ value = DSI_TIMING_FIELD(dphy_timing->clktrail, period, 1) << 24 |
+ DSI_TIMING_FIELD(dphy_timing->clkpost, period, 1) << 16 |
+ DSI_TIMING_FIELD(dphy_timing->clkzero, period, 1) << 8 |
+ DSI_TIMING_FIELD(dphy_timing->lpx, period, 1);
+ writel(value, &ptiming->dsi_phy_timing_1);
+
+ value = DSI_TIMING_FIELD(dphy_timing->clkprepare, period, 1) << 16 |
+ DSI_TIMING_FIELD(dphy_timing->clkpre, period, 1) << 8 |
+ DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
+ writel(value, &ptiming->dsi_phy_timing_2);
+
+ value = DSI_TIMING_FIELD(dphy_timing->taget, period, 1) << 16 |
+ DSI_TIMING_FIELD(dphy_timing->tasure, period, 1) << 8 |
+ DSI_TIMING_FIELD(dphy_timing->tago, period, 1);
+ writel(value, &ptiming->dsi_bta_timing);
+}
+
+static void tegra_dsi_configure(struct udevice *dev,
+ unsigned long mode_flags)
+{
+ struct tegra_dsi_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct display_timing *timing = &priv->timing;
+
+ struct dsi_misc_reg *misc = &priv->dsi->misc;
+ struct dsi_pkt_seq_reg *pkt = &priv->dsi->pkt;
+ struct dsi_pkt_len_reg *len = &priv->dsi->len;
+
+ unsigned int hact, hsw, hbp, hfp, i, mul, div;
+ const u32 *pkt_seq;
+ u32 value;
+
+ tegra_dsi_get_muldiv(device->format, &mul, &div);
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
+ printf("[DSI] Non-burst video mode with sync pulses\n");
+ pkt_seq = pkt_seq_video_non_burst_sync_pulses;
+ } else if (mode_flags & MIPI_DSI_MODE_VIDEO) {
+ printf("[DSI] Non-burst video mode with sync events\n");
+ pkt_seq = pkt_seq_video_non_burst_sync_events;
+ } else {
+ printf("[DSI] Command mode\n");
+ pkt_seq = pkt_seq_command_mode;
+ }
+
+ value = DSI_CONTROL_CHANNEL(0) |
+ DSI_CONTROL_FORMAT(priv->format) |
+ DSI_CONTROL_LANES(device->lanes - 1) |
+ DSI_CONTROL_SOURCE(0);
+ writel(value, &misc->dsi_ctrl);
+
+ writel(priv->video_fifo_depth, &misc->dsi_max_threshold);
+
+ value = DSI_HOST_CONTROL_HS;
+ writel(value, &misc->host_dsi_ctrl);
+
+ value = readl(&misc->dsi_ctrl);
+
+ if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+ value |= DSI_CONTROL_HS_CLK_CTRL;
+
+ value &= ~DSI_CONTROL_TX_TRIG(3);
+
+ /* enable DCS commands for command mode */
+ if (mode_flags & MIPI_DSI_MODE_VIDEO)
+ value &= ~DSI_CONTROL_DCS_ENABLE;
+ else
+ value |= DSI_CONTROL_DCS_ENABLE;
+
+ value |= DSI_CONTROL_VIDEO_ENABLE;
+ value &= ~DSI_CONTROL_HOST_ENABLE;
+ writel(value, &misc->dsi_ctrl);
+
+ for (i = 0; i < NUM_PKT_SEQ; i++)
+ writel(pkt_seq[i], &pkt->dsi_pkt_seq_0_lo + i);
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO) {
+ /* horizontal active pixels */
+ hact = timing->hactive.typ * mul / div;
+
+ /* horizontal sync width */
+ hsw = timing->hsync_len.typ * mul / div;
+
+ /* horizontal back porch */
+ hbp = timing->hback_porch.typ * mul / div;
+
+ if ((mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0)
+ hbp += hsw;
+
+ /* horizontal front porch */
+ hfp = timing->hfront_porch.typ * mul / div;
+
+ /* subtract packet overhead */
+ hsw -= 10;
+ hbp -= 14;
+ hfp -= 8;
+
+ writel(hsw << 16 | 0, &len->dsi_pkt_len_0_1);
+ writel(hact << 16 | hbp, &len->dsi_pkt_len_2_3);
+ writel(hfp, &len->dsi_pkt_len_4_5);
+ writel(0x0f0f << 16, &len->dsi_pkt_len_6_7);
+ } else {
+ /* 1 byte (DCS command) + pixel data */
+ value = 1 + timing->hactive.typ * mul / div;
+
+ writel(0, &len->dsi_pkt_len_0_1);
+ writel(value << 16, &len->dsi_pkt_len_2_3);
+ writel(value << 16, &len->dsi_pkt_len_4_5);
+ writel(0, &len->dsi_pkt_len_6_7);
+
+ value = MIPI_DCS_WRITE_MEMORY_START << 8 |
+ MIPI_DCS_WRITE_MEMORY_CONTINUE;
+ writel(value, &len->dsi_dcs_cmds);
+ }
+
+ /* set SOL delay (for non-burst mode only) */
+ writel(8 * mul / div, &misc->dsi_sol_delay);
+}
+
+static int tegra_dsi_encoder_enable(struct udevice *dev)
+{
+ struct tegra_dsi_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct display_timing *timing = &priv->timing;
+ struct dsi_misc_reg *misc = &priv->dsi->misc;
+ unsigned int mul, div;
+ unsigned long bclk, plld, period;
+ u32 value;
+ int ret;
+
+ /* Disable interrupt */
+ writel(0, &misc->int_enable);
+
+ tegra_dsi_pad_calibrate(&priv->dsi->pad);
+
+ tegra_dsi_get_muldiv(device->format, &mul, &div);
+
+ /* compute byte clock */
+ bclk = (timing->pixelclock.typ * mul) / (div * device->lanes);
+
+ tegra_dsi_set_timeout(&priv->dsi->timeout, bclk, 60);
+
+ /*
+ * Compute bit clock and round up to the next MHz.
+ */
+ plld = DIV_ROUND_UP(bclk * 8, USEC_PER_SEC) * USEC_PER_SEC;
+ period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, plld);
+
+ ret = mipi_dphy_timing_get_default(&priv->dphy_timing, period);
+ if (ret < 0) {
+ printf("%s: failed to get D-PHY timing: %d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = mipi_dphy_timing_validate(&priv->dphy_timing, period);
+ if (ret < 0) {
+ printf("%s: failed to validate D-PHY timing: %d\n", __func__, ret);
+ return ret;
+ }
+
+ /*
+ * The D-PHY timing fields are expressed in byte-clock cycles, so
+ * multiply the period by 8.
+ */
+ tegra_dsi_set_phy_timing(&priv->dsi->ptiming,
+ period * 8, &priv->dphy_timing);
+
+ /* Perform panel HW setup */
+ ret = panel_enable_backlight(priv->panel);
+ if (ret)
+ return ret;
+
+ tegra_dsi_configure(dev, 0);
+
+ ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT);
+ if (ret)
+ return ret;
+
+ tegra_dsi_configure(dev, device->mode_flags);
+
+ tegra_dc_enable_controller(dev);
+
+ /* enable DSI controller */
+ value = readl(&misc->dsi_pwr_ctrl);
+ value |= DSI_POWER_CONTROL_ENABLE;
+ writel(value, &misc->dsi_pwr_ctrl);
+
+ return 0;
+}
+
+static int tegra_dsi_bridge_set_panel(struct udevice *dev, int percent)
+{
+ /* Is not used in tegra dc */
+ return 0;
+}
+
+static int tegra_dsi_panel_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ struct tegra_dsi_priv *priv = dev_get_priv(dev);
+
+ memcpy(timing, &priv->timing, sizeof(*timing));
+
+ return 0;
+}
+
+static void tegra_dsi_init_clocks(struct udevice *dev)
+{
+ struct tegra_dsi_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ unsigned int mul, div;
+ unsigned long bclk, plld;
+
+ tegra_dsi_get_muldiv(device->format, &mul, &div);
+
+ bclk = (priv->timing.pixelclock.typ * mul) /
+ (div * device->lanes);
+
+ plld = DIV_ROUND_UP(bclk * 8, USEC_PER_SEC);
+
+ switch (clock_get_osc_freq()) {
+ case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
+ case CLOCK_OSC_FREQ_48_0: /* OSC is 48Mhz */
+ clock_set_rate(CLOCK_ID_DISPLAY, plld, 12, 0, 8);
+ break;
+
+ case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
+ clock_set_rate(CLOCK_ID_DISPLAY, plld, 26, 0, 8);
+ break;
+
+ case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
+ case CLOCK_OSC_FREQ_16_8: /* OSC is 16.8Mhz */
+ clock_set_rate(CLOCK_ID_DISPLAY, plld, 13, 0, 8);
+ break;
+
+ case CLOCK_OSC_FREQ_19_2:
+ case CLOCK_OSC_FREQ_38_4:
+ default:
+ /*
+ * These are not supported.
+ */
+ break;
+ }
+
+ priv->dsi_clk = clock_decode_periph_id(dev);
+
+ clock_enable(priv->dsi_clk);
+ udelay(2);
+ reset_set_enable(priv->dsi_clk, 0);
+}
+
+static int tegra_dsi_bridge_probe(struct udevice *dev)
+{
+ struct tegra_dsi_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct mipi_dsi_panel_plat *mipi_plat;
+ int ret;
+
+ priv->dsi = (struct dsi_ctlr *)dev_read_addr_ptr(dev);
+ if (!priv->dsi) {
+ printf("%s: No display controller address\n", __func__);
+ return -EINVAL;
+ }
+
+ priv->video_fifo_depth = 480;
+ priv->host_fifo_depth = 64;
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "avdd-dsi-csi-supply", &priv->avdd);
+ if (ret)
+ debug("%s: Cannot get avdd-dsi-csi-supply: error %d\n",
+ __func__, ret);
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev,
+ "panel", &priv->panel);
+ if (ret) {
+ printf("%s: Cannot get panel: error %d\n", __func__, ret);
+ return log_ret(ret);
+ }
+
+ panel_get_display_timing(priv->panel, &priv->timing);
+
+ mipi_plat = dev_get_plat(priv->panel);
+ mipi_plat->device = device;
+
+ priv->host.dev = (struct device *)dev;
+ priv->host.ops = &tegra_dsi_bridge_host_ops;
+
+ device->host = &priv->host;
+ device->lanes = mipi_plat->lanes;
+ device->format = mipi_plat->format;
+ device->mode_flags = mipi_plat->mode_flags;
+
+ tegra_dsi_get_format(device->format, &priv->format);
+
+ if (priv->avdd) {
+ ret = regulator_set_enable(priv->avdd, true);
+ if (ret)
+ return ret;
+ }
+
+ tegra_dsi_init_clocks(dev);
+
+ return 0;
+}
+
+static const struct panel_ops tegra_dsi_bridge_ops = {
+ .enable_backlight = tegra_dsi_encoder_enable,
+ .set_backlight = tegra_dsi_bridge_set_panel,
+ .get_display_timing = tegra_dsi_panel_timings,
+};
+
+static const struct udevice_id tegra_dsi_bridge_ids[] = {
+ { .compatible = "nvidia,tegra30-dsi" },
+ { }
+};
+
+U_BOOT_DRIVER(tegra_dsi) = {
+ .name = "tegra_dsi",
+ .id = UCLASS_PANEL,
+ .of_match = tegra_dsi_bridge_ids,
+ .ops = &tegra_dsi_bridge_ops,
+ .probe = tegra_dsi_bridge_probe,
+ .plat_auto = sizeof(struct tegra_dc_plat),
+ .priv_auto = sizeof(struct tegra_dsi_priv),
+};
diff --git a/drivers/video/tegra20/tegra-pwm-backlight.c b/drivers/video/tegra20/tegra-pwm-backlight.c
new file mode 100644
index 00000000000..bb677daa8a1
--- /dev/null
+++ b/drivers/video/tegra20/tegra-pwm-backlight.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <[email protected]>
+ */
+
+#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT
+
+#include <backlight.h>
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/display.h>
+
+#define TEGRA_DISPLAY_A_BASE 0x54200000
+#define TEGRA_DISPLAY_B_BASE 0x54240000
+
+#define TEGRA_PWM_BL_MIN_BRIGHTNESS 0x10
+#define TEGRA_PWM_BL_MAX_BRIGHTNESS 0xFF
+
+#define TEGRA_PWM_BL_PERIOD 0xFF
+#define TEGRA_PWM_BL_CLK_DIV 0x14
+#define TEGRA_PWM_BL_CLK_SELECT 0x00
+
+#define PM_PERIOD_SHIFT 18
+#define PM_CLK_DIVIDER_SHIFT 4
+
+#define TEGRA_PWM_PM0 0
+#define TEGRA_PWM_PM1 1
+
+struct tegra_pwm_backlight_priv {
+ struct dc_ctlr *dc; /* Display controller regmap */
+
+ u32 pwm_source;
+ u32 period;
+ u32 clk_div;
+ u32 clk_select;
+ u32 dft_brightness;
+};
+
+static int tegra_pwm_backlight_set_brightness(struct udevice *dev, int percent)
+{
+ struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
+ struct dc_cmd_reg *cmd = &priv->dc->cmd;
+ struct dc_com_reg *com = &priv->dc->com;
+ unsigned int ctrl;
+ unsigned long out_sel;
+ unsigned long cmd_state;
+
+ if (percent == BACKLIGHT_DEFAULT)
+ percent = priv->dft_brightness;
+
+ if (percent < TEGRA_PWM_BL_MIN_BRIGHTNESS)
+ percent = TEGRA_PWM_BL_MIN_BRIGHTNESS;
+
+ if (percent > TEGRA_PWM_BL_MAX_BRIGHTNESS)
+ percent = TEGRA_PWM_BL_MAX_BRIGHTNESS;
+
+ ctrl = ((priv->period << PM_PERIOD_SHIFT) |
+ (priv->clk_div << PM_CLK_DIVIDER_SHIFT) |
+ priv->clk_select);
+
+ /* The new value should be effected immediately */
+ cmd_state = readl(&cmd->state_access);
+ writel((cmd_state | (1 << 2)), &cmd->state_access);
+
+ switch (priv->pwm_source) {
+ case TEGRA_PWM_PM0:
+ /* Select the LM0 on PM0 */
+ out_sel = readl(&com->pin_output_sel[5]);
+ out_sel &= ~(7 << 0);
+ out_sel |= (3 << 0);
+ writel(out_sel, &com->pin_output_sel[5]);
+ writel(ctrl, &com->pm0_ctrl);
+ writel(percent, &com->pm0_duty_cycle);
+ break;
+ case TEGRA_PWM_PM1:
+ /* Select the LM1 on PM1 */
+ out_sel = readl(&com->pin_output_sel[5]);
+ out_sel &= ~(7 << 4);
+ out_sel |= (3 << 4);
+ writel(out_sel, &com->pin_output_sel[5]);
+ writel(ctrl, &com->pm1_ctrl);
+ writel(percent, &com->pm1_duty_cycle);
+ break;
+ default:
+ break;
+ }
+
+ writel(cmd_state, &cmd->state_access);
+ return 0;
+}
+
+static int tegra_pwm_backlight_enable(struct udevice *dev)
+{
+ struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
+
+ return tegra_pwm_backlight_set_brightness(dev, priv->dft_brightness);
+}
+
+static int tegra_pwm_backlight_probe(struct udevice *dev)
+{
+ struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
+
+ if (dev_read_bool(dev, "nvidia,display-b-base"))
+ priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_B_BASE;
+ else
+ priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_A_BASE;
+
+ if (!priv->dc) {
+ log_err("no display controller address\n");
+ return -EINVAL;
+ }
+
+ priv->pwm_source =
+ dev_read_u32_default(dev, "nvidia,pwm-source",
+ TEGRA_PWM_PM0);
+ priv->period =
+ dev_read_u32_default(dev, "nvidia,period",
+ TEGRA_PWM_BL_PERIOD);
+ priv->clk_div =
+ dev_read_u32_default(dev, "nvidia,clock-div",
+ TEGRA_PWM_BL_CLK_DIV);
+ priv->clk_select =
+ dev_read_u32_default(dev, "nvidia,clock-select",
+ TEGRA_PWM_BL_CLK_SELECT);
+ priv->dft_brightness =
+ dev_read_u32_default(dev, "nvidia,default-brightness",
+ TEGRA_PWM_BL_MAX_BRIGHTNESS);
+
+ return 0;
+}
+
+static const struct backlight_ops tegra_pwm_backlight_ops = {
+ .enable = tegra_pwm_backlight_enable,
+ .set_brightness = tegra_pwm_backlight_set_brightness,
+};
+
+static const struct udevice_id tegra_pwm_backlight_ids[] = {
+ { .compatible = "nvidia,tegra-pwm-backlight" },
+ { }
+};
+
+U_BOOT_DRIVER(tegra_pwm_backlight) = {
+ .name = "tegra_pwm_backlight",
+ .id = UCLASS_PANEL_BACKLIGHT,
+ .of_match = tegra_pwm_backlight_ids,
+ .probe = tegra_pwm_backlight_probe,
+ .ops = &tegra_pwm_backlight_ops,
+ .priv_auto = sizeof(struct tegra_pwm_backlight_priv),
+};
diff --git a/drivers/video/tidss/Kconfig b/drivers/video/tidss/Kconfig
index 2a5e56ea4ee..95086f3a5d6 100644
--- a/drivers/video/tidss/Kconfig
+++ b/drivers/video/tidss/Kconfig
@@ -16,3 +16,9 @@ menuconfig VIDEO_TIDSS
DPI . This option enables these supports which can be used on
devices which have OLDI or HDMI display connected.
+config SPL_VIDEO_TIDSS
+ bool "Enable TIDSS video support in SPL Stage"
+ depends on SPL_VIDEO
+ help
+ This options enables tidss driver in SPL stage. If
+ you need to use tidss at SPL stage use this config.
diff --git a/drivers/video/tidss/Makefile b/drivers/video/tidss/Makefile
index f4f8c6c470a..a29cee2a414 100644
--- a/drivers/video/tidss/Makefile
+++ b/drivers/video/tidss/Makefile
@@ -9,4 +9,4 @@
# Author: Tomi Valkeinen <[email protected]>
-obj-${CONFIG_VIDEO_TIDSS} = tidss_drv.o
+obj-${CONFIG_$(SPL_)VIDEO_TIDSS} = tidss_drv.o
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 1225de23332..a21fde0e1d4 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -86,7 +86,7 @@ static void vidconsole_newline(struct udevice *dev)
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
- const int rows = CONFIG_CONSOLE_SCROLL_LINES;
+ const int rows = CONFIG_VAL(CONSOLE_SCROLL_LINES);
int i, ret;
priv->xcur_frac = priv->xstart_frac;
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index da89f431441..8396bdfb11e 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -132,7 +132,7 @@ int video_reserve(ulong *addrp)
/* Allocate space for PCI video devices in case there were not bound */
if (*addrp == gd->video_top)
- *addrp -= CONFIG_VIDEO_PCI_DEFAULT_FB_SIZE;
+ *addrp -= CONFIG_VAL(VIDEO_PCI_DEFAULT_FB_SIZE);
gd->video_bottom = *addrp;
gd->fb_base = *addrp;
@@ -149,7 +149,7 @@ int video_fill(struct udevice *dev, u32 colour)
switch (priv->bpix) {
case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
u16 *ppix = priv->fb;
u16 *end = priv->fb + priv->fb_size;
@@ -158,7 +158,7 @@ int video_fill(struct udevice *dev, u32 colour)
break;
}
case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
u32 *ppix = priv->fb;
u32 *end = priv->fb + priv->fb_size;
@@ -212,14 +212,14 @@ u32 video_index_to_colour(struct video_priv *priv, unsigned int idx)
{
switch (priv->bpix) {
case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
return ((colours[idx].r >> 3) << 11) |
((colours[idx].g >> 2) << 5) |
((colours[idx].b >> 3) << 0);
}
break;
case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
if (priv->format == VIDEO_X2R10G10B10)
return (colours[idx].r << 22) |
(colours[idx].g << 12) |
@@ -513,8 +513,8 @@ static int video_post_probe(struct udevice *dev)
return ret;
}
- if (IS_ENABLED(CONFIG_VIDEO_LOGO) &&
- !IS_ENABLED(CONFIG_SPLASH_SCREEN) && !plat->hide_logo) {
+ if (CONFIG_IS_ENABLED(VIDEO_LOGO) &&
+ !CONFIG_IS_ENABLED(SPLASH_SCREEN) && !plat->hide_logo) {
ret = show_splash(dev);
if (ret) {
log_debug("Cannot show splash screen\n");
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index 6188a13e44e..47e52c4f69c 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -320,7 +320,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
switch (bmp_bpix) {
case 1:
case 8:
- if (IS_ENABLED(CONFIG_VIDEO_BMP_RLE8)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BMP_RLE8)) {
u32 compression = get_unaligned_le32(
&bmp->header.compression);
debug("compressed %d %d\n", compression, BMP_BI_RLE8);
@@ -348,7 +348,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
case 16:
- if (IS_ENABLED(CONFIG_BMP_16BPP)) {
+ if (CONFIG_IS_ENABLED(BMP_16BPP)) {
for (i = 0; i < height; ++i) {
schedule();
for (j = 0; j < width; j++) {
@@ -361,7 +361,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
case 24:
- if (IS_ENABLED(CONFIG_BMP_24BPP)) {
+ if (CONFIG_IS_ENABLED(BMP_24BPP)) {
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
if (bpix == 16) {
@@ -395,7 +395,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
case 32:
- if (IS_ENABLED(CONFIG_BMP_32BPP)) {
+ if (CONFIG_IS_ENABLED(BMP_32BPP)) {
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
if (eformat == VIDEO_X2R10G10B10) {
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index de9bc90359c..31bb21c534e 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -336,7 +336,7 @@ static int virtio_uclass_child_pre_probe(struct udevice *vdev)
/* Transport features always preserved to pass to finalize_features */
for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
if ((device_features & (1ULL << i)) &&
- (i == VIRTIO_F_VERSION_1))
+ (i == VIRTIO_F_VERSION_1 || i == VIRTIO_F_IOMMU_PLATFORM))
__virtio_set_bit(vdev->parent, i);
debug("(%s) final negotiated features supported %016llx\n",
@@ -373,6 +373,12 @@ static int virtio_bootdev_hunt(struct bootdev_hunter *info, bool show)
{
int ret;
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = uclass_probe_all(UCLASS_PCI);
+ if (ret && ret != -ENOENT)
+ return log_msg_ret("pci", ret);
+ }
+
ret = uclass_probe_all(UCLASS_VIRTIO);
if (ret && ret != -ENOENT)
return log_msg_ret("vir", ret);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index cfde4007f5e..3cdc2d2d6fd 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -218,25 +218,6 @@ static int virtio_pci_set_status(struct udevice *udev, u8 status)
return 0;
}
-static int virtio_pci_reset(struct udevice *udev)
-{
- struct virtio_pci_priv *priv = dev_get_priv(udev);
-
- /* 0 status means a reset */
- iowrite8(0, &priv->common->device_status);
-
- /*
- * After writing 0 to device_status, the driver MUST wait for a read
- * of device_status to return 0 before reinitializing the device.
- * This will flush out the status write, and flush in device writes,
- * including MSI-X interrupts, if any.
- */
- while (ioread8(&priv->common->device_status))
- udelay(1000);
-
- return 0;
-}
-
static int virtio_pci_get_features(struct udevice *udev, u64 *features)
{
struct virtio_pci_priv *priv = dev_get_priv(udev);
@@ -363,6 +344,25 @@ static int virtio_pci_find_vqs(struct udevice *udev, unsigned int nvqs,
return 0;
}
+static int virtio_pci_reset(struct udevice *udev)
+{
+ struct virtio_pci_priv *priv = dev_get_priv(udev);
+
+ /* 0 status means a reset */
+ iowrite8(0, &priv->common->device_status);
+
+ /*
+ * After writing 0 to device_status, the driver MUST wait for a read
+ * of device_status to return 0 before reinitializing the device.
+ * This will flush out the status write, and flush in device writes,
+ * including MSI-X interrupts, if any.
+ */
+ while (ioread8(&priv->common->device_status))
+ udelay(1000);
+
+ return virtio_pci_del_vqs(udev);
+}
+
static int virtio_pci_notify(struct udevice *udev, struct virtqueue *vq)
{
struct virtio_pci_priv *priv = dev_get_priv(udev);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index f71bab78477..c9adcce5c09 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -6,6 +6,7 @@
* virtio ring implementation
*/
+#include <bouncebuf.h>
#include <common.h>
#include <dm.h>
#include <log.h>
@@ -15,15 +16,63 @@
#include <virtio_ring.h>
#include <linux/bug.h>
#include <linux/compat.h>
+#include <linux/kernel.h>
+
+static void *virtio_alloc_pages(struct udevice *vdev, u32 npages)
+{
+ return memalign(PAGE_SIZE, npages * PAGE_SIZE);
+}
+
+static void virtio_free_pages(struct udevice *vdev, void *ptr, u32 npages)
+{
+ free(ptr);
+}
+
+static int __bb_force_page_align(struct bounce_buffer *state)
+{
+ const ulong align_mask = PAGE_SIZE - 1;
+
+ if ((ulong)state->user_buffer & align_mask)
+ return 0;
+
+ if (state->len != state->len_aligned)
+ return 0;
+
+ return 1;
+}
static unsigned int virtqueue_attach_desc(struct virtqueue *vq, unsigned int i,
struct virtio_sg *sg, u16 flags)
{
struct vring_desc_shadow *desc_shadow = &vq->vring_desc_shadow[i];
struct vring_desc *desc = &vq->vring.desc[i];
+ void *addr;
+
+ if (IS_ENABLED(CONFIG_BOUNCE_BUFFER) && vq->vring.bouncebufs) {
+ struct bounce_buffer *bb = &vq->vring.bouncebufs[i];
+ unsigned int bbflags;
+ int ret;
+
+ if (flags & VRING_DESC_F_WRITE)
+ bbflags = GEN_BB_WRITE;
+ else
+ bbflags = GEN_BB_READ;
+
+ ret = bounce_buffer_start_extalign(bb, sg->addr, sg->length,
+ bbflags, PAGE_SIZE,
+ __bb_force_page_align);
+ if (ret) {
+ debug("%s: failed to allocate bounce buffer (length 0x%zx)\n",
+ vq->vdev->name, sg->length);
+ }
+
+ addr = bb->bounce_buffer;
+ } else {
+ addr = sg->addr;
+ }
/* Update the shadow descriptor. */
- desc_shadow->addr = (u64)(uintptr_t)sg->addr;
+ desc_shadow->addr = (u64)(uintptr_t)addr;
desc_shadow->len = sg->length;
desc_shadow->flags = flags;
@@ -36,6 +85,19 @@ static unsigned int virtqueue_attach_desc(struct virtqueue *vq, unsigned int i,
return desc_shadow->next;
}
+static void virtqueue_detach_desc(struct virtqueue *vq, unsigned int idx)
+{
+ struct vring_desc *desc = &vq->vring.desc[idx];
+ struct bounce_buffer *bb;
+
+ if (!IS_ENABLED(CONFIG_BOUNCE_BUFFER) || !vq->vring.bouncebufs)
+ return;
+
+ bb = &vq->vring.bouncebufs[idx];
+ bounce_buffer_stop(bb);
+ desc->addr = cpu_to_virtio64(vq->vdev, (u64)(uintptr_t)bb->user_buffer);
+}
+
int virtqueue_add(struct virtqueue *vq, struct virtio_sg *sgs[],
unsigned int out_sgs, unsigned int in_sgs)
{
@@ -154,10 +216,12 @@ static void detach_buf(struct virtqueue *vq, unsigned int head)
i = head;
while (vq->vring_desc_shadow[i].flags & VRING_DESC_F_NEXT) {
+ virtqueue_detach_desc(vq, i);
i = vq->vring_desc_shadow[i].next;
vq->num_free++;
}
+ virtqueue_detach_desc(vq, i);
vq->vring_desc_shadow[i].next = vq->free_head;
vq->free_head = head;
@@ -271,8 +335,11 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
unsigned int vring_align,
struct udevice *udev)
{
+ struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
+ struct udevice *vdev = uc_priv->vdev;
struct virtqueue *vq;
void *queue = NULL;
+ struct bounce_buffer *bbs = NULL;
struct vring vring;
/* We assume num is a power of 2 */
@@ -283,7 +350,9 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
/* TODO: allocate each queue chunk individually */
for (; num && vring_size(num, vring_align) > PAGE_SIZE; num /= 2) {
- queue = memalign(PAGE_SIZE, vring_size(num, vring_align));
+ size_t sz = vring_size(num, vring_align);
+
+ queue = virtio_alloc_pages(vdev, DIV_ROUND_UP(sz, PAGE_SIZE));
if (queue)
break;
}
@@ -293,30 +362,44 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
if (!queue) {
/* Try to get a single page. You are my only hope! */
- queue = memalign(PAGE_SIZE, vring_size(num, vring_align));
+ queue = virtio_alloc_pages(vdev, 1);
}
if (!queue)
return NULL;
memset(queue, 0, vring_size(num, vring_align));
- vring_init(&vring, num, queue, vring_align);
- vq = __vring_new_virtqueue(index, vring, udev);
- if (!vq) {
- free(queue);
- return NULL;
+ if (virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
+ bbs = calloc(num, sizeof(*bbs));
+ if (!bbs)
+ goto err_free_queue;
}
+
+ vring_init(&vring, num, queue, vring_align, bbs);
+
+ vq = __vring_new_virtqueue(index, vring, udev);
+ if (!vq)
+ goto err_free_bbs;
+
debug("(%s): created vring @ %p for vq @ %p with num %u\n", udev->name,
queue, vq, num);
return vq;
+
+err_free_bbs:
+ free(bbs);
+err_free_queue:
+ virtio_free_pages(vdev, queue, DIV_ROUND_UP(vring.size, PAGE_SIZE));
+ return NULL;
}
void vring_del_virtqueue(struct virtqueue *vq)
{
- free(vq->vring.desc);
+ virtio_free_pages(vq->vdev, vq->vring.desc,
+ DIV_ROUND_UP(vq->vring.size, PAGE_SIZE));
free(vq->vring_desc_shadow);
list_del(&vq->list);
+ free(vq->vring.bouncebufs);
free(vq);
}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b5ac8f7f50d..646663528a6 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -31,6 +31,7 @@ config WATCHDOG_TIMEOUT_MSECS
default 30000 if ARCH_SOCFPGA
default 16000 if ARCH_SUNXI
default 5376 if ULP_WATCHDOG
+ default 15000 if ARCH_BCM283X
default 60000
help
Watchdog timeout in msec
@@ -184,12 +185,28 @@ config WDT_MESON_GXBB
Select this to enable Meson watchdog timer,
which can be found on some Amlogic platforms.
-config WDT_MPC8xx
- bool "MPC8xx watchdog timer support"
- depends on WDT && MPC8xx
- select HW_WATCHDOG
+config WDT_MPC8xxx
+ bool "MPC8xxx watchdog timer support"
+ depends on WDT && (MPC8xx || MPC83xx)
+ help
+ Select this to enable mpc8xxx watchdog timer
+
+config WDT_MPC8xxx_BME
+ bool "Enable MPC8xx Bus Monitoring"
+ depends on WDT_MPC8xxx && MPC8xx
+ help
+ Select this to enable mpc8xx Bus Monitor.
+
+config WDT_MPC8xxx_BMT
+ int "MPC8xx Bus Monitor Timing" if WDT_MPC8xxx_BME
+ range 0 255
+ default 255
+ depends on WDT_MPC8xxx
help
- Select this to enable mpc8xx watchdog timer
+ Bus monitor timing. Defines the timeout period, in 8 system clock
+ resolution, for the bus monitor.
+
+ Maximum timeout is 2,040 clocks (255 x 8).
config WDT_MT7620
bool "MediaTek MT7620 watchdog timer support"
@@ -327,6 +344,14 @@ config WDT_SUNXI
help
Enable support for the watchdog timer in Allwinner sunxi SoCs.
+config WDT_BCM2835
+ bool "Broadcom 2835 watchdog timer support"
+ depends on WDT && ARCH_BCM283X
+ default y
+ help
+ Enable support for the watchdog timer in Broadcom 283X SoCs such
+ as Raspberry Pi boards.
+
config XILINX_TB_WATCHDOG
bool "Xilinx Axi watchdog timer support"
depends on WDT
@@ -352,6 +377,14 @@ config WDT_TANGIER
Intel Tangier SoC. If you're using a board with Intel Tangier
SoC, say Y here.
+config WDT_ARM_SMC
+ bool "ARM SMC watchdog timer support"
+ depends on WDT && ARM_SMCCC
+ imply WATCHDOG
+ help
+ Select this to enable Arm SMC watchdog timer. This watchdog will manage
+ a watchdog based on ARM SMCCC communication.
+
config SPL_WDT
bool "Enable driver model for watchdog timer drivers in SPL"
depends on SPL_DM
@@ -359,4 +392,11 @@ config SPL_WDT
Enable driver model for watchdog timer in SPL.
This is similar to CONFIG_WDT in U-Boot.
+config WDT_FTWDT010
+ bool "Faraday Technology ftwdt010 watchdog timer support"
+ depends on WDT
+ imply WATCHDOG
+ help
+ Faraday Technology ftwdt010 watchdog is an architecture independent
+ watchdog. It is usually used in SoC chip design.
endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 446d961d7d2..fd5d9c7376e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -18,18 +18,21 @@ obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
obj-$(CONFIG_WDT_ALARM_SANDBOX) += sandbox_alarm-wdt.o
obj-$(CONFIG_WDT_APPLE) += apple_wdt.o
+obj-$(CONFIG_WDT_ARM_SMC) += arm_smc_wdt.o
obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
obj-$(CONFIG_WDT_AST2600) += ast2600_wdt.o
+obj-$(CONFIG_WDT_BCM2835) += bcm2835_wdt.o
obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
obj-$(CONFIG_WDT_BOOKE) += booke_wdt.o
obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
+obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o
obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o
-obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
+obj-$(CONFIG_WDT_MPC8xxx) += mpc8xxx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
diff --git a/drivers/watchdog/arm_smc_wdt.c b/drivers/watchdog/arm_smc_wdt.c
new file mode 100644
index 00000000000..0ea44445700
--- /dev/null
+++ b/drivers/watchdog/arm_smc_wdt.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * ARM Secure Monitor Call watchdog driver
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ * This file is based on Linux driver drivers/watchdog/arm_smc_wdt.c
+ */
+
+#define LOG_CATEGORY UCLASS_WDT
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/arm-smccc.h>
+#include <linux/psci.h>
+#include <wdt.h>
+
+#define DRV_NAME "arm_smc_wdt"
+
+#define WDT_TIMEOUT_SECS(TIMEOUT) ((TIMEOUT) / 1000)
+
+enum smcwd_call {
+ SMCWD_INIT = 0,
+ SMCWD_SET_TIMEOUT = 1,
+ SMCWD_ENABLE = 2,
+ SMCWD_PET = 3,
+ SMCWD_GET_TIMELEFT = 4,
+};
+
+struct smcwd_priv_data {
+ u32 smc_id;
+ unsigned int min_timeout;
+ unsigned int max_timeout;
+};
+
+static int smcwd_call(struct udevice *dev, enum smcwd_call call,
+ unsigned long arg, struct arm_smccc_res *res)
+{
+ struct smcwd_priv_data *priv = dev_get_priv(dev);
+ struct arm_smccc_res local_res;
+
+ if (!res)
+ res = &local_res;
+
+ arm_smccc_smc(priv->smc_id, call, arg, 0, 0, 0, 0, 0, res);
+
+ if (res->a0 == PSCI_RET_NOT_SUPPORTED)
+ return -ENODEV;
+ if (res->a0 == PSCI_RET_INVALID_PARAMS)
+ return -EINVAL;
+ if (res->a0 != PSCI_RET_SUCCESS)
+ return -EIO;
+
+ return 0;
+}
+
+static int smcwd_reset(struct udevice *dev)
+{
+ return smcwd_call(dev, SMCWD_PET, 0, NULL);
+}
+
+static int smcwd_stop(struct udevice *dev)
+{
+ return smcwd_call(dev, SMCWD_ENABLE, 0, NULL);
+}
+
+static int smcwd_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct smcwd_priv_data *priv = dev_get_priv(dev);
+ u64 timeout_sec = WDT_TIMEOUT_SECS(timeout_ms);
+ int err;
+
+ if (timeout_sec < priv->min_timeout || timeout_sec > priv->max_timeout) {
+ dev_err(dev, "Timeout value not supported\n");
+ return -EINVAL;
+ }
+
+ err = smcwd_call(dev, SMCWD_SET_TIMEOUT, timeout_sec, NULL);
+ if (err) {
+ dev_err(dev, "Timeout out configuration failed\n");
+ return err;
+ }
+
+ return smcwd_call(dev, SMCWD_ENABLE, 1, NULL);
+}
+
+static int smcwd_probe(struct udevice *dev)
+{
+ struct smcwd_priv_data *priv = dev_get_priv(dev);
+ struct arm_smccc_res res;
+ int err;
+
+ priv->smc_id = dev_read_u32_default(dev, "arm,smc-id", 0x82003D06);
+
+ err = smcwd_call(dev, SMCWD_INIT, 0, &res);
+ if (err < 0) {
+ dev_err(dev, "Init failed %i\n", err);
+ return err;
+ }
+
+ priv->min_timeout = res.a1;
+ priv->max_timeout = res.a2;
+
+ return 0;
+}
+
+static const struct wdt_ops smcwd_ops = {
+ .start = smcwd_start,
+ .stop = smcwd_stop,
+ .reset = smcwd_reset,
+};
+
+static const struct udevice_id smcwd_dt_ids[] = {
+ { .compatible = "arm,smc-wdt" },
+ {}
+};
+
+U_BOOT_DRIVER(wdt_sandbox) = {
+ .name = "smcwd",
+ .id = UCLASS_WDT,
+ .of_match = smcwd_dt_ids,
+ .priv_auto = sizeof(struct smcwd_priv_data),
+ .probe = smcwd_probe,
+ .ops = &smcwd_ops,
+};
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
new file mode 100644
index 00000000000..3c1ead3dda6
--- /dev/null
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013 Lubomir Rintel <[email protected]>
+ * Copyright (C) 2023 Etienne DublĂ© (CNRS) <[email protected]>
+ *
+ * This code is mostly derived from the linux driver.
+ */
+
+#include <dm.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+
+#define PM_RSTC 0x1c
+#define PM_WDOG 0x24
+
+#define PM_PASSWORD 0x5a000000
+
+/* The hardware supports a maximum timeout value of 0xfffff ticks
+ * (just below 16 seconds).
+ */
+#define PM_WDOG_MAX_TICKS 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+#define MS_TO_WDOG_TICKS(x) (((x) << 16) / 1000)
+
+struct bcm2835_wdt_priv {
+ void __iomem *base;
+ u64 timeout_ticks;
+};
+
+static int bcm2835_wdt_start_ticks(struct udevice *dev,
+ u64 timeout_ticks, ulong flags)
+{
+ struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+ void __iomem *base = priv->base;
+ u32 cur;
+
+ writel(PM_PASSWORD | timeout_ticks, base + PM_WDOG);
+ cur = readl(base + PM_RSTC);
+ writel(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET,
+ base + PM_RSTC);
+
+ return 0;
+}
+
+static int bcm2835_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+
+ priv->timeout_ticks = MS_TO_WDOG_TICKS(timeout_ms);
+
+ if (priv->timeout_ticks > PM_WDOG_MAX_TICKS) {
+ printf("bcm2835_wdt: the timeout value is too high, using ~16s instead.\n");
+ priv->timeout_ticks = PM_WDOG_MAX_TICKS;
+ }
+
+ return bcm2835_wdt_start_ticks(dev, priv->timeout_ticks, flags);
+}
+
+static int bcm2835_wdt_reset(struct udevice *dev)
+{
+ struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+
+ /* restart the timer with the value of priv->timeout_ticks
+ * saved from the last bcm2835_wdt_start() call.
+ */
+ return bcm2835_wdt_start_ticks(dev, priv->timeout_ticks, 0);
+}
+
+static int bcm2835_wdt_stop(struct udevice *dev)
+{
+ struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+ void __iomem *base = priv->base;
+
+ writel(PM_PASSWORD | PM_RSTC_RESET, base + PM_RSTC);
+
+ return 0;
+}
+
+static int bcm2835_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ int ret;
+
+ /* use a timeout of 10 ticks (~150us) */
+ ret = bcm2835_wdt_start_ticks(dev, 10, flags);
+ if (ret)
+ return ret;
+
+ mdelay(500);
+
+ return 0;
+}
+
+static const struct wdt_ops bcm2835_wdt_ops = {
+ .reset = bcm2835_wdt_reset,
+ .start = bcm2835_wdt_start,
+ .stop = bcm2835_wdt_stop,
+ .expire_now = bcm2835_wdt_expire_now,
+};
+
+static const struct udevice_id bcm2835_wdt_ids[] = {
+ { .compatible = "brcm,bcm2835-pm" },
+ { .compatible = "brcm,bcm2835-pm-wdt" },
+ { /* sentinel */ }
+};
+
+static int bcm2835_wdt_probe(struct udevice *dev)
+{
+ struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -EINVAL;
+
+ priv->timeout_ticks = PM_WDOG_MAX_TICKS;
+
+ bcm2835_wdt_stop(dev);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(bcm2835_wdt) = {
+ .name = "bcm2835_wdt",
+ .id = UCLASS_WDT,
+ .of_match = bcm2835_wdt_ids,
+ .probe = bcm2835_wdt_probe,
+ .priv_auto = sizeof(struct bcm2835_wdt_priv),
+ .ops = &bcm2835_wdt_ops,
+};
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
new file mode 100644
index 00000000000..a6b33b17209
--- /dev/null
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Watchdog driver for the FTWDT010 Watch Dog Driver
+ *
+ * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com)
+ * Based on sa1100_wdt.c by Oleg Drokin <[email protected]>
+ * Based on SoftDog driver by Alan Cox <[email protected]>
+ *
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Macpaul Lin, Andes Technology Corporation <[email protected]>
+ *
+ * 27/11/2004 Initial release, Faraday.
+ * 12/01/2011 Port to u-boot, Macpaul Lin.
+ * 22/08/2022 Port to DM
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <log.h>
+#include <asm/io.h>
+#include <faraday/ftwdt010_wdt.h>
+
+struct ftwdt010_wdt_priv {
+ struct ftwdt010_wdt __iomem *regs;
+};
+
+/*
+ * Set the watchdog time interval.
+ * Counter is 32 bit.
+ */
+static int ftwdt010_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
+ struct ftwdt010_wdt *wd = priv->regs;
+ unsigned int reg;
+
+ debug("Activating WDT %llu ms\n", timeout_ms);
+
+ /* Check if disabled */
+ if (readl(&wd->wdcr) & ~FTWDT010_WDCR_ENABLE) {
+ printf("sorry, watchdog is disabled\n");
+ return -1;
+ }
+
+ /*
+ * In a 66MHz system,
+ * if you set WDLOAD as 0x03EF1480 (66000000)
+ * the reset timer is 1 second.
+ */
+ reg = FTWDT010_WDLOAD(timeout_ms * FTWDT010_TIMEOUT_FACTOR);
+
+ writel(reg, &wd->wdload);
+
+ return 0;
+}
+
+static int ftwdt010_wdt_reset(struct udevice *dev)
+{
+ struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
+ struct ftwdt010_wdt *wd = priv->regs;
+
+ /* clear control register */
+ writel(0, &wd->wdcr);
+
+ /* Write Magic number */
+ writel(FTWDT010_WDRESTART_MAGIC, &wd->wdrestart);
+
+ /* Enable WDT */
+ writel((FTWDT010_WDCR_RST | FTWDT010_WDCR_ENABLE), &wd->wdcr);
+
+ return 0;
+}
+
+static int ftwdt010_wdt_stop(struct udevice *dev)
+{
+ struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
+ struct ftwdt010_wdt *wd = priv->regs;
+
+ debug("Deactivating WDT..\n");
+
+ /*
+ * It was defined with CONFIG_WATCHDOG_NOWAYOUT in Linux
+ *
+ * Shut off the timer.
+ * Lock it in if it's a module and we defined ...NOWAYOUT
+ */
+ writel(0, &wd->wdcr);
+ return 0;
+}
+
+static int ftwdt010_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
+ struct ftwdt010_wdt *wd = priv->regs;
+
+ debug("Expiring WDT..\n");
+ writel(FTWDT010_WDLOAD(0), &wd->wdload);
+ return ftwdt010_wdt_reset(dev);
+}
+
+static int ftwdt010_wdt_probe(struct udevice *dev)
+{
+ struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
+
+ priv->regs = dev_read_addr_ptr(dev);
+ if (!priv->regs)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct wdt_ops ftwdt010_wdt_ops = {
+ .start = ftwdt010_wdt_start,
+ .reset = ftwdt010_wdt_reset,
+ .stop = ftwdt010_wdt_stop,
+ .expire_now = ftwdt010_wdt_expire_now,
+};
+
+static const struct udevice_id ftwdt010_wdt_ids[] = {
+ { .compatible = "faraday,ftwdt010" },
+ {}
+};
+
+U_BOOT_DRIVER(ftwdt010_wdt) = {
+ .name = "ftwdt010_wdt",
+ .id = UCLASS_WDT,
+ .of_match = ftwdt010_wdt_ids,
+ .ops = &ftwdt010_wdt_ops,
+ .probe = ftwdt010_wdt_probe,
+ .priv_auto = sizeof(struct ftwdt010_wdt_priv),
+};
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
deleted file mode 100644
index c8b104d8f56..00000000000
--- a/drivers/watchdog/mpc8xx_wdt.c
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2017 CS Systemes d'Information
- */
-
-#include <common.h>
-#include <env.h>
-#include <dm.h>
-#include <wdt.h>
-#include <mpc8xx.h>
-#include <asm/cpm_8xx.h>
-#include <asm/io.h>
-
-void hw_watchdog_reset(void)
-{
- immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
-
- out_be16(&immap->im_siu_conf.sc_swsr, 0x556c); /* write magic1 */
- out_be16(&immap->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */
-}
-
-static int mpc8xx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
-{
- immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
- u32 val = CONFIG_SYS_SYPCR;
- const char *mode = env_get("watchdog_mode");
-
- if (strcmp(mode, "off") == 0)
- val = val & ~(SYPCR_SWE | SYPCR_SWRI);
- else if (strcmp(mode, "nmi") == 0)
- val = (val & ~SYPCR_SWRI) | SYPCR_SWE;
-
- out_be32(&immap->im_siu_conf.sc_sypcr, val);
-
- if (!(in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE))
- return -EBUSY;
- return 0;
-
-}
-
-static int mpc8xx_wdt_stop(struct udevice *dev)
-{
- immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
-
- out_be32(&immap->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE);
-
- if (in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE)
- return -EBUSY;
- return 0;
-}
-
-static int mpc8xx_wdt_reset(struct udevice *dev)
-{
- hw_watchdog_reset();
-
- return 0;
-}
-
-static const struct wdt_ops mpc8xx_wdt_ops = {
- .start = mpc8xx_wdt_start,
- .reset = mpc8xx_wdt_reset,
- .stop = mpc8xx_wdt_stop,
-};
-
-static const struct udevice_id mpc8xx_wdt_ids[] = {
- { .compatible = "fsl,pq1-wdt" },
- {}
-};
-
-U_BOOT_DRIVER(wdt_mpc8xx) = {
- .name = "wdt_mpc8xx",
- .id = UCLASS_WDT,
- .of_match = mpc8xx_wdt_ids,
- .ops = &mpc8xx_wdt_ops,
-};
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
new file mode 100644
index 00000000000..f28636ca901
--- /dev/null
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2017 CS Systemes d'Information
+ */
+
+#include <common.h>
+#include <env.h>
+#include <dm.h>
+#include <wdt.h>
+#include <clock_legacy.h>
+#include <asm/io.h>
+
+struct mpc8xxx_wdt {
+ __be32 res0;
+ __be32 swcrr; /* System watchdog control register */
+#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
+#define SWCRR_BME 0x00000080 /* Bus monitor enable (mpc8xx) */
+#define SWCRR_SWF 0x00000008 /* Software Watchdog Freeze (mpc8xx). */
+#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
+#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
+#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
+ __be32 swcnr; /* System watchdog count register */
+ u8 res1[2];
+ __be16 swsrr; /* System watchdog service register */
+ u8 res2[0xf0];
+};
+
+struct mpc8xxx_wdt_priv {
+ struct mpc8xxx_wdt __iomem *base;
+};
+
+static int mpc8xxx_wdt_reset(struct udevice *dev)
+{
+ struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
+
+ out_be16(&priv->base->swsrr, 0x556c); /* write magic1 */
+ out_be16(&priv->base->swsrr, 0xaa39); /* write magic2 */
+
+ return 0;
+}
+
+static int mpc8xxx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+ struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
+ const char *mode = env_get("watchdog_mode");
+ ulong prescaler = dev_get_driver_data(dev);
+ u16 swtc = min_t(u16, timeout * get_board_sys_clk() / 1000 / prescaler, U16_MAX);
+ u32 val;
+
+ mpc8xxx_wdt_reset(dev);
+
+ if (strcmp(mode, "off") == 0)
+ val = (swtc << 16) | SWCRR_SWPR;
+ else if (strcmp(mode, "nmi") == 0)
+ val = (swtc << 16) | SWCRR_SWPR | SWCRR_SWEN;
+ else
+ val = (swtc << 16) | SWCRR_SWPR | SWCRR_SWEN | SWCRR_SWRI;
+
+ if (IS_ENABLED(CONFIG_WDT_MPC8xxx_BME))
+ val |= (CONFIG_WDT_MPC8xxx_BMT << 8) | SWCRR_BME;
+
+ out_be32(&priv->base->swcrr, val);
+
+ if (!(in_be32(&priv->base->swcrr) & SWCRR_SWEN))
+ return -EBUSY;
+ return 0;
+
+}
+
+static int mpc8xxx_wdt_stop(struct udevice *dev)
+{
+ struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
+
+ clrbits_be32(&priv->base->swcrr, SWCRR_SWEN);
+
+ if (in_be32(&priv->base->swcrr) & SWCRR_SWEN)
+ return -EBUSY;
+ return 0;
+}
+
+static int mpc8xxx_wdt_of_to_plat(struct udevice *dev)
+{
+ struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
+
+ priv->base = (void __iomem *)devfdt_remap_addr(dev);
+
+ if (!priv->base)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct wdt_ops mpc8xxx_wdt_ops = {
+ .start = mpc8xxx_wdt_start,
+ .reset = mpc8xxx_wdt_reset,
+ .stop = mpc8xxx_wdt_stop,
+};
+
+static const struct udevice_id mpc8xxx_wdt_ids[] = {
+ { .compatible = "fsl,pq1-wdt", .data = 0x800 },
+ { .compatible = "fsl,pq2pro-wdt", .data = 0x10000 },
+ {}
+};
+
+U_BOOT_DRIVER(wdt_mpc8xxx) = {
+ .name = "wdt_mpc8xxx",
+ .id = UCLASS_WDT,
+ .of_match = mpc8xxx_wdt_ids,
+ .ops = &mpc8xxx_wdt_ops,
+ .of_to_plat = mpc8xxx_wdt_of_to_plat,
+ .priv_auto = sizeof(struct mpc8xxx_wdt_priv),
+};
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 0ee74d036c7..6cb9149fa77 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -1,6 +1,6 @@
config PVBLOCK
bool "Xen para-virtualized block device"
- depends on DM
+ depends on DM && XEN
select BLK
help
This driver implements the front-end of the Xen virtual
diff --git a/drivers/xen/hypervisor.c b/drivers/xen/hypervisor.c
index 16c7c96c94e..0b2311ba267 100644
--- a/drivers/xen/hypervisor.c
+++ b/drivers/xen/hypervisor.c
@@ -264,8 +264,15 @@ void clear_evtchn(uint32_t port)
int xen_init(void)
{
+ int el = current_el();
+
debug("%s\n", __func__);
+ if (el != 1) {
+ puts("XEN:\tnot running from EL1\n");
+ return 0;
+ }
+
map_shared_info(NULL);
init_events();
init_xenbus();