summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/skd_main.c7
-rw-r--r--drivers/cpuidle/cpuidle-powernv.c2
-rw-r--r--drivers/cpuidle/cpuidle-pseries.c16
-rw-r--r--drivers/dma/imx-dma.c2
-rw-r--r--drivers/firewire/net.c7
-rw-r--r--drivers/firewire/ohci.c8
-rw-r--r--drivers/firmware/dmi-sysfs.c2
-rw-r--r--drivers/firmware/dmi_scan.c64
-rw-r--r--drivers/gpio/gpio-uniphier.c2
-rw-r--r--drivers/gpio/gpiolib-acpi.c75
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c5
-rw-r--r--drivers/i2c/busses/Kconfig8
-rw-r--r--drivers/i2c/busses/i2c-acorn.c8
-rw-r--r--drivers/i2c/busses/i2c-davinci.c37
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c20
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h2
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c57
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c29
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c64
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c2
-rw-r--r--drivers/i2c/busses/i2c-gpio.c122
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c68
-rw-r--r--drivers/i2c/busses/i2c-imx.c20
-rw-r--r--drivers/i2c/busses/i2c-ismt.c42
-rw-r--r--drivers/i2c/busses/i2c-meson.c34
-rw-r--r--drivers/i2c/busses/i2c-mpc.c57
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c40
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c20
-rw-r--r--drivers/i2c/busses/i2c-mxs.c4
-rw-r--r--drivers/i2c/busses/i2c-rcar.c62
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c17
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c191
-rw-r--r--drivers/i2c/i2c-core-base.c212
-rw-r--r--drivers/i2c/i2c-core-smbus.c45
-rw-r--r--drivers/i2c/i2c-dev.c2
-rw-r--r--drivers/i2c/muxes/Kconfig6
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c38
-rw-r--r--drivers/i2c/muxes/i2c-mux-reg.c3
-rw-r--r--drivers/irqchip/irq-stm32-exti.c3
-rw-r--r--drivers/macintosh/adb.c24
-rw-r--r--drivers/macintosh/adbhid.c55
-rw-r--r--drivers/macintosh/ams/ams-input.c4
-rw-r--r--drivers/macintosh/therm_adt746x.c4
-rw-r--r--drivers/macintosh/via-pmu-backlight.c2
-rw-r--r--drivers/macintosh/windfarm_pm112.c8
-rw-r--r--drivers/macintosh/windfarm_pm121.c5
-rw-r--r--drivers/macintosh/windfarm_pm72.c2
-rw-r--r--drivers/macintosh/windfarm_pm81.c5
-rw-r--r--drivers/macintosh/windfarm_pm91.c5
-rw-r--r--drivers/macintosh/windfarm_rm31.c2
-rw-r--r--drivers/mailbox/qcom-apcs-ipc-mailbox.c35
-rw-r--r--drivers/mailbox/ti-msgmgr.c14
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/cxl/context.c2
-rw-r--r--drivers/misc/cxl/cxl.h3
-rw-r--r--drivers/misc/cxl/cxllib.c3
-rw-r--r--drivers/misc/cxl/file.c15
-rw-r--r--drivers/misc/cxl/native.c13
-rw-r--r--drivers/misc/cxl/pci.c2
-rw-r--r--drivers/misc/eeprom/Kconfig1
-rw-r--r--drivers/misc/eeprom/at24.c731
-rw-r--r--drivers/misc/lkdtm.h4
-rw-r--r--drivers/misc/lkdtm_core.c4
-rw-r--r--drivers/misc/lkdtm_usercopy.c101
-rw-r--r--drivers/misc/ocxl/Kconfig31
-rw-r--r--drivers/misc/ocxl/Makefile11
-rw-r--r--drivers/misc/ocxl/afu_irq.c202
-rw-r--r--drivers/misc/ocxl/config.c723
-rw-r--r--drivers/misc/ocxl/context.c279
-rw-r--r--drivers/misc/ocxl/file.c432
-rw-r--r--drivers/misc/ocxl/link.c647
-rw-r--r--drivers/misc/ocxl/main.c33
-rw-r--r--drivers/misc/ocxl/ocxl_internal.h131
-rw-r--r--drivers/misc/ocxl/pasid.c107
-rw-r--r--drivers/misc/ocxl/pci.c585
-rw-r--r--drivers/misc/ocxl/sysfs.c142
-rw-r--r--drivers/misc/ocxl/trace.c6
-rw-r--r--drivers/misc/ocxl/trace.h182
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c18
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h2
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c3
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c6
-rw-r--r--drivers/net/ethernet/jme.c2
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c12
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_debug.c6
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c3
-rw-r--r--drivers/net/ethernet/rocker/rocker_main.c18
-rw-r--r--drivers/net/usb/lan78xx.c2
-rw-r--r--drivers/net/usb/r8152.c13
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c6
-rw-r--r--drivers/ntb/hw/amd/ntb_hw_amd.c4
-rw-r--r--drivers/ntb/hw/idt/ntb_hw_idt.c37
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.c313
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.h58
-rw-r--r--drivers/ntb/hw/mscc/ntb_hw_switchtec.c603
-rw-r--r--drivers/ntb/ntb.c4
-rw-r--r--drivers/ntb/ntb_transport.c3
-rw-r--r--drivers/ntb/test/ntb_perf.c1824
-rw-r--r--drivers/ntb/test/ntb_pingpong.c450
-rw-r--r--drivers/ntb/test/ntb_tool.c1825
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c13
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c3
-rw-r--r--drivers/pci/hotplug/rpaphp.h8
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c107
-rw-r--r--drivers/pci/iov.c11
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c3
-rw-r--r--drivers/pinctrl/Kconfig15
-rw-r--r--drivers/pinctrl/Makefile3
-rw-r--r--drivers/pinctrl/core.c24
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c81
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.h13
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx25.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx35.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx50.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx51.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx53.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6dl.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6q.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6sl.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6sx.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx6ul.c52
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx7d.c10
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx7ulp.c7
-rw-r--r--drivers/pinctrl/freescale/pinctrl-vf610.c5
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c6
-rw-r--r--drivers/pinctrl/intel/pinctrl-cannonlake.c65
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c59
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c179
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.h3
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c7
-rw-r--r--drivers/pinctrl/mediatek/Kconfig15
-rw-r--r--drivers/pinctrl/mediatek/Makefile3
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7622.c1597
-rw-r--r--drivers/pinctrl/meson/Kconfig9
-rw-r--r--drivers/pinctrl/meson/Makefile2
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c118
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-axg-pmx.h62
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-axg.c975
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.h1
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c4
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c5
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c10
-rw-r--r--drivers/pinctrl/pinctrl-adi2.c13
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c4
-rw-r--r--drivers/pinctrl/pinctrl-at91.c4
-rw-r--r--drivers/pinctrl/pinctrl-axp209.c4
-rw-r--r--drivers/pinctrl/pinctrl-gemini.c84
-rw-r--r--drivers/pinctrl/pinctrl-ingenic.c4
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08.c54
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c511
-rw-r--r--drivers/pinctrl/pinctrl-palmas.c4
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c31
-rw-r--r--drivers/pinctrl/pinctrl-single.c10
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c40
-rw-r--r--drivers/pinctrl/pinctrl-tz1090-pdc.c9
-rw-r--r--drivers/pinctrl/pinctrl-tz1090.c9
-rw-r--r--drivers/pinctrl/pinctrl-utils.c4
-rw-r--r--drivers/pinctrl/pinctrl-xway.c10
-rw-r--r--drivers/pinctrl/pinmux.c4
-rw-r--r--drivers/pinctrl/pxa/pinctrl-pxa2xx.c4
-rw-r--r--drivers/pinctrl/qcom/Kconfig8
-rw-r--r--drivers/pinctrl/qcom/Makefile1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c5
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8998.c1590
-rw-r--r--drivers/pinctrl/samsung/Kconfig1
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos-arm.c33
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos-arm64.c33
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c33
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.h6
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos5440.c21
-rw-r--r--drivers/pinctrl/samsung/pinctrl-s3c24xx.c23
-rw-r--r--drivers/pinctrl/samsung/pinctrl-s3c64xx.c27
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c37
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h6
-rw-r--r--drivers/pinctrl/sh-pfc/Kconfig5
-rw-r--r--drivers/pinctrl/sh-pfc/Makefile1
-rw-r--r--drivers/pinctrl/sh-pfc/core.c6
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7791.c62
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7794.c473
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795.c193
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7796.c66
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77970.c2329
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77995.c88
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h17
-rw-r--r--drivers/pinctrl/spear/pinctrl-plgpio.c8
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c4
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd.c2
-rw-r--r--drivers/pinctrl/stm32/Kconfig12
-rw-r--r--drivers/pinctrl/stm32/Makefile2
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.c3
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.h3
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32f429.c3
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32f469.c6
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32f746.c3
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32f769.c1827
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32h743.c6
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32mp157.c2188
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.c9
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-core.c176
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-vt8500.c4
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8505.c4
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8650.c4
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8750.c4
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wm8850.c4
-rw-r--r--drivers/ps3/ps3av.c11
-rw-r--r--drivers/rtc/Kconfig27
-rw-r--r--drivers/rtc/Makefile3
-rw-r--r--drivers/rtc/rtc-ac100.c19
-rw-r--r--drivers/rtc/rtc-at32ap700x.c287
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c15
-rw-r--r--drivers/rtc/rtc-cros-ec.c413
-rw-r--r--drivers/rtc/rtc-mxc_v2.c419
-rw-r--r--drivers/rtc/rtc-omap.c5
-rw-r--r--drivers/rtc/rtc-opal.c12
-rw-r--r--drivers/rtc/rtc-r7301.c4
-rw-r--r--drivers/rtc/rtc-r9701.c6
-rw-r--r--drivers/rtc/rtc-stm32.c4
-rw-r--r--drivers/rtc/rtc-sun6i.c4
-rw-r--r--drivers/scsi/scsi_debugfs.c40
-rw-r--r--drivers/scsi/scsi_lib.c9
-rw-r--r--drivers/scsi/sd.c41
-rw-r--r--drivers/scsi/sd.h11
-rw-r--r--drivers/scsi/sd_zbc.c235
228 files changed, 22132 insertions, 4252 deletions
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index de0d08133c7e..e41935ab41ef 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -32,7 +32,6 @@
#include <linux/aer.h>
#include <linux/wait.h>
#include <linux/stringify.h>
-#include <linux/slab_def.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <linux/io.h>
@@ -2603,7 +2602,8 @@ static void *skd_alloc_dma(struct skd_device *skdev, struct kmem_cache *s,
buf = kmem_cache_alloc(s, gfp);
if (!buf)
return NULL;
- *dma_handle = dma_map_single(dev, buf, s->size, dir);
+ *dma_handle = dma_map_single(dev, buf,
+ kmem_cache_size(s), dir);
if (dma_mapping_error(dev, *dma_handle)) {
kmem_cache_free(s, buf);
buf = NULL;
@@ -2618,7 +2618,8 @@ static void skd_free_dma(struct skd_device *skdev, struct kmem_cache *s,
if (!vaddr)
return;
- dma_unmap_single(&skdev->pdev->dev, dma_handle, s->size, dir);
+ dma_unmap_single(&skdev->pdev->dev, dma_handle,
+ kmem_cache_size(s), dir);
kmem_cache_free(s, vaddr);
}
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index e06605b21841..1a8234e706bc 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -76,6 +76,8 @@ static int snooze_loop(struct cpuidle_device *dev,
ppc64_runlatch_on();
clear_thread_flag(TIF_POLLING_NRFLAG);
+ local_irq_disable();
+
return index;
}
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index a187a39fb866..9e56bc411061 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -51,8 +51,6 @@ static inline void idle_loop_epilog(unsigned long in_purr)
get_lppaca()->wait_state_cycles = cpu_to_be64(wait_cycles);
get_lppaca()->idle = 0;
- if (irqs_disabled())
- local_irq_enable();
ppc64_runlatch_on();
}
@@ -87,6 +85,8 @@ static int snooze_loop(struct cpuidle_device *dev,
HMT_medium();
clear_thread_flag(TIF_POLLING_NRFLAG);
+ local_irq_disable();
+
idle_loop_epilog(in_purr);
return index;
@@ -121,6 +121,7 @@ static int dedicated_cede_loop(struct cpuidle_device *dev,
HMT_medium();
check_and_cede_processor();
+ local_irq_disable();
get_lppaca()->donate_dedicated_cpu = 0;
idle_loop_epilog(in_purr);
@@ -145,6 +146,7 @@ static int shared_cede_loop(struct cpuidle_device *dev,
*/
check_and_cede_processor();
+ local_irq_disable();
idle_loop_epilog(in_purr);
return index;
@@ -172,11 +174,17 @@ static struct cpuidle_state dedicated_states[] = {
* States for shared partition case.
*/
static struct cpuidle_state shared_states[] = {
+ { /* Snooze */
+ .name = "snooze",
+ .desc = "snooze",
+ .exit_latency = 0,
+ .target_residency = 0,
+ .enter = &snooze_loop },
{ /* Shared Cede */
.name = "Shared Cede",
.desc = "Shared Cede",
- .exit_latency = 0,
- .target_residency = 0,
+ .exit_latency = 10,
+ .target_residency = 100,
.enter = &shared_cede_loop },
};
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 331f863c605e..715b39ae5a46 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -765,7 +765,7 @@ static int imxdma_alloc_chan_resources(struct dma_chan *chan)
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
if (!desc)
break;
- __memzero(&desc->desc, sizeof(struct dma_async_tx_descriptor));
+ memset(&desc->desc, 0, sizeof(struct dma_async_tx_descriptor));
dma_async_tx_descriptor_init(&desc->desc, chan);
desc->desc.tx_submit = imxdma_tx_submit;
/* txd.flags will be overwritten in prep funcs */
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 242359c2d1f1..60e75e6d9104 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1480,9 +1480,14 @@ static int fwnet_probe(struct fw_unit *unit,
goto out;
dev->local_fifo = dev->handler.offset;
+ /*
+ * default MTU: RFC 2734 cl. 4, RFC 3146 cl. 4
+ * maximum MTU: RFC 2734 cl. 4.2, fragment encapsulation header's
+ * maximum possible datagram_size + 1 = 0xfff + 1
+ */
net->mtu = 1500U;
net->min_mtu = ETH_MIN_MTU;
- net->max_mtu = 0xfff;
+ net->max_mtu = 4096U;
/* Set our hardware address while we're at it */
ha = (union fwnet_hwaddr *)net->dev_addr;
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index ccf52368a073..45c048751f3b 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1128,7 +1128,13 @@ static int context_add_buffer(struct context *ctx)
return -ENOMEM;
offset = (void *)&desc->buffer - (void *)desc;
- desc->buffer_size = PAGE_SIZE - offset;
+ /*
+ * Some controllers, like JMicron ones, always issue 0x20-byte DMA reads
+ * for descriptors, even 0x10-byte ones. This can cause page faults when
+ * an IOMMU is in use and the oversized read crosses a page boundary.
+ * Work around this by always leaving at least 0x10 bytes of padding.
+ */
+ desc->buffer_size = PAGE_SIZE - offset - 0x10;
desc->buffer_bus = bus_addr + offset;
desc->used = 0;
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
index d5de6ee8466d..ecf2eeb5f6f9 100644
--- a/drivers/firmware/dmi-sysfs.c
+++ b/drivers/firmware/dmi-sysfs.c
@@ -652,7 +652,7 @@ static int __init dmi_sysfs_init(void)
int val;
if (!dmi_kobj) {
- pr_err("dmi-sysfs: dmi entry is absent.\n");
+ pr_debug("dmi-sysfs: dmi entry is absent.\n");
error = -ENODATA;
goto err;
}
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 783041964439..e763e1484331 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -18,7 +18,7 @@ EXPORT_SYMBOL_GPL(dmi_kobj);
* of and an antecedent to, SMBIOS, which stands for System
* Management BIOS. See further: http://www.dmtf.org/standards
*/
-static const char dmi_empty_string[] = " ";
+static const char dmi_empty_string[] = "";
static u32 dmi_ver __initdata;
static u32 dmi_len;
@@ -26,11 +26,6 @@ static u16 dmi_num;
static u8 smbios_entry_point[32];
static int smbios_entry_point_size;
-/*
- * Catch too early calls to dmi_check_system():
- */
-static int dmi_initialized;
-
/* DMI system identification string used during boot */
static char dmi_ids_string[128] __initdata;
@@ -44,25 +39,21 @@ static int dmi_memdev_nr;
static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
{
const u8 *bp = ((u8 *) dm) + dm->length;
+ const u8 *nsp;
if (s) {
- s--;
- while (s > 0 && *bp) {
+ while (--s > 0 && *bp)
bp += strlen(bp) + 1;
- s--;
- }
- if (*bp != 0) {
- size_t len = strlen(bp)+1;
- size_t cmp_len = len > 8 ? 8 : len;
-
- if (!memcmp(bp, dmi_empty_string, cmp_len))
- return dmi_empty_string;
+ /* Strings containing only spaces are considered empty */
+ nsp = bp;
+ while (*nsp == ' ')
+ nsp++;
+ if (*nsp != '\0')
return bp;
- }
}
- return "";
+ return dmi_empty_string;
}
static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
@@ -633,7 +624,7 @@ void __init dmi_scan_machine(void)
if (!dmi_smbios3_present(buf)) {
dmi_available = 1;
- goto out;
+ return;
}
}
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
@@ -651,7 +642,7 @@ void __init dmi_scan_machine(void)
if (!dmi_present(buf)) {
dmi_available = 1;
- goto out;
+ return;
}
} else if (IS_ENABLED(CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK)) {
p = dmi_early_remap(0xF0000, 0x10000);
@@ -668,7 +659,7 @@ void __init dmi_scan_machine(void)
if (!dmi_smbios3_present(buf)) {
dmi_available = 1;
dmi_early_unmap(p, 0x10000);
- goto out;
+ return;
}
memcpy(buf, buf + 16, 16);
}
@@ -686,7 +677,7 @@ void __init dmi_scan_machine(void)
if (!dmi_present(buf)) {
dmi_available = 1;
dmi_early_unmap(p, 0x10000);
- goto out;
+ return;
}
memcpy(buf, buf + 16, 16);
}
@@ -694,8 +685,6 @@ void __init dmi_scan_machine(void)
}
error:
pr_info("DMI not present or invalid.\n");
- out:
- dmi_initialized = 1;
}
static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
@@ -715,10 +704,8 @@ static int __init dmi_init(void)
u8 *dmi_table;
int ret = -ENOMEM;
- if (!dmi_available) {
- ret = -ENODATA;
- goto err;
- }
+ if (!dmi_available)
+ return 0;
/*
* Set up dmi directory at /sys/firmware/dmi. This entry should stay
@@ -784,19 +771,20 @@ static bool dmi_matches(const struct dmi_system_id *dmi)
{
int i;
- WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
-
for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
int s = dmi->matches[i].slot;
if (s == DMI_NONE)
break;
if (dmi_ident[s]) {
- if (!dmi->matches[i].exact_match &&
- strstr(dmi_ident[s], dmi->matches[i].substr))
- continue;
- else if (dmi->matches[i].exact_match &&
- !strcmp(dmi_ident[s], dmi->matches[i].substr))
- continue;
+ if (dmi->matches[i].exact_match) {
+ if (!strcmp(dmi_ident[s],
+ dmi->matches[i].substr))
+ continue;
+ } else {
+ if (strstr(dmi_ident[s],
+ dmi->matches[i].substr))
+ continue;
+ }
}
/* No match */
@@ -826,6 +814,8 @@ static bool dmi_is_end_of_table(const struct dmi_system_id *dmi)
* Walk the blacklist table running matching functions until someone
* returns non zero or we hit the end. Callback function is called for
* each successful match. Returns the number of matches.
+ *
+ * dmi_scan_machine must be called before this function is called.
*/
int dmi_check_system(const struct dmi_system_id *list)
{
@@ -854,6 +844,8 @@ EXPORT_SYMBOL(dmi_check_system);
*
* Walk the blacklist table until the first match is found. Return the
* pointer to the matching entry or NULL if there's no match.
+ *
+ * dmi_scan_machine must be called before this function is called.
*/
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
{
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index 016d7427ebfa..761d8279abca 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -505,4 +505,4 @@ module_platform_driver(uniphier_gpio_driver);
MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
MODULE_DESCRIPTION("UniPhier GPIO driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 0ecffd172a80..e2232cbcec8b 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -58,58 +58,6 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
return ACPI_HANDLE(gc->parent) == data;
}
-#ifdef CONFIG_PINCTRL
-/**
- * acpi_gpiochip_pin_to_gpio_offset() - translates ACPI GPIO to Linux GPIO
- * @gdev: GPIO device
- * @pin: ACPI GPIO pin number from GpioIo/GpioInt resource
- *
- * Function takes ACPI GpioIo/GpioInt pin number as a parameter and
- * translates it to a corresponding offset suitable to be passed to a
- * GPIO controller driver.
- *
- * Typically the returned offset is same as @pin, but if the GPIO
- * controller uses pin controller and the mapping is not contiguous the
- * offset might be different.
- */
-static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev, int pin)
-{
- struct gpio_pin_range *pin_range;
-
- /* If there are no ranges in this chip, use 1:1 mapping */
- if (list_empty(&gdev->pin_ranges))
- return pin;
-
- list_for_each_entry(pin_range, &gdev->pin_ranges, node) {
- const struct pinctrl_gpio_range *range = &pin_range->range;
- int i;
-
- if (range->pins) {
- for (i = 0; i < range->npins; i++) {
- if (range->pins[i] == pin)
- return range->base + i - gdev->base;
- }
- } else {
- if (pin >= range->pin_base &&
- pin < range->pin_base + range->npins) {
- unsigned gpio_base;
-
- gpio_base = range->base - gdev->base;
- return gpio_base + pin - range->pin_base;
- }
- }
- }
-
- return -EINVAL;
-}
-#else
-static inline int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev,
- int pin)
-{
- return pin;
-}
-#endif
-
/**
* acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
* @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
@@ -125,7 +73,6 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
struct gpio_chip *chip;
acpi_handle handle;
acpi_status status;
- int offset;
status = acpi_get_handle(NULL, path, &handle);
if (ACPI_FAILURE(status))
@@ -135,11 +82,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
if (!chip)
return ERR_PTR(-EPROBE_DEFER);
- offset = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
- if (offset < 0)
- return ERR_PTR(offset);
-
- return gpiochip_get_desc(chip, offset);
+ return gpiochip_get_desc(chip, pin);
}
static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
@@ -216,10 +159,6 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
if (!handler)
return AE_OK;
- pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
- if (pin < 0)
- return AE_BAD_PARAMETER;
-
desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event");
if (IS_ERR(desc)) {
dev_err(chip->parent, "Failed to request GPIO\n");
@@ -871,12 +810,6 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
struct gpio_desc *desc;
bool found;
- pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
- if (pin < 0) {
- status = AE_BAD_PARAMETER;
- goto out;
- }
-
mutex_lock(&achip->conn_lock);
found = false;
@@ -1009,11 +942,7 @@ static struct gpio_desc *acpi_gpiochip_parse_own_gpio(
if (ret < 0)
return ERR_PTR(ret);
- ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]);
- if (ret < 0)
- return ERR_PTR(ret);
-
- desc = gpiochip_get_desc(chip, ret);
+ desc = gpiochip_get_desc(chip, gpios[0]);
if (IS_ERR(desc))
return desc;
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 1147bddb8b2c..3df0efd69ae3 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -649,6 +649,11 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
if (bit_adap->getscl == NULL)
adap->quirks = &i2c_bit_quirk_no_clk_stretch;
+ /* Bring bus to a known state. Looks like STOP if bus is not free yet */
+ setscl(bit_adap, 1);
+ udelay(bit_adap->udelay);
+ setsda(bit_adap, 1);
+
ret = add_adapter(adap);
if (ret < 0)
return ret;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 009345d8f49d..a9805c7cb305 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -603,6 +603,14 @@ config I2C_GPIO
This is a very simple bitbanging I2C driver utilizing the
arch-neutral GPIO API to control the SCL and SDA lines.
+config I2C_GPIO_FAULT_INJECTOR
+ bool "GPIO-based fault injector"
+ depends on I2C_GPIO
+ help
+ This adds some functionality to the i2c-gpio driver which can inject
+ faults to an I2C bus, so another bus master can be stress-tested.
+ This is for debugging. If unsure, say 'no'.
+
config I2C_HIGHLANDER
tristate "Highlander FPGA SMBus interface"
depends on SH_HIGHLANDER
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 9d7be5af2bf2..f4a5ae69bf6a 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/acorn/char/i2c.c
+ * ARM IOC/IOMD i2c driver.
*
* Copyright (C) 2000 Russell King
*
@@ -7,8 +7,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * ARM IOC/IOMD i2c driver.
- *
* On Acorn machines, the following i2c devices are on the bus:
* - PCF8583 real time clock & static RAM
*/
@@ -94,3 +92,7 @@ static int __init i2c_ioc_init(void)
}
module_init(i2c_ioc_init);
+
+MODULE_AUTHOR("Russell King <linux@armlinux.org.uk>");
+MODULE_DESCRIPTION("ARM IOC/IOMD i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 2ead9b9eebb7..75d6ab177055 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -33,7 +33,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/cpufreq.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/of_device.h>
#include <linux/platform_data/i2c-davinci.h>
#include <linux/pm_runtime.h>
@@ -139,7 +139,6 @@ struct davinci_i2c_dev {
u8 terminate;
struct i2c_adapter adapter;
#ifdef CONFIG_CPU_FREQ
- struct completion xfr_complete;
struct notifier_block freq_transition;
#endif
struct davinci_i2c_platform_data *pdata;
@@ -294,7 +293,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
}
/*
- * This routine does i2c bus recovery by using i2c_generic_gpio_recovery
+ * This routine does i2c bus recovery by using i2c_generic_scl_recovery
* which is provided by I2C Bus recovery infrastructure.
*/
static void davinci_i2c_prepare_recovery(struct i2c_adapter *adap)
@@ -316,7 +315,7 @@ static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap)
}
static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = {
- .recover_bus = i2c_generic_gpio_recovery,
+ .recover_bus = i2c_generic_scl_recovery,
.prepare_recovery = davinci_i2c_prepare_recovery,
.unprepare_recovery = davinci_i2c_unprepare_recovery,
};
@@ -567,9 +566,6 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
}
ret = num;
-#ifdef CONFIG_CPU_FREQ
- complete(&dev->xfr_complete);
-#endif
out:
pm_runtime_mark_last_busy(dev->dev);
@@ -717,13 +713,15 @@ static int i2c_davinci_cpufreq_transition(struct notifier_block *nb,
struct davinci_i2c_dev *dev;
dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
+
+ i2c_lock_adapter(&dev->adapter);
if (val == CPUFREQ_PRECHANGE) {
- wait_for_completion(&dev->xfr_complete);
davinci_i2c_reset_ctrl(dev, 0);
} else if (val == CPUFREQ_POSTCHANGE) {
i2c_davinci_calc_clk_dividers(dev);
davinci_i2c_reset_ctrl(dev, 1);
}
+ i2c_unlock_adapter(&dev->adapter);
return 0;
}
@@ -769,6 +767,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
struct davinci_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem;
+ struct i2c_bus_recovery_info *rinfo;
int r, irq;
irq = platform_get_irq(pdev, 0);
@@ -789,9 +788,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
}
init_completion(&dev->cmd_complete);
-#ifdef CONFIG_CPU_FREQ
- init_completion(&dev->xfr_complete);
-#endif
+
dev->dev = &pdev->dev;
dev->irq = irq;
dev->pdata = dev_get_platdata(&pdev->dev);
@@ -868,10 +865,20 @@ static int davinci_i2c_probe(struct platform_device *pdev)
if (dev->pdata->has_pfunc)
adap->bus_recovery_info = &davinci_i2c_scl_recovery_info;
- else if (dev->pdata->scl_pin) {
- adap->bus_recovery_info = &davinci_i2c_gpio_recovery_info;
- adap->bus_recovery_info->scl_gpio = dev->pdata->scl_pin;
- adap->bus_recovery_info->sda_gpio = dev->pdata->sda_pin;
+ else if (dev->pdata->gpio_recovery) {
+ rinfo = &davinci_i2c_gpio_recovery_info;
+ adap->bus_recovery_info = rinfo;
+ rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl",
+ GPIOD_OUT_HIGH_OPEN_DRAIN);
+ if (IS_ERR(rinfo->scl_gpiod)) {
+ r = PTR_ERR(rinfo->scl_gpiod);
+ goto err_unuse_clocks;
+ }
+ rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
+ if (IS_ERR(rinfo->sda_gpiod)) {
+ r = PTR_ERR(rinfo->sda_gpiod);
+ goto err_unuse_clocks;
+ }
}
adap->nr = pdev->id;
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index d1a69372432f..27ebd90de43b 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -21,6 +21,7 @@
* ----------------------------------------------------------------------------
*
*/
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/errno.h>
@@ -185,6 +186,19 @@ unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
return dev->get_clk_rate_khz(dev);
}
+int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare)
+{
+ if (IS_ERR(dev->clk))
+ return PTR_ERR(dev->clk);
+
+ if (prepare)
+ return clk_prepare_enable(dev->clk);
+
+ clk_disable_unprepare(dev->clk);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(i2c_dw_prepare_clk);
+
int i2c_dw_acquire_lock(struct dw_i2c_dev *dev)
{
int ret;
@@ -217,7 +231,11 @@ int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
if (timeout <= 0) {
dev_warn(dev->dev, "timeout waiting for bus ready\n");
- return -ETIMEDOUT;
+ i2c_recover_bus(&dev->adapter);
+
+ if (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY)
+ return -ETIMEDOUT;
+ return 0;
}
timeout--;
usleep_range(1000, 1100);
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 9fee4c054d3d..8707c76b2fee 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -284,6 +284,7 @@ struct dw_i2c_dev {
void (*disable_int)(struct dw_i2c_dev *dev);
int (*init)(struct dw_i2c_dev *dev);
int mode;
+ struct i2c_bus_recovery_info rinfo;
};
#define ACCESS_SWAP 0x00000001
@@ -299,6 +300,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable);
void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable);
unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
+int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
void i2c_dw_release_lock(struct dw_i2c_dev *dev);
int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 418c233075d3..ae691884d071 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -25,11 +25,13 @@
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/export.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include "i2c-designware-core.h"
@@ -443,6 +445,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init implicitly disables the adapter */
+ i2c_recover_bus(&dev->adapter);
i2c_dw_init_master(dev);
ret = -ETIMEDOUT;
goto done;
@@ -613,6 +616,56 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
+static void i2c_dw_prepare_recovery(struct i2c_adapter *adap)
+{
+ struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+
+ i2c_dw_disable(dev);
+ reset_control_assert(dev->rst);
+ i2c_dw_prepare_clk(dev, false);
+}
+
+static void i2c_dw_unprepare_recovery(struct i2c_adapter *adap)
+{
+ struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+
+ i2c_dw_prepare_clk(dev, true);
+ reset_control_deassert(dev->rst);
+ i2c_dw_init_master(dev);
+}
+
+static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
+{
+ struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
+ struct i2c_adapter *adap = &dev->adapter;
+ struct gpio_desc *gpio;
+ int r;
+
+ gpio = devm_gpiod_get(dev->dev, "scl", GPIOD_OUT_HIGH);
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
+ if (r == -ENOENT)
+ return 0;
+ return r;
+ }
+ rinfo->scl_gpiod = gpio;
+
+ gpio = devm_gpiod_get_optional(dev->dev, "sda", GPIOD_IN);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
+ rinfo->sda_gpiod = gpio;
+
+ rinfo->recover_bus = i2c_generic_scl_recovery;
+ rinfo->prepare_recovery = i2c_dw_prepare_recovery;
+ rinfo->unprepare_recovery = i2c_dw_unprepare_recovery;
+ adap->bus_recovery_info = rinfo;
+
+ dev_info(dev->dev, "running with gpio recovery mode! scl%s",
+ rinfo->sda_gpiod ? ",sda" : "");
+
+ return 0;
+}
+
int i2c_dw_probe(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
@@ -652,6 +705,10 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
return ret;
}
+ ret = i2c_dw_init_recovery_info(dev);
+ if (ret)
+ return ret;
+
/*
* Increment PM usage count during adapter registration in order to
* avoid possible spurious runtime suspend when adapter device is
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 153b947702c5..5660daf6c92e 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -202,29 +202,6 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;
dev->mode = DW_IC_SLAVE;
-
- switch (dev->clk_freq) {
- case 100000:
- dev->slave_cfg |= DW_IC_CON_SPEED_STD;
- break;
- case 3400000:
- dev->slave_cfg |= DW_IC_CON_SPEED_HIGH;
- break;
- default:
- dev->slave_cfg |= DW_IC_CON_SPEED_FAST;
- }
-}
-
-static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
-{
- if (IS_ERR(i_dev->clk))
- return PTR_ERR(i_dev->clk);
-
- if (prepare)
- return clk_prepare_enable(i_dev->clk);
-
- clk_disable_unprepare(i_dev->clk);
- return 0;
}
static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
@@ -356,7 +333,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
i2c_dw_configure_master(dev);
dev->clk = devm_clk_get(&pdev->dev, NULL);
- if (!i2c_dw_plat_prepare_clk(dev, true)) {
+ if (!i2c_dw_prepare_clk(dev, true)) {
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
if (!dev->sda_hold_time && ht)
@@ -472,7 +449,7 @@ static int dw_i2c_plat_suspend(struct device *dev)
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
i_dev->disable(i_dev);
- i2c_dw_plat_prepare_clk(i_dev, false);
+ i2c_dw_prepare_clk(i_dev, false);
return 0;
}
@@ -481,7 +458,7 @@ static int dw_i2c_plat_resume(struct device *dev)
{
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
- i2c_dw_plat_prepare_clk(i_dev, true);
+ i2c_dw_prepare_clk(i_dev, true);
i_dev->init(i_dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index ea9578ab19a1..d42558d1b002 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -51,9 +51,7 @@ static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
*/
static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
{
- u32 sda_falling_time, scl_falling_time;
u32 reg, comp_param1;
- u32 hcnt, lcnt;
int ret;
ret = i2c_dw_acquire_lock(dev);
@@ -79,68 +77,6 @@ static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
/* Disable the adapter. */
__i2c_dw_enable_and_wait(dev, false);
- /* Set standard and fast speed deviders for high/low periods. */
- sda_falling_time = dev->sda_falling_time ?: 300; /* ns */
- scl_falling_time = dev->scl_falling_time ?: 300; /* ns */
-
- /* Set SCL timing parameters for standard-mode. */
- if (dev->ss_hcnt && dev->ss_lcnt) {
- hcnt = dev->ss_hcnt;
- lcnt = dev->ss_lcnt;
- } else {
- hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
- 4000, /* tHD;STA = tHIGH = 4.0 us */
- sda_falling_time,
- 0, /* 0: DW default, 1: Ideal */
- 0); /* No offset */
- lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
- 4700, /* tLOW = 4.7 us */
- scl_falling_time,
- 0); /* No offset */
- }
- dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
- dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
- dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
- /* Set SCL timing parameters for fast-mode or fast-mode plus. */
- if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) {
- hcnt = dev->fp_hcnt;
- lcnt = dev->fp_lcnt;
- } else if (dev->fs_hcnt && dev->fs_lcnt) {
- hcnt = dev->fs_hcnt;
- lcnt = dev->fs_lcnt;
- } else {
- hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
- 600, /* tHD;STA = tHIGH = 0.6 us */
- sda_falling_time,
- 0, /* 0: DW default, 1: Ideal */
- 0); /* No offset */
- lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
- 1300, /* tLOW = 1.3 us */
- scl_falling_time,
- 0); /* No offset */
- }
- dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
- dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
- dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
- if ((dev->slave_cfg & DW_IC_CON_SPEED_MASK) ==
- DW_IC_CON_SPEED_HIGH) {
- if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
- != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
- dev_err(dev->dev, "High Speed not supported!\n");
- dev->slave_cfg &= ~DW_IC_CON_SPEED_MASK;
- dev->slave_cfg |= DW_IC_CON_SPEED_FAST;
- } else if (dev->hs_hcnt && dev->hs_lcnt) {
- hcnt = dev->hs_hcnt;
- lcnt = dev->hs_lcnt;
- dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
- dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
- dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
- hcnt, lcnt);
- }
- }
-
/* Configure SDA Hold Time if required. */
reg = dw_readl(dev, DW_IC_COMP_VERSION);
if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 3855e0b11877..b02428498f6d 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -170,7 +170,7 @@
#define HSI2C_HS_TX_CLOCK 1000000
#define HSI2C_FS_TX_CLOCK 100000
-#define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(1000))
+#define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(100))
#define HSI2C_EXYNOS7 BIT(0)
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index d80ea6ce91bb..58abb3eced58 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -7,6 +7,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/debugfs.h>
+#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
@@ -23,6 +25,9 @@ struct i2c_gpio_private_data {
struct i2c_adapter adap;
struct i2c_algo_bit_data bit_data;
struct i2c_gpio_platform_data pdata;
+#ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR
+ struct dentry *debug_dir;
+#endif
};
/*
@@ -34,7 +39,7 @@ static void i2c_gpio_setsda_val(void *data, int state)
{
struct i2c_gpio_private_data *priv = data;
- gpiod_set_value(priv->sda, state);
+ gpiod_set_value_cansleep(priv->sda, state);
}
/*
@@ -47,23 +52,125 @@ static void i2c_gpio_setscl_val(void *data, int state)
{
struct i2c_gpio_private_data *priv = data;
- gpiod_set_value(priv->scl, state);
+ gpiod_set_value_cansleep(priv->scl, state);
}
static int i2c_gpio_getsda(void *data)
{
struct i2c_gpio_private_data *priv = data;
- return gpiod_get_value(priv->sda);
+ return gpiod_get_value_cansleep(priv->sda);
}
static int i2c_gpio_getscl(void *data)
{
struct i2c_gpio_private_data *priv = data;
- return gpiod_get_value(priv->scl);
+ return gpiod_get_value_cansleep(priv->scl);
+}
+
+#ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR
+static struct dentry *i2c_gpio_debug_dir;
+
+#define setsda(bd, val) ((bd)->setsda((bd)->data, val))
+#define setscl(bd, val) ((bd)->setscl((bd)->data, val))
+#define getsda(bd) ((bd)->getsda((bd)->data))
+#define getscl(bd) ((bd)->getscl((bd)->data))
+
+#define WIRE_ATTRIBUTE(wire) \
+static int fops_##wire##_get(void *data, u64 *val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_adapter(&priv->adap); \
+ *val = get##wire(&priv->bit_data); \
+ i2c_unlock_adapter(&priv->adap); \
+ return 0; \
+} \
+static int fops_##wire##_set(void *data, u64 val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_adapter(&priv->adap); \
+ set##wire(&priv->bit_data, val); \
+ i2c_unlock_adapter(&priv->adap); \
+ return 0; \
+} \
+DEFINE_DEBUGFS_ATTRIBUTE(fops_##wire, fops_##wire##_get, fops_##wire##_set, "%llu\n")
+
+WIRE_ATTRIBUTE(scl);
+WIRE_ATTRIBUTE(sda);
+
+static int fops_incomplete_transfer_set(void *data, u64 addr)
+{
+ struct i2c_gpio_private_data *priv = data;
+ struct i2c_algo_bit_data *bit_data = &priv->bit_data;
+ int i, pattern;
+
+ if (addr > 0x7f)
+ return -EINVAL;
+
+ /* ADDR (7 bit) + RD (1 bit) + SDA hi (1 bit) */
+ pattern = (addr << 2) | 3;
+
+ i2c_lock_adapter(&priv->adap);
+
+ /* START condition */
+ setsda(bit_data, 0);
+ udelay(bit_data->udelay);
+
+ /* Send ADDR+RD, request ACK, don't send STOP */
+ for (i = 8; i >= 0; i--) {
+ setscl(bit_data, 0);
+ udelay(bit_data->udelay / 2);
+ setsda(bit_data, (pattern >> i) & 1);
+ udelay((bit_data->udelay + 1) / 2);
+ setscl(bit_data, 1);
+ udelay(bit_data->udelay);
+ }
+
+ i2c_unlock_adapter(&priv->adap);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_transfer, NULL, fops_incomplete_transfer_set, "%llu\n");
+
+static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
+{
+ struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev);
+
+ /*
+ * If there will be a debugfs-dir per i2c adapter somewhen, put the
+ * 'fault-injector' dir there. Until then, we have a global dir with
+ * all adapters as subdirs.
+ */
+ if (!i2c_gpio_debug_dir) {
+ i2c_gpio_debug_dir = debugfs_create_dir("i2c-fault-injector", NULL);
+ if (!i2c_gpio_debug_dir)
+ return;
+ }
+
+ priv->debug_dir = debugfs_create_dir(pdev->name, i2c_gpio_debug_dir);
+ if (!priv->debug_dir)
+ return;
+
+ debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl);
+ debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda);
+ debugfs_create_file_unsafe("incomplete_transfer", 0200, priv->debug_dir,
+ priv, &fops_incomplete_transfer);
}
+static void i2c_gpio_fault_injector_exit(struct platform_device *pdev)
+{
+ struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev);
+
+ debugfs_remove_recursive(priv->debug_dir);
+}
+#else
+static inline void i2c_gpio_fault_injector_init(struct platform_device *pdev) {}
+static inline void i2c_gpio_fault_injector_exit(struct platform_device *pdev) {}
+#endif /* CONFIG_I2C_GPIO_FAULT_INJECTOR*/
+
static void of_i2c_gpio_get_props(struct device_node *np,
struct i2c_gpio_platform_data *pdata)
{
@@ -179,6 +286,9 @@ static int i2c_gpio_probe(struct platform_device *pdev)
if (IS_ERR(priv->scl))
return PTR_ERR(priv->scl);
+ if (gpiod_cansleep(priv->sda) || gpiod_cansleep(priv->scl))
+ dev_warn(dev, "Slow GPIO pins might wreak havoc into I2C/SMBus bus timing");
+
bit_data->setsda = i2c_gpio_setsda_val;
bit_data->setscl = i2c_gpio_setscl_val;
@@ -228,6 +338,8 @@ static int i2c_gpio_probe(struct platform_device *pdev)
pdata->scl_is_output_only
? ", no clock stretching" : "");
+ i2c_gpio_fault_injector_init(pdev);
+
return 0;
}
@@ -236,6 +348,8 @@ static int i2c_gpio_remove(struct platform_device *pdev)
struct i2c_gpio_private_data *priv;
struct i2c_adapter *adap;
+ i2c_gpio_fault_injector_exit(pdev);
+
priv = platform_get_drvdata(pdev);
adap = &priv->adap;
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index e86801a63120..e6da2c7a9a3e 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -30,6 +30,7 @@
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -90,6 +91,8 @@
#define FAST_PLUS_MAX_BITRATE 3400000
#define HIGHSPEED_MAX_BITRATE 5000000
+#define I2C_PM_TIMEOUT 10 /* ms */
+
enum lpi2c_imx_mode {
STANDARD, /* 100+Kbps */
FAST, /* 400+Kbps */
@@ -274,8 +277,8 @@ static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
unsigned int temp;
int ret;
- ret = clk_enable(lpi2c_imx->clk);
- if (ret)
+ ret = pm_runtime_get_sync(lpi2c_imx->adapter.dev.parent);
+ if (ret < 0)
return ret;
temp = MCR_RST;
@@ -284,7 +287,7 @@ static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
ret = lpi2c_imx_config(lpi2c_imx);
if (ret)
- goto clk_disable;
+ goto rpm_put;
temp = readl(lpi2c_imx->base + LPI2C_MCR);
temp |= MCR_MEN;
@@ -292,8 +295,9 @@ static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
return 0;
-clk_disable:
- clk_disable(lpi2c_imx->clk);
+rpm_put:
+ pm_runtime_mark_last_busy(lpi2c_imx->adapter.dev.parent);
+ pm_runtime_put_autosuspend(lpi2c_imx->adapter.dev.parent);
return ret;
}
@@ -306,7 +310,8 @@ static int lpi2c_imx_master_disable(struct lpi2c_imx_struct *lpi2c_imx)
temp &= ~MCR_MEN;
writel(temp, lpi2c_imx->base + LPI2C_MCR);
- clk_disable(lpi2c_imx->clk);
+ pm_runtime_mark_last_busy(lpi2c_imx->adapter.dev.parent);
+ pm_runtime_put_autosuspend(lpi2c_imx->adapter.dev.parent);
return 0;
}
@@ -606,22 +611,31 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
return ret;
}
+ pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
temp = readl(lpi2c_imx->base + LPI2C_PARAM);
lpi2c_imx->txfifosize = 1 << (temp & 0x0f);
lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f);
- clk_disable(lpi2c_imx->clk);
-
ret = i2c_add_adapter(&lpi2c_imx->adapter);
if (ret)
- goto clk_unprepare;
+ goto rpm_disable;
+
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
dev_info(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n");
return 0;
-clk_unprepare:
- clk_unprepare(lpi2c_imx->clk);
+rpm_disable:
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
return ret;
}
@@ -632,28 +646,48 @@ static int lpi2c_imx_remove(struct platform_device *pdev)
i2c_del_adapter(&lpi2c_imx->adapter);
- clk_unprepare(lpi2c_imx->clk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
-static int lpi2c_imx_suspend(struct device *dev)
+static int lpi2c_runtime_suspend(struct device *dev)
{
+ struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(lpi2c_imx->clk);
pinctrl_pm_select_sleep_state(dev);
return 0;
}
-static int lpi2c_imx_resume(struct device *dev)
+static int lpi2c_runtime_resume(struct device *dev)
{
+ struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
+ int ret;
+
pinctrl_pm_select_default_state(dev);
+ ret = clk_prepare_enable(lpi2c_imx->clk);
+ if (ret) {
+ dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
+ return ret;
+ }
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(imx_lpi2c_pm, lpi2c_imx_suspend, lpi2c_imx_resume);
+static const struct dev_pm_ops lpi2c_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(lpi2c_runtime_suspend,
+ lpi2c_runtime_resume, NULL)
+};
+#define IMX_LPI2C_PM (&lpi2c_pm_ops)
+#else
+#define IMX_LPI2C_PM NULL
+#endif
static struct platform_driver lpi2c_imx_driver = {
.probe = lpi2c_imx_probe,
@@ -661,7 +695,7 @@ static struct platform_driver lpi2c_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = lpi2c_imx_of_match,
- .pm = &imx_lpi2c_pm,
+ .pm = IMX_LPI2C_PM,
},
};
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index f96830ffd9f1..999557729ad2 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -37,6 +37,7 @@
#include <linux/dmapool.h>
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -46,7 +47,6 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
-#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/i2c-imx.h>
#include <linux/platform_device.h>
@@ -1006,26 +1006,26 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
PINCTRL_STATE_DEFAULT);
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
"gpio");
- rinfo->sda_gpio = of_get_named_gpio(pdev->dev.of_node, "sda-gpios", 0);
- rinfo->scl_gpio = of_get_named_gpio(pdev->dev.of_node, "scl-gpios", 0);
+ rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
+ rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH);
- if (rinfo->sda_gpio == -EPROBE_DEFER ||
- rinfo->scl_gpio == -EPROBE_DEFER) {
+ if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
+ PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
- } else if (!gpio_is_valid(rinfo->sda_gpio) ||
- !gpio_is_valid(rinfo->scl_gpio) ||
+ } else if (IS_ERR(rinfo->sda_gpiod) ||
+ IS_ERR(rinfo->scl_gpiod) ||
IS_ERR(i2c_imx->pinctrl_pins_default) ||
IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
dev_dbg(&pdev->dev, "recovery information incomplete\n");
return 0;
}
- dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
- rinfo->scl_gpio, rinfo->sda_gpio);
+ dev_dbg(&pdev->dev, "using scl%s for recovery\n",
+ rinfo->sda_gpiod ? ",sda" : "");
rinfo->prepare_recovery = i2c_imx_prepare_recovery;
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
- rinfo->recover_bus = i2c_generic_gpio_recovery;
+ rinfo->recover_bus = i2c_generic_scl_recovery;
i2c_imx->adapter.bus_recovery_info = rinfo;
return 0;
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
index b51adffa4841..0d1c3ec8cb40 100644
--- a/drivers/i2c/busses/i2c-ismt.c
+++ b/drivers/i2c/busses/i2c-ismt.c
@@ -172,7 +172,7 @@ struct ismt_priv {
dma_addr_t io_rng_dma; /* descriptor HW base addr */
u8 head; /* ring buffer head pointer */
struct completion cmp; /* interrupt completion */
- u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* temp R/W data buffer */
+ u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */
};
/**
@@ -320,10 +320,12 @@ static int ismt_process_desc(const struct ismt_desc *desc,
struct ismt_priv *priv, int size,
char read_write)
{
- u8 *dma_buffer = priv->dma_buffer;
+ u8 *dma_buffer = PTR_ALIGN(&priv->buffer[0], 16);
dev_dbg(&priv->pci_dev->dev, "Processing completed descriptor\n");
__ismt_desc_dump(&priv->pci_dev->dev, desc);
+ ismt_gen_reg_dump(priv);
+ ismt_mstr_reg_dump(priv);
if (desc->status & ISMT_DESC_SCS) {
if (read_write == I2C_SMBUS_WRITE &&
@@ -393,11 +395,12 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
struct ismt_desc *desc;
struct ismt_priv *priv = i2c_get_adapdata(adap);
struct device *dev = &priv->pci_dev->dev;
+ u8 *dma_buffer = PTR_ALIGN(&priv->buffer[0], 16);
desc = &priv->hw[priv->head];
/* Initialize the DMA buffer */
- memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer));
+ memset(priv->buffer, 0, sizeof(priv->buffer));
/* Initialize the descriptor */
memset(desc, 0, sizeof(struct ismt_desc));
@@ -446,8 +449,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->wr_len_cmd = 2;
dma_size = 2;
dma_direction = DMA_TO_DEVICE;
- priv->dma_buffer[0] = command;
- priv->dma_buffer[1] = data->byte;
+ dma_buffer[0] = command;
+ dma_buffer[1] = data->byte;
} else {
/* Read Byte */
dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: READ\n");
@@ -466,9 +469,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->wr_len_cmd = 3;
dma_size = 3;
dma_direction = DMA_TO_DEVICE;
- priv->dma_buffer[0] = command;
- priv->dma_buffer[1] = data->word & 0xff;
- priv->dma_buffer[2] = data->word >> 8;
+ dma_buffer[0] = command;
+ dma_buffer[1] = data->word & 0xff;
+ dma_buffer[2] = data->word >> 8;
} else {
/* Read Word */
dev_dbg(dev, "I2C_SMBUS_WORD_DATA: READ\n");
@@ -486,9 +489,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->rd_len = 2;
dma_size = 3;
dma_direction = DMA_BIDIRECTIONAL;
- priv->dma_buffer[0] = command;
- priv->dma_buffer[1] = data->word & 0xff;
- priv->dma_buffer[2] = data->word >> 8;
+ dma_buffer[0] = command;
+ dma_buffer[1] = data->word & 0xff;
+ dma_buffer[2] = data->word >> 8;
break;
case I2C_SMBUS_BLOCK_DATA:
@@ -499,8 +502,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
dma_direction = DMA_TO_DEVICE;
desc->wr_len_cmd = dma_size;
desc->control |= ISMT_DESC_BLK;
- priv->dma_buffer[0] = command;
- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
+ dma_buffer[0] = command;
+ memcpy(&dma_buffer[1], &data->block[1], dma_size - 1);
} else {
/* Block Read */
dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n");
@@ -527,8 +530,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
dma_direction = DMA_TO_DEVICE;
desc->wr_len_cmd = dma_size;
desc->control |= ISMT_DESC_I2C;
- priv->dma_buffer[0] = command;
- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
+ dma_buffer[0] = command;
+ memcpy(&dma_buffer[1], &data->block[1], dma_size - 1);
} else {
/* i2c Block Read */
dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n");
@@ -557,23 +560,22 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
if (dma_size != 0) {
dev_dbg(dev, " dev=%p\n", dev);
dev_dbg(dev, " data=%p\n", data);
- dev_dbg(dev, " dma_buffer=%p\n", priv->dma_buffer);
+ dev_dbg(dev, " dma_buffer=%p\n", dma_buffer);
dev_dbg(dev, " dma_size=%d\n", dma_size);
dev_dbg(dev, " dma_direction=%d\n", dma_direction);
dma_addr = dma_map_single(dev,
- priv->dma_buffer,
+ dma_buffer,
dma_size,
dma_direction);
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "Error in mapping dma buffer %p\n",
- priv->dma_buffer);
+ dma_buffer);
return -EIO;
}
- dev_dbg(dev, " dma_addr = 0x%016llX\n",
- (unsigned long long)dma_addr);
+ dev_dbg(dev, " dma_addr = %pad\n", &dma_addr);
desc->dptr_low = lower_32_bits(dma_addr);
desc->dptr_high = upper_32_bits(dma_addr);
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 88d15b92ec35..90f5d0407d73 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -57,6 +58,10 @@ enum {
STATE_WRITE,
};
+struct meson_i2c_data {
+ unsigned char div_factor;
+};
+
/**
* struct meson_i2c - Meson I2C device private data
*
@@ -64,7 +69,6 @@ enum {
* @dev: Pointer to device structure
* @regs: Base address of the device memory mapped registers
* @clk: Pointer to clock structure
- * @irq: IRQ number
* @msg: Pointer to the current I2C message
* @state: Current state in the driver state machine
* @last: Flag set for the last message in the transfer
@@ -75,6 +79,7 @@ enum {
* @done: Completion used to wait for transfer termination
* @tokens: Sequence of tokens to be written to the device
* @num_tokens: Number of tokens
+ * @data: Pointer to the controlller's platform data
*/
struct meson_i2c {
struct i2c_adapter adap;
@@ -93,6 +98,8 @@ struct meson_i2c {
struct completion done;
u32 tokens[2];
int num_tokens;
+
+ const struct meson_i2c_data *data;
};
static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask,
@@ -128,7 +135,7 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
unsigned long clk_rate = clk_get_rate(i2c->clk);
unsigned int div;
- div = DIV_ROUND_UP(clk_rate, freq * 4);
+ div = DIV_ROUND_UP(clk_rate, freq * i2c->data->div_factor);
/* clock divider has 12 bits */
if (div >= (1 << 12)) {
@@ -376,6 +383,9 @@ static int meson_i2c_probe(struct platform_device *pdev)
spin_lock_init(&i2c->lock);
init_completion(&i2c->done);
+ i2c->data = (const struct meson_i2c_data *)
+ of_device_get_match_data(&pdev->dev);
+
i2c->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c->clk)) {
dev_err(&pdev->dev, "can't get device clock\n");
@@ -440,11 +450,25 @@ static int meson_i2c_remove(struct platform_device *pdev)
return 0;
}
+static const struct meson_i2c_data i2c_meson6_data = {
+ .div_factor = 4,
+};
+
+static const struct meson_i2c_data i2c_gxbb_data = {
+ .div_factor = 4,
+};
+
+static const struct meson_i2c_data i2c_axg_data = {
+ .div_factor = 3,
+};
+
static const struct of_device_id meson_i2c_match[] = {
- { .compatible = "amlogic,meson6-i2c" },
- { .compatible = "amlogic,meson-gxbb-i2c" },
- { },
+ { .compatible = "amlogic,meson6-i2c", .data = &i2c_meson6_data },
+ { .compatible = "amlogic,meson-gxbb-i2c", .data = &i2c_gxbb_data },
+ { .compatible = "amlogic,meson-axg-i2c", .data = &i2c_axg_data },
+ {},
};
+
MODULE_DEVICE_TABLE(of, meson_i2c_match);
static struct platform_driver meson_i2c_driver = {
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 950a9d74f54d..d94f05c8b8b7 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -78,9 +78,7 @@ struct mpc_i2c_divider {
};
struct mpc_i2c_data {
- void (*setup)(struct device_node *node, struct mpc_i2c *i2c,
- u32 clock, u32 prescaler);
- u32 prescaler;
+ void (*setup)(struct device_node *node, struct mpc_i2c *i2c, u32 clock);
};
static inline void writeccr(struct mpc_i2c *i2c, u32 x)
@@ -201,7 +199,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
};
static int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
- int prescaler, u32 *real_clk)
+ u32 *real_clk)
{
const struct mpc_i2c_divider *div = NULL;
unsigned int pvr = mfspr(SPRN_PVR);
@@ -236,7 +234,7 @@ static int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
static void mpc_i2c_setup_52xx(struct device_node *node,
struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+ u32 clock)
{
int ret, fdr;
@@ -246,7 +244,7 @@ static void mpc_i2c_setup_52xx(struct device_node *node,
return;
}
- ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler, &i2c->real_clk);
+ ret = mpc_i2c_get_fdr_52xx(node, clock, &i2c->real_clk);
fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */
writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR);
@@ -258,7 +256,7 @@ static void mpc_i2c_setup_52xx(struct device_node *node,
#else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
static void mpc_i2c_setup_52xx(struct device_node *node,
struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+ u32 clock)
{
}
#endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
@@ -266,7 +264,7 @@ static void mpc_i2c_setup_52xx(struct device_node *node,
#ifdef CONFIG_PPC_MPC512x
static void mpc_i2c_setup_512x(struct device_node *node,
struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+ u32 clock)
{
struct device_node *node_ctrl;
void __iomem *ctrl;
@@ -289,12 +287,12 @@ static void mpc_i2c_setup_512x(struct device_node *node,
}
/* The clock setup for the 52xx works also fine for the 512x */
- mpc_i2c_setup_52xx(node, i2c, clock, prescaler);
+ mpc_i2c_setup_52xx(node, i2c, clock);
}
#else /* CONFIG_PPC_MPC512x */
static void mpc_i2c_setup_512x(struct device_node *node,
struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+ u32 clock)
{
}
#endif /* CONFIG_PPC_MPC512x */
@@ -332,14 +330,18 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void)
if (prop) {
/*
* Map and check POR Device Status Register 2
- * (PORDEVSR2) at 0xE0014
+ * (PORDEVSR2) at 0xE0014. Note than while MPC8533
+ * and MPC8544 indicate SEC frequency ratio
+ * configuration as bit 26 in PORDEVSR2, other MPC8xxx
+ * parts may store it differently or may not have it
+ * at all.
*/
reg = ioremap(get_immrbase() + *prop + 0x14, 0x4);
if (!reg)
printk(KERN_ERR
"Error: couldn't map PORDEVSR2\n");
else
- val = in_be32(reg) & 0x00000080; /* sec-cfg */
+ val = in_be32(reg) & 0x00000020; /* sec-cfg */
iounmap(reg);
}
}
@@ -350,7 +352,11 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void)
static u32 mpc_i2c_get_prescaler_8xxx(void)
{
- /* mpc83xx and mpc82xx all have prescaler 1 */
+ /*
+ * According to the AN2919 all MPC824x have prescaler 1, while MPC83xx
+ * may have prescaler 1, 2, or 3, depending on the power-on
+ * configuration.
+ */
u32 prescaler = 1;
/* mpc85xx */
@@ -367,6 +373,10 @@ static u32 mpc_i2c_get_prescaler_8xxx(void)
|| (SVR_SOC_VER(svr) == SVR_8610))
/* the above 85xx SoCs have prescaler 1 */
prescaler = 1;
+ else if ((SVR_SOC_VER(svr) == SVR_8533)
+ || (SVR_SOC_VER(svr) == SVR_8544))
+ /* the above 85xx SoCs have prescaler 3 or 2 */
+ prescaler = mpc_i2c_get_sec_cfg_8xxx() ? 3 : 2;
else
/* all the other 85xx have prescaler 2 */
prescaler = 2;
@@ -376,9 +386,10 @@ static u32 mpc_i2c_get_prescaler_8xxx(void)
}
static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
- u32 prescaler, u32 *real_clk)
+ u32 *real_clk)
{
const struct mpc_i2c_divider *div = NULL;
+ u32 prescaler = mpc_i2c_get_prescaler_8xxx();
u32 divider;
int i;
@@ -388,12 +399,6 @@ static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
return -EINVAL;
}
- /* Determine proper divider value */
- if (of_device_is_compatible(node, "fsl,mpc8544-i2c"))
- prescaler = mpc_i2c_get_sec_cfg_8xxx() ? 3 : 2;
- if (!prescaler)
- prescaler = mpc_i2c_get_prescaler_8xxx();
-
divider = fsl_get_sys_freq() / clock / prescaler;
pr_debug("I2C: src_clock=%d clock=%d divider=%d\n",
@@ -415,7 +420,7 @@ static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
static void mpc_i2c_setup_8xxx(struct device_node *node,
struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+ u32 clock)
{
int ret, fdr;
@@ -426,7 +431,7 @@ static void mpc_i2c_setup_8xxx(struct device_node *node,
return;
}
- ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler, &i2c->real_clk);
+ ret = mpc_i2c_get_fdr_8xxx(node, clock, &i2c->real_clk);
fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */
writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR);
@@ -440,7 +445,7 @@ static void mpc_i2c_setup_8xxx(struct device_node *node,
#else /* !CONFIG_FSL_SOC */
static void mpc_i2c_setup_8xxx(struct device_node *node,
struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+ u32 clock)
{
}
#endif /* CONFIG_FSL_SOC */
@@ -711,11 +716,11 @@ static int fsl_i2c_probe(struct platform_device *op)
if (match->data) {
const struct mpc_i2c_data *data = match->data;
- data->setup(op->dev.of_node, i2c, clock, data->prescaler);
+ data->setup(op->dev.of_node, i2c, clock);
} else {
/* Backwards compatibility */
if (of_get_property(op->dev.of_node, "dfsrr", NULL))
- mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock, 0);
+ mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock);
}
prop = of_get_property(op->dev.of_node, "fsl,timeout", &plen);
@@ -813,12 +818,10 @@ static const struct mpc_i2c_data mpc_i2c_data_8313 = {
static const struct mpc_i2c_data mpc_i2c_data_8543 = {
.setup = mpc_i2c_setup_8xxx,
- .prescaler = 2,
};
static const struct mpc_i2c_data mpc_i2c_data_8544 = {
.setup = mpc_i2c_setup_8xxx,
- .prescaler = 3,
};
static const struct of_device_id mpc_i2c_of_match[] = {
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 09d288ce0ddb..cf23a746cc17 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -61,6 +61,7 @@
#define I2C_DMA_HARD_RST 0x0002
#define I2C_DMA_4G_MODE 0x0001
+#define I2C_DEFAULT_CLK_DIV 5
#define I2C_DEFAULT_SPEED 100000 /* hz */
#define MAX_FS_MODE_SPEED 400000
#define MAX_HS_MODE_SPEED 3400000
@@ -127,6 +128,7 @@ enum I2C_REGS_OFFSET {
OFFSET_DEBUGSTAT = 0x64,
OFFSET_DEBUGCTRL = 0x68,
OFFSET_TRANSFER_LEN_AUX = 0x6c,
+ OFFSET_CLOCK_DIV = 0x70,
};
struct mtk_i2c_compatible {
@@ -136,6 +138,7 @@ struct mtk_i2c_compatible {
unsigned char auto_restart: 1;
unsigned char aux_len_reg: 1;
unsigned char support_33bits: 1;
+ unsigned char timing_adjust: 1;
};
struct mtk_i2c {
@@ -176,6 +179,15 @@ static const struct i2c_adapter_quirks mt7622_i2c_quirks = {
.max_num_msgs = 255,
};
+static const struct mtk_i2c_compatible mt2712_compat = {
+ .pmic_i2c = 0,
+ .dcm = 1,
+ .auto_restart = 1,
+ .aux_len_reg = 1,
+ .support_33bits = 1,
+ .timing_adjust = 1,
+};
+
static const struct mtk_i2c_compatible mt6577_compat = {
.quirks = &mt6577_i2c_quirks,
.pmic_i2c = 0,
@@ -183,6 +195,7 @@ static const struct mtk_i2c_compatible mt6577_compat = {
.auto_restart = 0,
.aux_len_reg = 0,
.support_33bits = 0,
+ .timing_adjust = 0,
};
static const struct mtk_i2c_compatible mt6589_compat = {
@@ -192,6 +205,7 @@ static const struct mtk_i2c_compatible mt6589_compat = {
.auto_restart = 0,
.aux_len_reg = 0,
.support_33bits = 0,
+ .timing_adjust = 0,
};
static const struct mtk_i2c_compatible mt7622_compat = {
@@ -201,6 +215,7 @@ static const struct mtk_i2c_compatible mt7622_compat = {
.auto_restart = 1,
.aux_len_reg = 1,
.support_33bits = 0,
+ .timing_adjust = 0,
};
static const struct mtk_i2c_compatible mt8173_compat = {
@@ -209,9 +224,11 @@ static const struct mtk_i2c_compatible mt8173_compat = {
.auto_restart = 1,
.aux_len_reg = 1,
.support_33bits = 1,
+ .timing_adjust = 0,
};
static const struct of_device_id mtk_i2c_of_match[] = {
+ { .compatible = "mediatek,mt2712-i2c", .data = &mt2712_compat },
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
@@ -271,6 +288,9 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
if (i2c->dev_comp->dcm)
writew(I2C_DCM_DISABLE, i2c->base + OFFSET_DCM_EN);
+ if (i2c->dev_comp->timing_adjust)
+ writew(I2C_DEFAULT_CLK_DIV - 1, i2c->base + OFFSET_CLOCK_DIV);
+
writew(i2c->timing_reg, i2c->base + OFFSET_TIMING);
writew(i2c->high_speed_reg, i2c->base + OFFSET_HS);
@@ -725,10 +745,6 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (!i2c)
return -ENOMEM;
- ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c);
- if (ret)
- return -EINVAL;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(i2c->base))
@@ -759,6 +775,13 @@ static int mtk_i2c_probe(struct platform_device *pdev)
i2c->adap.timeout = 2 * HZ;
i2c->adap.retries = 1;
+ ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c);
+ if (ret)
+ return -EINVAL;
+
+ if (i2c->dev_comp->timing_adjust)
+ i2c->clk_src_div *= I2C_DEFAULT_CLK_DIV;
+
if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
return -EINVAL;
@@ -838,10 +861,19 @@ static int mtk_i2c_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int mtk_i2c_resume(struct device *dev)
{
+ int ret;
struct mtk_i2c *i2c = dev_get_drvdata(dev);
+ ret = mtk_i2c_clock_enable(i2c);
+ if (ret) {
+ dev_err(dev, "clock enable failed!\n");
+ return ret;
+ }
+
mtk_i2c_init_hw(i2c);
+ mtk_i2c_clock_disable(i2c);
+
return 0;
}
#endif
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a832c45276a4..440fe4a96e68 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -135,6 +135,7 @@ struct mv64xxx_i2c_data {
u32 freq_m;
u32 freq_n;
struct clk *clk;
+ struct clk *reg_clk;
wait_queue_head_t waitq;
spinlock_t lock;
struct i2c_msg *msg;
@@ -894,13 +895,20 @@ mv64xxx_i2c_probe(struct platform_device *pd)
init_waitqueue_head(&drv_data->waitq);
spin_lock_init(&drv_data->lock);
- /* Not all platforms have a clk */
+ /* Not all platforms have clocks */
drv_data->clk = devm_clk_get(&pd->dev, NULL);
if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(drv_data->clk))
clk_prepare_enable(drv_data->clk);
+ drv_data->reg_clk = devm_clk_get(&pd->dev, "reg");
+ if (IS_ERR(drv_data->reg_clk) &&
+ PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (!IS_ERR(drv_data->reg_clk))
+ clk_prepare_enable(drv_data->reg_clk);
+
drv_data->irq = platform_get_irq(pd, 0);
if (pdata) {
@@ -950,9 +958,8 @@ exit_free_irq:
exit_reset:
reset_control_assert(drv_data->rstc);
exit_clk:
- /* Not all platforms have a clk */
- if (!IS_ERR(drv_data->clk))
- clk_disable_unprepare(drv_data->clk);
+ clk_disable_unprepare(drv_data->reg_clk);
+ clk_disable_unprepare(drv_data->clk);
return rc;
}
@@ -965,9 +972,8 @@ mv64xxx_i2c_remove(struct platform_device *dev)
i2c_del_adapter(&drv_data->adapter);
free_irq(drv_data->irq, drv_data);
reset_control_assert(drv_data->rstc);
- /* Not all platforms have a clk */
- if (!IS_ERR(drv_data->clk))
- clk_disable_unprepare(drv_data->clk);
+ clk_disable_unprepare(drv_data->reg_clk);
+ clk_disable_unprepare(drv_data->clk);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index d4e8f1954f23..e617bd600794 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -181,7 +181,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
if (msg->flags & I2C_M_RD) {
- i2c->dma_read = 1;
+ i2c->dma_read = true;
i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
/*
@@ -239,7 +239,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
goto read_init_dma_fail;
}
} else {
- i2c->dma_read = 0;
+ i2c->dma_read = false;
i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
/*
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 15d764afec3b..4159ebcec2bb 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -62,7 +62,7 @@
#define MIE (1 << 3) /* master if enable */
#define TSBE (1 << 2)
#define FSB (1 << 1) /* force stop bit */
-#define ESG (1 << 0) /* en startbit gen */
+#define ESG (1 << 0) /* enable start bit gen */
/* ICSSR (also for ICSIER) */
#define GCAR (1 << 6) /* general call received */
@@ -132,6 +132,7 @@ struct rcar_i2c_priv {
int pos;
u32 icccr;
u32 flags;
+ u8 recovery_icmcr; /* protected by adapter lock */
enum rcar_i2c_type devtype;
struct i2c_client *slave;
@@ -158,6 +159,46 @@ static u32 rcar_i2c_read(struct rcar_i2c_priv *priv, int reg)
return readl(priv->io + reg);
}
+static int rcar_i2c_get_scl(struct i2c_adapter *adap)
+{
+ struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ return !!(rcar_i2c_read(priv, ICMCR) & FSCL);
+
+};
+
+static void rcar_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+ struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ if (val)
+ priv->recovery_icmcr |= FSCL;
+ else
+ priv->recovery_icmcr &= ~FSCL;
+
+ rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
+};
+
+/* No get_sda, because the HW only reports its bus free logic, not SDA itself */
+
+static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val)
+{
+ struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ if (val)
+ priv->recovery_icmcr |= FSDA;
+ else
+ priv->recovery_icmcr &= ~FSDA;
+
+ rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
+};
+
+static struct i2c_bus_recovery_info rcar_i2c_bri = {
+ .get_scl = rcar_i2c_get_scl,
+ .set_scl = rcar_i2c_set_scl,
+ .set_sda = rcar_i2c_set_sda,
+ .recover_bus = i2c_generic_scl_recovery,
+};
static void rcar_i2c_init(struct rcar_i2c_priv *priv)
{
/* reset master mode */
@@ -170,7 +211,7 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
{
- int i;
+ int i, ret;
for (i = 0; i < LOOP_TIMEOUT; i++) {
/* make sure that bus is not busy */
@@ -179,7 +220,15 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
udelay(1);
}
- return -EBUSY;
+ /* Waiting did not help, try to recover */
+ priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL;
+ ret = i2c_recover_bus(&priv->adap);
+
+ /* No failure when recovering, so check bus busy bit again */
+ if (ret == 0)
+ ret = (rcar_i2c_read(priv, ICMCR) & FSDA) ? -EBUSY : 0;
+
+ return ret;
}
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, struct i2c_timings *t)
@@ -282,7 +331,7 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
/*
- * We don't have a testcase but the HW engineers say that the write order
+ * We don't have a test case but the HW engineers say that the write order
* of ICMSR and ICMCR depends on whether we issue START or REP_START. Since
* it didn't cause a drawback for me, let's rather be safe than sorry.
*/
@@ -359,7 +408,7 @@ static void rcar_i2c_dma(struct rcar_i2c_priv *priv)
int len;
/* Do not use DMA if it's not available or for messages < 8 bytes */
- if (IS_ERR(chan) || msg->len < 8)
+ if (IS_ERR(chan) || msg->len < 8 || !(msg->flags & I2C_M_DMA_SAFE))
return;
if (read) {
@@ -440,7 +489,7 @@ static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
/*
* Try to use DMA to transmit the rest of the data if
- * address transfer pashe just finished.
+ * address transfer phase just finished.
*/
if (msr & MAT)
rcar_i2c_dma(priv);
@@ -851,6 +900,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
adap->retries = 3;
adap->dev.parent = dev;
adap->dev.of_node = dev->of_node;
+ adap->bus_recovery_info = &rcar_i2c_bri;
i2c_set_adapdata(adap, priv);
strlcpy(adap->name, pdev->name, sizeof(adap->name));
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index fe234578380a..e1a18d989f83 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -161,6 +161,7 @@ enum rk3x_i2c_state {
};
/**
+ * struct rk3x_i2c_soc_data:
* @grf_offset: offset inside the grf regmap for setting the i2c type
* @calc_timings: Callback function for i2c timing information calculated
*/
@@ -194,7 +195,7 @@ struct rk3x_i2c_soc_data {
struct rk3x_i2c {
struct i2c_adapter adap;
struct device *dev;
- struct rk3x_i2c_soc_data *soc_data;
+ const struct rk3x_i2c_soc_data *soc_data;
/* Hardware resources */
void __iomem *regs;
@@ -1164,27 +1165,27 @@ static const struct rk3x_i2c_soc_data rk3399_soc_data = {
static const struct of_device_id rk3x_i2c_match[] = {
{
.compatible = "rockchip,rv1108-i2c",
- .data = (void *)&rv1108_soc_data
+ .data = &rv1108_soc_data
},
{
.compatible = "rockchip,rk3066-i2c",
- .data = (void *)&rk3066_soc_data
+ .data = &rk3066_soc_data
},
{
.compatible = "rockchip,rk3188-i2c",
- .data = (void *)&rk3188_soc_data
+ .data = &rk3188_soc_data
},
{
.compatible = "rockchip,rk3228-i2c",
- .data = (void *)&rk3228_soc_data
+ .data = &rk3228_soc_data
},
{
.compatible = "rockchip,rk3288-i2c",
- .data = (void *)&rk3288_soc_data
+ .data = &rk3288_soc_data
},
{
.compatible = "rockchip,rk3399-i2c",
- .data = (void *)&rk3399_soc_data
+ .data = &rk3399_soc_data
},
{},
};
@@ -1207,7 +1208,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
return -ENOMEM;
match = of_match_node(rk3x_i2c_match, np);
- i2c->soc_data = (struct rk3x_i2c_soc_data *)match->data;
+ i2c->soc_data = match->data;
/* use common interface to get I2C timing properties */
i2c_parse_fw_timings(&pdev->dev, &i2c->t, true);
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index c03acdf71397..d856bc211715 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -40,21 +40,21 @@
/* BUS: S A8 ACK P(*) */
/* IRQ: DTE WAIT */
/* ICIC: */
-/* ICCR: 0x94 0x90 */
+/* ICCR: 0x94 0x90 */
/* ICDR: A8 */
/* */
/* 1 byte transmit */
/* BUS: S A8 ACK D8(1) ACK P(*) */
/* IRQ: DTE WAIT WAIT */
/* ICIC: -DTE */
-/* ICCR: 0x94 0x90 */
+/* ICCR: 0x94 0x90 */
/* ICDR: A8 D8(1) */
/* */
/* 2 byte transmit */
/* BUS: S A8 ACK D8(1) ACK D8(2) ACK P(*) */
/* IRQ: DTE WAIT WAIT WAIT */
/* ICIC: -DTE */
-/* ICCR: 0x94 0x90 */
+/* ICCR: 0x94 0x90 */
/* ICDR: A8 D8(1) D8(2) */
/* */
/* 3 bytes or more, +---------+ gets repeated */
@@ -113,7 +113,6 @@ enum sh_mobile_i2c_op {
OP_TX_FIRST,
OP_TX,
OP_TX_STOP,
- OP_TX_STOP_DATA,
OP_TX_TO_RX,
OP_RX,
OP_RX_STOP,
@@ -145,11 +144,12 @@ struct sh_mobile_i2c_data {
struct dma_chan *dma_rx;
struct scatterlist sg;
enum dma_data_direction dma_direction;
+ u8 *dma_buf;
};
struct sh_mobile_dt_config {
int clks_per_count;
- void (*setup)(struct sh_mobile_i2c_data *pd);
+ int (*setup)(struct sh_mobile_i2c_data *pd);
};
#define IIC_FLAG_HAS_ICIC67 (1 << 0)
@@ -246,36 +246,10 @@ static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf)
return (((count_khz * (tHIGH + tf)) + 5000) / 10000);
}
-static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
+static int sh_mobile_i2c_check_timing(struct sh_mobile_i2c_data *pd)
{
- unsigned long i2c_clk_khz;
- u32 tHIGH, tLOW, tf;
- uint16_t max_val;
-
- /* Get clock rate after clock is enabled */
- clk_prepare_enable(pd->clk);
- i2c_clk_khz = clk_get_rate(pd->clk) / 1000;
- clk_disable_unprepare(pd->clk);
- i2c_clk_khz /= pd->clks_per_count;
-
- if (pd->bus_speed == STANDARD_MODE) {
- tLOW = 47; /* tLOW = 4.7 us */
- tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */
- tf = 3; /* tf = 0.3 us */
- } else if (pd->bus_speed == FAST_MODE) {
- tLOW = 13; /* tLOW = 1.3 us */
- tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */
- tf = 3; /* tf = 0.3 us */
- } else {
- dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
- pd->bus_speed);
- return -EINVAL;
- }
-
- pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf);
- pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf);
+ u16 max_val = pd->flags & IIC_FLAG_HAS_ICIC67 ? 0x1ff : 0xff;
- max_val = pd->flags & IIC_FLAG_HAS_ICIC67 ? 0x1ff : 0xff;
if (pd->iccl > max_val || pd->icch > max_val) {
dev_err(pd->dev, "timing values out of range: L/H=0x%x/0x%x\n",
pd->iccl, pd->icch);
@@ -298,35 +272,43 @@ static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
return 0;
}
-static void activate_ch(struct sh_mobile_i2c_data *pd)
+static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
{
- /* Wake up device and enable clock */
- pm_runtime_get_sync(pd->dev);
- clk_prepare_enable(pd->clk);
+ unsigned long i2c_clk_khz;
+ u32 tHIGH, tLOW, tf;
- /* Enable channel and configure rx ack */
- iic_set_clr(pd, ICCR, ICCR_ICE, 0);
+ i2c_clk_khz = clk_get_rate(pd->clk) / 1000 / pd->clks_per_count;
- /* Mask all interrupts */
- iic_wr(pd, ICIC, 0);
+ if (pd->bus_speed == STANDARD_MODE) {
+ tLOW = 47; /* tLOW = 4.7 us */
+ tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */
+ tf = 3; /* tf = 0.3 us */
+ } else if (pd->bus_speed == FAST_MODE) {
+ tLOW = 13; /* tLOW = 1.3 us */
+ tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */
+ tf = 3; /* tf = 0.3 us */
+ } else {
+ dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
+ pd->bus_speed);
+ return -EINVAL;
+ }
- /* Set the clock */
- iic_wr(pd, ICCL, pd->iccl & 0xff);
- iic_wr(pd, ICCH, pd->icch & 0xff);
+ pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf);
+ pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf);
+
+ return sh_mobile_i2c_check_timing(pd);
}
-static void deactivate_ch(struct sh_mobile_i2c_data *pd)
+static int sh_mobile_i2c_v2_init(struct sh_mobile_i2c_data *pd)
{
- /* Clear/disable interrupts */
- iic_wr(pd, ICSR, 0);
- iic_wr(pd, ICIC, 0);
+ unsigned long clks_per_cycle;
- /* Disable channel */
- iic_set_clr(pd, ICCR, 0, ICCR_ICE);
+ /* L = 5, H = 4, L + H = 9 */
+ clks_per_cycle = clk_get_rate(pd->clk) / pd->bus_speed;
+ pd->iccl = DIV_ROUND_UP(clks_per_cycle * 5 / 9 - 1, pd->clks_per_count);
+ pd->icch = DIV_ROUND_UP(clks_per_cycle * 4 / 9 - 5, pd->clks_per_count);
- /* Disable clock and mark device as idle */
- clk_disable_unprepare(pd->clk);
- pm_runtime_put_sync(pd->dev);
+ return sh_mobile_i2c_check_timing(pd);
}
static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
@@ -350,10 +332,7 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
case OP_TX: /* write data */
iic_wr(pd, ICDR, data);
break;
- case OP_TX_STOP_DATA: /* write data and issue a stop afterwards */
- iic_wr(pd, ICDR, data);
- /* fallthrough */
- case OP_TX_STOP: /* issue a stop */
+ case OP_TX_STOP: /* issue a stop (or rep_start) */
iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS
: ICCR_ICE | ICCR_TRS | ICCR_BBSY);
break;
@@ -387,11 +366,6 @@ static bool sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd)
return pd->pos == -1;
}
-static bool sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd)
-{
- return pd->pos == pd->msg->len - 1;
-}
-
static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd,
unsigned char *buf)
{
@@ -409,20 +383,12 @@ static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd)
unsigned char data;
if (pd->pos == pd->msg->len) {
- /* Send stop if we haven't yet (DMA case) */
- if (pd->send_stop && pd->stop_after_dma)
- i2c_op(pd, OP_TX_STOP, 0);
+ i2c_op(pd, OP_TX_STOP, 0);
return 1;
}
sh_mobile_i2c_get_data(pd, &data);
-
- if (sh_mobile_i2c_is_last_byte(pd))
- i2c_op(pd, OP_TX_STOP_DATA, data);
- else if (sh_mobile_i2c_is_first_byte(pd))
- i2c_op(pd, OP_TX_FIRST, data);
- else
- i2c_op(pd, OP_TX, data);
+ i2c_op(pd, sh_mobile_i2c_is_first_byte(pd) ? OP_TX_FIRST : OP_TX, data);
pd->pos++;
return 0;
@@ -464,8 +430,9 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
break;
}
data = i2c_op(pd, OP_RX_STOP_DATA, 0);
- } else
+ } else if (real_pos >= 0) {
data = i2c_op(pd, OP_RX, 0);
+ }
if (real_pos >= 0)
pd->msg->buf[real_pos] = data;
@@ -548,6 +515,8 @@ static void sh_mobile_i2c_dma_callback(void *data)
pd->pos = pd->msg->len;
pd->stop_after_dma = true;
+ i2c_release_dma_safe_msg_buf(pd->msg, pd->dma_buf);
+
iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE);
}
@@ -608,7 +577,7 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd)
if (IS_ERR(chan))
return;
- dma_addr = dma_map_single(chan->device->dev, pd->msg->buf, pd->msg->len, dir);
+ dma_addr = dma_map_single(chan->device->dev, pd->dma_buf, pd->msg->len, dir);
if (dma_mapping_error(chan->device->dev, dma_addr)) {
dev_dbg(pd->dev, "dma map failed, using PIO\n");
return;
@@ -651,10 +620,10 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
if (do_init) {
/* Initialize channel registers */
- iic_set_clr(pd, ICCR, 0, ICCR_ICE);
+ iic_wr(pd, ICCR, ICCR_SCP);
/* Enable channel and configure rx ack */
- iic_set_clr(pd, ICCR, ICCR_ICE, 0);
+ iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP);
/* Set the clock */
iic_wr(pd, ICCL, pd->iccl & 0xff);
@@ -665,7 +634,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
pd->pos = -1;
pd->sr = 0;
- if (pd->msg->len > 8)
+ pd->dma_buf = i2c_get_dma_safe_msg_buf(pd->msg, 8);
+ if (pd->dma_buf)
sh_mobile_i2c_xfer_dma(pd);
/* Enable all interrupts to begin with */
@@ -731,7 +701,8 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
int i;
long timeout;
- activate_ch(pd);
+ /* Wake up device and enable clock */
+ pm_runtime_get_sync(pd->dev);
/* Process all messages */
for (i = 0; i < num; i++) {
@@ -768,11 +739,13 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
break;
}
- deactivate_ch(pd);
+ /* Disable channel */
+ iic_wr(pd, ICCR, ICCR_SCP);
- if (!err)
- err = num;
- return err;
+ /* Disable clock and mark device as idle */
+ pm_runtime_put_sync(pd->dev);
+
+ return err ?: num;
}
static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
@@ -789,7 +762,7 @@ static const struct i2c_algorithm sh_mobile_i2c_algorithm = {
* r8a7740 chip has lasting errata on I2C I/O pad reset.
* this is work-around for it.
*/
-static void sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd)
+static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd)
{
iic_set_clr(pd, ICCR, ICCR_ICE, 0);
iic_rd(pd, ICCR); /* dummy read */
@@ -810,14 +783,23 @@ static void sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd)
udelay(10);
iic_wr(pd, ICCR, ICCR_TRS);
udelay(10);
+
+ return sh_mobile_i2c_init(pd);
}
static const struct sh_mobile_dt_config default_dt_config = {
.clks_per_count = 1,
+ .setup = sh_mobile_i2c_init,
};
static const struct sh_mobile_dt_config fast_clock_dt_config = {
.clks_per_count = 2,
+ .setup = sh_mobile_i2c_init,
+};
+
+static const struct sh_mobile_dt_config v2_freq_calc_dt_config = {
+ .clks_per_count = 2,
+ .setup = sh_mobile_i2c_v2_init,
};
static const struct sh_mobile_dt_config r8a7740_dt_config = {
@@ -828,7 +810,7 @@ static const struct sh_mobile_dt_config r8a7740_dt_config = {
static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
{ .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },
- { .compatible = "renesas,iic-r8a7790", .data = &fast_clock_dt_config },
+ { .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config },
{ .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config },
@@ -910,32 +892,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
return PTR_ERR(pd->reg);
ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed);
- pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
+ pd->bus_speed = (ret || !bus_speed) ? STANDARD_MODE : bus_speed;
pd->clks_per_count = 1;
- config = of_device_get_match_data(&dev->dev);
- if (config) {
- pd->clks_per_count = config->clks_per_count;
-
- if (config->setup)
- config->setup(pd);
- }
-
- /* The IIC blocks on SH-Mobile ARM processors
- * come with two new bits in ICIC.
- */
+ /* Newer variants come with two new bits in ICIC */
if (resource_size(res) > 0x17)
pd->flags |= IIC_FLAG_HAS_ICIC67;
- ret = sh_mobile_i2c_init(pd);
- if (ret)
- return ret;
-
- /* Init DMA */
- sg_init_table(&pd->sg, 1);
- pd->dma_direction = DMA_NONE;
- pd->dma_rx = pd->dma_tx = ERR_PTR(-EPROBE_DEFER);
-
/* Enable Runtime PM for this device.
*
* Also tell the Runtime PM core to ignore children
@@ -948,6 +911,24 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
*/
pm_suspend_ignore_children(&dev->dev, true);
pm_runtime_enable(&dev->dev);
+ pm_runtime_get_sync(&dev->dev);
+
+ config = of_device_get_match_data(&dev->dev);
+ if (config) {
+ pd->clks_per_count = config->clks_per_count;
+ ret = config->setup(pd);
+ } else {
+ ret = sh_mobile_i2c_init(pd);
+ }
+
+ pm_runtime_put_sync(&dev->dev);
+ if (ret)
+ return ret;
+
+ /* Init DMA */
+ sg_init_table(&pd->sg, 1);
+ pd->dma_direction = DMA_NONE;
+ pd->dma_rx = pd->dma_tx = ERR_PTR(-EPROBE_DEFER);
/* setup the private data */
adap = &pd->adap;
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index f7829a74140c..5a00bf443d06 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -27,7 +27,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/idr.h>
@@ -134,52 +134,22 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
/* i2c bus recovery routines */
static int get_scl_gpio_value(struct i2c_adapter *adap)
{
- return gpio_get_value(adap->bus_recovery_info->scl_gpio);
+ return gpiod_get_value_cansleep(adap->bus_recovery_info->scl_gpiod);
}
static void set_scl_gpio_value(struct i2c_adapter *adap, int val)
{
- gpio_set_value(adap->bus_recovery_info->scl_gpio, val);
+ gpiod_set_value_cansleep(adap->bus_recovery_info->scl_gpiod, val);
}
static int get_sda_gpio_value(struct i2c_adapter *adap)
{
- return gpio_get_value(adap->bus_recovery_info->sda_gpio);
+ return gpiod_get_value_cansleep(adap->bus_recovery_info->sda_gpiod);
}
-static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap)
+static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
{
- struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
- struct device *dev = &adap->dev;
- int ret = 0;
-
- ret = gpio_request_one(bri->scl_gpio, GPIOF_OPEN_DRAIN |
- GPIOF_OUT_INIT_HIGH, "i2c-scl");
- if (ret) {
- dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio);
- return ret;
- }
-
- if (bri->get_sda) {
- if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) {
- /* work without SDA polling */
- dev_warn(dev, "Can't get SDA gpio: %d. Not using SDA polling\n",
- bri->sda_gpio);
- bri->get_sda = NULL;
- }
- }
-
- return ret;
-}
-
-static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap)
-{
- struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
-
- if (bri->get_sda)
- gpio_free(bri->sda_gpio);
-
- gpio_free(bri->scl_gpio);
+ gpiod_set_value_cansleep(adap->bus_recovery_info->sda_gpiod, val);
}
/*
@@ -190,7 +160,7 @@ static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap)
#define RECOVERY_NDELAY 5000
#define RECOVERY_CLK_CNT 9
-static int i2c_generic_recovery(struct i2c_adapter *adap)
+int i2c_generic_scl_recovery(struct i2c_adapter *adap)
{
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
int i = 0, val = 1, ret = 0;
@@ -199,6 +169,8 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
bri->prepare_recovery(adap);
bri->set_scl(adap, val);
+ if (bri->set_sda)
+ bri->set_sda(adap, 1);
ndelay(RECOVERY_NDELAY);
/*
@@ -227,33 +199,25 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
if (bri->get_sda && !bri->get_sda(adap))
ret = -EBUSY;
+ /* If all went well, send STOP for a sane bus state. */
+ if (ret == 0 && bri->set_sda) {
+ bri->set_scl(adap, 0);
+ ndelay(RECOVERY_NDELAY / 2);
+ bri->set_sda(adap, 0);
+ ndelay(RECOVERY_NDELAY / 2);
+ bri->set_scl(adap, 1);
+ ndelay(RECOVERY_NDELAY / 2);
+ bri->set_sda(adap, 1);
+ ndelay(RECOVERY_NDELAY / 2);
+ }
+
if (bri->unprepare_recovery)
bri->unprepare_recovery(adap);
return ret;
}
-
-int i2c_generic_scl_recovery(struct i2c_adapter *adap)
-{
- return i2c_generic_recovery(adap);
-}
EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);
-int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
-{
- int ret;
-
- ret = i2c_get_gpios_for_recovery(adap);
- if (ret)
- return ret;
-
- ret = i2c_generic_recovery(adap);
- i2c_put_gpios_for_recovery(adap);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery);
-
int i2c_recover_bus(struct i2c_adapter *adap)
{
if (!adap->bus_recovery_info)
@@ -277,21 +241,19 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
goto err;
}
- /* Generic GPIO recovery */
- if (bri->recover_bus == i2c_generic_gpio_recovery) {
- if (!gpio_is_valid(bri->scl_gpio)) {
- err_str = "invalid SCL gpio";
- goto err;
- }
-
- if (gpio_is_valid(bri->sda_gpio))
- bri->get_sda = get_sda_gpio_value;
- else
- bri->get_sda = NULL;
-
+ if (bri->scl_gpiod && bri->recover_bus == i2c_generic_scl_recovery) {
bri->get_scl = get_scl_gpio_value;
bri->set_scl = set_scl_gpio_value;
- } else if (bri->recover_bus == i2c_generic_scl_recovery) {
+ if (bri->sda_gpiod) {
+ bri->get_sda = get_sda_gpio_value;
+ /* FIXME: add proper flag instead of '0' once available */
+ if (gpiod_get_direction(bri->sda_gpiod) == 0)
+ bri->set_sda = set_sda_gpio_value;
+ }
+ return;
+ }
+
+ if (bri->recover_bus == i2c_generic_scl_recovery) {
/* Generic SCL recovery */
if (!bri->set_scl || !bri->get_scl) {
err_str = "no {get|set}_scl() found";
@@ -1976,63 +1938,35 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
EXPORT_SYMBOL(i2c_transfer);
/**
- * i2c_master_send - issue a single I2C message in master transmit mode
- * @client: Handle to slave device
- * @buf: Data that will be written to the slave
- * @count: How many bytes to write, must be less than 64k since msg.len is u16
- *
- * Returns negative errno, or else the number of bytes written.
- */
-int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
-{
- int ret;
- struct i2c_adapter *adap = client->adapter;
- struct i2c_msg msg;
-
- msg.addr = client->addr;
- msg.flags = client->flags & I2C_M_TEN;
- msg.len = count;
- msg.buf = (char *)buf;
-
- ret = i2c_transfer(adap, &msg, 1);
-
- /*
- * If everything went ok (i.e. 1 msg transmitted), return #bytes
- * transmitted, else error code.
- */
- return (ret == 1) ? count : ret;
-}
-EXPORT_SYMBOL(i2c_master_send);
-
-/**
- * i2c_master_recv - issue a single I2C message in master receive mode
+ * i2c_transfer_buffer_flags - issue a single I2C message transferring data
+ * to/from a buffer
* @client: Handle to slave device
- * @buf: Where to store data read from slave
- * @count: How many bytes to read, must be less than 64k since msg.len is u16
+ * @buf: Where the data is stored
+ * @count: How many bytes to transfer, must be less than 64k since msg.len is u16
+ * @flags: The flags to be used for the message, e.g. I2C_M_RD for reads
*
- * Returns negative errno, or else the number of bytes read.
+ * Returns negative errno, or else the number of bytes transferred.
*/
-int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
+int i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf,
+ int count, u16 flags)
{
- struct i2c_adapter *adap = client->adapter;
- struct i2c_msg msg;
int ret;
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = flags | (client->flags & I2C_M_TEN),
+ .len = count,
+ .buf = buf,
+ };
- msg.addr = client->addr;
- msg.flags = client->flags & I2C_M_TEN;
- msg.flags |= I2C_M_RD;
- msg.len = count;
- msg.buf = buf;
-
- ret = i2c_transfer(adap, &msg, 1);
+ ret = i2c_transfer(client->adapter, &msg, 1);
/*
- * If everything went ok (i.e. 1 msg received), return #bytes received,
- * else error code.
+ * If everything went ok (i.e. 1 msg transferred), return #bytes
+ * transferred, else error code.
*/
return (ret == 1) ? count : ret;
}
-EXPORT_SYMBOL(i2c_master_recv);
+EXPORT_SYMBOL(i2c_transfer_buffer_flags);
/* ----------------------------------------------------
* the i2c address scanning function
@@ -2265,6 +2199,52 @@ void i2c_put_adapter(struct i2c_adapter *adap)
}
EXPORT_SYMBOL(i2c_put_adapter);
+/**
+ * i2c_get_dma_safe_msg_buf() - get a DMA safe buffer for the given i2c_msg
+ * @msg: the message to be checked
+ * @threshold: the minimum number of bytes for which using DMA makes sense
+ *
+ * Return: NULL if a DMA safe buffer was not obtained. Use msg->buf with PIO.
+ * Or a valid pointer to be used with DMA. After use, release it by
+ * calling i2c_release_dma_safe_msg_buf().
+ *
+ * This function must only be called from process context!
+ */
+u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold)
+{
+ if (msg->len < threshold)
+ return NULL;
+
+ if (msg->flags & I2C_M_DMA_SAFE)
+ return msg->buf;
+
+ pr_debug("using bounce buffer for addr=0x%02x, len=%d\n",
+ msg->addr, msg->len);
+
+ if (msg->flags & I2C_M_RD)
+ return kzalloc(msg->len, GFP_KERNEL);
+ else
+ return kmemdup(msg->buf, msg->len, GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(i2c_get_dma_safe_msg_buf);
+
+/**
+ * i2c_release_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg
+ * @msg: the message to be synced with
+ * @buf: the buffer obtained from i2c_get_dma_safe_msg_buf(). May be NULL.
+ */
+void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf)
+{
+ if (!buf || buf == msg->buf)
+ return;
+
+ if (msg->flags & I2C_M_RD)
+ memcpy(msg->buf, buf, msg->len);
+
+ kfree(buf);
+}
+EXPORT_SYMBOL_GPL(i2c_release_dma_safe_msg_buf);
+
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index a1082c04ac5c..59d5cf376f6a 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -18,6 +18,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
+#include <linux/slab.h>
#define CREATE_TRACE_POINTS
#include <trace/events/smbus.h>
@@ -291,6 +292,22 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,
}
EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
+static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)
+{
+ bool is_read = msg->flags & I2C_M_RD;
+ unsigned char *dma_buf;
+
+ dma_buf = kzalloc(I2C_SMBUS_BLOCK_MAX + (is_read ? 2 : 3), GFP_KERNEL);
+ if (!dma_buf)
+ return;
+
+ msg->buf = dma_buf;
+ msg->flags |= I2C_M_DMA_SAFE;
+
+ if (init_val)
+ msg->buf[0] = init_val;
+}
+
/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
@@ -368,6 +385,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
msg[1].flags |= I2C_M_RECV_LEN;
msg[1].len = 1; /* block length will be added by
the underlying bus driver */
+ i2c_smbus_try_get_dmabuf(&msg[1], 0);
} else {
msg[0].len = data->block[0] + 2;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
@@ -376,8 +394,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
data->block[0]);
return -EINVAL;
}
+
+ i2c_smbus_try_get_dmabuf(&msg[0], command);
for (i = 1; i < msg[0].len; i++)
- msgbuf0[i] = data->block[i-1];
+ msg[0].buf[i] = data->block[i - 1];
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
@@ -389,12 +409,16 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
data->block[0]);
return -EINVAL;
}
+
msg[0].len = data->block[0] + 2;
+ i2c_smbus_try_get_dmabuf(&msg[0], command);
for (i = 1; i < msg[0].len; i++)
- msgbuf0[i] = data->block[i-1];
+ msg[0].buf[i] = data->block[i - 1];
+
msg[1].flags |= I2C_M_RECV_LEN;
msg[1].len = 1; /* block length will be added by
the underlying bus driver */
+ i2c_smbus_try_get_dmabuf(&msg[1], 0);
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
@@ -406,10 +430,13 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
if (read_write == I2C_SMBUS_READ) {
msg[1].len = data->block[0];
+ i2c_smbus_try_get_dmabuf(&msg[1], 0);
} else {
msg[0].len = data->block[0] + 1;
+
+ i2c_smbus_try_get_dmabuf(&msg[0], command);
for (i = 1; i <= data->block[0]; i++)
- msgbuf0[i] = data->block[i];
+ msg[0].buf[i] = data->block[i];
}
break;
default:
@@ -457,14 +484,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < data->block[0]; i++)
- data->block[i+1] = msgbuf1[i];
+ data->block[i + 1] = msg[1].buf[i];
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL:
- for (i = 0; i < msgbuf1[0] + 1; i++)
- data->block[i] = msgbuf1[i];
+ for (i = 0; i < msg[1].buf[0] + 1; i++)
+ data->block[i] = msg[1].buf[i];
break;
}
+
+ if (msg[0].flags & I2C_M_DMA_SAFE)
+ kfree(msg[0].buf);
+ if (msg[1].flags & I2C_M_DMA_SAFE)
+ kfree(msg[1].buf);
+
return 0;
}
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 2cab27a68479..036a03f0d0a6 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -264,6 +264,8 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
res = PTR_ERR(msgs[i].buf);
break;
}
+ /* memdup_user allocates with GFP_KERNEL, so DMA is ok */
+ msgs[i].flags |= I2C_M_DMA_SAFE;
/*
* If the message length is received from the slave (similar
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index 0f5c8fc36625..52a4a922e7e6 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -64,11 +64,11 @@ config I2C_MUX_PCA9541
will be called i2c-mux-pca9541.
config I2C_MUX_PCA954x
- tristate "Philips PCA954x I2C Mux/switches"
+ tristate "NXP PCA954x and PCA984x I2C Mux/switches"
depends on GPIOLIB || COMPILE_TEST
help
- If you say yes here you get support for the Philips PCA954x
- I2C mux/switch devices.
+ If you say yes here you get support for the NXP PCA954x
+ and PCA984x I2C mux/switch devices.
This driver can also be built as a module. If so, the module
will be called i2c-mux-pca954x.
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 2ca068d8b92d..fbb84c7ef282 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -4,11 +4,11 @@
* Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
* Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
*
- * This module supports the PCA954x series of I2C multiplexer/switch chips
- * made by Philips Semiconductors.
+ * This module supports the PCA954x and PCA954x series of I2C multiplexer/switch
+ * chips made by NXP Semiconductors.
* This includes the:
- * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547
- * and PCA9548.
+ * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547,
+ * PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849.
*
* These chips are all controlled via the I2C bus itself, and all have a
* single 8-bit register. The upstream "parent" bus fans out to two,
@@ -63,6 +63,10 @@ enum pca_type {
pca_9546,
pca_9547,
pca_9548,
+ pca_9846,
+ pca_9847,
+ pca_9848,
+ pca_9849,
};
struct chip_desc {
@@ -129,6 +133,24 @@ static const struct chip_desc chips[] = {
.nchans = 8,
.muxtype = pca954x_isswi,
},
+ [pca_9846] = {
+ .nchans = 4,
+ .muxtype = pca954x_isswi,
+ },
+ [pca_9847] = {
+ .nchans = 8,
+ .enable = 0x8,
+ .muxtype = pca954x_ismux,
+ },
+ [pca_9848] = {
+ .nchans = 8,
+ .muxtype = pca954x_isswi,
+ },
+ [pca_9849] = {
+ .nchans = 4,
+ .enable = 0x4,
+ .muxtype = pca954x_ismux,
+ },
};
static const struct i2c_device_id pca954x_id[] = {
@@ -140,6 +162,10 @@ static const struct i2c_device_id pca954x_id[] = {
{ "pca9546", pca_9546 },
{ "pca9547", pca_9547 },
{ "pca9548", pca_9548 },
+ { "pca9846", pca_9846 },
+ { "pca9847", pca_9847 },
+ { "pca9848", pca_9848 },
+ { "pca9849", pca_9849 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pca954x_id);
@@ -154,6 +180,10 @@ static const struct of_device_id pca954x_of_match[] = {
{ .compatible = "nxp,pca9546", .data = &chips[pca_9546] },
{ .compatible = "nxp,pca9547", .data = &chips[pca_9547] },
{ .compatible = "nxp,pca9548", .data = &chips[pca_9548] },
+ { .compatible = "nxp,pca9846", .data = &chips[pca_9846] },
+ { .compatible = "nxp,pca9847", .data = &chips[pca_9847] },
+ { .compatible = "nxp,pca9848", .data = &chips[pca_9848] },
+ { .compatible = "nxp,pca9849", .data = &chips[pca_9849] },
{}
};
MODULE_DEVICE_TABLE(of, pca954x_of_match);
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index f6c9c3dc6cad..c948e5a4cb04 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -177,6 +177,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
sizeof(mux->data));
} else {
ret = i2c_mux_reg_probe_dt(mux, pdev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
if (ret < 0) {
dev_err(&pdev->dev, "Error parsing device tree");
return ret;
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 31ab0dee2ce7..36f0fbe36c35 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Maxime Coquelin 2015
+ * Copyright (C) STMicroelectronics 2017
* Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
- * License terms: GNU General Public License (GPL), version 2
*/
#include <linux/bitops.h>
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 289800b5235d..4c8097e0e6fe 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -203,18 +203,17 @@ static int adb_scan_bus(void)
}
/* Now fill in the handler_id field of the adb_handler entries. */
- printk(KERN_DEBUG "adb devices:");
+ pr_debug("adb devices:\n");
for (i = 1; i < 16; i++) {
if (adb_handler[i].original_address == 0)
continue;
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
(i << 4) | 0xf);
adb_handler[i].handler_id = req.reply[2];
- printk(" [%d]: %d %x", i, adb_handler[i].original_address,
- adb_handler[i].handler_id);
+ pr_debug(" [%d]: %d %x\n", i, adb_handler[i].original_address,
+ adb_handler[i].handler_id);
devmask |= 1 << i;
}
- printk("\n");
return devmask;
}
@@ -225,9 +224,9 @@ static int adb_scan_bus(void)
static int
adb_probe_task(void *x)
{
- printk(KERN_INFO "adb: starting probe task...\n");
+ pr_debug("adb: starting probe task...\n");
do_adb_reset_bus();
- printk(KERN_INFO "adb: finished probe task...\n");
+ pr_debug("adb: finished probe task...\n");
up(&adb_probe_mutex);
@@ -337,7 +336,7 @@ static int __init adb_init(void)
adb_controller->init())
adb_controller = NULL;
if (adb_controller == NULL) {
- printk(KERN_WARNING "Warning: no ADB interface detected\n");
+ pr_warn("Warning: no ADB interface detected\n");
} else {
#ifdef CONFIG_PPC
if (of_machine_is_compatible("AAPL,PowerBook1998") ||
@@ -480,8 +479,7 @@ adb_register(int default_id, int handler_id, struct adb_ids *ids,
(!handler_id || (handler_id == adb_handler[i].handler_id) ||
try_handler_change(i, handler_id))) {
if (adb_handler[i].handler != 0) {
- printk(KERN_ERR
- "Two handlers for ADB device %d\n",
+ pr_err("Two handlers for ADB device %d\n",
default_id);
continue;
}
@@ -535,10 +533,10 @@ adb_input(unsigned char *buf, int nb, int autopoll)
id = buf[0] >> 4;
if (dump_adb_input) {
- printk(KERN_INFO "adb packet: ");
+ pr_info("adb packet: ");
for (i = 0; i < nb; ++i)
- printk(" %x", buf[i]);
- printk(", id = %d\n", id);
+ pr_cont(" %x", buf[i]);
+ pr_cont(", id = %d\n", id);
}
write_lock_irqsave(&adb_handler_lock, flags);
handler = adb_handler[id].handler;
@@ -884,7 +882,7 @@ static void __init
adbdev_init(void)
{
if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) {
- printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
+ pr_err("adb: unable to get major %d\n", ADB_MAJOR);
return;
}
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index e091193104f7..a261892c03b3 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -268,7 +268,7 @@ adbhid_keyboard_input(unsigned char *data, int nb, int apoll)
int id = (data[0] >> 4) & 0x0f;
if (!adbhid[id]) {
- printk(KERN_ERR "ADB HID on ID %d not yet registered, packet %#02x, %#02x, %#02x, %#02x\n",
+ pr_err("ADB HID on ID %d not yet registered, packet %#02x, %#02x, %#02x, %#02x\n",
id, data[0], data[1], data[2], data[3]);
return;
}
@@ -320,8 +320,7 @@ adbhid_input_keycode(int id, int scancode, int repeat)
ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE;
}
} else {
- printk(KERN_INFO "Spurious caps lock event "
- "(scancode 0xff).\n");
+ pr_info("Spurious caps lock event (scancode 0xff).\n");
}
}
}
@@ -397,8 +396,8 @@ adbhid_input_keycode(int id, int scancode, int repeat)
input_report_key(adbhid[id]->input, key, !up_flag);
input_sync(adbhid[id]->input);
} else
- printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
- up_flag ? "released" : "pressed");
+ pr_info("Unhandled ADB key (scancode %#02x) %s.\n", keycode,
+ up_flag ? "released" : "pressed");
}
@@ -408,7 +407,7 @@ adbhid_mouse_input(unsigned char *data, int nb, int autopoll)
int id = (data[0] >> 4) & 0x0f;
if (!adbhid[id]) {
- printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id);
+ pr_err("ADB HID on ID %d not yet registered\n", id);
return;
}
@@ -506,7 +505,7 @@ adbhid_buttons_input(unsigned char *data, int nb, int autopoll)
int id = (data[0] >> 4) & 0x0f;
if (!adbhid[id]) {
- printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id);
+ pr_err("ADB HID on ID %d not yet registered\n", id);
return;
}
@@ -534,8 +533,8 @@ adbhid_buttons_input(unsigned char *data, int nb, int autopoll)
break;
default:
- printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
- data[0], data[1], data[2], data[3]);
+ pr_info("Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
+ data[0], data[1], data[2], data[3]);
break;
}
}
@@ -609,14 +608,14 @@ adbhid_buttons_input(unsigned char *data, int nb, int autopoll)
break;
default:
- printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
- data[0], data[1], data[2], data[3]);
+ pr_info("Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
+ data[0], data[1], data[2], data[3]);
break;
}
break;
default:
- printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
- data[0], data[1], data[2], data[3]);
+ pr_info("Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
+ data[0], data[1], data[2], data[3]);
break;
}
}
@@ -760,7 +759,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
int i;
if (adbhid[id]) {
- printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);
+ pr_err("Trying to reregister ADB HID on ID %d\n", id);
return -EEXIST;
}
@@ -799,24 +798,24 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
- printk(KERN_INFO "Detected ADB keyboard, type ");
+ pr_info("Detected ADB keyboard, type ");
switch (original_handler_id) {
default:
- printk("<unknown>.\n");
+ pr_cont("<unknown>.\n");
input_dev->id.version = ADB_KEYBOARD_UNKNOWN;
break;
case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
case 0xC0: case 0xC3: case 0xC6:
- printk("ANSI.\n");
+ pr_cont("ANSI.\n");
input_dev->id.version = ADB_KEYBOARD_ANSI;
break;
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
case 0xC4: case 0xC7:
- printk("ISO, swapping keys.\n");
+ pr_cont("ISO, swapping keys.\n");
input_dev->id.version = ADB_KEYBOARD_ISO;
i = hid->keycode[10];
hid->keycode[10] = hid->keycode[50];
@@ -825,7 +824,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:
case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:
- printk("JIS.\n");
+ pr_cont("JIS.\n");
input_dev->id.version = ADB_KEYBOARD_JIS;
break;
}
@@ -884,7 +883,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
/* else fall through */
default:
- printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n");
+ pr_info("Trying to register unknown ADB device to input layer.\n");
err = -ENODEV;
goto fail;
}
@@ -1073,12 +1072,12 @@ adbhid_probe(void)
(req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) &&
(req.reply[3] == 0x49) && (req.reply[4] == 0x54)) {
if (adb_try_handler_change(id, 0x42)) {
- printk("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id);
+ pr_cont("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id);
mouse_kind = ADBMOUSE_MACALLY2;
}
}
}
- printk("\n");
+ pr_cont("\n");
adb_get_infos(id, &default_id, &cur_handler_id);
reg |= adbhid_input_reregister(id, default_id, org_handler_id,
@@ -1093,12 +1092,12 @@ init_trackpad(int id)
struct adb_request req;
unsigned char r1_buffer[8];
- printk(" (trackpad)");
+ pr_cont(" (trackpad)");
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
ADB_READREG(id,1));
if (req.reply_len < 8)
- printk("bad length for reg. 1\n");
+ pr_cont("bad length for reg. 1\n");
else
{
memcpy(r1_buffer, &req.reply[1], 8);
@@ -1146,7 +1145,7 @@ init_trackball(int id)
{
struct adb_request req;
- printk(" (trackman/mouseman)");
+ pr_cont(" (trackman/mouseman)");
adb_request(&req, NULL, ADBREQ_SYNC, 3,
ADB_WRITEREG(id,1), 00,0x81);
@@ -1178,7 +1177,7 @@ init_turbomouse(int id)
{
struct adb_request req;
- printk(" (TurboMouse 5)");
+ pr_cont(" (TurboMouse 5)");
adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
@@ -1214,7 +1213,7 @@ init_microspeed(int id)
{
struct adb_request req;
- printk(" (Microspeed/MacPoint or compatible)");
+ pr_cont(" (Microspeed/MacPoint or compatible)");
adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
@@ -1254,7 +1253,7 @@ init_ms_a3(int id)
{
struct adb_request req;
- printk(" (Mouse Systems A3 Mouse, or compatible)");
+ pr_cont(" (Mouse Systems A3 Mouse, or compatible)");
adb_request(&req, NULL, ADBREQ_SYNC, 3,
ADB_WRITEREG(id, 0x2),
0x00,
diff --git a/drivers/macintosh/ams/ams-input.c b/drivers/macintosh/ams/ams-input.c
index 2edae7dfcab2..fe248f6a30c1 100644
--- a/drivers/macintosh/ams/ams-input.c
+++ b/drivers/macintosh/ams/ams-input.c
@@ -91,7 +91,7 @@ static int ams_input_enable(void)
return error;
}
- joystick = 1;
+ joystick = true;
return 0;
}
@@ -104,7 +104,7 @@ static void ams_input_disable(void)
ams_info.idev = NULL;
}
- joystick = 0;
+ joystick = false;
}
static ssize_t ams_input_show_joystick(struct device *dev,
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index f433521a6f9d..d7cd5afa38cd 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -230,7 +230,7 @@ static void update_fans_speed (struct thermostat *th)
/* we don't care about local sensor, so we start at sensor 1 */
for (i = 1; i < 3; i++) {
- int started = 0;
+ bool started = false;
int fan_number = (th->type == ADT7460 && i == 2);
int var = th->temps[i] - th->limits[i];
@@ -243,7 +243,7 @@ static void update_fans_speed (struct thermostat *th)
if (abs(var - th->last_var[fan_number]) < 2)
continue;
- started = 1;
+ started = true;
new_speed = fan_speed + ((var-1)*step);
if (new_speed < fan_speed)
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index 89ed51571b62..50ada02ae75d 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -137,7 +137,7 @@ void pmu_backlight_set_sleep(int sleep)
}
#endif /* CONFIG_PM */
-void __init pmu_backlight_init()
+void __init pmu_backlight_init(void)
{
struct backlight_properties props;
struct backlight_device *bd;
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
index 96d16fca68b2..fec91db1142e 100644
--- a/drivers/macintosh/windfarm_pm112.c
+++ b/drivers/macintosh/windfarm_pm112.c
@@ -96,14 +96,14 @@ static int cpu_last_target;
static struct wf_pid_state backside_pid;
static int backside_tick;
static struct wf_pid_state slots_pid;
-static int slots_started;
+static bool slots_started;
static struct wf_pid_state drive_bay_pid;
static int drive_bay_tick;
static int nr_cores;
static int have_all_controls;
static int have_all_sensors;
-static int started;
+static bool started;
static int failure_state;
#define FAILURE_SENSOR 1
@@ -462,7 +462,7 @@ static void slots_fan_tick(void)
/* first time; initialize things */
printk(KERN_INFO "windfarm: Slots control loop started.\n");
wf_pid_init(&slots_pid, &slots_param);
- slots_started = 1;
+ slots_started = true;
}
err = slots_power->ops->get_value(slots_power, &power);
@@ -506,7 +506,7 @@ static void pm112_tick(void)
int i, last_failure;
if (!started) {
- started = 1;
+ started = true;
printk(KERN_INFO "windfarm: CPUs control loops started.\n");
for (i = 0; i < nr_cores; ++i) {
if (create_cpu_loop(i) < 0) {
diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c
index b350fb86ff08..4d72d8f58cb6 100644
--- a/drivers/macintosh/windfarm_pm121.c
+++ b/drivers/macintosh/windfarm_pm121.c
@@ -246,7 +246,8 @@ enum {
static struct wf_control *controls[N_CONTROLS] = {};
/* Set to kick the control loop into life */
-static int pm121_all_controls_ok, pm121_all_sensors_ok, pm121_started;
+static int pm121_all_controls_ok, pm121_all_sensors_ok;
+static bool pm121_started;
enum {
FAILURE_FAN = 1 << 0,
@@ -806,7 +807,7 @@ static void pm121_tick(void)
pm121_create_sys_fans(i);
pm121_create_cpu_fans();
- pm121_started = 1;
+ pm121_started = true;
}
/* skipping ticks */
diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c
index e88cfb36a74d..833021508c05 100644
--- a/drivers/macintosh/windfarm_pm72.c
+++ b/drivers/macintosh/windfarm_pm72.c
@@ -611,7 +611,7 @@ static void pm72_tick(void)
int i, last_failure;
if (!started) {
- started = 1;
+ started = true;
printk(KERN_INFO "windfarm: CPUs control loops started.\n");
for (i = 0; i < nr_chips; ++i) {
if (cpu_setup_pid(i) < 0) {
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index 93faf298a3c5..d9ea45581b9e 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -140,7 +140,8 @@ static struct wf_control *fan_system;
static struct wf_control *cpufreq_clamp;
/* Set to kick the control loop into life */
-static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok, wf_smu_started;
+static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok;
+static bool wf_smu_started;
/* Failure handling.. could be nicer */
#define FAILURE_FAN 0x01
@@ -549,7 +550,7 @@ static void wf_smu_tick(void)
DBG("wf: creating control loops !\n");
wf_smu_create_sys_fans();
wf_smu_create_cpu_fans();
- wf_smu_started = 1;
+ wf_smu_started = true;
}
/* Skipping ticks */
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index 81fdf40c5b82..7fd73dcb2b0a 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -75,7 +75,8 @@ static struct wf_control *fan_slots;
static struct wf_control *cpufreq_clamp;
/* Set to kick the control loop into life */
-static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok, wf_smu_started;
+static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok;
+static bool wf_smu_started;
static bool wf_smu_overtemp;
/* Failure handling.. could be nicer */
@@ -467,7 +468,7 @@ static void wf_smu_tick(void)
wf_smu_create_drive_fans();
wf_smu_create_slots_fans();
wf_smu_create_cpu_fans();
- wf_smu_started = 1;
+ wf_smu_started = true;
}
/* Skipping ticks */
diff --git a/drivers/macintosh/windfarm_rm31.c b/drivers/macintosh/windfarm_rm31.c
index a0cd9c7f9835..9ce87cc0597f 100644
--- a/drivers/macintosh/windfarm_rm31.c
+++ b/drivers/macintosh/windfarm_rm31.c
@@ -514,7 +514,7 @@ static void rm31_tick(void)
int i, last_failure;
if (!started) {
- started = 1;
+ started = true;
printk(KERN_INFO "windfarm: CPUs control loops started.\n");
for (i = 0; i < nr_chips; ++i) {
if (cpu_setup_pid(i) < 0) {
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
index 9924c6d7f05d..57bde0dfd12f 100644
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/mailbox_controller.h>
#define QCOM_APCS_IPC_BITS 32
@@ -26,8 +27,17 @@ struct qcom_apcs_ipc {
struct mbox_controller mbox;
struct mbox_chan mbox_chans[QCOM_APCS_IPC_BITS];
- void __iomem *reg;
+ struct regmap *regmap;
unsigned long offset;
+ struct platform_device *clk;
+};
+
+static const struct regmap_config apcs_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1000,
+ .fast_io = true,
};
static int qcom_apcs_ipc_send_data(struct mbox_chan *chan, void *data)
@@ -36,9 +46,7 @@ static int qcom_apcs_ipc_send_data(struct mbox_chan *chan, void *data)
struct qcom_apcs_ipc, mbox);
unsigned long idx = (unsigned long)chan->con_priv;
- writel(BIT(idx), apcs->reg);
-
- return 0;
+ return regmap_write(apcs->regmap, apcs->offset, BIT(idx));
}
static const struct mbox_chan_ops qcom_apcs_ipc_ops = {
@@ -47,7 +55,9 @@ static const struct mbox_chan_ops qcom_apcs_ipc_ops = {
static int qcom_apcs_ipc_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct qcom_apcs_ipc *apcs;
+ struct regmap *regmap;
struct resource *res;
unsigned long offset;
void __iomem *base;
@@ -63,9 +73,14 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
+ regmap = devm_regmap_init_mmio(&pdev->dev, base, &apcs_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
offset = (unsigned long)of_device_get_match_data(&pdev->dev);
- apcs->reg = base + offset;
+ apcs->regmap = regmap;
+ apcs->offset = offset;
/* Initialize channel identifiers */
for (i = 0; i < ARRAY_SIZE(apcs->mbox_chans); i++)
@@ -82,6 +97,14 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
return ret;
}
+ if (of_device_is_compatible(np, "qcom,msm8916-apcs-kpss-global")) {
+ apcs->clk = platform_device_register_data(&pdev->dev,
+ "qcom-apcs-msm8916-clk",
+ -1, NULL, 0);
+ if (IS_ERR(apcs->clk))
+ dev_err(&pdev->dev, "failed to register APCS clk\n");
+ }
+
platform_set_drvdata(pdev, apcs);
return 0;
@@ -90,8 +113,10 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
static int qcom_apcs_ipc_remove(struct platform_device *pdev)
{
struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
+ struct platform_device *clk = apcs->clk;
mbox_controller_unregister(&apcs->mbox);
+ platform_device_unregister(clk);
return 0;
}
diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c
index 54b9e4cb4cfa..78753a87ba4d 100644
--- a/drivers/mailbox/ti-msgmgr.c
+++ b/drivers/mailbox/ti-msgmgr.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Texas Instruments' Message Manager Driver
*
- * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -291,7 +283,7 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data)
desc = inst->desc;
if (desc->max_message_size < message->len) {
- dev_err(dev, "Queue %s message length %d > max %d\n",
+ dev_err(dev, "Queue %s message length %zu > max %d\n",
qinst->name, message->len, desc->max_message_size);
return -EINVAL;
}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6722073e339b..03605f8fc0dc 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -512,5 +512,6 @@ source "drivers/misc/mic/Kconfig"
source "drivers/misc/genwqe/Kconfig"
source "drivers/misc/echo/Kconfig"
source "drivers/misc/cxl/Kconfig"
+source "drivers/misc/ocxl/Kconfig"
source "drivers/misc/cardreader/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 8d8cc096063b..c3c8624f4d95 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -55,7 +55,8 @@ obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
-obj-$(CONFIG_MISC_RTSX) += cardreader/
+obj-$(CONFIG_OCXL) += ocxl/
+obj-$(CONFIG_MISC_RTSX) += cardreader/
lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index 12a41b2753f0..7ff315ad3692 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -45,6 +45,8 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
ctx->pid = NULL; /* Set in start work ioctl */
mutex_init(&ctx->mapping_lock);
ctx->mapping = NULL;
+ ctx->tidr = 0;
+ ctx->assign_tidr = false;
if (cxl_is_power8()) {
spin_lock_init(&ctx->sste_lock);
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index a798c2ccd67d..4f015da78f28 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -630,6 +630,9 @@ struct cxl_context {
struct list_head extra_irq_contexts;
struct mm_struct *mm;
+
+ u16 tidr;
+ bool assign_tidr;
};
struct cxl_irq_info;
diff --git a/drivers/misc/cxl/cxllib.c b/drivers/misc/cxl/cxllib.c
index dc9bc1807fdf..30ccba436b3b 100644
--- a/drivers/misc/cxl/cxllib.c
+++ b/drivers/misc/cxl/cxllib.c
@@ -199,10 +199,11 @@ int cxllib_get_PE_attributes(struct task_struct *task,
*/
attr->pid = mm->context.id;
mmput(mm);
+ attr->tid = task->thread.tidr;
} else {
attr->pid = 0;
+ attr->tid = 0;
}
- attr->tid = 0;
return 0;
}
EXPORT_SYMBOL_GPL(cxllib_get_PE_attributes);
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 90341ccda9bd..0162516f5e57 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -173,7 +173,7 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
* flags are set it's invalid
*/
if (work.reserved1 || work.reserved2 || work.reserved3 ||
- work.reserved4 || work.reserved5 || work.reserved6 ||
+ work.reserved4 || work.reserved5 ||
(work.flags & ~CXL_START_WORK_ALL)) {
rc = -EINVAL;
goto out;
@@ -186,12 +186,16 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
rc = -EINVAL;
goto out;
}
+
if ((rc = afu_register_irqs(ctx, work.num_interrupts)))
goto out;
if (work.flags & CXL_START_WORK_AMR)
amr = work.amr & mfspr(SPRN_UAMOR);
+ if (work.flags & CXL_START_WORK_TID)
+ ctx->assign_tidr = true;
+
ctx->mmio_err_ff = !!(work.flags & CXL_START_WORK_ERR_FF);
/*
@@ -263,8 +267,15 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
goto out;
}
- ctx->status = STARTED;
rc = 0;
+ if (work.flags & CXL_START_WORK_TID) {
+ work.tid = ctx->tidr;
+ if (copy_to_user(uwork, &work, sizeof(work)))
+ rc = -EFAULT;
+ }
+
+ ctx->status = STARTED;
+
out:
mutex_unlock(&ctx->status_mutex);
return rc;
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 02b6b45b4c20..1b3d7c65ea3f 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -16,6 +16,7 @@
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <asm/synch.h>
+#include <asm/switch_to.h>
#include <misc/cxl-base.h>
#include "cxl.h"
@@ -655,6 +656,7 @@ static void update_ivtes_directed(struct cxl_context *ctx)
static int process_element_entry_psl9(struct cxl_context *ctx, u64 wed, u64 amr)
{
u32 pid;
+ int rc;
cxl_assign_psn_space(ctx);
@@ -673,7 +675,16 @@ static int process_element_entry_psl9(struct cxl_context *ctx, u64 wed, u64 amr)
pid = ctx->mm->context.id;
}
- ctx->elem->common.tid = 0;
+ /* Assign a unique TIDR (thread id) for the current thread */
+ if (!(ctx->tidr) && (ctx->assign_tidr)) {
+ rc = set_thread_tidr(current);
+ if (rc)
+ return -ENODEV;
+ ctx->tidr = current->thread.tidr;
+ pr_devel("%s: current tidr: %d\n", __func__, ctx->tidr);
+ }
+
+ ctx->elem->common.tid = cpu_to_be32(ctx->tidr);
ctx->elem->common.pid = cpu_to_be32(pid);
ctx->elem->sr = cpu_to_be64(calculate_sr(ctx));
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 19969ee86d6f..758842f65a1b 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -125,8 +125,6 @@ static const struct pci_device_id cxl_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0601), },
{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0623), },
{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0628), },
- { PCI_DEVICE_CLASS(0x120000, ~0), },
-
{ }
};
MODULE_DEVICE_TABLE(pci, cxl_pci_tbl);
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index de58762097c4..68a1ac929917 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -4,6 +4,7 @@ config EEPROM_AT24
tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
depends on I2C && SYSFS
select NVMEM
+ select REGMAP_I2C
help
Enable this driver to get read/write support to most I2C EEPROMs
and compatible devices like FRAMs, SRAMs, ROMs etc. After you
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 4d63ac8a82e0..01f9c4921c50 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -24,8 +24,10 @@
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
#include <linux/platform_data/at24.h>
#include <linux/pm_runtime.h>
+#include <linux/gpio/consumer.h>
/*
* I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
@@ -55,14 +57,13 @@
* which won't work on pure SMBus systems.
*/
+struct at24_client {
+ struct i2c_client *client;
+ struct regmap *regmap;
+};
+
struct at24_data {
struct at24_platform_data chip;
- int use_smbus;
- int use_smbus_write;
-
- ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t);
- ssize_t (*write_func)(struct at24_data *,
- const char *, unsigned int, size_t);
/*
* Lock protects against activities from other Linux tasks,
@@ -70,18 +71,20 @@ struct at24_data {
*/
struct mutex lock;
- u8 *writebuf;
- unsigned write_max;
- unsigned num_addresses;
+ unsigned int write_max;
+ unsigned int num_addresses;
+ unsigned int offset_adj;
struct nvmem_config nvmem_config;
struct nvmem_device *nvmem;
+ struct gpio_desc *wp_gpio;
+
/*
* Some chips tie up multiple I2C addresses; dummy devices reserve
* them for us, and we'll use them with SMBus calls.
*/
- struct i2c_client *client[];
+ struct at24_client client[];
};
/*
@@ -93,27 +96,17 @@ struct at24_data {
*
* This value is forced to be a power of two so that writes align on pages.
*/
-static unsigned io_limit = 128;
-module_param(io_limit, uint, 0);
-MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)");
+static unsigned int at24_io_limit = 128;
+module_param_named(io_limit, at24_io_limit, uint, 0);
+MODULE_PARM_DESC(at24_io_limit, "Maximum bytes per I/O (default 128)");
/*
* Specs often allow 5 msec for a page write, sometimes 20 msec;
* it's important to recover from write timeouts.
*/
-static unsigned write_timeout = 25;
-module_param(write_timeout, uint, 0);
-MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
-
-#define AT24_SIZE_BYTELEN 5
-#define AT24_SIZE_FLAGS 8
-
-#define AT24_BITMASK(x) (BIT(x) - 1)
-
-/* create non-zero magic value for given eeprom parameters */
-#define AT24_DEVICE_MAGIC(_len, _flags) \
- ((1 << AT24_SIZE_FLAGS | (_flags)) \
- << AT24_SIZE_BYTELEN | ilog2(_len))
+static unsigned int at24_write_timeout = 25;
+module_param_named(write_timeout, at24_write_timeout, uint, 0);
+MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)");
/*
* Both reads and writes fail if the previous write didn't complete yet. This
@@ -126,118 +119,123 @@ MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
* iteration of processing the request. Both should be unsigned integers
* holding at least 32 bits.
*/
-#define loop_until_timeout(tout, op_time) \
- for (tout = jiffies + msecs_to_jiffies(write_timeout), op_time = 0; \
+#define at24_loop_until_timeout(tout, op_time) \
+ for (tout = jiffies + msecs_to_jiffies(at24_write_timeout), \
+ op_time = 0; \
op_time ? time_before(op_time, tout) : true; \
usleep_range(1000, 1500), op_time = jiffies)
+struct at24_chip_data {
+ /*
+ * these fields mirror their equivalents in
+ * struct at24_platform_data
+ */
+ u32 byte_len;
+ u8 flags;
+};
+
+#define AT24_CHIP_DATA(_name, _len, _flags) \
+ static const struct at24_chip_data _name = { \
+ .byte_len = _len, .flags = _flags, \
+ }
+
+/* needs 8 addresses as A0-A2 are ignored */
+AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR);
+/* old variants can't be handled with this generic entry! */
+AT24_CHIP_DATA(at24_data_24c01, 1024 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs01, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c02, 2048 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs02, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24mac402, 48 / 8,
+ AT24_FLAG_MAC | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24mac602, 64 / 8,
+ AT24_FLAG_MAC | AT24_FLAG_READONLY);
+/* spd is a 24c02 in memory DIMMs */
+AT24_CHIP_DATA(at24_data_spd, 2048 / 8,
+ AT24_FLAG_READONLY | AT24_FLAG_IRUGO);
+AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs04, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+/* 24rf08 quirk is handled at i2c-core */
+AT24_CHIP_DATA(at24_data_24c08, 8192 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs08, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c16, 16384 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs16, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c32, 32768 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24cs32, 16,
+ AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c64, 65536 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24cs64, 16,
+ AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c128, 131072 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c256, 262144 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c512, 524288 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c1024, 1048576 / 8, AT24_FLAG_ADDR16);
+/* identical to 24c08 ? */
+AT24_CHIP_DATA(at24_data_INT3499, 8192 / 8, 0);
+
static const struct i2c_device_id at24_ids[] = {
- /* needs 8 addresses as A0-A2 are ignored */
- { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
- /* old variants can't be handled with this generic entry! */
- { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
- { "24cs01", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
- { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
- { "24cs02", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
- { "24mac402", AT24_DEVICE_MAGIC(48 / 8,
- AT24_FLAG_MAC | AT24_FLAG_READONLY) },
- { "24mac602", AT24_DEVICE_MAGIC(64 / 8,
- AT24_FLAG_MAC | AT24_FLAG_READONLY) },
- /* spd is a 24c02 in memory DIMMs */
- { "spd", AT24_DEVICE_MAGIC(2048 / 8,
- AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
- { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
- { "24cs04", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
- /* 24rf08 quirk is handled at i2c-core */
- { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },
- { "24cs08", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
- { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },
- { "24cs16", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
- { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },
- { "24cs32", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_ADDR16 |
- AT24_FLAG_SERIAL |
- AT24_FLAG_READONLY) },
- { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },
- { "24cs64", AT24_DEVICE_MAGIC(16,
- AT24_FLAG_ADDR16 |
- AT24_FLAG_SERIAL |
- AT24_FLAG_READONLY) },
- { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },
- { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },
- { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },
- { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) },
- { "at24", 0 },
+ { "24c00", (kernel_ulong_t)&at24_data_24c00 },
+ { "24c01", (kernel_ulong_t)&at24_data_24c01 },
+ { "24cs01", (kernel_ulong_t)&at24_data_24cs01 },
+ { "24c02", (kernel_ulong_t)&at24_data_24c02 },
+ { "24cs02", (kernel_ulong_t)&at24_data_24cs02 },
+ { "24mac402", (kernel_ulong_t)&at24_data_24mac402 },
+ { "24mac602", (kernel_ulong_t)&at24_data_24mac602 },
+ { "spd", (kernel_ulong_t)&at24_data_spd },
+ { "24c04", (kernel_ulong_t)&at24_data_24c04 },
+ { "24cs04", (kernel_ulong_t)&at24_data_24cs04 },
+ { "24c08", (kernel_ulong_t)&at24_data_24c08 },
+ { "24cs08", (kernel_ulong_t)&at24_data_24cs08 },
+ { "24c16", (kernel_ulong_t)&at24_data_24c16 },
+ { "24cs16", (kernel_ulong_t)&at24_data_24cs16 },
+ { "24c32", (kernel_ulong_t)&at24_data_24c32 },
+ { "24cs32", (kernel_ulong_t)&at24_data_24cs32 },
+ { "24c64", (kernel_ulong_t)&at24_data_24c64 },
+ { "24cs64", (kernel_ulong_t)&at24_data_24cs64 },
+ { "24c128", (kernel_ulong_t)&at24_data_24c128 },
+ { "24c256", (kernel_ulong_t)&at24_data_24c256 },
+ { "24c512", (kernel_ulong_t)&at24_data_24c512 },
+ { "24c1024", (kernel_ulong_t)&at24_data_24c1024 },
+ { "at24", 0 },
{ /* END OF LIST */ }
};
MODULE_DEVICE_TABLE(i2c, at24_ids);
static const struct of_device_id at24_of_match[] = {
- {
- .compatible = "atmel,24c00",
- .data = (void *)AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR)
- },
- {
- .compatible = "atmel,24c01",
- .data = (void *)AT24_DEVICE_MAGIC(1024 / 8, 0)
- },
- {
- .compatible = "atmel,24c02",
- .data = (void *)AT24_DEVICE_MAGIC(2048 / 8, 0)
- },
- {
- .compatible = "atmel,spd",
- .data = (void *)AT24_DEVICE_MAGIC(2048 / 8,
- AT24_FLAG_READONLY | AT24_FLAG_IRUGO)
- },
- {
- .compatible = "atmel,24c04",
- .data = (void *)AT24_DEVICE_MAGIC(4096 / 8, 0)
- },
- {
- .compatible = "atmel,24c08",
- .data = (void *)AT24_DEVICE_MAGIC(8192 / 8, 0)
- },
- {
- .compatible = "atmel,24c16",
- .data = (void *)AT24_DEVICE_MAGIC(16384 / 8, 0)
- },
- {
- .compatible = "atmel,24c32",
- .data = (void *)AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16)
- },
- {
- .compatible = "atmel,24c64",
- .data = (void *)AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16)
- },
- {
- .compatible = "atmel,24c128",
- .data = (void *)AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16)
- },
- {
- .compatible = "atmel,24c256",
- .data = (void *)AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16)
- },
- {
- .compatible = "atmel,24c512",
- .data = (void *)AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16)
- },
- {
- .compatible = "atmel,24c1024",
- .data = (void *)AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16)
- },
- { },
+ { .compatible = "atmel,24c00", .data = &at24_data_24c00 },
+ { .compatible = "atmel,24c01", .data = &at24_data_24c01 },
+ { .compatible = "atmel,24cs01", .data = &at24_data_24cs01 },
+ { .compatible = "atmel,24c02", .data = &at24_data_24c02 },
+ { .compatible = "atmel,24cs02", .data = &at24_data_24cs02 },
+ { .compatible = "atmel,24mac402", .data = &at24_data_24mac402 },
+ { .compatible = "atmel,24mac602", .data = &at24_data_24mac602 },
+ { .compatible = "atmel,spd", .data = &at24_data_spd },
+ { .compatible = "atmel,24c04", .data = &at24_data_24c04 },
+ { .compatible = "atmel,24cs04", .data = &at24_data_24cs04 },
+ { .compatible = "atmel,24c08", .data = &at24_data_24c08 },
+ { .compatible = "atmel,24cs08", .data = &at24_data_24cs08 },
+ { .compatible = "atmel,24c16", .data = &at24_data_24c16 },
+ { .compatible = "atmel,24cs16", .data = &at24_data_24cs16 },
+ { .compatible = "atmel,24c32", .data = &at24_data_24c32 },
+ { .compatible = "atmel,24cs32", .data = &at24_data_24cs32 },
+ { .compatible = "atmel,24c64", .data = &at24_data_24c64 },
+ { .compatible = "atmel,24cs64", .data = &at24_data_24cs64 },
+ { .compatible = "atmel,24c128", .data = &at24_data_24c128 },
+ { .compatible = "atmel,24c256", .data = &at24_data_24c256 },
+ { .compatible = "atmel,24c512", .data = &at24_data_24c512 },
+ { .compatible = "atmel,24c1024", .data = &at24_data_24c1024 },
+ { /* END OF LIST */ },
};
MODULE_DEVICE_TABLE(of, at24_of_match);
static const struct acpi_device_id at24_acpi_ids[] = {
- { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
- { }
+ { "INT3499", (kernel_ulong_t)&at24_data_INT3499 },
+ { /* END OF LIST */ }
};
MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
@@ -251,20 +249,11 @@ MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
* Slave address and byte offset derive from the offset. Always
* set the byte address; on a multi-master board, another master
* may have changed the chip's "current" address pointer.
- *
- * REVISIT some multi-address chips don't rollover page reads to
- * the next slave address, so we may need to truncate the count.
- * Those chips might need another quirk flag.
- *
- * If the real hardware used four adjacent 24c02 chips and that
- * were misconfigured as one 24c08, that would be a similar effect:
- * one "eeprom" file not four, but larger reads would fail when
- * they crossed certain pages.
*/
-static struct i2c_client *at24_translate_offset(struct at24_data *at24,
- unsigned int *offset)
+static struct at24_client *at24_translate_offset(struct at24_data *at24,
+ unsigned int *offset)
{
- unsigned i;
+ unsigned int i;
if (at24->chip.flags & AT24_FLAG_ADDR16) {
i = *offset >> 16;
@@ -274,168 +263,55 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
*offset &= 0xff;
}
- return at24->client[i];
+ return &at24->client[i];
}
-static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
+static size_t at24_adjust_read_count(struct at24_data *at24,
unsigned int offset, size_t count)
{
- unsigned long timeout, read_time;
- struct i2c_client *client;
- int status;
-
- client = at24_translate_offset(at24, &offset);
-
- if (count > io_limit)
- count = io_limit;
-
- /* Smaller eeproms can work given some SMBus extension calls */
- if (count > I2C_SMBUS_BLOCK_MAX)
- count = I2C_SMBUS_BLOCK_MAX;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_smbus_read_i2c_block_data_or_emulated(client,
- offset,
- count, buf);
-
- dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, read_time;
- struct i2c_client *client;
- struct i2c_msg msg[2];
- int status, i;
- u8 msgbuf[2];
-
- memset(msg, 0, sizeof(msg));
- client = at24_translate_offset(at24, &offset);
-
- if (count > io_limit)
- count = io_limit;
+ unsigned int bits;
+ size_t remainder;
/*
- * When we have a better choice than SMBus calls, use a combined I2C
- * message. Write address; then read up to io_limit data bytes. Note
- * that read page rollover helps us here (unlike writes). msgbuf is
- * u8 and will cast to our needs.
+ * In case of multi-address chips that don't rollover reads to
+ * the next slave address: truncate the count to the slave boundary,
+ * so that the read never straddles slaves.
*/
- i = 0;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msgbuf[i++] = offset >> 8;
- msgbuf[i++] = offset;
-
- msg[0].addr = client->addr;
- msg[0].buf = msgbuf;
- msg[0].len = i;
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_transfer(client->adapter, msg, 2);
- if (status == 2)
- status = count;
-
- dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
+ if (at24->chip.flags & AT24_FLAG_NO_RDROL) {
+ bits = (at24->chip.flags & AT24_FLAG_ADDR16) ? 16 : 8;
+ remainder = BIT(bits) - offset;
+ if (count > remainder)
+ count = remainder;
}
- return -ETIMEDOUT;
+ if (count > at24_io_limit)
+ count = at24_io_limit;
+
+ return count;
}
-static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
+static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,
+ unsigned int offset, size_t count)
{
unsigned long timeout, read_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
- struct i2c_msg msg[2];
- u8 addrbuf[2];
- int status;
-
- client = at24_translate_offset(at24, &offset);
-
- memset(msg, 0, sizeof(msg));
- msg[0].addr = client->addr;
- msg[0].buf = addrbuf;
-
- /*
- * The address pointer of the device is shared between the regular
- * EEPROM array and the serial number block. The dummy write (part of
- * the sequential read protocol) ensures the address pointer is reset
- * to the desired position.
- */
- if (at24->chip.flags & AT24_FLAG_ADDR16) {
- /*
- * For 16 bit address pointers, the word address must contain
- * a '10' sequence in bits 11 and 10 regardless of the
- * intended position of the address pointer.
- */
- addrbuf[0] = 0x08;
- addrbuf[1] = offset;
- msg[0].len = 2;
- } else {
- /*
- * Otherwise the word address must begin with a '10' sequence,
- * regardless of the intended address.
- */
- addrbuf[0] = 0x80 + offset;
- msg[0].len = 1;
- }
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
+ struct regmap *regmap;
+ int ret;
- loop_until_timeout(timeout, read_time) {
- status = i2c_transfer(client->adapter, msg, 2);
- if (status == 2)
- return count;
- }
+ at24_client = at24_translate_offset(at24, &offset);
+ regmap = at24_client->regmap;
+ client = at24_client->client;
+ count = at24_adjust_read_count(at24, offset, count);
- return -ETIMEDOUT;
-}
+ /* adjust offset for mac and serial read ops */
+ offset += at24->offset_adj;
-static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, read_time;
- struct i2c_client *client;
- struct i2c_msg msg[2];
- u8 addrbuf[2];
- int status;
-
- client = at24_translate_offset(at24, &offset);
-
- memset(msg, 0, sizeof(msg));
- msg[0].addr = client->addr;
- msg[0].buf = addrbuf;
- /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
- addrbuf[0] = 0xa0 - at24->chip.byte_len + offset;
- msg[0].len = 1;
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = buf;
- msg[1].len = count;
-
- loop_until_timeout(timeout, read_time) {
- status = i2c_transfer(client->adapter, msg, 2);
- if (status == 2)
+ at24_loop_until_timeout(timeout, read_time) {
+ ret = regmap_bulk_read(regmap, offset, buf, count);
+ dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+ count, offset, ret, jiffies);
+ if (!ret)
return count;
}
@@ -454,7 +330,7 @@ static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf,
static size_t at24_adjust_write_count(struct at24_data *at24,
unsigned int offset, size_t count)
{
- unsigned next_page;
+ unsigned int next_page;
/* write_max is at most a page */
if (count > at24->write_max)
@@ -468,91 +344,25 @@ static size_t at24_adjust_write_count(struct at24_data *at24,
return count;
}
-static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24,
- const char *buf,
- unsigned int offset, size_t count)
+static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf,
+ unsigned int offset, size_t count)
{
unsigned long timeout, write_time;
+ struct at24_client *at24_client;
struct i2c_client *client;
- ssize_t status = 0;
-
- client = at24_translate_offset(at24, &offset);
- count = at24_adjust_write_count(at24, offset, count);
-
- loop_until_timeout(timeout, write_time) {
- status = i2c_smbus_write_i2c_block_data(client,
- offset, count, buf);
- if (status == 0)
- status = count;
-
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24,
- const char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, write_time;
- struct i2c_client *client;
- ssize_t status = 0;
-
- client = at24_translate_offset(at24, &offset);
-
- loop_until_timeout(timeout, write_time) {
- status = i2c_smbus_write_byte_data(client, offset, buf[0]);
- if (status == 0)
- status = count;
-
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
- return count;
- }
-
- return -ETIMEDOUT;
-}
-
-static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
- unsigned int offset, size_t count)
-{
- unsigned long timeout, write_time;
- struct i2c_client *client;
- struct i2c_msg msg;
- ssize_t status = 0;
- int i = 0;
+ struct regmap *regmap;
+ int ret;
- client = at24_translate_offset(at24, &offset);
+ at24_client = at24_translate_offset(at24, &offset);
+ regmap = at24_client->regmap;
+ client = at24_client->client;
count = at24_adjust_write_count(at24, offset, count);
- msg.addr = client->addr;
- msg.flags = 0;
-
- /* msg.buf is u8 and casts will mask the values */
- msg.buf = at24->writebuf;
- if (at24->chip.flags & AT24_FLAG_ADDR16)
- msg.buf[i++] = offset >> 8;
-
- msg.buf[i++] = offset;
- memcpy(&msg.buf[i], buf, count);
- msg.len = i + count;
-
- loop_until_timeout(timeout, write_time) {
- status = i2c_transfer(client->adapter, &msg, 1);
- if (status == 1)
- status = count;
-
- dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
- count, offset, status, jiffies);
-
- if (status == count)
+ at24_loop_until_timeout(timeout, write_time) {
+ ret = regmap_bulk_write(regmap, offset, buf, count);
+ dev_dbg(&client->dev, "write %zu@%d --> %d (%ld)\n",
+ count, offset, ret, jiffies);
+ if (!ret)
return count;
}
@@ -562,7 +372,7 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
- struct device *dev = &at24->client[0]->dev;
+ struct device *dev = &at24->client[0].client->dev;
char *buf = val;
int ret;
@@ -587,7 +397,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
while (count) {
int status;
- status = at24->read_func(at24, buf, off, count);
+ status = at24_regmap_read(at24, buf, off, count);
if (status < 0) {
mutex_unlock(&at24->lock);
pm_runtime_put(dev);
@@ -608,7 +418,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
static int at24_write(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
- struct device *dev = &at24->client[0]->dev;
+ struct device *dev = &at24->client[0].client->dev;
char *buf = val;
int ret;
@@ -629,12 +439,14 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
* from this host, but not from other I2C masters.
*/
mutex_lock(&at24->lock);
+ gpiod_set_value_cansleep(at24->wp_gpio, 0);
while (count) {
int status;
- status = at24->write_func(at24, buf, off, count);
+ status = at24_regmap_write(at24, buf, off, count);
if (status < 0) {
+ gpiod_set_value_cansleep(at24->wp_gpio, 1);
mutex_unlock(&at24->lock);
pm_runtime_put(dev);
return status;
@@ -644,6 +456,7 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
count -= status;
}
+ gpiod_set_value_cansleep(at24->wp_gpio, 1);
mutex_unlock(&at24->lock);
pm_runtime_put(dev);
@@ -658,6 +471,8 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
if (device_property_present(dev, "read-only"))
chip->flags |= AT24_FLAG_READONLY;
+ if (device_property_present(dev, "no-read-rollover"))
+ chip->flags |= AT24_FLAG_NO_RDROL;
err = device_property_read_u32(dev, "size", &val);
if (!err)
@@ -676,16 +491,38 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
}
}
+static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
+{
+ if (flags & AT24_FLAG_MAC) {
+ /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
+ return 0xa0 - byte_len;
+ } else if (flags & AT24_FLAG_SERIAL && flags & AT24_FLAG_ADDR16) {
+ /*
+ * For 16 bit address pointers, the word address must contain
+ * a '10' sequence in bits 11 and 10 regardless of the
+ * intended position of the address pointer.
+ */
+ return 0x0800;
+ } else if (flags & AT24_FLAG_SERIAL) {
+ /*
+ * Otherwise the word address must begin with a '10' sequence,
+ * regardless of the intended address.
+ */
+ return 0x0080;
+ } else {
+ return 0;
+ }
+}
+
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
- struct at24_platform_data chip;
- kernel_ulong_t magic = 0;
+ struct at24_platform_data chip = { 0 };
+ const struct at24_chip_data *cd = NULL;
bool writable;
- int use_smbus = 0;
- int use_smbus_write = 0;
struct at24_data *at24;
int err;
- unsigned i, num_addresses;
+ unsigned int i, num_addresses;
+ struct regmap_config regmap_config = { };
u8 test_byte;
if (client->dev.platform_data) {
@@ -698,28 +535,22 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
*/
if (client->dev.of_node &&
of_match_device(at24_of_match, &client->dev)) {
- magic = (kernel_ulong_t)
- of_device_get_match_data(&client->dev);
+ cd = of_device_get_match_data(&client->dev);
} else if (id) {
- magic = id->driver_data;
+ cd = (void *)id->driver_data;
} else {
const struct acpi_device_id *aid;
aid = acpi_match_device(at24_acpi_ids, &client->dev);
if (aid)
- magic = aid->driver_data;
+ cd = (void *)aid->driver_data;
}
- if (!magic)
+ if (!cd)
return -ENODEV;
- chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
- magic >>= AT24_SIZE_BYTELEN;
- chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
-
+ chip.byte_len = cd->byte_len;
+ chip.flags = cd->flags;
at24_get_pdata(&client->dev, &chip);
-
- chip.setup = NULL;
- chip.context = NULL;
}
if (!is_power_of_2(chip.byte_len))
@@ -733,43 +564,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_warn(&client->dev,
"page_size looks suspicious (no power of 2)!\n");
- /*
- * REVISIT: the size of the EUI-48 byte array is 6 in at24mac402, while
- * the call to ilog2() in AT24_DEVICE_MAGIC() rounds it down to 4.
- *
- * Eventually we'll get rid of the magic values altoghether in favor of
- * real structs, but for now just manually set the right size.
- */
- if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4)
- chip.byte_len = 6;
-
- /* Use I2C operations unless we're stuck with SMBus extensions. */
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- if (chip.flags & AT24_FLAG_ADDR16)
- return -EPFNOSUPPORT;
-
- if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- use_smbus = I2C_SMBUS_I2C_BLOCK_DATA;
- } else if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_WORD_DATA)) {
- use_smbus = I2C_SMBUS_WORD_DATA;
- } else if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
- use_smbus = I2C_SMBUS_BYTE_DATA;
- } else {
- return -EPFNOSUPPORT;
- }
-
- if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
- use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA;
- } else if (i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
- use_smbus_write = I2C_SMBUS_BYTE_DATA;
- chip.page_size = 1;
- }
- }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) &&
+ !i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
+ chip.page_size = 1;
if (chip.flags & AT24_FLAG_TAKE8ADDR)
num_addresses = 8;
@@ -777,16 +575,28 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
num_addresses = DIV_ROUND_UP(chip.byte_len,
(chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
+ regmap_config.val_bits = 8;
+ regmap_config.reg_bits = (chip.flags & AT24_FLAG_ADDR16) ? 16 : 8;
+
at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) +
- num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
+ num_addresses * sizeof(struct at24_client), GFP_KERNEL);
if (!at24)
return -ENOMEM;
mutex_init(&at24->lock);
- at24->use_smbus = use_smbus;
- at24->use_smbus_write = use_smbus_write;
at24->chip = chip;
at24->num_addresses = num_addresses;
+ at24->offset_adj = at24_get_offset_adj(chip.flags, chip.byte_len);
+
+ at24->wp_gpio = devm_gpiod_get_optional(&client->dev,
+ "wp", GPIOD_OUT_HIGH);
+ if (IS_ERR(at24->wp_gpio))
+ return PTR_ERR(at24->wp_gpio);
+
+ at24->client[0].client = client;
+ at24->client[0].regmap = devm_regmap_init_i2c(client, &regmap_config);
+ if (IS_ERR(at24->client[0].regmap))
+ return PTR_ERR(at24->client[0].regmap);
if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) {
dev_err(&client->dev,
@@ -794,59 +604,32 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -EINVAL;
}
- if (chip.flags & AT24_FLAG_SERIAL) {
- at24->read_func = at24_eeprom_read_serial;
- } else if (chip.flags & AT24_FLAG_MAC) {
- at24->read_func = at24_eeprom_read_mac;
- } else {
- at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
- : at24_eeprom_read_i2c;
- }
-
- if (at24->use_smbus) {
- if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA)
- at24->write_func = at24_eeprom_write_smbus_block;
- else
- at24->write_func = at24_eeprom_write_smbus_byte;
- } else {
- at24->write_func = at24_eeprom_write_i2c;
- }
-
writable = !(chip.flags & AT24_FLAG_READONLY);
if (writable) {
- if (!use_smbus || use_smbus_write) {
-
- unsigned write_max = chip.page_size;
-
- if (write_max > io_limit)
- write_max = io_limit;
- if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
- write_max = I2C_SMBUS_BLOCK_MAX;
- at24->write_max = write_max;
-
- /* buffer (data + address at the beginning) */
- at24->writebuf = devm_kzalloc(&client->dev,
- write_max + 2, GFP_KERNEL);
- if (!at24->writebuf)
- return -ENOMEM;
- } else {
- dev_warn(&client->dev,
- "cannot write due to controller restrictions.");
- }
+ at24->write_max = min_t(unsigned int,
+ chip.page_size, at24_io_limit);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) &&
+ at24->write_max > I2C_SMBUS_BLOCK_MAX)
+ at24->write_max = I2C_SMBUS_BLOCK_MAX;
}
- at24->client[0] = client;
-
/* use dummy devices for multiple-address chips */
for (i = 1; i < num_addresses; i++) {
- at24->client[i] = i2c_new_dummy(client->adapter,
- client->addr + i);
- if (!at24->client[i]) {
+ at24->client[i].client = i2c_new_dummy(client->adapter,
+ client->addr + i);
+ if (!at24->client[i].client) {
dev_err(&client->dev, "address 0x%02x unavailable\n",
client->addr + i);
err = -EADDRINUSE;
goto err_clients;
}
+ at24->client[i].regmap = devm_regmap_init_i2c(
+ at24->client[i].client,
+ &regmap_config);
+ if (IS_ERR(at24->client[i].regmap)) {
+ err = PTR_ERR(at24->client[i].regmap);
+ goto err_clients;
+ }
}
i2c_set_clientdata(client, at24);
@@ -890,12 +673,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
chip.byte_len, client->name,
writable ? "writable" : "read-only", at24->write_max);
- if (use_smbus == I2C_SMBUS_WORD_DATA ||
- use_smbus == I2C_SMBUS_BYTE_DATA) {
- dev_notice(&client->dev, "Falling back to %s reads, "
- "performance will suffer\n", use_smbus ==
- I2C_SMBUS_WORD_DATA ? "word" : "byte");
- }
/* export data to kernel code */
if (chip.setup)
@@ -905,8 +682,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
err_clients:
for (i = 1; i < num_addresses; i++)
- if (at24->client[i])
- i2c_unregister_device(at24->client[i]);
+ if (at24->client[i].client)
+ i2c_unregister_device(at24->client[i].client);
pm_runtime_disable(&client->dev);
@@ -923,7 +700,7 @@ static int at24_remove(struct i2c_client *client)
nvmem_unregister(at24->nvmem);
for (i = 1; i < at24->num_addresses; i++)
- i2c_unregister_device(at24->client[i]);
+ i2c_unregister_device(at24->client[i].client);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
@@ -946,12 +723,12 @@ static struct i2c_driver at24_driver = {
static int __init at24_init(void)
{
- if (!io_limit) {
- pr_err("at24: io_limit must not be 0!\n");
+ if (!at24_io_limit) {
+ pr_err("at24: at24_io_limit must not be 0!\n");
return -EINVAL;
}
- io_limit = rounddown_pow_of_two(io_limit);
+ at24_io_limit = rounddown_pow_of_two(at24_io_limit);
return i2c_add_driver(&at24_driver);
}
module_init(at24_init);
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index 687a0dbbe199..9e513dcfd809 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -76,8 +76,8 @@ void __init lkdtm_usercopy_init(void);
void __exit lkdtm_usercopy_exit(void);
void lkdtm_USERCOPY_HEAP_SIZE_TO(void);
void lkdtm_USERCOPY_HEAP_SIZE_FROM(void);
-void lkdtm_USERCOPY_HEAP_FLAG_TO(void);
-void lkdtm_USERCOPY_HEAP_FLAG_FROM(void);
+void lkdtm_USERCOPY_HEAP_WHITELIST_TO(void);
+void lkdtm_USERCOPY_HEAP_WHITELIST_FROM(void);
void lkdtm_USERCOPY_STACK_FRAME_TO(void);
void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
void lkdtm_USERCOPY_STACK_BEYOND(void);
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index 4942da93d066..2154d1bfd18b 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -177,8 +177,8 @@ static const struct crashtype crashtypes[] = {
CRASHTYPE(ATOMIC_TIMING),
CRASHTYPE(USERCOPY_HEAP_SIZE_TO),
CRASHTYPE(USERCOPY_HEAP_SIZE_FROM),
- CRASHTYPE(USERCOPY_HEAP_FLAG_TO),
- CRASHTYPE(USERCOPY_HEAP_FLAG_FROM),
+ CRASHTYPE(USERCOPY_HEAP_WHITELIST_TO),
+ CRASHTYPE(USERCOPY_HEAP_WHITELIST_FROM),
CRASHTYPE(USERCOPY_STACK_FRAME_TO),
CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
CRASHTYPE(USERCOPY_STACK_BEYOND),
diff --git a/drivers/misc/lkdtm_usercopy.c b/drivers/misc/lkdtm_usercopy.c
index a64372cc148d..9725aed305bb 100644
--- a/drivers/misc/lkdtm_usercopy.c
+++ b/drivers/misc/lkdtm_usercopy.c
@@ -20,7 +20,7 @@
*/
static volatile size_t unconst = 0;
static volatile size_t cache_size = 1024;
-static struct kmem_cache *bad_cache;
+static struct kmem_cache *whitelist_cache;
static const unsigned char test_text[] = "This is a test.\n";
@@ -115,10 +115,16 @@ free_user:
vm_munmap(user_addr, PAGE_SIZE);
}
+/*
+ * This checks for whole-object size validation with hardened usercopy,
+ * with or without usercopy whitelisting.
+ */
static void do_usercopy_heap_size(bool to_user)
{
unsigned long user_addr;
unsigned char *one, *two;
+ void __user *test_user_addr;
+ void *test_kern_addr;
size_t size = unconst + 1024;
one = kmalloc(size, GFP_KERNEL);
@@ -139,27 +145,30 @@ static void do_usercopy_heap_size(bool to_user)
memset(one, 'A', size);
memset(two, 'B', size);
+ test_user_addr = (void __user *)(user_addr + 16);
+ test_kern_addr = one + 16;
+
if (to_user) {
pr_info("attempting good copy_to_user of correct size\n");
- if (copy_to_user((void __user *)user_addr, one, size)) {
+ if (copy_to_user(test_user_addr, test_kern_addr, size / 2)) {
pr_warn("copy_to_user failed unexpectedly?!\n");
goto free_user;
}
pr_info("attempting bad copy_to_user of too large size\n");
- if (copy_to_user((void __user *)user_addr, one, 2 * size)) {
+ if (copy_to_user(test_user_addr, test_kern_addr, size)) {
pr_warn("copy_to_user failed, but lacked Oops\n");
goto free_user;
}
} else {
pr_info("attempting good copy_from_user of correct size\n");
- if (copy_from_user(one, (void __user *)user_addr, size)) {
+ if (copy_from_user(test_kern_addr, test_user_addr, size / 2)) {
pr_warn("copy_from_user failed unexpectedly?!\n");
goto free_user;
}
pr_info("attempting bad copy_from_user of too large size\n");
- if (copy_from_user(one, (void __user *)user_addr, 2 * size)) {
+ if (copy_from_user(test_kern_addr, test_user_addr, size)) {
pr_warn("copy_from_user failed, but lacked Oops\n");
goto free_user;
}
@@ -172,77 +181,79 @@ free_kernel:
kfree(two);
}
-static void do_usercopy_heap_flag(bool to_user)
+/*
+ * This checks for the specific whitelist window within an object. If this
+ * test passes, then do_usercopy_heap_size() tests will pass too.
+ */
+static void do_usercopy_heap_whitelist(bool to_user)
{
- unsigned long user_addr;
- unsigned char *good_buf = NULL;
- unsigned char *bad_buf = NULL;
+ unsigned long user_alloc;
+ unsigned char *buf = NULL;
+ unsigned char __user *user_addr;
+ size_t offset, size;
/* Make sure cache was prepared. */
- if (!bad_cache) {
+ if (!whitelist_cache) {
pr_warn("Failed to allocate kernel cache\n");
return;
}
/*
- * Allocate one buffer from each cache (kmalloc will have the
- * SLAB_USERCOPY flag already, but "bad_cache" won't).
+ * Allocate a buffer with a whitelisted window in the buffer.
*/
- good_buf = kmalloc(cache_size, GFP_KERNEL);
- bad_buf = kmem_cache_alloc(bad_cache, GFP_KERNEL);
- if (!good_buf || !bad_buf) {
- pr_warn("Failed to allocate buffers from caches\n");
+ buf = kmem_cache_alloc(whitelist_cache, GFP_KERNEL);
+ if (!buf) {
+ pr_warn("Failed to allocate buffer from whitelist cache\n");
goto free_alloc;
}
/* Allocate user memory we'll poke at. */
- user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
+ user_alloc = vm_mmap(NULL, 0, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
- if (user_addr >= TASK_SIZE) {
+ if (user_alloc >= TASK_SIZE) {
pr_warn("Failed to allocate user memory\n");
goto free_alloc;
}
+ user_addr = (void __user *)user_alloc;
- memset(good_buf, 'A', cache_size);
- memset(bad_buf, 'B', cache_size);
+ memset(buf, 'B', cache_size);
+
+ /* Whitelisted window in buffer, from kmem_cache_create_usercopy. */
+ offset = (cache_size / 4) + unconst;
+ size = (cache_size / 16) + unconst;
if (to_user) {
- pr_info("attempting good copy_to_user with SLAB_USERCOPY\n");
- if (copy_to_user((void __user *)user_addr, good_buf,
- cache_size)) {
+ pr_info("attempting good copy_to_user inside whitelist\n");
+ if (copy_to_user(user_addr, buf + offset, size)) {
pr_warn("copy_to_user failed unexpectedly?!\n");
goto free_user;
}
- pr_info("attempting bad copy_to_user w/o SLAB_USERCOPY\n");
- if (copy_to_user((void __user *)user_addr, bad_buf,
- cache_size)) {
+ pr_info("attempting bad copy_to_user outside whitelist\n");
+ if (copy_to_user(user_addr, buf + offset - 1, size)) {
pr_warn("copy_to_user failed, but lacked Oops\n");
goto free_user;
}
} else {
- pr_info("attempting good copy_from_user with SLAB_USERCOPY\n");
- if (copy_from_user(good_buf, (void __user *)user_addr,
- cache_size)) {
+ pr_info("attempting good copy_from_user inside whitelist\n");
+ if (copy_from_user(buf + offset, user_addr, size)) {
pr_warn("copy_from_user failed unexpectedly?!\n");
goto free_user;
}
- pr_info("attempting bad copy_from_user w/o SLAB_USERCOPY\n");
- if (copy_from_user(bad_buf, (void __user *)user_addr,
- cache_size)) {
+ pr_info("attempting bad copy_from_user outside whitelist\n");
+ if (copy_from_user(buf + offset - 1, user_addr, size)) {
pr_warn("copy_from_user failed, but lacked Oops\n");
goto free_user;
}
}
free_user:
- vm_munmap(user_addr, PAGE_SIZE);
+ vm_munmap(user_alloc, PAGE_SIZE);
free_alloc:
- if (bad_buf)
- kmem_cache_free(bad_cache, bad_buf);
- kfree(good_buf);
+ if (buf)
+ kmem_cache_free(whitelist_cache, buf);
}
/* Callable tests. */
@@ -256,14 +267,14 @@ void lkdtm_USERCOPY_HEAP_SIZE_FROM(void)
do_usercopy_heap_size(false);
}
-void lkdtm_USERCOPY_HEAP_FLAG_TO(void)
+void lkdtm_USERCOPY_HEAP_WHITELIST_TO(void)
{
- do_usercopy_heap_flag(true);
+ do_usercopy_heap_whitelist(true);
}
-void lkdtm_USERCOPY_HEAP_FLAG_FROM(void)
+void lkdtm_USERCOPY_HEAP_WHITELIST_FROM(void)
{
- do_usercopy_heap_flag(false);
+ do_usercopy_heap_whitelist(false);
}
void lkdtm_USERCOPY_STACK_FRAME_TO(void)
@@ -314,11 +325,15 @@ free_user:
void __init lkdtm_usercopy_init(void)
{
/* Prepare cache that lacks SLAB_USERCOPY flag. */
- bad_cache = kmem_cache_create("lkdtm-no-usercopy", cache_size, 0,
- 0, NULL);
+ whitelist_cache =
+ kmem_cache_create_usercopy("lkdtm-usercopy", cache_size,
+ 0, 0,
+ cache_size / 4,
+ cache_size / 16,
+ NULL);
}
void __exit lkdtm_usercopy_exit(void)
{
- kmem_cache_destroy(bad_cache);
+ kmem_cache_destroy(whitelist_cache);
}
diff --git a/drivers/misc/ocxl/Kconfig b/drivers/misc/ocxl/Kconfig
new file mode 100644
index 000000000000..4bbdb0d3c8ee
--- /dev/null
+++ b/drivers/misc/ocxl/Kconfig
@@ -0,0 +1,31 @@
+#
+# Open Coherent Accelerator (OCXL) compatible devices
+#
+
+config OCXL_BASE
+ bool
+ default n
+ select PPC_COPRO_BASE
+
+config OCXL
+ tristate "OpenCAPI coherent accelerator support"
+ depends on PPC_POWERNV && PCI && EEH
+ select OCXL_BASE
+ default m
+ help
+ Select this option to enable the ocxl driver for Open
+ Coherent Accelerator Processor Interface (OpenCAPI) devices.
+
+ OpenCAPI allows FPGA and ASIC accelerators to be coherently
+ attached to a CPU over an OpenCAPI link.
+
+ The ocxl driver enables userspace programs to access these
+ accelerators through devices in /dev/ocxl/.
+
+ For more information, see http://opencapi.org.
+
+ This is not to be confused with the support for IBM CAPI
+ accelerators (CONFIG_CXL), which are PCI-based instead of a
+ dedicated OpenCAPI link, and don't follow the same protocol.
+
+ If unsure, say N.
diff --git a/drivers/misc/ocxl/Makefile b/drivers/misc/ocxl/Makefile
new file mode 100644
index 000000000000..5229dcda8297
--- /dev/null
+++ b/drivers/misc/ocxl/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+ccflags-$(CONFIG_PPC_WERROR) += -Werror
+
+ocxl-y += main.o pci.o config.o file.o pasid.o
+ocxl-y += link.o context.o afu_irq.o sysfs.o trace.o
+obj-$(CONFIG_OCXL) += ocxl.o
+
+# For tracepoints to include our trace.h from tracepoint infrastructure:
+CFLAGS_trace.o := -I$(src)
+
+# ccflags-y += -DDEBUG
diff --git a/drivers/misc/ocxl/afu_irq.c b/drivers/misc/ocxl/afu_irq.c
new file mode 100644
index 000000000000..e70cfa24577f
--- /dev/null
+++ b/drivers/misc/ocxl/afu_irq.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/interrupt.h>
+#include <linux/eventfd.h>
+#include <asm/pnv-ocxl.h>
+#include "ocxl_internal.h"
+#include "trace.h"
+
+struct afu_irq {
+ int id;
+ int hw_irq;
+ unsigned int virq;
+ char *name;
+ u64 trigger_page;
+ struct eventfd_ctx *ev_ctx;
+};
+
+static int irq_offset_to_id(struct ocxl_context *ctx, u64 offset)
+{
+ return (offset - ctx->afu->irq_base_offset) >> PAGE_SHIFT;
+}
+
+static u64 irq_id_to_offset(struct ocxl_context *ctx, int id)
+{
+ return ctx->afu->irq_base_offset + (id << PAGE_SHIFT);
+}
+
+static irqreturn_t afu_irq_handler(int virq, void *data)
+{
+ struct afu_irq *irq = (struct afu_irq *) data;
+
+ trace_ocxl_afu_irq_receive(virq);
+ if (irq->ev_ctx)
+ eventfd_signal(irq->ev_ctx, 1);
+ return IRQ_HANDLED;
+}
+
+static int setup_afu_irq(struct ocxl_context *ctx, struct afu_irq *irq)
+{
+ int rc;
+
+ irq->virq = irq_create_mapping(NULL, irq->hw_irq);
+ if (!irq->virq) {
+ pr_err("irq_create_mapping failed\n");
+ return -ENOMEM;
+ }
+ pr_debug("hw_irq %d mapped to virq %u\n", irq->hw_irq, irq->virq);
+
+ irq->name = kasprintf(GFP_KERNEL, "ocxl-afu-%u", irq->virq);
+ if (!irq->name) {
+ irq_dispose_mapping(irq->virq);
+ return -ENOMEM;
+ }
+
+ rc = request_irq(irq->virq, afu_irq_handler, 0, irq->name, irq);
+ if (rc) {
+ kfree(irq->name);
+ irq->name = NULL;
+ irq_dispose_mapping(irq->virq);
+ pr_err("request_irq failed: %d\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
+static void release_afu_irq(struct afu_irq *irq)
+{
+ free_irq(irq->virq, irq);
+ irq_dispose_mapping(irq->virq);
+ kfree(irq->name);
+}
+
+int ocxl_afu_irq_alloc(struct ocxl_context *ctx, u64 *irq_offset)
+{
+ struct afu_irq *irq;
+ int rc;
+
+ irq = kzalloc(sizeof(struct afu_irq), GFP_KERNEL);
+ if (!irq)
+ return -ENOMEM;
+
+ /*
+ * We limit the number of afu irqs per context and per link to
+ * avoid a single process or user depleting the pool of IPIs
+ */
+
+ mutex_lock(&ctx->irq_lock);
+
+ irq->id = idr_alloc(&ctx->irq_idr, irq, 0, MAX_IRQ_PER_CONTEXT,
+ GFP_KERNEL);
+ if (irq->id < 0) {
+ rc = -ENOSPC;
+ goto err_unlock;
+ }
+
+ rc = ocxl_link_irq_alloc(ctx->afu->fn->link, &irq->hw_irq,
+ &irq->trigger_page);
+ if (rc)
+ goto err_idr;
+
+ rc = setup_afu_irq(ctx, irq);
+ if (rc)
+ goto err_alloc;
+
+ *irq_offset = irq_id_to_offset(ctx, irq->id);
+
+ trace_ocxl_afu_irq_alloc(ctx->pasid, irq->id, irq->virq, irq->hw_irq,
+ *irq_offset);
+ mutex_unlock(&ctx->irq_lock);
+ return 0;
+
+err_alloc:
+ ocxl_link_free_irq(ctx->afu->fn->link, irq->hw_irq);
+err_idr:
+ idr_remove(&ctx->irq_idr, irq->id);
+err_unlock:
+ mutex_unlock(&ctx->irq_lock);
+ kfree(irq);
+ return rc;
+}
+
+static void afu_irq_free(struct afu_irq *irq, struct ocxl_context *ctx)
+{
+ trace_ocxl_afu_irq_free(ctx->pasid, irq->id);
+ if (ctx->mapping)
+ unmap_mapping_range(ctx->mapping,
+ irq_id_to_offset(ctx, irq->id),
+ 1 << PAGE_SHIFT, 1);
+ release_afu_irq(irq);
+ if (irq->ev_ctx)
+ eventfd_ctx_put(irq->ev_ctx);
+ ocxl_link_free_irq(ctx->afu->fn->link, irq->hw_irq);
+ kfree(irq);
+}
+
+int ocxl_afu_irq_free(struct ocxl_context *ctx, u64 irq_offset)
+{
+ struct afu_irq *irq;
+ int id = irq_offset_to_id(ctx, irq_offset);
+
+ mutex_lock(&ctx->irq_lock);
+
+ irq = idr_find(&ctx->irq_idr, id);
+ if (!irq) {
+ mutex_unlock(&ctx->irq_lock);
+ return -EINVAL;
+ }
+ idr_remove(&ctx->irq_idr, irq->id);
+ afu_irq_free(irq, ctx);
+ mutex_unlock(&ctx->irq_lock);
+ return 0;
+}
+
+void ocxl_afu_irq_free_all(struct ocxl_context *ctx)
+{
+ struct afu_irq *irq;
+ int id;
+
+ mutex_lock(&ctx->irq_lock);
+ idr_for_each_entry(&ctx->irq_idr, irq, id)
+ afu_irq_free(irq, ctx);
+ mutex_unlock(&ctx->irq_lock);
+}
+
+int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset, int eventfd)
+{
+ struct afu_irq *irq;
+ struct eventfd_ctx *ev_ctx;
+ int rc = 0, id = irq_offset_to_id(ctx, irq_offset);
+
+ mutex_lock(&ctx->irq_lock);
+ irq = idr_find(&ctx->irq_idr, id);
+ if (!irq) {
+ rc = -EINVAL;
+ goto unlock;
+ }
+
+ ev_ctx = eventfd_ctx_fdget(eventfd);
+ if (IS_ERR(ev_ctx)) {
+ rc = -EINVAL;
+ goto unlock;
+ }
+
+ irq->ev_ctx = ev_ctx;
+unlock:
+ mutex_unlock(&ctx->irq_lock);
+ return rc;
+}
+
+u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset)
+{
+ struct afu_irq *irq;
+ int id = irq_offset_to_id(ctx, irq_offset);
+ u64 addr = 0;
+
+ mutex_lock(&ctx->irq_lock);
+ irq = idr_find(&ctx->irq_idr, id);
+ if (irq)
+ addr = irq->trigger_page;
+ mutex_unlock(&ctx->irq_lock);
+ return addr;
+}
diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c
new file mode 100644
index 000000000000..2e30de9c694a
--- /dev/null
+++ b/drivers/misc/ocxl/config.c
@@ -0,0 +1,723 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/pci.h>
+#include <asm/pnv-ocxl.h>
+#include <misc/ocxl.h>
+#include <misc/ocxl-config.h>
+
+#define EXTRACT_BIT(val, bit) (!!(val & BIT(bit)))
+#define EXTRACT_BITS(val, s, e) ((val & GENMASK(e, s)) >> s)
+
+#define OCXL_DVSEC_AFU_IDX_MASK GENMASK(5, 0)
+#define OCXL_DVSEC_ACTAG_MASK GENMASK(11, 0)
+#define OCXL_DVSEC_PASID_MASK GENMASK(19, 0)
+#define OCXL_DVSEC_PASID_LOG_MASK GENMASK(4, 0)
+
+#define OCXL_DVSEC_TEMPL_VERSION 0x0
+#define OCXL_DVSEC_TEMPL_NAME 0x4
+#define OCXL_DVSEC_TEMPL_AFU_VERSION 0x1C
+#define OCXL_DVSEC_TEMPL_MMIO_GLOBAL 0x20
+#define OCXL_DVSEC_TEMPL_MMIO_GLOBAL_SZ 0x28
+#define OCXL_DVSEC_TEMPL_MMIO_PP 0x30
+#define OCXL_DVSEC_TEMPL_MMIO_PP_SZ 0x38
+#define OCXL_DVSEC_TEMPL_MEM_SZ 0x3C
+#define OCXL_DVSEC_TEMPL_WWID 0x40
+
+#define OCXL_MAX_AFU_PER_FUNCTION 64
+#define OCXL_TEMPL_LEN 0x58
+#define OCXL_TEMPL_NAME_LEN 24
+#define OCXL_CFG_TIMEOUT 3
+
+static int find_dvsec(struct pci_dev *dev, int dvsec_id)
+{
+ int vsec = 0;
+ u16 vendor, id;
+
+ while ((vsec = pci_find_next_ext_capability(dev, vsec,
+ OCXL_EXT_CAP_ID_DVSEC))) {
+ pci_read_config_word(dev, vsec + OCXL_DVSEC_VENDOR_OFFSET,
+ &vendor);
+ pci_read_config_word(dev, vsec + OCXL_DVSEC_ID_OFFSET, &id);
+ if (vendor == PCI_VENDOR_ID_IBM && id == dvsec_id)
+ return vsec;
+ }
+ return 0;
+}
+
+static int find_dvsec_afu_ctrl(struct pci_dev *dev, u8 afu_idx)
+{
+ int vsec = 0;
+ u16 vendor, id;
+ u8 idx;
+
+ while ((vsec = pci_find_next_ext_capability(dev, vsec,
+ OCXL_EXT_CAP_ID_DVSEC))) {
+ pci_read_config_word(dev, vsec + OCXL_DVSEC_VENDOR_OFFSET,
+ &vendor);
+ pci_read_config_word(dev, vsec + OCXL_DVSEC_ID_OFFSET, &id);
+
+ if (vendor == PCI_VENDOR_ID_IBM &&
+ id == OCXL_DVSEC_AFU_CTRL_ID) {
+ pci_read_config_byte(dev,
+ vsec + OCXL_DVSEC_AFU_CTRL_AFU_IDX,
+ &idx);
+ if (idx == afu_idx)
+ return vsec;
+ }
+ }
+ return 0;
+}
+
+static int read_pasid(struct pci_dev *dev, struct ocxl_fn_config *fn)
+{
+ u16 val;
+ int pos;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PASID);
+ if (!pos) {
+ /*
+ * PASID capability is not mandatory, but there
+ * shouldn't be any AFU
+ */
+ dev_dbg(&dev->dev, "Function doesn't require any PASID\n");
+ fn->max_pasid_log = -1;
+ goto out;
+ }
+ pci_read_config_word(dev, pos + PCI_PASID_CAP, &val);
+ fn->max_pasid_log = EXTRACT_BITS(val, 8, 12);
+
+out:
+ dev_dbg(&dev->dev, "PASID capability:\n");
+ dev_dbg(&dev->dev, " Max PASID log = %d\n", fn->max_pasid_log);
+ return 0;
+}
+
+static int read_dvsec_tl(struct pci_dev *dev, struct ocxl_fn_config *fn)
+{
+ int pos;
+
+ pos = find_dvsec(dev, OCXL_DVSEC_TL_ID);
+ if (!pos && PCI_FUNC(dev->devfn) == 0) {
+ dev_err(&dev->dev, "Can't find TL DVSEC\n");
+ return -ENODEV;
+ }
+ if (pos && PCI_FUNC(dev->devfn) != 0) {
+ dev_err(&dev->dev, "TL DVSEC is only allowed on function 0\n");
+ return -ENODEV;
+ }
+ fn->dvsec_tl_pos = pos;
+ return 0;
+}
+
+static int read_dvsec_function(struct pci_dev *dev, struct ocxl_fn_config *fn)
+{
+ int pos, afu_present;
+ u32 val;
+
+ pos = find_dvsec(dev, OCXL_DVSEC_FUNC_ID);
+ if (!pos) {
+ dev_err(&dev->dev, "Can't find function DVSEC\n");
+ return -ENODEV;
+ }
+ fn->dvsec_function_pos = pos;
+
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_FUNC_OFF_INDEX, &val);
+ afu_present = EXTRACT_BIT(val, 31);
+ if (!afu_present) {
+ fn->max_afu_index = -1;
+ dev_dbg(&dev->dev, "Function doesn't define any AFU\n");
+ goto out;
+ }
+ fn->max_afu_index = EXTRACT_BITS(val, 24, 29);
+
+out:
+ dev_dbg(&dev->dev, "Function DVSEC:\n");
+ dev_dbg(&dev->dev, " Max AFU index = %d\n", fn->max_afu_index);
+ return 0;
+}
+
+static int read_dvsec_afu_info(struct pci_dev *dev, struct ocxl_fn_config *fn)
+{
+ int pos;
+
+ if (fn->max_afu_index < 0) {
+ fn->dvsec_afu_info_pos = -1;
+ return 0;
+ }
+
+ pos = find_dvsec(dev, OCXL_DVSEC_AFU_INFO_ID);
+ if (!pos) {
+ dev_err(&dev->dev, "Can't find AFU information DVSEC\n");
+ return -ENODEV;
+ }
+ fn->dvsec_afu_info_pos = pos;
+ return 0;
+}
+
+static int read_dvsec_vendor(struct pci_dev *dev)
+{
+ int pos;
+ u32 cfg, tlx, dlx;
+
+ /*
+ * vendor specific DVSEC is optional
+ *
+ * It's currently only used on function 0 to specify the
+ * version of some logic blocks. Some older images may not
+ * even have it so we ignore any errors
+ */
+ if (PCI_FUNC(dev->devfn) != 0)
+ return 0;
+
+ pos = find_dvsec(dev, OCXL_DVSEC_VENDOR_ID);
+ if (!pos)
+ return 0;
+
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_VENDOR_CFG_VERS, &cfg);
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_VENDOR_TLX_VERS, &tlx);
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_VENDOR_DLX_VERS, &dlx);
+
+ dev_dbg(&dev->dev, "Vendor specific DVSEC:\n");
+ dev_dbg(&dev->dev, " CFG version = 0x%x\n", cfg);
+ dev_dbg(&dev->dev, " TLX version = 0x%x\n", tlx);
+ dev_dbg(&dev->dev, " DLX version = 0x%x\n", dlx);
+ return 0;
+}
+
+static int validate_function(struct pci_dev *dev, struct ocxl_fn_config *fn)
+{
+ if (fn->max_pasid_log == -1 && fn->max_afu_index >= 0) {
+ dev_err(&dev->dev,
+ "AFUs are defined but no PASIDs are requested\n");
+ return -EINVAL;
+ }
+
+ if (fn->max_afu_index > OCXL_MAX_AFU_PER_FUNCTION) {
+ dev_err(&dev->dev,
+ "Max AFU index out of architectural limit (%d vs %d)\n",
+ fn->max_afu_index, OCXL_MAX_AFU_PER_FUNCTION);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int ocxl_config_read_function(struct pci_dev *dev, struct ocxl_fn_config *fn)
+{
+ int rc;
+
+ rc = read_pasid(dev, fn);
+ if (rc) {
+ dev_err(&dev->dev, "Invalid PASID configuration: %d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = read_dvsec_tl(dev, fn);
+ if (rc) {
+ dev_err(&dev->dev,
+ "Invalid Transaction Layer DVSEC configuration: %d\n",
+ rc);
+ return -ENODEV;
+ }
+
+ rc = read_dvsec_function(dev, fn);
+ if (rc) {
+ dev_err(&dev->dev,
+ "Invalid Function DVSEC configuration: %d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = read_dvsec_afu_info(dev, fn);
+ if (rc) {
+ dev_err(&dev->dev, "Invalid AFU configuration: %d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = read_dvsec_vendor(dev);
+ if (rc) {
+ dev_err(&dev->dev,
+ "Invalid vendor specific DVSEC configuration: %d\n",
+ rc);
+ return -ENODEV;
+ }
+
+ rc = validate_function(dev, fn);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ocxl_config_read_function);
+
+static int read_afu_info(struct pci_dev *dev, struct ocxl_fn_config *fn,
+ int offset, u32 *data)
+{
+ u32 val;
+ unsigned long timeout = jiffies + (HZ * OCXL_CFG_TIMEOUT);
+ int pos = fn->dvsec_afu_info_pos;
+
+ /* Protect 'data valid' bit */
+ if (EXTRACT_BIT(offset, 31)) {
+ dev_err(&dev->dev, "Invalid offset in AFU info DVSEC\n");
+ return -EINVAL;
+ }
+
+ pci_write_config_dword(dev, pos + OCXL_DVSEC_AFU_INFO_OFF, offset);
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_AFU_INFO_OFF, &val);
+ while (!EXTRACT_BIT(val, 31)) {
+ if (time_after_eq(jiffies, timeout)) {
+ dev_err(&dev->dev,
+ "Timeout while reading AFU info DVSEC (offset=%d)\n",
+ offset);
+ return -EBUSY;
+ }
+ cpu_relax();
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_AFU_INFO_OFF, &val);
+ }
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_AFU_INFO_DATA, data);
+ return 0;
+}
+
+int ocxl_config_check_afu_index(struct pci_dev *dev,
+ struct ocxl_fn_config *fn, int afu_idx)
+{
+ u32 val;
+ int rc, templ_major, templ_minor, len;
+
+ pci_write_config_word(dev, fn->dvsec_afu_info_pos, afu_idx);
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val);
+ if (rc)
+ return rc;
+
+ /* AFU index map can have holes */
+ if (!val)
+ return 0;
+
+ templ_major = EXTRACT_BITS(val, 8, 15);
+ templ_minor = EXTRACT_BITS(val, 0, 7);
+ dev_dbg(&dev->dev, "AFU descriptor template version %d.%d\n",
+ templ_major, templ_minor);
+
+ len = EXTRACT_BITS(val, 16, 31);
+ if (len != OCXL_TEMPL_LEN) {
+ dev_warn(&dev->dev,
+ "Unexpected template length in AFU information (%#x)\n",
+ len);
+ }
+ return 1;
+}
+EXPORT_SYMBOL_GPL(ocxl_config_check_afu_index);
+
+static int read_afu_name(struct pci_dev *dev, struct ocxl_fn_config *fn,
+ struct ocxl_afu_config *afu)
+{
+ int i, rc;
+ u32 val, *ptr;
+
+ BUILD_BUG_ON(OCXL_AFU_NAME_SZ < OCXL_TEMPL_NAME_LEN);
+ for (i = 0; i < OCXL_TEMPL_NAME_LEN; i += 4) {
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_NAME + i, &val);
+ if (rc)
+ return rc;
+ ptr = (u32 *) &afu->name[i];
+ *ptr = val;
+ }
+ afu->name[OCXL_AFU_NAME_SZ - 1] = '\0'; /* play safe */
+ return 0;
+}
+
+static int read_afu_mmio(struct pci_dev *dev, struct ocxl_fn_config *fn,
+ struct ocxl_afu_config *afu)
+{
+ int rc;
+ u32 val;
+
+ /*
+ * Global MMIO
+ */
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MMIO_GLOBAL, &val);
+ if (rc)
+ return rc;
+ afu->global_mmio_bar = EXTRACT_BITS(val, 0, 2);
+ afu->global_mmio_offset = EXTRACT_BITS(val, 16, 31) << 16;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MMIO_GLOBAL + 4, &val);
+ if (rc)
+ return rc;
+ afu->global_mmio_offset += (u64) val << 32;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MMIO_GLOBAL_SZ, &val);
+ if (rc)
+ return rc;
+ afu->global_mmio_size = val;
+
+ /*
+ * Per-process MMIO
+ */
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MMIO_PP, &val);
+ if (rc)
+ return rc;
+ afu->pp_mmio_bar = EXTRACT_BITS(val, 0, 2);
+ afu->pp_mmio_offset = EXTRACT_BITS(val, 16, 31) << 16;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MMIO_PP + 4, &val);
+ if (rc)
+ return rc;
+ afu->pp_mmio_offset += (u64) val << 32;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MMIO_PP_SZ, &val);
+ if (rc)
+ return rc;
+ afu->pp_mmio_stride = val;
+
+ return 0;
+}
+
+static int read_afu_control(struct pci_dev *dev, struct ocxl_afu_config *afu)
+{
+ int pos;
+ u8 val8;
+ u16 val16;
+
+ pos = find_dvsec_afu_ctrl(dev, afu->idx);
+ if (!pos) {
+ dev_err(&dev->dev, "Can't find AFU control DVSEC for AFU %d\n",
+ afu->idx);
+ return -ENODEV;
+ }
+ afu->dvsec_afu_control_pos = pos;
+
+ pci_read_config_byte(dev, pos + OCXL_DVSEC_AFU_CTRL_PASID_SUP, &val8);
+ afu->pasid_supported_log = EXTRACT_BITS(val8, 0, 4);
+
+ pci_read_config_word(dev, pos + OCXL_DVSEC_AFU_CTRL_ACTAG_SUP, &val16);
+ afu->actag_supported = EXTRACT_BITS(val16, 0, 11);
+ return 0;
+}
+
+static bool char_allowed(int c)
+{
+ /*
+ * Permitted Characters : Alphanumeric, hyphen, underscore, comma
+ */
+ if ((c >= 0x30 && c <= 0x39) /* digits */ ||
+ (c >= 0x41 && c <= 0x5A) /* upper case */ ||
+ (c >= 0x61 && c <= 0x7A) /* lower case */ ||
+ c == 0 /* NULL */ ||
+ c == 0x2D /* - */ ||
+ c == 0x5F /* _ */ ||
+ c == 0x2C /* , */)
+ return true;
+ return false;
+}
+
+static int validate_afu(struct pci_dev *dev, struct ocxl_afu_config *afu)
+{
+ int i;
+
+ if (!afu->name[0]) {
+ dev_err(&dev->dev, "Empty AFU name\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < OCXL_TEMPL_NAME_LEN; i++) {
+ if (!char_allowed(afu->name[i])) {
+ dev_err(&dev->dev,
+ "Invalid character in AFU name\n");
+ return -EINVAL;
+ }
+ }
+
+ if (afu->global_mmio_bar != 0 &&
+ afu->global_mmio_bar != 2 &&
+ afu->global_mmio_bar != 4) {
+ dev_err(&dev->dev, "Invalid global MMIO bar number\n");
+ return -EINVAL;
+ }
+ if (afu->pp_mmio_bar != 0 &&
+ afu->pp_mmio_bar != 2 &&
+ afu->pp_mmio_bar != 4) {
+ dev_err(&dev->dev, "Invalid per-process MMIO bar number\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int ocxl_config_read_afu(struct pci_dev *dev, struct ocxl_fn_config *fn,
+ struct ocxl_afu_config *afu, u8 afu_idx)
+{
+ int rc;
+ u32 val32;
+
+ /*
+ * First, we need to write the AFU idx for the AFU we want to
+ * access.
+ */
+ WARN_ON((afu_idx & OCXL_DVSEC_AFU_IDX_MASK) != afu_idx);
+ afu->idx = afu_idx;
+ pci_write_config_byte(dev,
+ fn->dvsec_afu_info_pos + OCXL_DVSEC_AFU_INFO_AFU_IDX,
+ afu->idx);
+
+ rc = read_afu_name(dev, fn, afu);
+ if (rc)
+ return rc;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_AFU_VERSION, &val32);
+ if (rc)
+ return rc;
+ afu->version_major = EXTRACT_BITS(val32, 24, 31);
+ afu->version_minor = EXTRACT_BITS(val32, 16, 23);
+ afu->afuc_type = EXTRACT_BITS(val32, 14, 15);
+ afu->afum_type = EXTRACT_BITS(val32, 12, 13);
+ afu->profile = EXTRACT_BITS(val32, 0, 7);
+
+ rc = read_afu_mmio(dev, fn, afu);
+ if (rc)
+ return rc;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MEM_SZ, &val32);
+ if (rc)
+ return rc;
+ afu->log_mem_size = EXTRACT_BITS(val32, 0, 7);
+
+ rc = read_afu_control(dev, afu);
+ if (rc)
+ return rc;
+
+ dev_dbg(&dev->dev, "AFU configuration:\n");
+ dev_dbg(&dev->dev, " name = %s\n", afu->name);
+ dev_dbg(&dev->dev, " version = %d.%d\n", afu->version_major,
+ afu->version_minor);
+ dev_dbg(&dev->dev, " global mmio bar = %hhu\n", afu->global_mmio_bar);
+ dev_dbg(&dev->dev, " global mmio offset = %#llx\n",
+ afu->global_mmio_offset);
+ dev_dbg(&dev->dev, " global mmio size = %#x\n", afu->global_mmio_size);
+ dev_dbg(&dev->dev, " pp mmio bar = %hhu\n", afu->pp_mmio_bar);
+ dev_dbg(&dev->dev, " pp mmio offset = %#llx\n", afu->pp_mmio_offset);
+ dev_dbg(&dev->dev, " pp mmio stride = %#x\n", afu->pp_mmio_stride);
+ dev_dbg(&dev->dev, " mem size (log) = %hhu\n", afu->log_mem_size);
+ dev_dbg(&dev->dev, " pasid supported (log) = %u\n",
+ afu->pasid_supported_log);
+ dev_dbg(&dev->dev, " actag supported = %u\n",
+ afu->actag_supported);
+
+ rc = validate_afu(dev, afu);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ocxl_config_read_afu);
+
+int ocxl_config_get_actag_info(struct pci_dev *dev, u16 *base, u16 *enabled,
+ u16 *supported)
+{
+ int rc;
+
+ /*
+ * This is really a simple wrapper for the kernel API, to
+ * avoid an external driver using ocxl as a library to call
+ * platform-dependent code
+ */
+ rc = pnv_ocxl_get_actag(dev, base, enabled, supported);
+ if (rc) {
+ dev_err(&dev->dev, "Can't get actag for device: %d\n", rc);
+ return rc;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ocxl_config_get_actag_info);
+
+void ocxl_config_set_afu_actag(struct pci_dev *dev, int pos, int actag_base,
+ int actag_count)
+{
+ u16 val;
+
+ val = actag_count & OCXL_DVSEC_ACTAG_MASK;
+ pci_write_config_byte(dev, pos + OCXL_DVSEC_AFU_CTRL_ACTAG_EN, val);
+
+ val = actag_base & OCXL_DVSEC_ACTAG_MASK;
+ pci_write_config_dword(dev, pos + OCXL_DVSEC_AFU_CTRL_ACTAG_BASE, val);
+}
+EXPORT_SYMBOL_GPL(ocxl_config_set_afu_actag);
+
+int ocxl_config_get_pasid_info(struct pci_dev *dev, int *count)
+{
+ return pnv_ocxl_get_pasid_count(dev, count);
+}
+EXPORT_SYMBOL_GPL(ocxl_config_get_pasid_info);
+
+void ocxl_config_set_afu_pasid(struct pci_dev *dev, int pos, int pasid_base,
+ u32 pasid_count_log)
+{
+ u8 val8;
+ u32 val32;
+
+ val8 = pasid_count_log & OCXL_DVSEC_PASID_LOG_MASK;
+ pci_write_config_byte(dev, pos + OCXL_DVSEC_AFU_CTRL_PASID_EN, val8);
+
+ pci_read_config_dword(dev, pos + OCXL_DVSEC_AFU_CTRL_PASID_BASE,
+ &val32);
+ val32 &= ~OCXL_DVSEC_PASID_MASK;
+ val32 |= pasid_base & OCXL_DVSEC_PASID_MASK;
+ pci_write_config_dword(dev, pos + OCXL_DVSEC_AFU_CTRL_PASID_BASE,
+ val32);
+}
+EXPORT_SYMBOL_GPL(ocxl_config_set_afu_pasid);
+
+void ocxl_config_set_afu_state(struct pci_dev *dev, int pos, int enable)
+{
+ u8 val;
+
+ pci_read_config_byte(dev, pos + OCXL_DVSEC_AFU_CTRL_ENABLE, &val);
+ if (enable)
+ val |= 1;
+ else
+ val &= 0xFE;
+ pci_write_config_byte(dev, pos + OCXL_DVSEC_AFU_CTRL_ENABLE, val);
+}
+EXPORT_SYMBOL_GPL(ocxl_config_set_afu_state);
+
+int ocxl_config_set_TL(struct pci_dev *dev, int tl_dvsec)
+{
+ u32 val;
+ __be32 *be32ptr;
+ u8 timers;
+ int i, rc;
+ long recv_cap;
+ char *recv_rate;
+
+ /*
+ * Skip on function != 0, as the TL can only be defined on 0
+ */
+ if (PCI_FUNC(dev->devfn) != 0)
+ return 0;
+
+ recv_rate = kzalloc(PNV_OCXL_TL_RATE_BUF_SIZE, GFP_KERNEL);
+ if (!recv_rate)
+ return -ENOMEM;
+ /*
+ * The spec defines 64 templates for messages in the
+ * Transaction Layer (TL).
+ *
+ * The host and device each support a subset, so we need to
+ * configure the transmitters on each side to send only
+ * templates the receiver understands, at a rate the receiver
+ * can process. Per the spec, template 0 must be supported by
+ * everybody. That's the template which has been used by the
+ * host and device so far.
+ *
+ * The sending rate limit must be set before the template is
+ * enabled.
+ */
+
+ /*
+ * Device -> host
+ */
+ rc = pnv_ocxl_get_tl_cap(dev, &recv_cap, recv_rate,
+ PNV_OCXL_TL_RATE_BUF_SIZE);
+ if (rc)
+ goto out;
+
+ for (i = 0; i < PNV_OCXL_TL_RATE_BUF_SIZE; i += 4) {
+ be32ptr = (__be32 *) &recv_rate[i];
+ pci_write_config_dword(dev,
+ tl_dvsec + OCXL_DVSEC_TL_SEND_RATE + i,
+ be32_to_cpu(*be32ptr));
+ }
+ val = recv_cap >> 32;
+ pci_write_config_dword(dev, tl_dvsec + OCXL_DVSEC_TL_SEND_CAP, val);
+ val = recv_cap & GENMASK(31, 0);
+ pci_write_config_dword(dev, tl_dvsec + OCXL_DVSEC_TL_SEND_CAP + 4, val);
+
+ /*
+ * Host -> device
+ */
+ for (i = 0; i < PNV_OCXL_TL_RATE_BUF_SIZE; i += 4) {
+ pci_read_config_dword(dev,
+ tl_dvsec + OCXL_DVSEC_TL_RECV_RATE + i,
+ &val);
+ be32ptr = (__be32 *) &recv_rate[i];
+ *be32ptr = cpu_to_be32(val);
+ }
+ pci_read_config_dword(dev, tl_dvsec + OCXL_DVSEC_TL_RECV_CAP, &val);
+ recv_cap = (long) val << 32;
+ pci_read_config_dword(dev, tl_dvsec + OCXL_DVSEC_TL_RECV_CAP + 4, &val);
+ recv_cap |= val;
+
+ rc = pnv_ocxl_set_tl_conf(dev, recv_cap, __pa(recv_rate),
+ PNV_OCXL_TL_RATE_BUF_SIZE);
+ if (rc)
+ goto out;
+
+ /*
+ * Opencapi commands needing to be retried are classified per
+ * the TL in 2 groups: short and long commands.
+ *
+ * The short back off timer it not used for now. It will be
+ * for opencapi 4.0.
+ *
+ * The long back off timer is typically used when an AFU hits
+ * a page fault but the NPU is already processing one. So the
+ * AFU needs to wait before it can resubmit. Having a value
+ * too low doesn't break anything, but can generate extra
+ * traffic on the link.
+ * We set it to 1.6 us for now. It's shorter than, but in the
+ * same order of magnitude as the time spent to process a page
+ * fault.
+ */
+ timers = 0x2 << 4; /* long timer = 1.6 us */
+ pci_write_config_byte(dev, tl_dvsec + OCXL_DVSEC_TL_BACKOFF_TIMERS,
+ timers);
+
+ rc = 0;
+out:
+ kfree(recv_rate);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ocxl_config_set_TL);
+
+int ocxl_config_terminate_pasid(struct pci_dev *dev, int afu_control, int pasid)
+{
+ u32 val;
+ unsigned long timeout;
+
+ pci_read_config_dword(dev, afu_control + OCXL_DVSEC_AFU_CTRL_TERM_PASID,
+ &val);
+ if (EXTRACT_BIT(val, 20)) {
+ dev_err(&dev->dev,
+ "Can't terminate PASID %#x, previous termination didn't complete\n",
+ pasid);
+ return -EBUSY;
+ }
+
+ val &= ~OCXL_DVSEC_PASID_MASK;
+ val |= pasid & OCXL_DVSEC_PASID_MASK;
+ val |= BIT(20);
+ pci_write_config_dword(dev,
+ afu_control + OCXL_DVSEC_AFU_CTRL_TERM_PASID,
+ val);
+
+ timeout = jiffies + (HZ * OCXL_CFG_TIMEOUT);
+ pci_read_config_dword(dev, afu_control + OCXL_DVSEC_AFU_CTRL_TERM_PASID,
+ &val);
+ while (EXTRACT_BIT(val, 20)) {
+ if (time_after_eq(jiffies, timeout)) {
+ dev_err(&dev->dev,
+ "Timeout while waiting for AFU to terminate PASID %#x\n",
+ pasid);
+ return -EBUSY;
+ }
+ cpu_relax();
+ pci_read_config_dword(dev,
+ afu_control + OCXL_DVSEC_AFU_CTRL_TERM_PASID,
+ &val);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ocxl_config_terminate_pasid);
+
+void ocxl_config_set_actag(struct pci_dev *dev, int func_dvsec, u32 tag_first,
+ u32 tag_count)
+{
+ u32 val;
+
+ val = (tag_first & OCXL_DVSEC_ACTAG_MASK) << 16;
+ val |= tag_count & OCXL_DVSEC_ACTAG_MASK;
+ pci_write_config_dword(dev, func_dvsec + OCXL_DVSEC_FUNC_OFF_ACTAG,
+ val);
+}
+EXPORT_SYMBOL_GPL(ocxl_config_set_actag);
diff --git a/drivers/misc/ocxl/context.c b/drivers/misc/ocxl/context.c
new file mode 100644
index 000000000000..909e8807824a
--- /dev/null
+++ b/drivers/misc/ocxl/context.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/sched/mm.h>
+#include "trace.h"
+#include "ocxl_internal.h"
+
+struct ocxl_context *ocxl_context_alloc(void)
+{
+ return kzalloc(sizeof(struct ocxl_context), GFP_KERNEL);
+}
+
+int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
+ struct address_space *mapping)
+{
+ int pasid;
+
+ ctx->afu = afu;
+ mutex_lock(&afu->contexts_lock);
+ pasid = idr_alloc(&afu->contexts_idr, ctx, afu->pasid_base,
+ afu->pasid_base + afu->pasid_max, GFP_KERNEL);
+ if (pasid < 0) {
+ mutex_unlock(&afu->contexts_lock);
+ return pasid;
+ }
+ afu->pasid_count++;
+ mutex_unlock(&afu->contexts_lock);
+
+ ctx->pasid = pasid;
+ ctx->status = OPENED;
+ mutex_init(&ctx->status_mutex);
+ ctx->mapping = mapping;
+ mutex_init(&ctx->mapping_lock);
+ init_waitqueue_head(&ctx->events_wq);
+ mutex_init(&ctx->xsl_error_lock);
+ mutex_init(&ctx->irq_lock);
+ idr_init(&ctx->irq_idr);
+ /*
+ * Keep a reference on the AFU to make sure it's valid for the
+ * duration of the life of the context
+ */
+ ocxl_afu_get(afu);
+ return 0;
+}
+
+/*
+ * Callback for when a translation fault triggers an error
+ * data: a pointer to the context which triggered the fault
+ * addr: the address that triggered the error
+ * dsisr: the value of the PPC64 dsisr register
+ */
+static void xsl_fault_error(void *data, u64 addr, u64 dsisr)
+{
+ struct ocxl_context *ctx = (struct ocxl_context *) data;
+
+ mutex_lock(&ctx->xsl_error_lock);
+ ctx->xsl_error.addr = addr;
+ ctx->xsl_error.dsisr = dsisr;
+ ctx->xsl_error.count++;
+ mutex_unlock(&ctx->xsl_error_lock);
+
+ wake_up_all(&ctx->events_wq);
+}
+
+int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
+{
+ int rc;
+
+ mutex_lock(&ctx->status_mutex);
+ if (ctx->status != OPENED) {
+ rc = -EIO;
+ goto out;
+ }
+
+ rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid,
+ current->mm->context.id, 0, amr, current->mm,
+ xsl_fault_error, ctx);
+ if (rc)
+ goto out;
+
+ ctx->status = ATTACHED;
+out:
+ mutex_unlock(&ctx->status_mutex);
+ return rc;
+}
+
+static int map_afu_irq(struct vm_area_struct *vma, unsigned long address,
+ u64 offset, struct ocxl_context *ctx)
+{
+ u64 trigger_addr;
+
+ trigger_addr = ocxl_afu_irq_get_addr(ctx, offset);
+ if (!trigger_addr)
+ return VM_FAULT_SIGBUS;
+
+ vm_insert_pfn(vma, address, trigger_addr >> PAGE_SHIFT);
+ return VM_FAULT_NOPAGE;
+}
+
+static int map_pp_mmio(struct vm_area_struct *vma, unsigned long address,
+ u64 offset, struct ocxl_context *ctx)
+{
+ u64 pp_mmio_addr;
+ int pasid_off;
+
+ if (offset >= ctx->afu->config.pp_mmio_stride)
+ return VM_FAULT_SIGBUS;
+
+ mutex_lock(&ctx->status_mutex);
+ if (ctx->status != ATTACHED) {
+ mutex_unlock(&ctx->status_mutex);
+ pr_debug("%s: Context not attached, failing mmio mmap\n",
+ __func__);
+ return VM_FAULT_SIGBUS;
+ }
+
+ pasid_off = ctx->pasid - ctx->afu->pasid_base;
+ pp_mmio_addr = ctx->afu->pp_mmio_start +
+ pasid_off * ctx->afu->config.pp_mmio_stride +
+ offset;
+
+ vm_insert_pfn(vma, address, pp_mmio_addr >> PAGE_SHIFT);
+ mutex_unlock(&ctx->status_mutex);
+ return VM_FAULT_NOPAGE;
+}
+
+static int ocxl_mmap_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct ocxl_context *ctx = vma->vm_file->private_data;
+ u64 offset;
+ int rc;
+
+ offset = vmf->pgoff << PAGE_SHIFT;
+ pr_debug("%s: pasid %d address 0x%lx offset 0x%llx\n", __func__,
+ ctx->pasid, vmf->address, offset);
+
+ if (offset < ctx->afu->irq_base_offset)
+ rc = map_pp_mmio(vma, vmf->address, offset, ctx);
+ else
+ rc = map_afu_irq(vma, vmf->address, offset, ctx);
+ return rc;
+}
+
+static const struct vm_operations_struct ocxl_vmops = {
+ .fault = ocxl_mmap_fault,
+};
+
+static int check_mmap_afu_irq(struct ocxl_context *ctx,
+ struct vm_area_struct *vma)
+{
+ /* only one page */
+ if (vma_pages(vma) != 1)
+ return -EINVAL;
+
+ /* check offset validty */
+ if (!ocxl_afu_irq_get_addr(ctx, vma->vm_pgoff << PAGE_SHIFT))
+ return -EINVAL;
+
+ /*
+ * trigger page should only be accessible in write mode.
+ *
+ * It's a bit theoretical, as a page mmaped with only
+ * PROT_WRITE is currently readable, but it doesn't hurt.
+ */
+ if ((vma->vm_flags & VM_READ) || (vma->vm_flags & VM_EXEC) ||
+ !(vma->vm_flags & VM_WRITE))
+ return -EINVAL;
+ vma->vm_flags &= ~(VM_MAYREAD | VM_MAYEXEC);
+ return 0;
+}
+
+static int check_mmap_mmio(struct ocxl_context *ctx,
+ struct vm_area_struct *vma)
+{
+ if ((vma_pages(vma) + vma->vm_pgoff) >
+ (ctx->afu->config.pp_mmio_stride >> PAGE_SHIFT))
+ return -EINVAL;
+ return 0;
+}
+
+int ocxl_context_mmap(struct ocxl_context *ctx, struct vm_area_struct *vma)
+{
+ int rc;
+
+ if ((vma->vm_pgoff << PAGE_SHIFT) < ctx->afu->irq_base_offset)
+ rc = check_mmap_mmio(ctx, vma);
+ else
+ rc = check_mmap_afu_irq(ctx, vma);
+ if (rc)
+ return rc;
+
+ vma->vm_flags |= VM_IO | VM_PFNMAP;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_ops = &ocxl_vmops;
+ return 0;
+}
+
+int ocxl_context_detach(struct ocxl_context *ctx)
+{
+ struct pci_dev *dev;
+ int afu_control_pos;
+ enum ocxl_context_status status;
+ int rc;
+
+ mutex_lock(&ctx->status_mutex);
+ status = ctx->status;
+ ctx->status = CLOSED;
+ mutex_unlock(&ctx->status_mutex);
+ if (status != ATTACHED)
+ return 0;
+
+ dev = to_pci_dev(ctx->afu->fn->dev.parent);
+ afu_control_pos = ctx->afu->config.dvsec_afu_control_pos;
+
+ mutex_lock(&ctx->afu->afu_control_lock);
+ rc = ocxl_config_terminate_pasid(dev, afu_control_pos, ctx->pasid);
+ mutex_unlock(&ctx->afu->afu_control_lock);
+ trace_ocxl_terminate_pasid(ctx->pasid, rc);
+ if (rc) {
+ /*
+ * If we timeout waiting for the AFU to terminate the
+ * pasid, then it's dangerous to clean up the Process
+ * Element entry in the SPA, as it may be referenced
+ * in the future by the AFU. In which case, we would
+ * checkstop because of an invalid PE access (FIR
+ * register 2, bit 42). So leave the PE
+ * defined. Caller shouldn't free the context so that
+ * PASID remains allocated.
+ *
+ * A link reset will be required to cleanup the AFU
+ * and the SPA.
+ */
+ if (rc == -EBUSY)
+ return rc;
+ }
+ rc = ocxl_link_remove_pe(ctx->afu->fn->link, ctx->pasid);
+ if (rc) {
+ dev_warn(&ctx->afu->dev,
+ "Couldn't remove PE entry cleanly: %d\n", rc);
+ }
+ return 0;
+}
+
+void ocxl_context_detach_all(struct ocxl_afu *afu)
+{
+ struct ocxl_context *ctx;
+ int tmp;
+
+ mutex_lock(&afu->contexts_lock);
+ idr_for_each_entry(&afu->contexts_idr, ctx, tmp) {
+ ocxl_context_detach(ctx);
+ /*
+ * We are force detaching - remove any active mmio
+ * mappings so userspace cannot interfere with the
+ * card if it comes back. Easiest way to exercise
+ * this is to unbind and rebind the driver via sysfs
+ * while it is in use.
+ */
+ mutex_lock(&ctx->mapping_lock);
+ if (ctx->mapping)
+ unmap_mapping_range(ctx->mapping, 0, 0, 1);
+ mutex_unlock(&ctx->mapping_lock);
+ }
+ mutex_unlock(&afu->contexts_lock);
+}
+
+void ocxl_context_free(struct ocxl_context *ctx)
+{
+ mutex_lock(&ctx->afu->contexts_lock);
+ ctx->afu->pasid_count--;
+ idr_remove(&ctx->afu->contexts_idr, ctx->pasid);
+ mutex_unlock(&ctx->afu->contexts_lock);
+
+ ocxl_afu_irq_free_all(ctx);
+ idr_destroy(&ctx->irq_idr);
+ /* reference to the AFU taken in ocxl_context_init */
+ ocxl_afu_put(ctx->afu);
+ kfree(ctx);
+}
diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c
new file mode 100644
index 000000000000..c90c1a578d2f
--- /dev/null
+++ b/drivers/misc/ocxl/file.c
@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/sched/signal.h>
+#include <linux/uaccess.h>
+#include <uapi/misc/ocxl.h>
+#include "ocxl_internal.h"
+
+
+#define OCXL_NUM_MINORS 256 /* Total to reserve */
+
+static dev_t ocxl_dev;
+static struct class *ocxl_class;
+static struct mutex minors_idr_lock;
+static struct idr minors_idr;
+
+static struct ocxl_afu *find_and_get_afu(dev_t devno)
+{
+ struct ocxl_afu *afu;
+ int afu_minor;
+
+ afu_minor = MINOR(devno);
+ /*
+ * We don't declare an RCU critical section here, as our AFU
+ * is protected by a reference counter on the device. By the time the
+ * minor number of a device is removed from the idr, the ref count of
+ * the device is already at 0, so no user API will access that AFU and
+ * this function can't return it.
+ */
+ afu = idr_find(&minors_idr, afu_minor);
+ if (afu)
+ ocxl_afu_get(afu);
+ return afu;
+}
+
+static int allocate_afu_minor(struct ocxl_afu *afu)
+{
+ int minor;
+
+ mutex_lock(&minors_idr_lock);
+ minor = idr_alloc(&minors_idr, afu, 0, OCXL_NUM_MINORS, GFP_KERNEL);
+ mutex_unlock(&minors_idr_lock);
+ return minor;
+}
+
+static void free_afu_minor(struct ocxl_afu *afu)
+{
+ mutex_lock(&minors_idr_lock);
+ idr_remove(&minors_idr, MINOR(afu->dev.devt));
+ mutex_unlock(&minors_idr_lock);
+}
+
+static int afu_open(struct inode *inode, struct file *file)
+{
+ struct ocxl_afu *afu;
+ struct ocxl_context *ctx;
+ int rc;
+
+ pr_debug("%s for device %x\n", __func__, inode->i_rdev);
+
+ afu = find_and_get_afu(inode->i_rdev);
+ if (!afu)
+ return -ENODEV;
+
+ ctx = ocxl_context_alloc();
+ if (!ctx) {
+ rc = -ENOMEM;
+ goto put_afu;
+ }
+
+ rc = ocxl_context_init(ctx, afu, inode->i_mapping);
+ if (rc)
+ goto put_afu;
+ file->private_data = ctx;
+ ocxl_afu_put(afu);
+ return 0;
+
+put_afu:
+ ocxl_afu_put(afu);
+ return rc;
+}
+
+static long afu_ioctl_attach(struct ocxl_context *ctx,
+ struct ocxl_ioctl_attach __user *uarg)
+{
+ struct ocxl_ioctl_attach arg;
+ u64 amr = 0;
+ int rc;
+
+ pr_debug("%s for context %d\n", __func__, ctx->pasid);
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+ return -EFAULT;
+
+ /* Make sure reserved fields are not set for forward compatibility */
+ if (arg.reserved1 || arg.reserved2 || arg.reserved3)
+ return -EINVAL;
+
+ amr = arg.amr & mfspr(SPRN_UAMOR);
+ rc = ocxl_context_attach(ctx, amr);
+ return rc;
+}
+
+#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
+ x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
+ x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
+ x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
+ "UNKNOWN")
+
+static long afu_ioctl(struct file *file, unsigned int cmd,
+ unsigned long args)
+{
+ struct ocxl_context *ctx = file->private_data;
+ struct ocxl_ioctl_irq_fd irq_fd;
+ u64 irq_offset;
+ long rc;
+
+ pr_debug("%s for context %d, command %s\n", __func__, ctx->pasid,
+ CMD_STR(cmd));
+
+ if (ctx->status == CLOSED)
+ return -EIO;
+
+ switch (cmd) {
+ case OCXL_IOCTL_ATTACH:
+ rc = afu_ioctl_attach(ctx,
+ (struct ocxl_ioctl_attach __user *) args);
+ break;
+
+ case OCXL_IOCTL_IRQ_ALLOC:
+ rc = ocxl_afu_irq_alloc(ctx, &irq_offset);
+ if (!rc) {
+ rc = copy_to_user((u64 __user *) args, &irq_offset,
+ sizeof(irq_offset));
+ if (rc)
+ ocxl_afu_irq_free(ctx, irq_offset);
+ }
+ break;
+
+ case OCXL_IOCTL_IRQ_FREE:
+ rc = copy_from_user(&irq_offset, (u64 __user *) args,
+ sizeof(irq_offset));
+ if (rc)
+ return -EFAULT;
+ rc = ocxl_afu_irq_free(ctx, irq_offset);
+ break;
+
+ case OCXL_IOCTL_IRQ_SET_FD:
+ rc = copy_from_user(&irq_fd, (u64 __user *) args,
+ sizeof(irq_fd));
+ if (rc)
+ return -EFAULT;
+ if (irq_fd.reserved)
+ return -EINVAL;
+ rc = ocxl_afu_irq_set_fd(ctx, irq_fd.irq_offset,
+ irq_fd.eventfd);
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static long afu_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long args)
+{
+ return afu_ioctl(file, cmd, args);
+}
+
+static int afu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct ocxl_context *ctx = file->private_data;
+
+ pr_debug("%s for context %d\n", __func__, ctx->pasid);
+ return ocxl_context_mmap(ctx, vma);
+}
+
+static bool has_xsl_error(struct ocxl_context *ctx)
+{
+ bool ret;
+
+ mutex_lock(&ctx->xsl_error_lock);
+ ret = !!ctx->xsl_error.addr;
+ mutex_unlock(&ctx->xsl_error_lock);
+
+ return ret;
+}
+
+/*
+ * Are there any events pending on the AFU
+ * ctx: The AFU context
+ * Returns: true if there are events pending
+ */
+static bool afu_events_pending(struct ocxl_context *ctx)
+{
+ if (has_xsl_error(ctx))
+ return true;
+ return false;
+}
+
+static unsigned int afu_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct ocxl_context *ctx = file->private_data;
+ unsigned int mask = 0;
+ bool closed;
+
+ pr_debug("%s for context %d\n", __func__, ctx->pasid);
+
+ poll_wait(file, &ctx->events_wq, wait);
+
+ mutex_lock(&ctx->status_mutex);
+ closed = (ctx->status == CLOSED);
+ mutex_unlock(&ctx->status_mutex);
+
+ if (afu_events_pending(ctx))
+ mask = POLLIN | POLLRDNORM;
+ else if (closed)
+ mask = POLLERR;
+
+ return mask;
+}
+
+/*
+ * Populate the supplied buffer with a single XSL error
+ * ctx: The AFU context to report the error from
+ * header: the event header to populate
+ * buf: The buffer to write the body into (should be at least
+ * AFU_EVENT_BODY_XSL_ERROR_SIZE)
+ * Return: the amount of buffer that was populated
+ */
+static ssize_t append_xsl_error(struct ocxl_context *ctx,
+ struct ocxl_kernel_event_header *header,
+ char __user *buf)
+{
+ struct ocxl_kernel_event_xsl_fault_error body;
+
+ memset(&body, 0, sizeof(body));
+
+ mutex_lock(&ctx->xsl_error_lock);
+ if (!ctx->xsl_error.addr) {
+ mutex_unlock(&ctx->xsl_error_lock);
+ return 0;
+ }
+
+ body.addr = ctx->xsl_error.addr;
+ body.dsisr = ctx->xsl_error.dsisr;
+ body.count = ctx->xsl_error.count;
+
+ ctx->xsl_error.addr = 0;
+ ctx->xsl_error.dsisr = 0;
+ ctx->xsl_error.count = 0;
+
+ mutex_unlock(&ctx->xsl_error_lock);
+
+ header->type = OCXL_AFU_EVENT_XSL_FAULT_ERROR;
+
+ if (copy_to_user(buf, &body, sizeof(body)))
+ return -EFAULT;
+
+ return sizeof(body);
+}
+
+#define AFU_EVENT_BODY_MAX_SIZE sizeof(struct ocxl_kernel_event_xsl_fault_error)
+
+/*
+ * Reports events on the AFU
+ * Format:
+ * Header (struct ocxl_kernel_event_header)
+ * Body (struct ocxl_kernel_event_*)
+ * Header...
+ */
+static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
+ loff_t *off)
+{
+ struct ocxl_context *ctx = file->private_data;
+ struct ocxl_kernel_event_header header;
+ ssize_t rc;
+ size_t used = 0;
+ DEFINE_WAIT(event_wait);
+
+ memset(&header, 0, sizeof(header));
+
+ /* Require offset to be 0 */
+ if (*off != 0)
+ return -EINVAL;
+
+ if (count < (sizeof(struct ocxl_kernel_event_header) +
+ AFU_EVENT_BODY_MAX_SIZE))
+ return -EINVAL;
+
+ for (;;) {
+ prepare_to_wait(&ctx->events_wq, &event_wait,
+ TASK_INTERRUPTIBLE);
+
+ if (afu_events_pending(ctx))
+ break;
+
+ if (ctx->status == CLOSED)
+ break;
+
+ if (file->f_flags & O_NONBLOCK) {
+ finish_wait(&ctx->events_wq, &event_wait);
+ return -EAGAIN;
+ }
+
+ if (signal_pending(current)) {
+ finish_wait(&ctx->events_wq, &event_wait);
+ return -ERESTARTSYS;
+ }
+
+ schedule();
+ }
+
+ finish_wait(&ctx->events_wq, &event_wait);
+
+ if (has_xsl_error(ctx)) {
+ used = append_xsl_error(ctx, &header, buf + sizeof(header));
+ if (used < 0)
+ return used;
+ }
+
+ if (!afu_events_pending(ctx))
+ header.flags |= OCXL_KERNEL_EVENT_FLAG_LAST;
+
+ if (copy_to_user(buf, &header, sizeof(header)))
+ return -EFAULT;
+
+ used += sizeof(header);
+
+ rc = (ssize_t) used;
+ return rc;
+}
+
+static int afu_release(struct inode *inode, struct file *file)
+{
+ struct ocxl_context *ctx = file->private_data;
+ int rc;
+
+ pr_debug("%s for device %x\n", __func__, inode->i_rdev);
+ rc = ocxl_context_detach(ctx);
+ mutex_lock(&ctx->mapping_lock);
+ ctx->mapping = NULL;
+ mutex_unlock(&ctx->mapping_lock);
+ wake_up_all(&ctx->events_wq);
+ if (rc != -EBUSY)
+ ocxl_context_free(ctx);
+ return 0;
+}
+
+static const struct file_operations ocxl_afu_fops = {
+ .owner = THIS_MODULE,
+ .open = afu_open,
+ .unlocked_ioctl = afu_ioctl,
+ .compat_ioctl = afu_compat_ioctl,
+ .mmap = afu_mmap,
+ .poll = afu_poll,
+ .read = afu_read,
+ .release = afu_release,
+};
+
+int ocxl_create_cdev(struct ocxl_afu *afu)
+{
+ int rc;
+
+ cdev_init(&afu->cdev, &ocxl_afu_fops);
+ rc = cdev_add(&afu->cdev, afu->dev.devt, 1);
+ if (rc) {
+ dev_err(&afu->dev, "Unable to add afu char device: %d\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
+void ocxl_destroy_cdev(struct ocxl_afu *afu)
+{
+ cdev_del(&afu->cdev);
+}
+
+int ocxl_register_afu(struct ocxl_afu *afu)
+{
+ int minor;
+
+ minor = allocate_afu_minor(afu);
+ if (minor < 0)
+ return minor;
+ afu->dev.devt = MKDEV(MAJOR(ocxl_dev), minor);
+ afu->dev.class = ocxl_class;
+ return device_register(&afu->dev);
+}
+
+void ocxl_unregister_afu(struct ocxl_afu *afu)
+{
+ free_afu_minor(afu);
+}
+
+static char *ocxl_devnode(struct device *dev, umode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "ocxl/%s", dev_name(dev));
+}
+
+int ocxl_file_init(void)
+{
+ int rc;
+
+ mutex_init(&minors_idr_lock);
+ idr_init(&minors_idr);
+
+ rc = alloc_chrdev_region(&ocxl_dev, 0, OCXL_NUM_MINORS, "ocxl");
+ if (rc) {
+ pr_err("Unable to allocate ocxl major number: %d\n", rc);
+ return rc;
+ }
+
+ ocxl_class = class_create(THIS_MODULE, "ocxl");
+ if (IS_ERR(ocxl_class)) {
+ pr_err("Unable to create ocxl class\n");
+ unregister_chrdev_region(ocxl_dev, OCXL_NUM_MINORS);
+ return PTR_ERR(ocxl_class);
+ }
+
+ ocxl_class->devnode = ocxl_devnode;
+ return 0;
+}
+
+void ocxl_file_exit(void)
+{
+ class_destroy(ocxl_class);
+ unregister_chrdev_region(ocxl_dev, OCXL_NUM_MINORS);
+ idr_destroy(&minors_idr);
+}
diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
new file mode 100644
index 000000000000..f30790582dc0
--- /dev/null
+++ b/drivers/misc/ocxl/link.c
@@ -0,0 +1,647 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/sched/mm.h>
+#include <linux/mutex.h>
+#include <linux/mmu_context.h>
+#include <asm/copro.h>
+#include <asm/pnv-ocxl.h>
+#include <misc/ocxl.h>
+#include "ocxl_internal.h"
+#include "trace.h"
+
+
+#define SPA_PASID_BITS 15
+#define SPA_PASID_MAX ((1 << SPA_PASID_BITS) - 1)
+#define SPA_PE_MASK SPA_PASID_MAX
+#define SPA_SPA_SIZE_LOG 22 /* Each SPA is 4 Mb */
+
+#define SPA_CFG_SF (1ull << (63-0))
+#define SPA_CFG_TA (1ull << (63-1))
+#define SPA_CFG_HV (1ull << (63-3))
+#define SPA_CFG_UV (1ull << (63-4))
+#define SPA_CFG_XLAT_hpt (0ull << (63-6)) /* Hashed page table (HPT) mode */
+#define SPA_CFG_XLAT_roh (2ull << (63-6)) /* Radix on HPT mode */
+#define SPA_CFG_XLAT_ror (3ull << (63-6)) /* Radix on Radix mode */
+#define SPA_CFG_PR (1ull << (63-49))
+#define SPA_CFG_TC (1ull << (63-54))
+#define SPA_CFG_DR (1ull << (63-59))
+
+#define SPA_XSL_TF (1ull << (63-3)) /* Translation fault */
+#define SPA_XSL_S (1ull << (63-38)) /* Store operation */
+
+#define SPA_PE_VALID 0x80000000
+
+
+struct pe_data {
+ struct mm_struct *mm;
+ /* callback to trigger when a translation fault occurs */
+ void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr);
+ /* opaque pointer to be passed to the above callback */
+ void *xsl_err_data;
+ struct rcu_head rcu;
+};
+
+struct spa {
+ struct ocxl_process_element *spa_mem;
+ int spa_order;
+ struct mutex spa_lock;
+ struct radix_tree_root pe_tree; /* Maps PE handles to pe_data */
+ char *irq_name;
+ int virq;
+ void __iomem *reg_dsisr;
+ void __iomem *reg_dar;
+ void __iomem *reg_tfc;
+ void __iomem *reg_pe_handle;
+ /*
+ * The following field are used by the memory fault
+ * interrupt handler. We can only have one interrupt at a
+ * time. The NPU won't raise another interrupt until the
+ * previous one has been ack'd by writing to the TFC register
+ */
+ struct xsl_fault {
+ struct work_struct fault_work;
+ u64 pe;
+ u64 dsisr;
+ u64 dar;
+ struct pe_data pe_data;
+ } xsl_fault;
+};
+
+/*
+ * A opencapi link can be used be by several PCI functions. We have
+ * one link per device slot.
+ *
+ * A linked list of opencapi links should suffice, as there's a
+ * limited number of opencapi slots on a system and lookup is only
+ * done when the device is probed
+ */
+struct link {
+ struct list_head list;
+ struct kref ref;
+ int domain;
+ int bus;
+ int dev;
+ atomic_t irq_available;
+ struct spa *spa;
+ void *platform_data;
+};
+static struct list_head links_list = LIST_HEAD_INIT(links_list);
+static DEFINE_MUTEX(links_list_lock);
+
+enum xsl_response {
+ CONTINUE,
+ ADDRESS_ERROR,
+ RESTART,
+};
+
+
+static void read_irq(struct spa *spa, u64 *dsisr, u64 *dar, u64 *pe)
+{
+ u64 reg;
+
+ *dsisr = in_be64(spa->reg_dsisr);
+ *dar = in_be64(spa->reg_dar);
+ reg = in_be64(spa->reg_pe_handle);
+ *pe = reg & SPA_PE_MASK;
+}
+
+static void ack_irq(struct spa *spa, enum xsl_response r)
+{
+ u64 reg = 0;
+
+ /* continue is not supported */
+ if (r == RESTART)
+ reg = PPC_BIT(31);
+ else if (r == ADDRESS_ERROR)
+ reg = PPC_BIT(30);
+ else
+ WARN(1, "Invalid irq response %d\n", r);
+
+ if (reg) {
+ trace_ocxl_fault_ack(spa->spa_mem, spa->xsl_fault.pe,
+ spa->xsl_fault.dsisr, spa->xsl_fault.dar, reg);
+ out_be64(spa->reg_tfc, reg);
+ }
+}
+
+static void xsl_fault_handler_bh(struct work_struct *fault_work)
+{
+ unsigned int flt = 0;
+ unsigned long access, flags, inv_flags = 0;
+ enum xsl_response r;
+ struct xsl_fault *fault = container_of(fault_work, struct xsl_fault,
+ fault_work);
+ struct spa *spa = container_of(fault, struct spa, xsl_fault);
+
+ int rc;
+
+ /*
+ * We need to release a reference on the mm whenever exiting this
+ * function (taken in the memory fault interrupt handler)
+ */
+ rc = copro_handle_mm_fault(fault->pe_data.mm, fault->dar, fault->dsisr,
+ &flt);
+ if (rc) {
+ pr_debug("copro_handle_mm_fault failed: %d\n", rc);
+ if (fault->pe_data.xsl_err_cb) {
+ fault->pe_data.xsl_err_cb(
+ fault->pe_data.xsl_err_data,
+ fault->dar, fault->dsisr);
+ }
+ r = ADDRESS_ERROR;
+ goto ack;
+ }
+
+ if (!radix_enabled()) {
+ /*
+ * update_mmu_cache() will not have loaded the hash
+ * since current->trap is not a 0x400 or 0x300, so
+ * just call hash_page_mm() here.
+ */
+ access = _PAGE_PRESENT | _PAGE_READ;
+ if (fault->dsisr & SPA_XSL_S)
+ access |= _PAGE_WRITE;
+
+ if (REGION_ID(fault->dar) != USER_REGION_ID)
+ access |= _PAGE_PRIVILEGED;
+
+ local_irq_save(flags);
+ hash_page_mm(fault->pe_data.mm, fault->dar, access, 0x300,
+ inv_flags);
+ local_irq_restore(flags);
+ }
+ r = RESTART;
+ack:
+ mmdrop(fault->pe_data.mm);
+ ack_irq(spa, r);
+}
+
+static irqreturn_t xsl_fault_handler(int irq, void *data)
+{
+ struct link *link = (struct link *) data;
+ struct spa *spa = link->spa;
+ u64 dsisr, dar, pe_handle;
+ struct pe_data *pe_data;
+ struct ocxl_process_element *pe;
+ int lpid, pid, tid;
+
+ read_irq(spa, &dsisr, &dar, &pe_handle);
+ trace_ocxl_fault(spa->spa_mem, pe_handle, dsisr, dar, -1);
+
+ WARN_ON(pe_handle > SPA_PE_MASK);
+ pe = spa->spa_mem + pe_handle;
+ lpid = be32_to_cpu(pe->lpid);
+ pid = be32_to_cpu(pe->pid);
+ tid = be32_to_cpu(pe->tid);
+ /* We could be reading all null values here if the PE is being
+ * removed while an interrupt kicks in. It's not supposed to
+ * happen if the driver notified the AFU to terminate the
+ * PASID, and the AFU waited for pending operations before
+ * acknowledging. But even if it happens, we won't find a
+ * memory context below and fail silently, so it should be ok.
+ */
+ if (!(dsisr & SPA_XSL_TF)) {
+ WARN(1, "Invalid xsl interrupt fault register %#llx\n", dsisr);
+ ack_irq(spa, ADDRESS_ERROR);
+ return IRQ_HANDLED;
+ }
+
+ rcu_read_lock();
+ pe_data = radix_tree_lookup(&spa->pe_tree, pe_handle);
+ if (!pe_data) {
+ /*
+ * Could only happen if the driver didn't notify the
+ * AFU about PASID termination before removing the PE,
+ * or the AFU didn't wait for all memory access to
+ * have completed.
+ *
+ * Either way, we fail early, but we shouldn't log an
+ * error message, as it is a valid (if unexpected)
+ * scenario
+ */
+ rcu_read_unlock();
+ pr_debug("Unknown mm context for xsl interrupt\n");
+ ack_irq(spa, ADDRESS_ERROR);
+ return IRQ_HANDLED;
+ }
+ WARN_ON(pe_data->mm->context.id != pid);
+
+ spa->xsl_fault.pe = pe_handle;
+ spa->xsl_fault.dar = dar;
+ spa->xsl_fault.dsisr = dsisr;
+ spa->xsl_fault.pe_data = *pe_data;
+ mmgrab(pe_data->mm); /* mm count is released by bottom half */
+
+ rcu_read_unlock();
+ schedule_work(&spa->xsl_fault.fault_work);
+ return IRQ_HANDLED;
+}
+
+static void unmap_irq_registers(struct spa *spa)
+{
+ pnv_ocxl_unmap_xsl_regs(spa->reg_dsisr, spa->reg_dar, spa->reg_tfc,
+ spa->reg_pe_handle);
+}
+
+static int map_irq_registers(struct pci_dev *dev, struct spa *spa)
+{
+ return pnv_ocxl_map_xsl_regs(dev, &spa->reg_dsisr, &spa->reg_dar,
+ &spa->reg_tfc, &spa->reg_pe_handle);
+}
+
+static int setup_xsl_irq(struct pci_dev *dev, struct link *link)
+{
+ struct spa *spa = link->spa;
+ int rc;
+ int hwirq;
+
+ rc = pnv_ocxl_get_xsl_irq(dev, &hwirq);
+ if (rc)
+ return rc;
+
+ rc = map_irq_registers(dev, spa);
+ if (rc)
+ return rc;
+
+ spa->irq_name = kasprintf(GFP_KERNEL, "ocxl-xsl-%x-%x-%x",
+ link->domain, link->bus, link->dev);
+ if (!spa->irq_name) {
+ unmap_irq_registers(spa);
+ dev_err(&dev->dev, "Can't allocate name for xsl interrupt\n");
+ return -ENOMEM;
+ }
+ /*
+ * At some point, we'll need to look into allowing a higher
+ * number of interrupts. Could we have an IRQ domain per link?
+ */
+ spa->virq = irq_create_mapping(NULL, hwirq);
+ if (!spa->virq) {
+ kfree(spa->irq_name);
+ unmap_irq_registers(spa);
+ dev_err(&dev->dev,
+ "irq_create_mapping failed for translation interrupt\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(&dev->dev, "hwirq %d mapped to virq %d\n", hwirq, spa->virq);
+
+ rc = request_irq(spa->virq, xsl_fault_handler, 0, spa->irq_name,
+ link);
+ if (rc) {
+ irq_dispose_mapping(spa->virq);
+ kfree(spa->irq_name);
+ unmap_irq_registers(spa);
+ dev_err(&dev->dev,
+ "request_irq failed for translation interrupt: %d\n",
+ rc);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void release_xsl_irq(struct link *link)
+{
+ struct spa *spa = link->spa;
+
+ if (spa->virq) {
+ free_irq(spa->virq, link);
+ irq_dispose_mapping(spa->virq);
+ }
+ kfree(spa->irq_name);
+ unmap_irq_registers(spa);
+}
+
+static int alloc_spa(struct pci_dev *dev, struct link *link)
+{
+ struct spa *spa;
+
+ spa = kzalloc(sizeof(struct spa), GFP_KERNEL);
+ if (!spa)
+ return -ENOMEM;
+
+ mutex_init(&spa->spa_lock);
+ INIT_RADIX_TREE(&spa->pe_tree, GFP_KERNEL);
+ INIT_WORK(&spa->xsl_fault.fault_work, xsl_fault_handler_bh);
+
+ spa->spa_order = SPA_SPA_SIZE_LOG - PAGE_SHIFT;
+ spa->spa_mem = (struct ocxl_process_element *)
+ __get_free_pages(GFP_KERNEL | __GFP_ZERO, spa->spa_order);
+ if (!spa->spa_mem) {
+ dev_err(&dev->dev, "Can't allocate Shared Process Area\n");
+ kfree(spa);
+ return -ENOMEM;
+ }
+ pr_debug("Allocated SPA for %x:%x:%x at %p\n", link->domain, link->bus,
+ link->dev, spa->spa_mem);
+
+ link->spa = spa;
+ return 0;
+}
+
+static void free_spa(struct link *link)
+{
+ struct spa *spa = link->spa;
+
+ pr_debug("Freeing SPA for %x:%x:%x\n", link->domain, link->bus,
+ link->dev);
+
+ if (spa && spa->spa_mem) {
+ free_pages((unsigned long) spa->spa_mem, spa->spa_order);
+ kfree(spa);
+ link->spa = NULL;
+ }
+}
+
+static int alloc_link(struct pci_dev *dev, int PE_mask, struct link **out_link)
+{
+ struct link *link;
+ int rc;
+
+ link = kzalloc(sizeof(struct link), GFP_KERNEL);
+ if (!link)
+ return -ENOMEM;
+
+ kref_init(&link->ref);
+ link->domain = pci_domain_nr(dev->bus);
+ link->bus = dev->bus->number;
+ link->dev = PCI_SLOT(dev->devfn);
+ atomic_set(&link->irq_available, MAX_IRQ_PER_LINK);
+
+ rc = alloc_spa(dev, link);
+ if (rc)
+ goto err_free;
+
+ rc = setup_xsl_irq(dev, link);
+ if (rc)
+ goto err_spa;
+
+ /* platform specific hook */
+ rc = pnv_ocxl_spa_setup(dev, link->spa->spa_mem, PE_mask,
+ &link->platform_data);
+ if (rc)
+ goto err_xsl_irq;
+
+ *out_link = link;
+ return 0;
+
+err_xsl_irq:
+ release_xsl_irq(link);
+err_spa:
+ free_spa(link);
+err_free:
+ kfree(link);
+ return rc;
+}
+
+static void free_link(struct link *link)
+{
+ release_xsl_irq(link);
+ free_spa(link);
+ kfree(link);
+}
+
+int ocxl_link_setup(struct pci_dev *dev, int PE_mask, void **link_handle)
+{
+ int rc = 0;
+ struct link *link;
+
+ mutex_lock(&links_list_lock);
+ list_for_each_entry(link, &links_list, list) {
+ /* The functions of a device all share the same link */
+ if (link->domain == pci_domain_nr(dev->bus) &&
+ link->bus == dev->bus->number &&
+ link->dev == PCI_SLOT(dev->devfn)) {
+ kref_get(&link->ref);
+ *link_handle = link;
+ goto unlock;
+ }
+ }
+ rc = alloc_link(dev, PE_mask, &link);
+ if (rc)
+ goto unlock;
+
+ list_add(&link->list, &links_list);
+ *link_handle = link;
+unlock:
+ mutex_unlock(&links_list_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ocxl_link_setup);
+
+static void release_xsl(struct kref *ref)
+{
+ struct link *link = container_of(ref, struct link, ref);
+
+ list_del(&link->list);
+ /* call platform code before releasing data */
+ pnv_ocxl_spa_release(link->platform_data);
+ free_link(link);
+}
+
+void ocxl_link_release(struct pci_dev *dev, void *link_handle)
+{
+ struct link *link = (struct link *) link_handle;
+
+ mutex_lock(&links_list_lock);
+ kref_put(&link->ref, release_xsl);
+ mutex_unlock(&links_list_lock);
+}
+EXPORT_SYMBOL_GPL(ocxl_link_release);
+
+static u64 calculate_cfg_state(bool kernel)
+{
+ u64 state;
+
+ state = SPA_CFG_DR;
+ if (mfspr(SPRN_LPCR) & LPCR_TC)
+ state |= SPA_CFG_TC;
+ if (radix_enabled())
+ state |= SPA_CFG_XLAT_ror;
+ else
+ state |= SPA_CFG_XLAT_hpt;
+ state |= SPA_CFG_HV;
+ if (kernel) {
+ if (mfmsr() & MSR_SF)
+ state |= SPA_CFG_SF;
+ } else {
+ state |= SPA_CFG_PR;
+ if (!test_tsk_thread_flag(current, TIF_32BIT))
+ state |= SPA_CFG_SF;
+ }
+ return state;
+}
+
+int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
+ u64 amr, struct mm_struct *mm,
+ void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr),
+ void *xsl_err_data)
+{
+ struct link *link = (struct link *) link_handle;
+ struct spa *spa = link->spa;
+ struct ocxl_process_element *pe;
+ int pe_handle, rc = 0;
+ struct pe_data *pe_data;
+
+ BUILD_BUG_ON(sizeof(struct ocxl_process_element) != 128);
+ if (pasid > SPA_PASID_MAX)
+ return -EINVAL;
+
+ mutex_lock(&spa->spa_lock);
+ pe_handle = pasid & SPA_PE_MASK;
+ pe = spa->spa_mem + pe_handle;
+
+ if (pe->software_state) {
+ rc = -EBUSY;
+ goto unlock;
+ }
+
+ pe_data = kmalloc(sizeof(*pe_data), GFP_KERNEL);
+ if (!pe_data) {
+ rc = -ENOMEM;
+ goto unlock;
+ }
+
+ pe_data->mm = mm;
+ pe_data->xsl_err_cb = xsl_err_cb;
+ pe_data->xsl_err_data = xsl_err_data;
+
+ memset(pe, 0, sizeof(struct ocxl_process_element));
+ pe->config_state = cpu_to_be64(calculate_cfg_state(pidr == 0));
+ pe->lpid = cpu_to_be32(mfspr(SPRN_LPID));
+ pe->pid = cpu_to_be32(pidr);
+ pe->tid = cpu_to_be32(tidr);
+ pe->amr = cpu_to_be64(amr);
+ pe->software_state = cpu_to_be32(SPA_PE_VALID);
+
+ mm_context_add_copro(mm);
+ /*
+ * Barrier is to make sure PE is visible in the SPA before it
+ * is used by the device. It also helps with the global TLBI
+ * invalidation
+ */
+ mb();
+ radix_tree_insert(&spa->pe_tree, pe_handle, pe_data);
+
+ /*
+ * The mm must stay valid for as long as the device uses it. We
+ * lower the count when the context is removed from the SPA.
+ *
+ * We grab mm_count (and not mm_users), as we don't want to
+ * end up in a circular dependency if a process mmaps its
+ * mmio, therefore incrementing the file ref count when
+ * calling mmap(), and forgets to unmap before exiting. In
+ * that scenario, when the kernel handles the death of the
+ * process, the file is not cleaned because unmap was not
+ * called, and the mm wouldn't be freed because we would still
+ * have a reference on mm_users. Incrementing mm_count solves
+ * the problem.
+ */
+ mmgrab(mm);
+ trace_ocxl_context_add(current->pid, spa->spa_mem, pasid, pidr, tidr);
+unlock:
+ mutex_unlock(&spa->spa_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ocxl_link_add_pe);
+
+int ocxl_link_remove_pe(void *link_handle, int pasid)
+{
+ struct link *link = (struct link *) link_handle;
+ struct spa *spa = link->spa;
+ struct ocxl_process_element *pe;
+ struct pe_data *pe_data;
+ int pe_handle, rc;
+
+ if (pasid > SPA_PASID_MAX)
+ return -EINVAL;
+
+ /*
+ * About synchronization with our memory fault handler:
+ *
+ * Before removing the PE, the driver is supposed to have
+ * notified the AFU, which should have cleaned up and make
+ * sure the PASID is no longer in use, including pending
+ * interrupts. However, there's no way to be sure...
+ *
+ * We clear the PE and remove the context from our radix
+ * tree. From that point on, any new interrupt for that
+ * context will fail silently, which is ok. As mentioned
+ * above, that's not expected, but it could happen if the
+ * driver or AFU didn't do the right thing.
+ *
+ * There could still be a bottom half running, but we don't
+ * need to wait/flush, as it is managing a reference count on
+ * the mm it reads from the radix tree.
+ */
+ pe_handle = pasid & SPA_PE_MASK;
+ pe = spa->spa_mem + pe_handle;
+
+ mutex_lock(&spa->spa_lock);
+
+ if (!(be32_to_cpu(pe->software_state) & SPA_PE_VALID)) {
+ rc = -EINVAL;
+ goto unlock;
+ }
+
+ trace_ocxl_context_remove(current->pid, spa->spa_mem, pasid,
+ be32_to_cpu(pe->pid), be32_to_cpu(pe->tid));
+
+ memset(pe, 0, sizeof(struct ocxl_process_element));
+ /*
+ * The barrier makes sure the PE is removed from the SPA
+ * before we clear the NPU context cache below, so that the
+ * old PE cannot be reloaded erroneously.
+ */
+ mb();
+
+ /*
+ * hook to platform code
+ * On powerpc, the entry needs to be cleared from the context
+ * cache of the NPU.
+ */
+ rc = pnv_ocxl_spa_remove_pe(link->platform_data, pe_handle);
+ WARN_ON(rc);
+
+ pe_data = radix_tree_delete(&spa->pe_tree, pe_handle);
+ if (!pe_data) {
+ WARN(1, "Couldn't find pe data when removing PE\n");
+ } else {
+ mm_context_remove_copro(pe_data->mm);
+ mmdrop(pe_data->mm);
+ kfree_rcu(pe_data, rcu);
+ }
+unlock:
+ mutex_unlock(&spa->spa_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ocxl_link_remove_pe);
+
+int ocxl_link_irq_alloc(void *link_handle, int *hw_irq, u64 *trigger_addr)
+{
+ struct link *link = (struct link *) link_handle;
+ int rc, irq;
+ u64 addr;
+
+ if (atomic_dec_if_positive(&link->irq_available) < 0)
+ return -ENOSPC;
+
+ rc = pnv_ocxl_alloc_xive_irq(&irq, &addr);
+ if (rc) {
+ atomic_inc(&link->irq_available);
+ return rc;
+ }
+
+ *hw_irq = irq;
+ *trigger_addr = addr;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ocxl_link_irq_alloc);
+
+void ocxl_link_free_irq(void *link_handle, int hw_irq)
+{
+ struct link *link = (struct link *) link_handle;
+
+ pnv_ocxl_free_xive_irq(hw_irq);
+ atomic_inc(&link->irq_available);
+}
+EXPORT_SYMBOL_GPL(ocxl_link_free_irq);
diff --git a/drivers/misc/ocxl/main.c b/drivers/misc/ocxl/main.c
new file mode 100644
index 000000000000..7210d9e059be
--- /dev/null
+++ b/drivers/misc/ocxl/main.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "ocxl_internal.h"
+
+static int __init init_ocxl(void)
+{
+ int rc = 0;
+
+ rc = ocxl_file_init();
+ if (rc)
+ return rc;
+
+ rc = pci_register_driver(&ocxl_pci_driver);
+ if (rc) {
+ ocxl_file_exit();
+ return rc;
+ }
+ return 0;
+}
+
+static void exit_ocxl(void)
+{
+ pci_unregister_driver(&ocxl_pci_driver);
+ ocxl_file_exit();
+}
+
+module_init(init_ocxl);
+module_exit(exit_ocxl);
+
+MODULE_DESCRIPTION("Open Coherent Accelerator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h
new file mode 100644
index 000000000000..5d421824afd9
--- /dev/null
+++ b/drivers/misc/ocxl/ocxl_internal.h
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#ifndef _OCXL_INTERNAL_H_
+#define _OCXL_INTERNAL_H_
+
+#include <linux/pci.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <misc/ocxl.h>
+
+#define MAX_IRQ_PER_LINK 2000
+#define MAX_IRQ_PER_CONTEXT MAX_IRQ_PER_LINK
+
+#define to_ocxl_function(d) container_of(d, struct ocxl_fn, dev)
+#define to_ocxl_afu(d) container_of(d, struct ocxl_afu, dev)
+
+extern struct pci_driver ocxl_pci_driver;
+
+
+struct ocxl_fn {
+ struct device dev;
+ int bar_used[3];
+ struct ocxl_fn_config config;
+ struct list_head afu_list;
+ int pasid_base;
+ int actag_base;
+ int actag_enabled;
+ int actag_supported;
+ struct list_head pasid_list;
+ struct list_head actag_list;
+ void *link;
+};
+
+struct ocxl_afu {
+ struct ocxl_fn *fn;
+ struct list_head list;
+ struct device dev;
+ struct cdev cdev;
+ struct ocxl_afu_config config;
+ int pasid_base;
+ int pasid_count; /* opened contexts */
+ int pasid_max; /* maximum number of contexts */
+ int actag_base;
+ int actag_enabled;
+ struct mutex contexts_lock;
+ struct idr contexts_idr;
+ struct mutex afu_control_lock;
+ u64 global_mmio_start;
+ u64 irq_base_offset;
+ void __iomem *global_mmio_ptr;
+ u64 pp_mmio_start;
+ struct bin_attribute attr_global_mmio;
+};
+
+enum ocxl_context_status {
+ CLOSED,
+ OPENED,
+ ATTACHED,
+};
+
+// Contains metadata about a translation fault
+struct ocxl_xsl_error {
+ u64 addr; // The address that triggered the fault
+ u64 dsisr; // the value of the dsisr register
+ u64 count; // The number of times this fault has been triggered
+};
+
+struct ocxl_context {
+ struct ocxl_afu *afu;
+ int pasid;
+ struct mutex status_mutex;
+ enum ocxl_context_status status;
+ struct address_space *mapping;
+ struct mutex mapping_lock;
+ wait_queue_head_t events_wq;
+ struct mutex xsl_error_lock;
+ struct ocxl_xsl_error xsl_error;
+ struct mutex irq_lock;
+ struct idr irq_idr;
+};
+
+struct ocxl_process_element {
+ __be64 config_state;
+ __be32 reserved1[11];
+ __be32 lpid;
+ __be32 tid;
+ __be32 pid;
+ __be32 reserved2[10];
+ __be64 amr;
+ __be32 reserved3[3];
+ __be32 software_state;
+};
+
+
+extern struct ocxl_afu *ocxl_afu_get(struct ocxl_afu *afu);
+extern void ocxl_afu_put(struct ocxl_afu *afu);
+
+extern int ocxl_create_cdev(struct ocxl_afu *afu);
+extern void ocxl_destroy_cdev(struct ocxl_afu *afu);
+extern int ocxl_register_afu(struct ocxl_afu *afu);
+extern void ocxl_unregister_afu(struct ocxl_afu *afu);
+
+extern int ocxl_file_init(void);
+extern void ocxl_file_exit(void);
+
+extern int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size);
+extern void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size);
+extern int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size);
+extern void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size);
+
+extern struct ocxl_context *ocxl_context_alloc(void);
+extern int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
+ struct address_space *mapping);
+extern int ocxl_context_attach(struct ocxl_context *ctx, u64 amr);
+extern int ocxl_context_mmap(struct ocxl_context *ctx,
+ struct vm_area_struct *vma);
+extern int ocxl_context_detach(struct ocxl_context *ctx);
+extern void ocxl_context_detach_all(struct ocxl_afu *afu);
+extern void ocxl_context_free(struct ocxl_context *ctx);
+
+extern int ocxl_sysfs_add_afu(struct ocxl_afu *afu);
+extern void ocxl_sysfs_remove_afu(struct ocxl_afu *afu);
+
+extern int ocxl_afu_irq_alloc(struct ocxl_context *ctx, u64 *irq_offset);
+extern int ocxl_afu_irq_free(struct ocxl_context *ctx, u64 irq_offset);
+extern void ocxl_afu_irq_free_all(struct ocxl_context *ctx);
+extern int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset,
+ int eventfd);
+extern u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset);
+
+#endif /* _OCXL_INTERNAL_H_ */
diff --git a/drivers/misc/ocxl/pasid.c b/drivers/misc/ocxl/pasid.c
new file mode 100644
index 000000000000..d14cb56e6920
--- /dev/null
+++ b/drivers/misc/ocxl/pasid.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include "ocxl_internal.h"
+
+
+struct id_range {
+ struct list_head list;
+ u32 start;
+ u32 end;
+};
+
+#ifdef DEBUG
+static void dump_list(struct list_head *head, char *type_str)
+{
+ struct id_range *cur;
+
+ pr_debug("%s ranges allocated:\n", type_str);
+ list_for_each_entry(cur, head, list) {
+ pr_debug("Range %d->%d\n", cur->start, cur->end);
+ }
+}
+#endif
+
+static int range_alloc(struct list_head *head, u32 size, int max_id,
+ char *type_str)
+{
+ struct list_head *pos;
+ struct id_range *cur, *new;
+ int rc, last_end;
+
+ new = kmalloc(sizeof(struct id_range), GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ pos = head;
+ last_end = -1;
+ list_for_each_entry(cur, head, list) {
+ if ((cur->start - last_end) > size)
+ break;
+ last_end = cur->end;
+ pos = &cur->list;
+ }
+
+ new->start = last_end + 1;
+ new->end = new->start + size - 1;
+
+ if (new->end > max_id) {
+ kfree(new);
+ rc = -ENOSPC;
+ } else {
+ list_add(&new->list, pos);
+ rc = new->start;
+ }
+
+#ifdef DEBUG
+ dump_list(head, type_str);
+#endif
+ return rc;
+}
+
+static void range_free(struct list_head *head, u32 start, u32 size,
+ char *type_str)
+{
+ bool found = false;
+ struct id_range *cur, *tmp;
+
+ list_for_each_entry_safe(cur, tmp, head, list) {
+ if (cur->start == start && cur->end == (start + size - 1)) {
+ found = true;
+ list_del(&cur->list);
+ kfree(cur);
+ break;
+ }
+ }
+ WARN_ON(!found);
+#ifdef DEBUG
+ dump_list(head, type_str);
+#endif
+}
+
+int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size)
+{
+ int max_pasid;
+
+ if (fn->config.max_pasid_log < 0)
+ return -ENOSPC;
+ max_pasid = 1 << fn->config.max_pasid_log;
+ return range_alloc(&fn->pasid_list, size, max_pasid, "afu pasid");
+}
+
+void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
+{
+ return range_free(&fn->pasid_list, start, size, "afu pasid");
+}
+
+int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size)
+{
+ int max_actag;
+
+ max_actag = fn->actag_enabled;
+ return range_alloc(&fn->actag_list, size, max_actag, "afu actag");
+}
+
+void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
+{
+ return range_free(&fn->actag_list, start, size, "afu actag");
+}
diff --git a/drivers/misc/ocxl/pci.c b/drivers/misc/ocxl/pci.c
new file mode 100644
index 000000000000..0051d9ec76cc
--- /dev/null
+++ b/drivers/misc/ocxl/pci.c
@@ -0,0 +1,585 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/idr.h>
+#include <asm/pnv-ocxl.h>
+#include "ocxl_internal.h"
+
+/*
+ * Any opencapi device which wants to use this 'generic' driver should
+ * use the 0x062B device ID. Vendors should define the subsystem
+ * vendor/device ID to help differentiate devices.
+ */
+static const struct pci_device_id ocxl_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x062B), },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, ocxl_pci_tbl);
+
+
+static struct ocxl_fn *ocxl_fn_get(struct ocxl_fn *fn)
+{
+ return (get_device(&fn->dev) == NULL) ? NULL : fn;
+}
+
+static void ocxl_fn_put(struct ocxl_fn *fn)
+{
+ put_device(&fn->dev);
+}
+
+struct ocxl_afu *ocxl_afu_get(struct ocxl_afu *afu)
+{
+ return (get_device(&afu->dev) == NULL) ? NULL : afu;
+}
+
+void ocxl_afu_put(struct ocxl_afu *afu)
+{
+ put_device(&afu->dev);
+}
+
+static struct ocxl_afu *alloc_afu(struct ocxl_fn *fn)
+{
+ struct ocxl_afu *afu;
+
+ afu = kzalloc(sizeof(struct ocxl_afu), GFP_KERNEL);
+ if (!afu)
+ return NULL;
+
+ mutex_init(&afu->contexts_lock);
+ mutex_init(&afu->afu_control_lock);
+ idr_init(&afu->contexts_idr);
+ afu->fn = fn;
+ ocxl_fn_get(fn);
+ return afu;
+}
+
+static void free_afu(struct ocxl_afu *afu)
+{
+ idr_destroy(&afu->contexts_idr);
+ ocxl_fn_put(afu->fn);
+ kfree(afu);
+}
+
+static void free_afu_dev(struct device *dev)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(dev);
+
+ ocxl_unregister_afu(afu);
+ free_afu(afu);
+}
+
+static int set_afu_device(struct ocxl_afu *afu, const char *location)
+{
+ struct ocxl_fn *fn = afu->fn;
+ int rc;
+
+ afu->dev.parent = &fn->dev;
+ afu->dev.release = free_afu_dev;
+ rc = dev_set_name(&afu->dev, "%s.%s.%hhu", afu->config.name, location,
+ afu->config.idx);
+ return rc;
+}
+
+static int assign_afu_actag(struct ocxl_afu *afu, struct pci_dev *dev)
+{
+ struct ocxl_fn *fn = afu->fn;
+ int actag_count, actag_offset;
+
+ /*
+ * if there were not enough actags for the function, each afu
+ * reduces its count as well
+ */
+ actag_count = afu->config.actag_supported *
+ fn->actag_enabled / fn->actag_supported;
+ actag_offset = ocxl_actag_afu_alloc(fn, actag_count);
+ if (actag_offset < 0) {
+ dev_err(&afu->dev, "Can't allocate %d actags for AFU: %d\n",
+ actag_count, actag_offset);
+ return actag_offset;
+ }
+ afu->actag_base = fn->actag_base + actag_offset;
+ afu->actag_enabled = actag_count;
+
+ ocxl_config_set_afu_actag(dev, afu->config.dvsec_afu_control_pos,
+ afu->actag_base, afu->actag_enabled);
+ dev_dbg(&afu->dev, "actag base=%d enabled=%d\n",
+ afu->actag_base, afu->actag_enabled);
+ return 0;
+}
+
+static void reclaim_afu_actag(struct ocxl_afu *afu)
+{
+ struct ocxl_fn *fn = afu->fn;
+ int start_offset, size;
+
+ start_offset = afu->actag_base - fn->actag_base;
+ size = afu->actag_enabled;
+ ocxl_actag_afu_free(afu->fn, start_offset, size);
+}
+
+static int assign_afu_pasid(struct ocxl_afu *afu, struct pci_dev *dev)
+{
+ struct ocxl_fn *fn = afu->fn;
+ int pasid_count, pasid_offset;
+
+ /*
+ * We only support the case where the function configuration
+ * requested enough PASIDs to cover all AFUs.
+ */
+ pasid_count = 1 << afu->config.pasid_supported_log;
+ pasid_offset = ocxl_pasid_afu_alloc(fn, pasid_count);
+ if (pasid_offset < 0) {
+ dev_err(&afu->dev, "Can't allocate %d PASIDs for AFU: %d\n",
+ pasid_count, pasid_offset);
+ return pasid_offset;
+ }
+ afu->pasid_base = fn->pasid_base + pasid_offset;
+ afu->pasid_count = 0;
+ afu->pasid_max = pasid_count;
+
+ ocxl_config_set_afu_pasid(dev, afu->config.dvsec_afu_control_pos,
+ afu->pasid_base,
+ afu->config.pasid_supported_log);
+ dev_dbg(&afu->dev, "PASID base=%d, enabled=%d\n",
+ afu->pasid_base, pasid_count);
+ return 0;
+}
+
+static void reclaim_afu_pasid(struct ocxl_afu *afu)
+{
+ struct ocxl_fn *fn = afu->fn;
+ int start_offset, size;
+
+ start_offset = afu->pasid_base - fn->pasid_base;
+ size = 1 << afu->config.pasid_supported_log;
+ ocxl_pasid_afu_free(afu->fn, start_offset, size);
+}
+
+static int reserve_fn_bar(struct ocxl_fn *fn, int bar)
+{
+ struct pci_dev *dev = to_pci_dev(fn->dev.parent);
+ int rc, idx;
+
+ if (bar != 0 && bar != 2 && bar != 4)
+ return -EINVAL;
+
+ idx = bar >> 1;
+ if (fn->bar_used[idx]++ == 0) {
+ rc = pci_request_region(dev, bar, "ocxl");
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+static void release_fn_bar(struct ocxl_fn *fn, int bar)
+{
+ struct pci_dev *dev = to_pci_dev(fn->dev.parent);
+ int idx;
+
+ if (bar != 0 && bar != 2 && bar != 4)
+ return;
+
+ idx = bar >> 1;
+ if (--fn->bar_used[idx] == 0)
+ pci_release_region(dev, bar);
+ WARN_ON(fn->bar_used[idx] < 0);
+}
+
+static int map_mmio_areas(struct ocxl_afu *afu, struct pci_dev *dev)
+{
+ int rc;
+
+ rc = reserve_fn_bar(afu->fn, afu->config.global_mmio_bar);
+ if (rc)
+ return rc;
+
+ rc = reserve_fn_bar(afu->fn, afu->config.pp_mmio_bar);
+ if (rc) {
+ release_fn_bar(afu->fn, afu->config.global_mmio_bar);
+ return rc;
+ }
+
+ afu->global_mmio_start =
+ pci_resource_start(dev, afu->config.global_mmio_bar) +
+ afu->config.global_mmio_offset;
+ afu->pp_mmio_start =
+ pci_resource_start(dev, afu->config.pp_mmio_bar) +
+ afu->config.pp_mmio_offset;
+
+ afu->global_mmio_ptr = ioremap(afu->global_mmio_start,
+ afu->config.global_mmio_size);
+ if (!afu->global_mmio_ptr) {
+ release_fn_bar(afu->fn, afu->config.pp_mmio_bar);
+ release_fn_bar(afu->fn, afu->config.global_mmio_bar);
+ dev_err(&dev->dev, "Error mapping global mmio area\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Leave an empty page between the per-process mmio area and
+ * the AFU interrupt mappings
+ */
+ afu->irq_base_offset = afu->config.pp_mmio_stride + PAGE_SIZE;
+ return 0;
+}
+
+static void unmap_mmio_areas(struct ocxl_afu *afu)
+{
+ if (afu->global_mmio_ptr) {
+ iounmap(afu->global_mmio_ptr);
+ afu->global_mmio_ptr = NULL;
+ }
+ afu->global_mmio_start = 0;
+ afu->pp_mmio_start = 0;
+ release_fn_bar(afu->fn, afu->config.pp_mmio_bar);
+ release_fn_bar(afu->fn, afu->config.global_mmio_bar);
+}
+
+static int configure_afu(struct ocxl_afu *afu, u8 afu_idx, struct pci_dev *dev)
+{
+ int rc;
+
+ rc = ocxl_config_read_afu(dev, &afu->fn->config, &afu->config, afu_idx);
+ if (rc)
+ return rc;
+
+ rc = set_afu_device(afu, dev_name(&dev->dev));
+ if (rc)
+ return rc;
+
+ rc = assign_afu_actag(afu, dev);
+ if (rc)
+ return rc;
+
+ rc = assign_afu_pasid(afu, dev);
+ if (rc) {
+ reclaim_afu_actag(afu);
+ return rc;
+ }
+
+ rc = map_mmio_areas(afu, dev);
+ if (rc) {
+ reclaim_afu_pasid(afu);
+ reclaim_afu_actag(afu);
+ return rc;
+ }
+ return 0;
+}
+
+static void deconfigure_afu(struct ocxl_afu *afu)
+{
+ unmap_mmio_areas(afu);
+ reclaim_afu_pasid(afu);
+ reclaim_afu_actag(afu);
+}
+
+static int activate_afu(struct pci_dev *dev, struct ocxl_afu *afu)
+{
+ int rc;
+
+ ocxl_config_set_afu_state(dev, afu->config.dvsec_afu_control_pos, 1);
+ /*
+ * Char device creation is the last step, as processes can
+ * call our driver immediately, so all our inits must be finished.
+ */
+ rc = ocxl_create_cdev(afu);
+ if (rc)
+ return rc;
+ return 0;
+}
+
+static void deactivate_afu(struct ocxl_afu *afu)
+{
+ struct pci_dev *dev = to_pci_dev(afu->fn->dev.parent);
+
+ ocxl_destroy_cdev(afu);
+ ocxl_config_set_afu_state(dev, afu->config.dvsec_afu_control_pos, 0);
+}
+
+static int init_afu(struct pci_dev *dev, struct ocxl_fn *fn, u8 afu_idx)
+{
+ int rc;
+ struct ocxl_afu *afu;
+
+ afu = alloc_afu(fn);
+ if (!afu)
+ return -ENOMEM;
+
+ rc = configure_afu(afu, afu_idx, dev);
+ if (rc) {
+ free_afu(afu);
+ return rc;
+ }
+
+ rc = ocxl_register_afu(afu);
+ if (rc)
+ goto err;
+
+ rc = ocxl_sysfs_add_afu(afu);
+ if (rc)
+ goto err;
+
+ rc = activate_afu(dev, afu);
+ if (rc)
+ goto err_sys;
+
+ list_add_tail(&afu->list, &fn->afu_list);
+ return 0;
+
+err_sys:
+ ocxl_sysfs_remove_afu(afu);
+err:
+ deconfigure_afu(afu);
+ device_unregister(&afu->dev);
+ return rc;
+}
+
+static void remove_afu(struct ocxl_afu *afu)
+{
+ list_del(&afu->list);
+ ocxl_context_detach_all(afu);
+ deactivate_afu(afu);
+ ocxl_sysfs_remove_afu(afu);
+ deconfigure_afu(afu);
+ device_unregister(&afu->dev);
+}
+
+static struct ocxl_fn *alloc_function(struct pci_dev *dev)
+{
+ struct ocxl_fn *fn;
+
+ fn = kzalloc(sizeof(struct ocxl_fn), GFP_KERNEL);
+ if (!fn)
+ return NULL;
+
+ INIT_LIST_HEAD(&fn->afu_list);
+ INIT_LIST_HEAD(&fn->pasid_list);
+ INIT_LIST_HEAD(&fn->actag_list);
+ return fn;
+}
+
+static void free_function(struct ocxl_fn *fn)
+{
+ WARN_ON(!list_empty(&fn->afu_list));
+ WARN_ON(!list_empty(&fn->pasid_list));
+ kfree(fn);
+}
+
+static void free_function_dev(struct device *dev)
+{
+ struct ocxl_fn *fn = to_ocxl_function(dev);
+
+ free_function(fn);
+}
+
+static int set_function_device(struct ocxl_fn *fn, struct pci_dev *dev)
+{
+ int rc;
+
+ fn->dev.parent = &dev->dev;
+ fn->dev.release = free_function_dev;
+ rc = dev_set_name(&fn->dev, "ocxlfn.%s", dev_name(&dev->dev));
+ if (rc)
+ return rc;
+ pci_set_drvdata(dev, fn);
+ return 0;
+}
+
+static int assign_function_actag(struct ocxl_fn *fn)
+{
+ struct pci_dev *dev = to_pci_dev(fn->dev.parent);
+ u16 base, enabled, supported;
+ int rc;
+
+ rc = ocxl_config_get_actag_info(dev, &base, &enabled, &supported);
+ if (rc)
+ return rc;
+
+ fn->actag_base = base;
+ fn->actag_enabled = enabled;
+ fn->actag_supported = supported;
+
+ ocxl_config_set_actag(dev, fn->config.dvsec_function_pos,
+ fn->actag_base, fn->actag_enabled);
+ dev_dbg(&fn->dev, "actag range starting at %d, enabled %d\n",
+ fn->actag_base, fn->actag_enabled);
+ return 0;
+}
+
+static int set_function_pasid(struct ocxl_fn *fn)
+{
+ struct pci_dev *dev = to_pci_dev(fn->dev.parent);
+ int rc, desired_count, max_count;
+
+ /* A function may not require any PASID */
+ if (fn->config.max_pasid_log < 0)
+ return 0;
+
+ rc = ocxl_config_get_pasid_info(dev, &max_count);
+ if (rc)
+ return rc;
+
+ desired_count = 1 << fn->config.max_pasid_log;
+
+ if (desired_count > max_count) {
+ dev_err(&fn->dev,
+ "Function requires more PASIDs than is available (%d vs. %d)\n",
+ desired_count, max_count);
+ return -ENOSPC;
+ }
+
+ fn->pasid_base = 0;
+ return 0;
+}
+
+static int configure_function(struct ocxl_fn *fn, struct pci_dev *dev)
+{
+ int rc;
+
+ rc = pci_enable_device(dev);
+ if (rc) {
+ dev_err(&dev->dev, "pci_enable_device failed: %d\n", rc);
+ return rc;
+ }
+
+ /*
+ * Once it has been confirmed to work on our hardware, we
+ * should reset the function, to force the adapter to restart
+ * from scratch.
+ * A function reset would also reset all its AFUs.
+ *
+ * Some hints for implementation:
+ *
+ * - there's not status bit to know when the reset is done. We
+ * should try reading the config space to know when it's
+ * done.
+ * - probably something like:
+ * Reset
+ * wait 100ms
+ * issue config read
+ * allow device up to 1 sec to return success on config
+ * read before declaring it broken
+ *
+ * Some shared logic on the card (CFG, TLX) won't be reset, so
+ * there's no guarantee that it will be enough.
+ */
+ rc = ocxl_config_read_function(dev, &fn->config);
+ if (rc)
+ return rc;
+
+ rc = set_function_device(fn, dev);
+ if (rc)
+ return rc;
+
+ rc = assign_function_actag(fn);
+ if (rc)
+ return rc;
+
+ rc = set_function_pasid(fn);
+ if (rc)
+ return rc;
+
+ rc = ocxl_link_setup(dev, 0, &fn->link);
+ if (rc)
+ return rc;
+
+ rc = ocxl_config_set_TL(dev, fn->config.dvsec_tl_pos);
+ if (rc) {
+ ocxl_link_release(dev, fn->link);
+ return rc;
+ }
+ return 0;
+}
+
+static void deconfigure_function(struct ocxl_fn *fn)
+{
+ struct pci_dev *dev = to_pci_dev(fn->dev.parent);
+
+ ocxl_link_release(dev, fn->link);
+ pci_disable_device(dev);
+}
+
+static struct ocxl_fn *init_function(struct pci_dev *dev)
+{
+ struct ocxl_fn *fn;
+ int rc;
+
+ fn = alloc_function(dev);
+ if (!fn)
+ return ERR_PTR(-ENOMEM);
+
+ rc = configure_function(fn, dev);
+ if (rc) {
+ free_function(fn);
+ return ERR_PTR(rc);
+ }
+
+ rc = device_register(&fn->dev);
+ if (rc) {
+ deconfigure_function(fn);
+ device_unregister(&fn->dev);
+ return ERR_PTR(rc);
+ }
+ return fn;
+}
+
+static void remove_function(struct ocxl_fn *fn)
+{
+ deconfigure_function(fn);
+ device_unregister(&fn->dev);
+}
+
+static int ocxl_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int rc, afu_count = 0;
+ u8 afu;
+ struct ocxl_fn *fn;
+
+ if (!radix_enabled()) {
+ dev_err(&dev->dev, "Unsupported memory model (hash)\n");
+ return -ENODEV;
+ }
+
+ fn = init_function(dev);
+ if (IS_ERR(fn)) {
+ dev_err(&dev->dev, "function init failed: %li\n",
+ PTR_ERR(fn));
+ return PTR_ERR(fn);
+ }
+
+ for (afu = 0; afu <= fn->config.max_afu_index; afu++) {
+ rc = ocxl_config_check_afu_index(dev, &fn->config, afu);
+ if (rc > 0) {
+ rc = init_afu(dev, fn, afu);
+ if (rc) {
+ dev_err(&dev->dev,
+ "Can't initialize AFU index %d\n", afu);
+ continue;
+ }
+ afu_count++;
+ }
+ }
+ dev_info(&dev->dev, "%d AFU(s) configured\n", afu_count);
+ return 0;
+}
+
+static void ocxl_remove(struct pci_dev *dev)
+{
+ struct ocxl_afu *afu, *tmp;
+ struct ocxl_fn *fn = pci_get_drvdata(dev);
+
+ list_for_each_entry_safe(afu, tmp, &fn->afu_list, list) {
+ remove_afu(afu);
+ }
+ remove_function(fn);
+}
+
+struct pci_driver ocxl_pci_driver = {
+ .name = "ocxl",
+ .id_table = ocxl_pci_tbl,
+ .probe = ocxl_probe,
+ .remove = ocxl_remove,
+ .shutdown = ocxl_remove,
+};
diff --git a/drivers/misc/ocxl/sysfs.c b/drivers/misc/ocxl/sysfs.c
new file mode 100644
index 000000000000..d9753a1db14b
--- /dev/null
+++ b/drivers/misc/ocxl/sysfs.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#include <linux/sysfs.h>
+#include "ocxl_internal.h"
+
+static ssize_t global_mmio_size_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(device);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ afu->config.global_mmio_size);
+}
+
+static ssize_t pp_mmio_size_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(device);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ afu->config.pp_mmio_stride);
+}
+
+static ssize_t afu_version_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(device);
+
+ return scnprintf(buf, PAGE_SIZE, "%hhu:%hhu\n",
+ afu->config.version_major,
+ afu->config.version_minor);
+}
+
+static ssize_t contexts_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(device);
+
+ return scnprintf(buf, PAGE_SIZE, "%d/%d\n",
+ afu->pasid_count, afu->pasid_max);
+}
+
+static struct device_attribute afu_attrs[] = {
+ __ATTR_RO(global_mmio_size),
+ __ATTR_RO(pp_mmio_size),
+ __ATTR_RO(afu_version),
+ __ATTR_RO(contexts),
+};
+
+static ssize_t global_mmio_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(kobj_to_dev(kobj));
+
+ if (count == 0 || off < 0 ||
+ off >= afu->config.global_mmio_size)
+ return 0;
+ memcpy_fromio(buf, afu->global_mmio_ptr + off, count);
+ return count;
+}
+
+static int global_mmio_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct ocxl_afu *afu = vma->vm_private_data;
+ unsigned long offset;
+
+ if (vmf->pgoff >= (afu->config.global_mmio_size >> PAGE_SHIFT))
+ return VM_FAULT_SIGBUS;
+
+ offset = vmf->pgoff;
+ offset += (afu->global_mmio_start >> PAGE_SHIFT);
+ vm_insert_pfn(vma, vmf->address, offset);
+ return VM_FAULT_NOPAGE;
+}
+
+static const struct vm_operations_struct global_mmio_vmops = {
+ .fault = global_mmio_fault,
+};
+
+static int global_mmio_mmap(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ struct vm_area_struct *vma)
+{
+ struct ocxl_afu *afu = to_ocxl_afu(kobj_to_dev(kobj));
+
+ if ((vma_pages(vma) + vma->vm_pgoff) >
+ (afu->config.global_mmio_size >> PAGE_SHIFT))
+ return -EINVAL;
+
+ vma->vm_flags |= VM_IO | VM_PFNMAP;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_ops = &global_mmio_vmops;
+ vma->vm_private_data = afu;
+ return 0;
+}
+
+int ocxl_sysfs_add_afu(struct ocxl_afu *afu)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {
+ rc = device_create_file(&afu->dev, &afu_attrs[i]);
+ if (rc)
+ goto err;
+ }
+
+ sysfs_attr_init(&afu->attr_global_mmio.attr);
+ afu->attr_global_mmio.attr.name = "global_mmio_area";
+ afu->attr_global_mmio.attr.mode = 0600;
+ afu->attr_global_mmio.size = afu->config.global_mmio_size;
+ afu->attr_global_mmio.read = global_mmio_read;
+ afu->attr_global_mmio.mmap = global_mmio_mmap;
+ rc = device_create_bin_file(&afu->dev, &afu->attr_global_mmio);
+ if (rc) {
+ dev_err(&afu->dev,
+ "Unable to create global mmio attr for afu: %d\n",
+ rc);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ for (i--; i >= 0; i--)
+ device_remove_file(&afu->dev, &afu_attrs[i]);
+ return rc;
+}
+
+void ocxl_sysfs_remove_afu(struct ocxl_afu *afu)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(afu_attrs); i++)
+ device_remove_file(&afu->dev, &afu_attrs[i]);
+ device_remove_bin_file(&afu->dev, &afu->attr_global_mmio);
+}
diff --git a/drivers/misc/ocxl/trace.c b/drivers/misc/ocxl/trace.c
new file mode 100644
index 000000000000..1e6947049697
--- /dev/null
+++ b/drivers/misc/ocxl/trace.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+#endif
diff --git a/drivers/misc/ocxl/trace.h b/drivers/misc/ocxl/trace.h
new file mode 100644
index 000000000000..bcb7ff330c1e
--- /dev/null
+++ b/drivers/misc/ocxl/trace.h
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017 IBM Corp.
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ocxl
+
+#if !defined(_TRACE_OCXL_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_OCXL_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(ocxl_context,
+ TP_PROTO(pid_t pid, void *spa, int pasid, u32 pidr, u32 tidr),
+ TP_ARGS(pid, spa, pasid, pidr, tidr),
+
+ TP_STRUCT__entry(
+ __field(pid_t, pid)
+ __field(void*, spa)
+ __field(int, pasid)
+ __field(u32, pidr)
+ __field(u32, tidr)
+ ),
+
+ TP_fast_assign(
+ __entry->pid = pid;
+ __entry->spa = spa;
+ __entry->pasid = pasid;
+ __entry->pidr = pidr;
+ __entry->tidr = tidr;
+ ),
+
+ TP_printk("linux pid=%d spa=0x%p pasid=0x%x pidr=0x%x tidr=0x%x",
+ __entry->pid,
+ __entry->spa,
+ __entry->pasid,
+ __entry->pidr,
+ __entry->tidr
+ )
+);
+
+DEFINE_EVENT(ocxl_context, ocxl_context_add,
+ TP_PROTO(pid_t pid, void *spa, int pasid, u32 pidr, u32 tidr),
+ TP_ARGS(pid, spa, pasid, pidr, tidr)
+);
+
+DEFINE_EVENT(ocxl_context, ocxl_context_remove,
+ TP_PROTO(pid_t pid, void *spa, int pasid, u32 pidr, u32 tidr),
+ TP_ARGS(pid, spa, pasid, pidr, tidr)
+);
+
+TRACE_EVENT(ocxl_terminate_pasid,
+ TP_PROTO(int pasid, int rc),
+ TP_ARGS(pasid, rc),
+
+ TP_STRUCT__entry(
+ __field(int, pasid)
+ __field(int, rc)
+ ),
+
+ TP_fast_assign(
+ __entry->pasid = pasid;
+ __entry->rc = rc;
+ ),
+
+ TP_printk("pasid=0x%x rc=%d",
+ __entry->pasid,
+ __entry->rc
+ )
+);
+
+DECLARE_EVENT_CLASS(ocxl_fault_handler,
+ TP_PROTO(void *spa, u64 pe, u64 dsisr, u64 dar, u64 tfc),
+ TP_ARGS(spa, pe, dsisr, dar, tfc),
+
+ TP_STRUCT__entry(
+ __field(void *, spa)
+ __field(u64, pe)
+ __field(u64, dsisr)
+ __field(u64, dar)
+ __field(u64, tfc)
+ ),
+
+ TP_fast_assign(
+ __entry->spa = spa;
+ __entry->pe = pe;
+ __entry->dsisr = dsisr;
+ __entry->dar = dar;
+ __entry->tfc = tfc;
+ ),
+
+ TP_printk("spa=%p pe=0x%llx dsisr=0x%llx dar=0x%llx tfc=0x%llx",
+ __entry->spa,
+ __entry->pe,
+ __entry->dsisr,
+ __entry->dar,
+ __entry->tfc
+ )
+);
+
+DEFINE_EVENT(ocxl_fault_handler, ocxl_fault,
+ TP_PROTO(void *spa, u64 pe, u64 dsisr, u64 dar, u64 tfc),
+ TP_ARGS(spa, pe, dsisr, dar, tfc)
+);
+
+DEFINE_EVENT(ocxl_fault_handler, ocxl_fault_ack,
+ TP_PROTO(void *spa, u64 pe, u64 dsisr, u64 dar, u64 tfc),
+ TP_ARGS(spa, pe, dsisr, dar, tfc)
+);
+
+TRACE_EVENT(ocxl_afu_irq_alloc,
+ TP_PROTO(int pasid, int irq_id, unsigned int virq, int hw_irq,
+ u64 irq_offset),
+ TP_ARGS(pasid, irq_id, virq, hw_irq, irq_offset),
+
+ TP_STRUCT__entry(
+ __field(int, pasid)
+ __field(int, irq_id)
+ __field(unsigned int, virq)
+ __field(int, hw_irq)
+ __field(u64, irq_offset)
+ ),
+
+ TP_fast_assign(
+ __entry->pasid = pasid;
+ __entry->irq_id = irq_id;
+ __entry->virq = virq;
+ __entry->hw_irq = hw_irq;
+ __entry->irq_offset = irq_offset;
+ ),
+
+ TP_printk("pasid=0x%x irq_id=%d virq=%u hw_irq=%d irq_offset=0x%llx",
+ __entry->pasid,
+ __entry->irq_id,
+ __entry->virq,
+ __entry->hw_irq,
+ __entry->irq_offset
+ )
+);
+
+TRACE_EVENT(ocxl_afu_irq_free,
+ TP_PROTO(int pasid, int irq_id),
+ TP_ARGS(pasid, irq_id),
+
+ TP_STRUCT__entry(
+ __field(int, pasid)
+ __field(int, irq_id)
+ ),
+
+ TP_fast_assign(
+ __entry->pasid = pasid;
+ __entry->irq_id = irq_id;
+ ),
+
+ TP_printk("pasid=0x%x irq_id=%d",
+ __entry->pasid,
+ __entry->irq_id
+ )
+);
+
+TRACE_EVENT(ocxl_afu_irq_receive,
+ TP_PROTO(int virq),
+ TP_ARGS(virq),
+
+ TP_STRUCT__entry(
+ __field(int, virq)
+ ),
+
+ TP_fast_assign(
+ __entry->virq = virq;
+ ),
+
+ TP_printk("virq=%d",
+ __entry->virq
+ )
+);
+
+#endif /* _TRACE_OCXL_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 7b08323e3f3d..74fc9af4aadb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12934,6 +12934,24 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features)
{
+ /*
+ * A skb with gso_size + header length > 9700 will cause a
+ * firmware panic. Drop GSO support.
+ *
+ * Eventually the upper layer should not pass these packets down.
+ *
+ * For speed, if the gso_size is <= 9000, assume there will
+ * not be 700 bytes of headers and pass it through. Only do a
+ * full (slow) validation if the gso_size is > 9000.
+ *
+ * (Due to the way SKB_BY_FRAGS works this will also do a full
+ * validation in that case.)
+ */
+ if (unlikely(skb_is_gso(skb) &&
+ (skb_shinfo(skb)->gso_size > 9000) &&
+ !skb_gso_validate_mac_len(skb, 9700)))
+ features &= ~NETIF_F_GSO_MASK;
+
features = vlan_features_check(skb, features);
return vxlan_features_check(skb, features);
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 1d37672902da..a14e8db51cdc 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -355,7 +355,7 @@ struct cxgb4_lld_info {
};
struct cxgb4_uld_info {
- const char *name;
+ char name[IFNAMSIZ];
void *handle;
unsigned int nrxq;
unsigned int rxq_size;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index c36c81959198..d81e2d37bc3d 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -991,9 +991,8 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
{
u32 i, copied = 0, wrb_cnt = skb_wrb_cnt(skb);
struct device *dev = &adapter->pdev->dev;
- struct be_queue_info *txq = &txo->q;
bool map_single = false;
- u32 head = txq->head;
+ u32 head;
dma_addr_t busaddr;
int len;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 56d6f1a4205a..5caaa9033841 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -3305,7 +3305,11 @@ static void handle_vpd_rsp(union ibmvnic_crq *crq,
*/
substr = strnstr(adapter->vpd->buff, "RM", adapter->vpd->len);
if (!substr) {
- dev_info(dev, "No FW level provided by VPD\n");
+ dev_info(dev, "Warning - No FW level has been provided in the VPD buffer by the VIOS Server\n");
+ ptr = strncpy((char *)adapter->fw_version, "N/A",
+ 3 * sizeof(char));
+ if (!ptr)
+ dev_err(dev, "Failed to inform that firmware version is unavailable to the adapter\n");
goto complete;
}
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 62d848df26ef..8a165842fa85 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1071,7 +1071,7 @@ static int
jme_process_receive(struct jme_adapter *jme, int limit)
{
struct jme_ring *rxring = &(jme->rxring[0]);
- struct rxdesc *rxdesc = rxring->desc;
+ struct rxdesc *rxdesc;
int i, j, ccnt, desccnt, mask = jme->rx_ring_mask;
if (unlikely(!atomic_dec_and_test(&jme->rx_cleaning)))
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 7bbd86f08e5f..3a9730612a70 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1362,6 +1362,15 @@ static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr,
return -EOPNOTSUPP;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void pxa168_eth_netpoll(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ pxa168_eth_int_handler(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
static void pxa168_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -1390,6 +1399,9 @@ static const struct net_device_ops pxa168_eth_netdev_ops = {
.ndo_do_ioctl = pxa168_eth_do_ioctl,
.ndo_change_mtu = pxa168_eth_change_mtu,
.ndo_tx_timeout = pxa168_eth_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = pxa168_eth_netpoll,
+#endif
};
static int pxa168_eth_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
index ffb402746ad4..1f9149bb2ae6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
@@ -65,7 +65,7 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
u32 hdr = readl(data);
length = FIELD_GET(NFP_NET_CFG_TLV_HEADER_LENGTH, hdr);
- offset = data - ctrl_mem + NFP_NET_CFG_TLV_BASE;
+ offset = data - ctrl_mem;
/* Advance past the header */
data += 4;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c
index f2633ec87a6a..fdf37abee3d3 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c
@@ -3649,10 +3649,8 @@ static u32 qed_grc_dump_big_ram(struct qed_hwfn *p_hwfn,
BIT(big_ram->is_256b_bit_offset[dev_data->chip_id]) ? 256
: 128;
- strncpy(type_name, big_ram->instance_name,
- strlen(big_ram->instance_name));
- strncpy(mem_name, big_ram->instance_name,
- strlen(big_ram->instance_name));
+ strscpy(type_name, big_ram->instance_name, sizeof(type_name));
+ strscpy(mem_name, big_ram->instance_name, sizeof(mem_name));
/* Dump memory header */
offset += qed_grc_dump_mem_hdr(p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 7b97a9969046..50038d946ced 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -1747,8 +1747,7 @@ static void ql_realign_skb(struct sk_buff *skb, int len)
*/
skb->data -= QLGE_SB_PAD - NET_IP_ALIGN;
skb->tail -= QLGE_SB_PAD - NET_IP_ALIGN;
- skb_copy_to_linear_data(skb, temp_addr,
- (unsigned int)len);
+ memmove(skb->data, temp_addr, len);
}
/*
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index fc8f8bdf6579..056cb6093630 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2902,6 +2902,12 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_alloc_ordered_workqueue;
}
+ err = rocker_probe_ports(rocker);
+ if (err) {
+ dev_err(&pdev->dev, "failed to probe ports\n");
+ goto err_probe_ports;
+ }
+
/* Only FIBs pointing to our own netdevs are programmed into
* the device, so no need to pass a callback.
*/
@@ -2918,22 +2924,16 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
- err = rocker_probe_ports(rocker);
- if (err) {
- dev_err(&pdev->dev, "failed to probe ports\n");
- goto err_probe_ports;
- }
-
dev_info(&pdev->dev, "Rocker switch with id %*phN\n",
(int)sizeof(rocker->hw.id), &rocker->hw.id);
return 0;
-err_probe_ports:
- unregister_switchdev_notifier(&rocker_switchdev_notifier);
err_register_switchdev_notifier:
unregister_fib_notifier(&rocker->fib_nb);
err_register_fib_notifier:
+ rocker_remove_ports(rocker);
+err_probe_ports:
destroy_workqueue(rocker->rocker_owq);
err_alloc_ordered_workqueue:
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);
@@ -2961,9 +2961,9 @@ static void rocker_remove(struct pci_dev *pdev)
{
struct rocker *rocker = pci_get_drvdata(pdev);
- rocker_remove_ports(rocker);
unregister_switchdev_notifier(&rocker_switchdev_notifier);
unregister_fib_notifier(&rocker->fib_nb);
+ rocker_remove_ports(rocker);
rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET);
destroy_workqueue(rocker->rocker_owq);
free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker);
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index ec56ff29aac4..60a604cc7647 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2006,7 +2006,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
{
int ret;
u32 mii_adv;
- struct phy_device *phydev = dev->net->phydev;
+ struct phy_device *phydev;
phydev = phy_find_first(dev->mdiobus);
if (!phydev) {
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0657203ffb91..958b2e8b90f6 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1848,11 +1848,9 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
if (opts2 & RD_IPV4_CS) {
if (opts3 & IPF)
checksum = CHECKSUM_NONE;
- else if ((opts2 & RD_UDP_CS) && (opts3 & UDPF))
- checksum = CHECKSUM_NONE;
- else if ((opts2 & RD_TCP_CS) && (opts3 & TCPF))
- checksum = CHECKSUM_NONE;
- else
+ else if ((opts2 & RD_UDP_CS) && !(opts3 & UDPF))
+ checksum = CHECKSUM_UNNECESSARY;
+ else if ((opts2 & RD_TCP_CS) && !(opts3 & TCPF))
checksum = CHECKSUM_UNNECESSARY;
} else if (opts2 & RD_IPV6_CS) {
if ((opts2 & RD_UDP_CS) && !(opts3 & UDPF))
@@ -3797,11 +3795,12 @@ static void set_carrier(struct r8152 *tp)
if (speed & LINK_STATUS) {
if (!netif_carrier_ok(netdev)) {
tp->rtl_ops.enable(tp);
- set_bit(RTL8152_SET_RX_MODE, &tp->flags);
netif_stop_queue(netdev);
napi_disable(napi);
netif_carrier_on(netdev);
rtl_start_rx(tp);
+ clear_bit(RTL8152_SET_RX_MODE, &tp->flags);
+ _rtl8152_set_rx_mode(netdev);
napi_enable(&tp->napi);
netif_wake_queue(netdev);
netif_info(tp, link, netdev, "carrier on\n");
@@ -4261,7 +4260,7 @@ static int rtl8152_post_reset(struct usb_interface *intf)
mutex_lock(&tp->control);
tp->rtl_ops.enable(tp);
rtl_start_rx(tp);
- rtl8152_set_rx_mode(netdev);
+ _rtl8152_set_rx_mode(netdev);
mutex_unlock(&tp->control);
}
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index cf95290b160c..8b39c160743d 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2760,9 +2760,6 @@ static void
vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
{
size_t sz, i, ring0_size, ring1_size, comp_size;
- struct vmxnet3_rx_queue *rq = &adapter->rx_queue[0];
-
-
if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE -
VMXNET3_MAX_ETH_HDR_SIZE) {
adapter->skb_buf_size = adapter->netdev->mtu +
@@ -2794,7 +2791,8 @@ vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
comp_size = ring0_size + ring1_size;
for (i = 0; i < adapter->num_rx_queues; i++) {
- rq = &adapter->rx_queue[i];
+ struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i];
+
rq->rx_ring[0].size = ring0_size;
rq->rx_ring[1].size = ring1_size;
rq->comp_ring.size = comp_size;
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c
index f0788aae05c9..3cfa46876239 100644
--- a/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -1020,6 +1020,10 @@ static int amd_ntb_init_pci(struct amd_ntb_dev *ndev,
goto err_dma_mask;
dev_warn(&pdev->dev, "Cannot DMA consistent highmem\n");
}
+ rc = dma_coerce_mask_and_coherent(&ndev->ntb.dev,
+ dma_get_mask(&pdev->dev));
+ if (rc)
+ goto err_dma_mask;
ndev->self_mmio = pci_iomap(pdev, 0, 0);
if (!ndev->self_mmio) {
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c
index 0cd79f367f7c..8d98872d0983 100644
--- a/drivers/ntb/hw/idt/ntb_hw_idt.c
+++ b/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -1744,20 +1744,19 @@ static int idt_ntb_msg_clear_mask(struct ntb_dev *ntb, u64 mask_bits)
* idt_ntb_msg_read() - read message register with specified index
* (NTB API callback)
* @ntb: NTB device context.
- * @midx: Message register index
* @pidx: OUT - Port index of peer device a message retrieved from
- * @msg: OUT - Data
+ * @midx: Message register index
*
* Read data from the specified message register and source register.
*
- * Return: zero on success, negative error if invalid argument passed.
+ * Return: inbound message register value.
*/
-static int idt_ntb_msg_read(struct ntb_dev *ntb, int midx, int *pidx, u32 *msg)
+static u32 idt_ntb_msg_read(struct ntb_dev *ntb, int *pidx, int midx)
{
struct idt_ntb_dev *ndev = to_ndev_ntb(ntb);
if (midx < 0 || IDT_MSG_CNT <= midx)
- return -EINVAL;
+ return ~(u32)0;
/* Retrieve source port index of the message */
if (pidx != NULL) {
@@ -1772,18 +1771,15 @@ static int idt_ntb_msg_read(struct ntb_dev *ntb, int midx, int *pidx, u32 *msg)
}
/* Retrieve data of the corresponding message register */
- if (msg != NULL)
- *msg = idt_nt_read(ndev, ntdata_tbl.msgs[midx].in);
-
- return 0;
+ return idt_nt_read(ndev, ntdata_tbl.msgs[midx].in);
}
/*
- * idt_ntb_msg_write() - write data to the specified message register
- * (NTB API callback)
+ * idt_ntb_peer_msg_write() - write data to the specified message register
+ * (NTB API callback)
* @ntb: NTB device context.
- * @midx: Message register index
* @pidx: Port index of peer device a message being sent to
+ * @midx: Message register index
* @msg: Data to send
*
* Just try to send data to a peer. Message status register should be
@@ -1791,7 +1787,8 @@ static int idt_ntb_msg_read(struct ntb_dev *ntb, int midx, int *pidx, u32 *msg)
*
* Return: zero on success, negative error if invalid argument passed.
*/
-static int idt_ntb_msg_write(struct ntb_dev *ntb, int midx, int pidx, u32 msg)
+static int idt_ntb_peer_msg_write(struct ntb_dev *ntb, int pidx, int midx,
+ u32 msg)
{
struct idt_ntb_dev *ndev = to_ndev_ntb(ntb);
unsigned long irqflags;
@@ -2058,7 +2055,7 @@ static const struct ntb_dev_ops idt_ntb_ops = {
.msg_set_mask = idt_ntb_msg_set_mask,
.msg_clear_mask = idt_ntb_msg_clear_mask,
.msg_read = idt_ntb_msg_read,
- .msg_write = idt_ntb_msg_write
+ .peer_msg_write = idt_ntb_peer_msg_write
};
/*
@@ -2073,7 +2070,7 @@ static int idt_register_device(struct idt_ntb_dev *ndev)
/* Initialize the rest of NTB device structure and register it */
ndev->ntb.ops = &idt_ntb_ops;
- ndev->ntb.topo = NTB_TOPO_PRI;
+ ndev->ntb.topo = NTB_TOPO_SWITCH;
ret = ntb_register_device(&ndev->ntb);
if (ret != 0) {
@@ -2269,7 +2266,7 @@ static ssize_t idt_dbgfs_info_read(struct file *filp, char __user *ubuf,
"Message data:\n");
for (idx = 0; idx < IDT_MSG_CNT; idx++) {
int src;
- (void)idt_ntb_msg_read(&ndev->ntb, idx, &src, &data);
+ data = idt_ntb_msg_read(&ndev->ntb, &src, idx);
off += scnprintf(strbuf + off, size - off,
"\t%hhu. 0x%08x from peer %hhu (Port %hhu)\n",
idx, data, src, ndev->peers[src].port);
@@ -2429,7 +2426,7 @@ static int idt_init_pci(struct idt_ntb_dev *ndev)
struct pci_dev *pdev = ndev->ntb.pdev;
int ret;
- /* Initialize the bit mask of DMA */
+ /* Initialize the bit mask of PCI/NTB DMA */
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (ret != 0) {
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
@@ -2450,6 +2447,12 @@ static int idt_init_pci(struct idt_ntb_dev *ndev)
dev_warn(&pdev->dev,
"Cannot set consistent DMA highmem bit mask\n");
}
+ ret = dma_coerce_mask_and_coherent(&ndev->ntb.dev,
+ dma_get_mask(&pdev->dev));
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to set NTB device DMA bit mask\n");
+ return ret;
+ }
/*
* Enable the device advanced error reporting. It's not critical to
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.c b/drivers/ntb/hw/intel/ntb_hw_intel.c
index 4de074a86073..156b45cd4a19 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.c
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.c
@@ -74,12 +74,6 @@ MODULE_AUTHOR("Intel Corporation");
#define bar0_off(base, bar) ((base) + ((bar) << 2))
#define bar2_off(base, bar) bar0_off(base, (bar) - 2)
-static const struct intel_ntb_reg atom_reg;
-static const struct intel_ntb_alt_reg atom_pri_reg;
-static const struct intel_ntb_alt_reg atom_sec_reg;
-static const struct intel_ntb_alt_reg atom_b2b_reg;
-static const struct intel_ntb_xlat_reg atom_pri_xlat;
-static const struct intel_ntb_xlat_reg atom_sec_xlat;
static const struct intel_ntb_reg xeon_reg;
static const struct intel_ntb_alt_reg xeon_pri_reg;
static const struct intel_ntb_alt_reg xeon_sec_reg;
@@ -184,15 +178,6 @@ static inline void _iowrite64(u64 val, void __iomem *mmio)
#endif
#endif
-static inline int pdev_is_atom(struct pci_dev *pdev)
-{
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_NTB_B2B_BWD:
- return 1;
- }
- return 0;
-}
-
static inline int pdev_is_xeon(struct pci_dev *pdev)
{
switch (pdev->device) {
@@ -1006,8 +991,7 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
{
struct intel_ntb_dev *ndev = filp->private_data;
- if (pdev_is_xeon(ndev->ntb.pdev) ||
- pdev_is_atom(ndev->ntb.pdev))
+ if (pdev_is_xeon(ndev->ntb.pdev))
return ndev_ntb_debugfs_read(filp, ubuf, count, offp);
else if (pdev_is_skx_xeon(ndev->ntb.pdev))
return ndev_ntb3_debugfs_read(filp, ubuf, count, offp);
@@ -1439,242 +1423,6 @@ static int intel_ntb_peer_spad_write(struct ntb_dev *ntb, int pidx,
ndev->peer_reg->spad);
}
-/* ATOM */
-
-static u64 atom_db_ioread(void __iomem *mmio)
-{
- return ioread64(mmio);
-}
-
-static void atom_db_iowrite(u64 bits, void __iomem *mmio)
-{
- iowrite64(bits, mmio);
-}
-
-static int atom_poll_link(struct intel_ntb_dev *ndev)
-{
- u32 ntb_ctl;
-
- ntb_ctl = ioread32(ndev->self_mmio + ATOM_NTBCNTL_OFFSET);
-
- if (ntb_ctl == ndev->ntb_ctl)
- return 0;
-
- ndev->ntb_ctl = ntb_ctl;
-
- ndev->lnk_sta = ioread32(ndev->self_mmio + ATOM_LINK_STATUS_OFFSET);
-
- return 1;
-}
-
-static int atom_link_is_up(struct intel_ntb_dev *ndev)
-{
- return ATOM_NTB_CTL_ACTIVE(ndev->ntb_ctl);
-}
-
-static int atom_link_is_err(struct intel_ntb_dev *ndev)
-{
- if (ioread32(ndev->self_mmio + ATOM_LTSSMSTATEJMP_OFFSET)
- & ATOM_LTSSMSTATEJMP_FORCEDETECT)
- return 1;
-
- if (ioread32(ndev->self_mmio + ATOM_IBSTERRRCRVSTS0_OFFSET)
- & ATOM_IBIST_ERR_OFLOW)
- return 1;
-
- return 0;
-}
-
-static inline enum ntb_topo atom_ppd_topo(struct intel_ntb_dev *ndev, u32 ppd)
-{
- struct device *dev = &ndev->ntb.pdev->dev;
-
- switch (ppd & ATOM_PPD_TOPO_MASK) {
- case ATOM_PPD_TOPO_B2B_USD:
- dev_dbg(dev, "PPD %d B2B USD\n", ppd);
- return NTB_TOPO_B2B_USD;
-
- case ATOM_PPD_TOPO_B2B_DSD:
- dev_dbg(dev, "PPD %d B2B DSD\n", ppd);
- return NTB_TOPO_B2B_DSD;
-
- case ATOM_PPD_TOPO_PRI_USD:
- case ATOM_PPD_TOPO_PRI_DSD: /* accept bogus PRI_DSD */
- case ATOM_PPD_TOPO_SEC_USD:
- case ATOM_PPD_TOPO_SEC_DSD: /* accept bogus SEC_DSD */
- dev_dbg(dev, "PPD %d non B2B disabled\n", ppd);
- return NTB_TOPO_NONE;
- }
-
- dev_dbg(dev, "PPD %d invalid\n", ppd);
- return NTB_TOPO_NONE;
-}
-
-static void atom_link_hb(struct work_struct *work)
-{
- struct intel_ntb_dev *ndev = hb_ndev(work);
- struct device *dev = &ndev->ntb.pdev->dev;
- unsigned long poll_ts;
- void __iomem *mmio;
- u32 status32;
-
- poll_ts = ndev->last_ts + ATOM_LINK_HB_TIMEOUT;
-
- /* Delay polling the link status if an interrupt was received,
- * unless the cached link status says the link is down.
- */
- if (time_after(poll_ts, jiffies) && atom_link_is_up(ndev)) {
- schedule_delayed_work(&ndev->hb_timer, poll_ts - jiffies);
- return;
- }
-
- if (atom_poll_link(ndev))
- ntb_link_event(&ndev->ntb);
-
- if (atom_link_is_up(ndev) || !atom_link_is_err(ndev)) {
- schedule_delayed_work(&ndev->hb_timer, ATOM_LINK_HB_TIMEOUT);
- return;
- }
-
- /* Link is down with error: recover the link! */
-
- mmio = ndev->self_mmio;
-
- /* Driver resets the NTB ModPhy lanes - magic! */
- iowrite8(0xe0, mmio + ATOM_MODPHY_PCSREG6);
- iowrite8(0x40, mmio + ATOM_MODPHY_PCSREG4);
- iowrite8(0x60, mmio + ATOM_MODPHY_PCSREG4);
- iowrite8(0x60, mmio + ATOM_MODPHY_PCSREG6);
-
- /* Driver waits 100ms to allow the NTB ModPhy to settle */
- msleep(100);
-
- /* Clear AER Errors, write to clear */
- status32 = ioread32(mmio + ATOM_ERRCORSTS_OFFSET);
- dev_dbg(dev, "ERRCORSTS = %x\n", status32);
- status32 &= PCI_ERR_COR_REP_ROLL;
- iowrite32(status32, mmio + ATOM_ERRCORSTS_OFFSET);
-
- /* Clear unexpected electrical idle event in LTSSM, write to clear */
- status32 = ioread32(mmio + ATOM_LTSSMERRSTS0_OFFSET);
- dev_dbg(dev, "LTSSMERRSTS0 = %x\n", status32);
- status32 |= ATOM_LTSSMERRSTS0_UNEXPECTEDEI;
- iowrite32(status32, mmio + ATOM_LTSSMERRSTS0_OFFSET);
-
- /* Clear DeSkew Buffer error, write to clear */
- status32 = ioread32(mmio + ATOM_DESKEWSTS_OFFSET);
- dev_dbg(dev, "DESKEWSTS = %x\n", status32);
- status32 |= ATOM_DESKEWSTS_DBERR;
- iowrite32(status32, mmio + ATOM_DESKEWSTS_OFFSET);
-
- status32 = ioread32(mmio + ATOM_IBSTERRRCRVSTS0_OFFSET);
- dev_dbg(dev, "IBSTERRRCRVSTS0 = %x\n", status32);
- status32 &= ATOM_IBIST_ERR_OFLOW;
- iowrite32(status32, mmio + ATOM_IBSTERRRCRVSTS0_OFFSET);
-
- /* Releases the NTB state machine to allow the link to retrain */
- status32 = ioread32(mmio + ATOM_LTSSMSTATEJMP_OFFSET);
- dev_dbg(dev, "LTSSMSTATEJMP = %x\n", status32);
- status32 &= ~ATOM_LTSSMSTATEJMP_FORCEDETECT;
- iowrite32(status32, mmio + ATOM_LTSSMSTATEJMP_OFFSET);
-
- /* There is a potential race between the 2 NTB devices recovering at the
- * same time. If the times are the same, the link will not recover and
- * the driver will be stuck in this loop forever. Add a random interval
- * to the recovery time to prevent this race.
- */
- schedule_delayed_work(&ndev->hb_timer, ATOM_LINK_RECOVERY_TIME
- + prandom_u32() % ATOM_LINK_RECOVERY_TIME);
-}
-
-static int atom_init_isr(struct intel_ntb_dev *ndev)
-{
- int rc;
-
- rc = ndev_init_isr(ndev, 1, ATOM_DB_MSIX_VECTOR_COUNT,
- ATOM_DB_MSIX_VECTOR_SHIFT, ATOM_DB_TOTAL_SHIFT);
- if (rc)
- return rc;
-
- /* ATOM doesn't have link status interrupt, poll on that platform */
- ndev->last_ts = jiffies;
- INIT_DELAYED_WORK(&ndev->hb_timer, atom_link_hb);
- schedule_delayed_work(&ndev->hb_timer, ATOM_LINK_HB_TIMEOUT);
-
- return 0;
-}
-
-static void atom_deinit_isr(struct intel_ntb_dev *ndev)
-{
- cancel_delayed_work_sync(&ndev->hb_timer);
- ndev_deinit_isr(ndev);
-}
-
-static int atom_init_ntb(struct intel_ntb_dev *ndev)
-{
- ndev->mw_count = ATOM_MW_COUNT;
- ndev->spad_count = ATOM_SPAD_COUNT;
- ndev->db_count = ATOM_DB_COUNT;
-
- switch (ndev->ntb.topo) {
- case NTB_TOPO_B2B_USD:
- case NTB_TOPO_B2B_DSD:
- ndev->self_reg = &atom_pri_reg;
- ndev->peer_reg = &atom_b2b_reg;
- ndev->xlat_reg = &atom_sec_xlat;
-
- /* Enable Bus Master and Memory Space on the secondary side */
- iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
- ndev->self_mmio + ATOM_SPCICMD_OFFSET);
-
- break;
-
- default:
- return -EINVAL;
- }
-
- ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
-
- return 0;
-}
-
-static int atom_init_dev(struct intel_ntb_dev *ndev)
-{
- u32 ppd;
- int rc;
-
- rc = pci_read_config_dword(ndev->ntb.pdev, ATOM_PPD_OFFSET, &ppd);
- if (rc)
- return -EIO;
-
- ndev->ntb.topo = atom_ppd_topo(ndev, ppd);
- if (ndev->ntb.topo == NTB_TOPO_NONE)
- return -EINVAL;
-
- rc = atom_init_ntb(ndev);
- if (rc)
- return rc;
-
- rc = atom_init_isr(ndev);
- if (rc)
- return rc;
-
- if (ndev->ntb.topo != NTB_TOPO_SEC) {
- /* Initiate PCI-E link training */
- rc = pci_write_config_dword(ndev->ntb.pdev, ATOM_PPD_OFFSET,
- ppd | ATOM_PPD_INIT_LINK);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
-static void atom_deinit_dev(struct intel_ntb_dev *ndev)
-{
- atom_deinit_isr(ndev);
-}
-
/* Skylake Xeon NTB */
static int skx_poll_link(struct intel_ntb_dev *ndev)
@@ -2586,6 +2334,10 @@ static int intel_ntb_init_pci(struct intel_ntb_dev *ndev, struct pci_dev *pdev)
goto err_dma_mask;
dev_warn(&pdev->dev, "Cannot DMA consistent highmem\n");
}
+ rc = dma_coerce_mask_and_coherent(&ndev->ntb.dev,
+ dma_get_mask(&pdev->dev));
+ if (rc)
+ goto err_dma_mask;
ndev->self_mmio = pci_iomap(pdev, 0, 0);
if (!ndev->self_mmio) {
@@ -2658,24 +2410,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
node = dev_to_node(&pdev->dev);
- if (pdev_is_atom(pdev)) {
- ndev = kzalloc_node(sizeof(*ndev), GFP_KERNEL, node);
- if (!ndev) {
- rc = -ENOMEM;
- goto err_ndev;
- }
-
- ndev_init_struct(ndev, pdev);
-
- rc = intel_ntb_init_pci(ndev, pdev);
- if (rc)
- goto err_init_pci;
-
- rc = atom_init_dev(ndev);
- if (rc)
- goto err_init_dev;
-
- } else if (pdev_is_xeon(pdev)) {
+ if (pdev_is_xeon(pdev)) {
ndev = kzalloc_node(sizeof(*ndev), GFP_KERNEL, node);
if (!ndev) {
rc = -ENOMEM;
@@ -2731,9 +2466,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
err_register:
ndev_deinit_debugfs(ndev);
- if (pdev_is_atom(pdev))
- atom_deinit_dev(ndev);
- else if (pdev_is_xeon(pdev) || pdev_is_skx_xeon(pdev))
+ if (pdev_is_xeon(pdev) || pdev_is_skx_xeon(pdev))
xeon_deinit_dev(ndev);
err_init_dev:
intel_ntb_deinit_pci(ndev);
@@ -2749,41 +2482,12 @@ static void intel_ntb_pci_remove(struct pci_dev *pdev)
ntb_unregister_device(&ndev->ntb);
ndev_deinit_debugfs(ndev);
- if (pdev_is_atom(pdev))
- atom_deinit_dev(ndev);
- else if (pdev_is_xeon(pdev) || pdev_is_skx_xeon(pdev))
+ if (pdev_is_xeon(pdev) || pdev_is_skx_xeon(pdev))
xeon_deinit_dev(ndev);
intel_ntb_deinit_pci(ndev);
kfree(ndev);
}
-static const struct intel_ntb_reg atom_reg = {
- .poll_link = atom_poll_link,
- .link_is_up = atom_link_is_up,
- .db_ioread = atom_db_ioread,
- .db_iowrite = atom_db_iowrite,
- .db_size = sizeof(u64),
- .ntb_ctl = ATOM_NTBCNTL_OFFSET,
- .mw_bar = {2, 4},
-};
-
-static const struct intel_ntb_alt_reg atom_pri_reg = {
- .db_bell = ATOM_PDOORBELL_OFFSET,
- .db_mask = ATOM_PDBMSK_OFFSET,
- .spad = ATOM_SPAD_OFFSET,
-};
-
-static const struct intel_ntb_alt_reg atom_b2b_reg = {
- .db_bell = ATOM_B2B_DOORBELL_OFFSET,
- .spad = ATOM_B2B_SPAD_OFFSET,
-};
-
-static const struct intel_ntb_xlat_reg atom_sec_xlat = {
- /* FIXME : .bar0_base = ATOM_SBAR0BASE_OFFSET, */
- /* FIXME : .bar2_limit = ATOM_SBAR2LMT_OFFSET, */
- .bar2_xlat = ATOM_SBAR2XLAT_OFFSET,
-};
-
static const struct intel_ntb_reg xeon_reg = {
.poll_link = xeon_poll_link,
.link_is_up = xeon_link_is_up,
@@ -2940,7 +2644,6 @@ static const struct file_operations intel_ntb_debugfs_info = {
};
static const struct pci_device_id intel_ntb_pci_tbl[] = {
- {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_BWD)},
{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_JSF)},
{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_SNB)},
{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_IVT)},
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.h b/drivers/ntb/hw/intel/ntb_hw_intel.h
index 2d6c38afb128..4415aa7ea775 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.h
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.h
@@ -66,7 +66,6 @@
#define PCI_DEVICE_ID_INTEL_NTB_B2B_HSX 0x2F0D
#define PCI_DEVICE_ID_INTEL_NTB_PS_HSX 0x2F0E
#define PCI_DEVICE_ID_INTEL_NTB_SS_HSX 0x2F0F
-#define PCI_DEVICE_ID_INTEL_NTB_B2B_BWD 0x0C4E
#define PCI_DEVICE_ID_INTEL_NTB_B2B_BDX 0x6F0D
#define PCI_DEVICE_ID_INTEL_NTB_PS_BDX 0x6F0E
#define PCI_DEVICE_ID_INTEL_NTB_SS_BDX 0x6F0F
@@ -196,63 +195,6 @@
#define SKX_DB_TOTAL_SHIFT 33
#define SKX_SPAD_COUNT 16
-/* Intel Atom hardware */
-
-#define ATOM_SBAR2XLAT_OFFSET 0x0008
-#define ATOM_PDOORBELL_OFFSET 0x0020
-#define ATOM_PDBMSK_OFFSET 0x0028
-#define ATOM_NTBCNTL_OFFSET 0x0060
-#define ATOM_SPAD_OFFSET 0x0080
-#define ATOM_PPD_OFFSET 0x00d4
-#define ATOM_PBAR2XLAT_OFFSET 0x8008
-#define ATOM_B2B_DOORBELL_OFFSET 0x8020
-#define ATOM_B2B_SPAD_OFFSET 0x8080
-#define ATOM_SPCICMD_OFFSET 0xb004
-#define ATOM_LINK_STATUS_OFFSET 0xb052
-#define ATOM_ERRCORSTS_OFFSET 0xb110
-#define ATOM_IP_BASE 0xc000
-#define ATOM_DESKEWSTS_OFFSET (ATOM_IP_BASE + 0x3024)
-#define ATOM_LTSSMERRSTS0_OFFSET (ATOM_IP_BASE + 0x3180)
-#define ATOM_LTSSMSTATEJMP_OFFSET (ATOM_IP_BASE + 0x3040)
-#define ATOM_IBSTERRRCRVSTS0_OFFSET (ATOM_IP_BASE + 0x3324)
-#define ATOM_MODPHY_PCSREG4 0x1c004
-#define ATOM_MODPHY_PCSREG6 0x1c006
-
-#define ATOM_PPD_INIT_LINK 0x0008
-#define ATOM_PPD_CONN_MASK 0x0300
-#define ATOM_PPD_CONN_TRANSPARENT 0x0000
-#define ATOM_PPD_CONN_B2B 0x0100
-#define ATOM_PPD_CONN_RP 0x0200
-#define ATOM_PPD_DEV_MASK 0x1000
-#define ATOM_PPD_DEV_USD 0x0000
-#define ATOM_PPD_DEV_DSD 0x1000
-#define ATOM_PPD_TOPO_MASK (ATOM_PPD_CONN_MASK | ATOM_PPD_DEV_MASK)
-#define ATOM_PPD_TOPO_PRI_USD (ATOM_PPD_CONN_TRANSPARENT | ATOM_PPD_DEV_USD)
-#define ATOM_PPD_TOPO_PRI_DSD (ATOM_PPD_CONN_TRANSPARENT | ATOM_PPD_DEV_DSD)
-#define ATOM_PPD_TOPO_SEC_USD (ATOM_PPD_CONN_RP | ATOM_PPD_DEV_USD)
-#define ATOM_PPD_TOPO_SEC_DSD (ATOM_PPD_CONN_RP | ATOM_PPD_DEV_DSD)
-#define ATOM_PPD_TOPO_B2B_USD (ATOM_PPD_CONN_B2B | ATOM_PPD_DEV_USD)
-#define ATOM_PPD_TOPO_B2B_DSD (ATOM_PPD_CONN_B2B | ATOM_PPD_DEV_DSD)
-
-#define ATOM_MW_COUNT 2
-#define ATOM_DB_COUNT 34
-#define ATOM_DB_VALID_MASK (BIT_ULL(ATOM_DB_COUNT) - 1)
-#define ATOM_DB_MSIX_VECTOR_COUNT 34
-#define ATOM_DB_MSIX_VECTOR_SHIFT 1
-#define ATOM_DB_TOTAL_SHIFT 34
-#define ATOM_SPAD_COUNT 16
-
-#define ATOM_NTB_CTL_DOWN_BIT BIT(16)
-#define ATOM_NTB_CTL_ACTIVE(x) !(x & ATOM_NTB_CTL_DOWN_BIT)
-
-#define ATOM_DESKEWSTS_DBERR BIT(15)
-#define ATOM_LTSSMERRSTS0_UNEXPECTEDEI BIT(20)
-#define ATOM_LTSSMSTATEJMP_FORCEDETECT BIT(2)
-#define ATOM_IBIST_ERR_OFLOW 0x7FFF7FFF
-
-#define ATOM_LINK_HB_TIMEOUT msecs_to_jiffies(1000)
-#define ATOM_LINK_RECOVERY_TIME msecs_to_jiffies(500)
-
/* Ntb control and link status */
#define NTB_CTL_CFG_LOCK BIT(0)
diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index afe8ed6f3b23..f624ae27eabe 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -94,6 +94,9 @@ struct switchtec_ntb {
struct ntb_ctrl_regs __iomem *mmio_self_ctrl;
struct ntb_ctrl_regs __iomem *mmio_peer_ctrl;
struct ntb_dbmsg_regs __iomem *mmio_self_dbmsg;
+ struct ntb_dbmsg_regs __iomem *mmio_peer_dbmsg;
+
+ void __iomem *mmio_xlink_win;
struct shared_mw *self_shared;
struct shared_mw __iomem *peer_shared;
@@ -109,6 +112,7 @@ struct switchtec_ntb {
int nr_direct_mw;
int nr_lut_mw;
+ int nr_rsvd_luts;
int direct_mw_to_bar[MAX_DIRECT_MW];
int peer_nr_direct_mw;
@@ -118,6 +122,7 @@ struct switchtec_ntb {
bool link_is_up;
enum ntb_speed link_speed;
enum ntb_width link_width;
+ struct work_struct link_reinit_work;
};
static struct switchtec_ntb *ntb_sndev(struct ntb_dev *ntb)
@@ -172,7 +177,7 @@ static int switchtec_ntb_part_op(struct switchtec_ntb *sndev,
if (ps == status) {
dev_err(&sndev->stdev->dev,
- "Timed out while peforming %s (%d). (%08x)",
+ "Timed out while performing %s (%d). (%08x)\n",
op_text[op], op,
ioread32(&ctl->partition_status));
@@ -185,10 +190,10 @@ static int switchtec_ntb_part_op(struct switchtec_ntb *sndev,
static int switchtec_ntb_send_msg(struct switchtec_ntb *sndev, int idx,
u32 val)
{
- if (idx < 0 || idx >= ARRAY_SIZE(sndev->mmio_self_dbmsg->omsg))
+ if (idx < 0 || idx >= ARRAY_SIZE(sndev->mmio_peer_dbmsg->omsg))
return -EINVAL;
- iowrite32(val, &sndev->mmio_self_dbmsg->omsg[idx].msg);
+ iowrite32(val, &sndev->mmio_peer_dbmsg->omsg[idx].msg);
return 0;
}
@@ -197,7 +202,7 @@ static int switchtec_ntb_mw_count(struct ntb_dev *ntb, int pidx)
{
struct switchtec_ntb *sndev = ntb_sndev(ntb);
int nr_direct_mw = sndev->peer_nr_direct_mw;
- int nr_lut_mw = sndev->peer_nr_lut_mw - 1;
+ int nr_lut_mw = sndev->peer_nr_lut_mw - sndev->nr_rsvd_luts;
if (pidx != NTB_DEF_PEER_IDX)
return -EINVAL;
@@ -210,12 +215,12 @@ static int switchtec_ntb_mw_count(struct ntb_dev *ntb, int pidx)
static int lut_index(struct switchtec_ntb *sndev, int mw_idx)
{
- return mw_idx - sndev->nr_direct_mw + 1;
+ return mw_idx - sndev->nr_direct_mw + sndev->nr_rsvd_luts;
}
static int peer_lut_index(struct switchtec_ntb *sndev, int mw_idx)
{
- return mw_idx - sndev->peer_nr_direct_mw + 1;
+ return mw_idx - sndev->peer_nr_direct_mw + sndev->nr_rsvd_luts;
}
static int switchtec_ntb_mw_get_align(struct ntb_dev *ntb, int pidx,
@@ -306,7 +311,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx,
if (pidx != NTB_DEF_PEER_IDX)
return -EINVAL;
- dev_dbg(&sndev->stdev->dev, "MW %d: part %d addr %pad size %pap",
+ dev_dbg(&sndev->stdev->dev, "MW %d: part %d addr %pad size %pap\n",
widx, pidx, &addr, &size);
if (widx >= switchtec_ntb_mw_count(ntb, pidx))
@@ -315,6 +320,19 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx,
if (xlate_pos < 12)
return -EINVAL;
+ if (!IS_ALIGNED(addr, BIT_ULL(xlate_pos))) {
+ /*
+ * In certain circumstances we can get a buffer that is
+ * not aligned to its size. (Most of the time
+ * dma_alloc_coherent ensures this). This can happen when
+ * using large buffers allocated by the CMA
+ * (see CMA_CONFIG_ALIGNMENT)
+ */
+ dev_err(&sndev->stdev->dev,
+ "ERROR: Memory window address is not aligned to it's size!\n");
+ return -EINVAL;
+ }
+
rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_LOCK,
NTB_CTRL_PART_STATUS_LOCKED);
if (rc)
@@ -337,7 +355,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx,
if (rc == -EIO) {
dev_err(&sndev->stdev->dev,
- "Hardware reported an error configuring mw %d: %08x",
+ "Hardware reported an error configuring mw %d: %08x\n",
widx, ioread32(&ctl->bar_error));
if (widx < nr_direct_mw)
@@ -355,8 +373,9 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx,
static int switchtec_ntb_peer_mw_count(struct ntb_dev *ntb)
{
struct switchtec_ntb *sndev = ntb_sndev(ntb);
+ int nr_lut_mw = sndev->nr_lut_mw - sndev->nr_rsvd_luts;
- return sndev->nr_direct_mw + (use_lut_mws ? sndev->nr_lut_mw - 1 : 0);
+ return sndev->nr_direct_mw + (use_lut_mws ? nr_lut_mw : 0);
}
static int switchtec_ntb_direct_get_addr(struct switchtec_ntb *sndev,
@@ -463,18 +482,69 @@ static void switchtec_ntb_set_link_speed(struct switchtec_ntb *sndev)
sndev->link_width = min(self_width, peer_width);
}
-enum {
+static int crosslink_is_enabled(struct switchtec_ntb *sndev)
+{
+ struct ntb_info_regs __iomem *inf = sndev->mmio_ntb;
+
+ return ioread8(&inf->ntp_info[sndev->peer_partition].xlink_enabled);
+}
+
+static void crosslink_init_dbmsgs(struct switchtec_ntb *sndev)
+{
+ int i;
+ u32 msg_map = 0;
+
+ if (!crosslink_is_enabled(sndev))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(sndev->mmio_peer_dbmsg->imsg); i++) {
+ int m = i | sndev->self_partition << 2;
+
+ msg_map |= m << i * 8;
+ }
+
+ iowrite32(msg_map, &sndev->mmio_peer_dbmsg->msg_map);
+ iowrite64(sndev->db_valid_mask << sndev->db_peer_shift,
+ &sndev->mmio_peer_dbmsg->odb_mask);
+}
+
+enum switchtec_msg {
LINK_MESSAGE = 0,
MSG_LINK_UP = 1,
MSG_LINK_DOWN = 2,
MSG_CHECK_LINK = 3,
+ MSG_LINK_FORCE_DOWN = 4,
};
-static void switchtec_ntb_check_link(struct switchtec_ntb *sndev)
+static int switchtec_ntb_reinit_peer(struct switchtec_ntb *sndev);
+
+static void link_reinit_work(struct work_struct *work)
+{
+ struct switchtec_ntb *sndev;
+
+ sndev = container_of(work, struct switchtec_ntb, link_reinit_work);
+
+ switchtec_ntb_reinit_peer(sndev);
+}
+
+static void switchtec_ntb_check_link(struct switchtec_ntb *sndev,
+ enum switchtec_msg msg)
{
int link_sta;
int old = sndev->link_is_up;
+ if (msg == MSG_LINK_FORCE_DOWN) {
+ schedule_work(&sndev->link_reinit_work);
+
+ if (sndev->link_is_up) {
+ sndev->link_is_up = 0;
+ ntb_link_event(&sndev->ntb);
+ dev_info(&sndev->stdev->dev, "ntb link forced down\n");
+ }
+
+ return;
+ }
+
link_sta = sndev->self_shared->link_sta;
if (link_sta) {
u64 peer = ioread64(&sndev->peer_shared->magic);
@@ -491,8 +561,11 @@ static void switchtec_ntb_check_link(struct switchtec_ntb *sndev)
if (link_sta != old) {
switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_CHECK_LINK);
ntb_link_event(&sndev->ntb);
- dev_info(&sndev->stdev->dev, "ntb link %s",
+ dev_info(&sndev->stdev->dev, "ntb link %s\n",
link_sta ? "up" : "down");
+
+ if (link_sta)
+ crosslink_init_dbmsgs(sndev);
}
}
@@ -500,7 +573,7 @@ static void switchtec_ntb_link_notification(struct switchtec_dev *stdev)
{
struct switchtec_ntb *sndev = stdev->sndev;
- switchtec_ntb_check_link(sndev);
+ switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
}
static u64 switchtec_ntb_link_is_up(struct ntb_dev *ntb,
@@ -523,12 +596,12 @@ static int switchtec_ntb_link_enable(struct ntb_dev *ntb,
{
struct switchtec_ntb *sndev = ntb_sndev(ntb);
- dev_dbg(&sndev->stdev->dev, "enabling link");
+ dev_dbg(&sndev->stdev->dev, "enabling link\n");
sndev->self_shared->link_sta = 1;
switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_UP);
- switchtec_ntb_check_link(sndev);
+ switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
return 0;
}
@@ -537,12 +610,12 @@ static int switchtec_ntb_link_disable(struct ntb_dev *ntb)
{
struct switchtec_ntb *sndev = ntb_sndev(ntb);
- dev_dbg(&sndev->stdev->dev, "disabling link");
+ dev_dbg(&sndev->stdev->dev, "disabling link\n");
sndev->self_shared->link_sta = 0;
- switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_UP);
+ switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_DOWN);
- switchtec_ntb_check_link(sndev);
+ switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
return 0;
}
@@ -638,7 +711,7 @@ static int switchtec_ntb_peer_db_addr(struct ntb_dev *ntb,
struct switchtec_ntb *sndev = ntb_sndev(ntb);
unsigned long offset;
- offset = (unsigned long)sndev->mmio_self_dbmsg->odb -
+ offset = (unsigned long)sndev->mmio_peer_dbmsg->odb -
(unsigned long)sndev->stdev->mmio;
offset += sndev->db_shift / 8;
@@ -656,7 +729,7 @@ static int switchtec_ntb_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
struct switchtec_ntb *sndev = ntb_sndev(ntb);
iowrite64(db_bits << sndev->db_peer_shift,
- &sndev->mmio_self_dbmsg->odb);
+ &sndev->mmio_peer_dbmsg->odb);
return 0;
}
@@ -777,24 +850,63 @@ static const struct ntb_dev_ops switchtec_ntb_ops = {
.peer_spad_addr = switchtec_ntb_peer_spad_addr,
};
-static void switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
+static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
{
+ u64 tpart_vec;
+ int self;
u64 part_map;
+ int bit;
sndev->ntb.pdev = sndev->stdev->pdev;
sndev->ntb.topo = NTB_TOPO_SWITCH;
sndev->ntb.ops = &switchtec_ntb_ops;
+ INIT_WORK(&sndev->link_reinit_work, link_reinit_work);
+
sndev->self_partition = sndev->stdev->partition;
sndev->mmio_ntb = sndev->stdev->mmio_ntb;
+
+ self = sndev->self_partition;
+ tpart_vec = ioread32(&sndev->mmio_ntb->ntp_info[self].target_part_high);
+ tpart_vec <<= 32;
+ tpart_vec |= ioread32(&sndev->mmio_ntb->ntp_info[self].target_part_low);
+
part_map = ioread64(&sndev->mmio_ntb->ep_map);
part_map &= ~(1 << sndev->self_partition);
- sndev->peer_partition = ffs(part_map) - 1;
- dev_dbg(&sndev->stdev->dev, "Partition ID %d of %d (%llx)",
- sndev->self_partition, sndev->stdev->partition_count,
- part_map);
+ if (!ffs(tpart_vec)) {
+ if (sndev->stdev->partition_count != 2) {
+ dev_err(&sndev->stdev->dev,
+ "ntb target partition not defined\n");
+ return -ENODEV;
+ }
+
+ bit = ffs(part_map);
+ if (!bit) {
+ dev_err(&sndev->stdev->dev,
+ "peer partition is not NT partition\n");
+ return -ENODEV;
+ }
+
+ sndev->peer_partition = bit - 1;
+ } else {
+ if (ffs(tpart_vec) != fls(tpart_vec)) {
+ dev_err(&sndev->stdev->dev,
+ "ntb driver only supports 1 pair of 1-1 ntb mapping\n");
+ return -ENODEV;
+ }
+
+ sndev->peer_partition = ffs(tpart_vec) - 1;
+ if (!(part_map & (1 << sndev->peer_partition))) {
+ dev_err(&sndev->stdev->dev,
+ "ntb target partition is not NT partition\n");
+ return -ENODEV;
+ }
+ }
+
+ dev_dbg(&sndev->stdev->dev, "Partition ID %d of %d\n",
+ sndev->self_partition, sndev->stdev->partition_count);
sndev->mmio_ctrl = (void * __iomem)sndev->mmio_ntb +
SWITCHTEC_NTB_REG_CTRL_OFFSET;
@@ -804,6 +916,283 @@ static void switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
sndev->mmio_self_ctrl = &sndev->mmio_ctrl[sndev->self_partition];
sndev->mmio_peer_ctrl = &sndev->mmio_ctrl[sndev->peer_partition];
sndev->mmio_self_dbmsg = &sndev->mmio_dbmsg[sndev->self_partition];
+ sndev->mmio_peer_dbmsg = sndev->mmio_self_dbmsg;
+
+ return 0;
+}
+
+static int config_rsvd_lut_win(struct switchtec_ntb *sndev,
+ struct ntb_ctrl_regs __iomem *ctl,
+ int lut_idx, int partition, u64 addr)
+{
+ int peer_bar = sndev->peer_direct_mw_to_bar[0];
+ u32 ctl_val;
+ int rc;
+
+ rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_LOCK,
+ NTB_CTRL_PART_STATUS_LOCKED);
+ if (rc)
+ return rc;
+
+ ctl_val = ioread32(&ctl->bar_entry[peer_bar].ctl);
+ ctl_val &= 0xFF;
+ ctl_val |= NTB_CTRL_BAR_LUT_WIN_EN;
+ ctl_val |= ilog2(LUT_SIZE) << 8;
+ ctl_val |= (sndev->nr_lut_mw - 1) << 14;
+ iowrite32(ctl_val, &ctl->bar_entry[peer_bar].ctl);
+
+ iowrite64((NTB_CTRL_LUT_EN | (partition << 1) | addr),
+ &ctl->lut_entry[lut_idx]);
+
+ rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_CFG,
+ NTB_CTRL_PART_STATUS_NORMAL);
+ if (rc) {
+ u32 bar_error, lut_error;
+
+ bar_error = ioread32(&ctl->bar_error);
+ lut_error = ioread32(&ctl->lut_error);
+ dev_err(&sndev->stdev->dev,
+ "Error setting up reserved lut window: %08x / %08x\n",
+ bar_error, lut_error);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int config_req_id_table(struct switchtec_ntb *sndev,
+ struct ntb_ctrl_regs __iomem *mmio_ctrl,
+ int *req_ids, int count)
+{
+ int i, rc = 0;
+ u32 error;
+ u32 proxy_id;
+
+ if (ioread32(&mmio_ctrl->req_id_table_size) < count) {
+ dev_err(&sndev->stdev->dev,
+ "Not enough requester IDs available.\n");
+ return -EFAULT;
+ }
+
+ rc = switchtec_ntb_part_op(sndev, mmio_ctrl,
+ NTB_CTRL_PART_OP_LOCK,
+ NTB_CTRL_PART_STATUS_LOCKED);
+ if (rc)
+ return rc;
+
+ iowrite32(NTB_PART_CTRL_ID_PROT_DIS,
+ &mmio_ctrl->partition_ctrl);
+
+ for (i = 0; i < count; i++) {
+ iowrite32(req_ids[i] << 16 | NTB_CTRL_REQ_ID_EN,
+ &mmio_ctrl->req_id_table[i]);
+
+ proxy_id = ioread32(&mmio_ctrl->req_id_table[i]);
+ dev_dbg(&sndev->stdev->dev,
+ "Requester ID %02X:%02X.%X -> BB:%02X.%X\n",
+ req_ids[i] >> 8, (req_ids[i] >> 3) & 0x1F,
+ req_ids[i] & 0x7, (proxy_id >> 4) & 0x1F,
+ (proxy_id >> 1) & 0x7);
+ }
+
+ rc = switchtec_ntb_part_op(sndev, mmio_ctrl,
+ NTB_CTRL_PART_OP_CFG,
+ NTB_CTRL_PART_STATUS_NORMAL);
+
+ if (rc == -EIO) {
+ error = ioread32(&mmio_ctrl->req_id_error);
+ dev_err(&sndev->stdev->dev,
+ "Error setting up the requester ID table: %08x\n",
+ error);
+ }
+
+ return 0;
+}
+
+static int crosslink_setup_mws(struct switchtec_ntb *sndev, int ntb_lut_idx,
+ u64 *mw_addrs, int mw_count)
+{
+ int rc, i;
+ struct ntb_ctrl_regs __iomem *ctl = sndev->mmio_self_ctrl;
+ u64 addr;
+ size_t size, offset;
+ int bar;
+ int xlate_pos;
+ u32 ctl_val;
+
+ rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_LOCK,
+ NTB_CTRL_PART_STATUS_LOCKED);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < sndev->nr_lut_mw; i++) {
+ if (i == ntb_lut_idx)
+ continue;
+
+ addr = mw_addrs[0] + LUT_SIZE * i;
+
+ iowrite64((NTB_CTRL_LUT_EN | (sndev->peer_partition << 1) |
+ addr),
+ &ctl->lut_entry[i]);
+ }
+
+ sndev->nr_direct_mw = min_t(int, sndev->nr_direct_mw, mw_count);
+
+ for (i = 0; i < sndev->nr_direct_mw; i++) {
+ bar = sndev->direct_mw_to_bar[i];
+ offset = (i == 0) ? LUT_SIZE * sndev->nr_lut_mw : 0;
+ addr = mw_addrs[i] + offset;
+ size = pci_resource_len(sndev->ntb.pdev, bar) - offset;
+ xlate_pos = ilog2(size);
+
+ if (offset && size > offset)
+ size = offset;
+
+ ctl_val = ioread32(&ctl->bar_entry[bar].ctl);
+ ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
+
+ iowrite32(ctl_val, &ctl->bar_entry[bar].ctl);
+ iowrite32(xlate_pos | size, &ctl->bar_entry[bar].win_size);
+ iowrite64(sndev->peer_partition | addr,
+ &ctl->bar_entry[bar].xlate_addr);
+ }
+
+ rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_CFG,
+ NTB_CTRL_PART_STATUS_NORMAL);
+ if (rc) {
+ u32 bar_error, lut_error;
+
+ bar_error = ioread32(&ctl->bar_error);
+ lut_error = ioread32(&ctl->lut_error);
+ dev_err(&sndev->stdev->dev,
+ "Error setting up cross link windows: %08x / %08x\n",
+ bar_error, lut_error);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int crosslink_setup_req_ids(struct switchtec_ntb *sndev,
+ struct ntb_ctrl_regs __iomem *mmio_ctrl)
+{
+ int req_ids[16];
+ int i;
+ u32 proxy_id;
+
+ for (i = 0; i < ARRAY_SIZE(req_ids); i++) {
+ proxy_id = ioread32(&sndev->mmio_self_ctrl->req_id_table[i]);
+
+ if (!(proxy_id & NTB_CTRL_REQ_ID_EN))
+ break;
+
+ req_ids[i] = ((proxy_id >> 1) & 0xFF);
+ }
+
+ return config_req_id_table(sndev, mmio_ctrl, req_ids, i);
+}
+
+/*
+ * In crosslink configuration there is a virtual partition in the
+ * middle of the two switches. The BARs in this partition have to be
+ * enumerated and assigned addresses.
+ */
+static int crosslink_enum_partition(struct switchtec_ntb *sndev,
+ u64 *bar_addrs)
+{
+ struct part_cfg_regs __iomem *part_cfg =
+ &sndev->stdev->mmio_part_cfg_all[sndev->peer_partition];
+ u32 pff = ioread32(&part_cfg->vep_pff_inst_id);
+ struct pff_csr_regs __iomem *mmio_pff =
+ &sndev->stdev->mmio_pff_csr[pff];
+ const u64 bar_space = 0x1000000000LL;
+ u64 bar_addr;
+ int bar_cnt = 0;
+ int i;
+
+ iowrite16(0x6, &mmio_pff->pcicmd);
+
+ for (i = 0; i < ARRAY_SIZE(mmio_pff->pci_bar64); i++) {
+ iowrite64(bar_space * i, &mmio_pff->pci_bar64[i]);
+ bar_addr = ioread64(&mmio_pff->pci_bar64[i]);
+ bar_addr &= ~0xf;
+
+ dev_dbg(&sndev->stdev->dev,
+ "Crosslink BAR%d addr: %llx\n",
+ i, bar_addr);
+
+ if (bar_addr != bar_space * i)
+ continue;
+
+ bar_addrs[bar_cnt++] = bar_addr;
+ }
+
+ return bar_cnt;
+}
+
+static int switchtec_ntb_init_crosslink(struct switchtec_ntb *sndev)
+{
+ int rc;
+ int bar = sndev->direct_mw_to_bar[0];
+ const int ntb_lut_idx = 1;
+ u64 bar_addrs[6];
+ u64 addr;
+ int offset;
+ int bar_cnt;
+
+ if (!crosslink_is_enabled(sndev))
+ return 0;
+
+ dev_info(&sndev->stdev->dev, "Using crosslink configuration\n");
+ sndev->ntb.topo = NTB_TOPO_CROSSLINK;
+
+ bar_cnt = crosslink_enum_partition(sndev, bar_addrs);
+ if (bar_cnt < sndev->nr_direct_mw + 1) {
+ dev_err(&sndev->stdev->dev,
+ "Error enumerating crosslink partition\n");
+ return -EINVAL;
+ }
+
+ addr = (bar_addrs[0] + SWITCHTEC_GAS_NTB_OFFSET +
+ SWITCHTEC_NTB_REG_DBMSG_OFFSET +
+ sizeof(struct ntb_dbmsg_regs) * sndev->peer_partition);
+
+ offset = addr & (LUT_SIZE - 1);
+ addr -= offset;
+
+ rc = config_rsvd_lut_win(sndev, sndev->mmio_self_ctrl, ntb_lut_idx,
+ sndev->peer_partition, addr);
+ if (rc)
+ return rc;
+
+ rc = crosslink_setup_mws(sndev, ntb_lut_idx, &bar_addrs[1],
+ bar_cnt - 1);
+ if (rc)
+ return rc;
+
+ rc = crosslink_setup_req_ids(sndev, sndev->mmio_peer_ctrl);
+ if (rc)
+ return rc;
+
+ sndev->mmio_xlink_win = pci_iomap_range(sndev->stdev->pdev, bar,
+ LUT_SIZE, LUT_SIZE);
+ if (!sndev->mmio_xlink_win) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ sndev->mmio_peer_dbmsg = sndev->mmio_xlink_win + offset;
+ sndev->nr_rsvd_luts++;
+
+ crosslink_init_dbmsgs(sndev);
+
+ return 0;
+}
+
+static void switchtec_ntb_deinit_crosslink(struct switchtec_ntb *sndev)
+{
+ if (sndev->mmio_xlink_win)
+ pci_iounmap(sndev->stdev->pdev, sndev->mmio_xlink_win);
}
static int map_bars(int *map, struct ntb_ctrl_regs __iomem *ctrl)
@@ -829,7 +1218,7 @@ static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev)
sndev->nr_lut_mw = ioread16(&sndev->mmio_self_ctrl->lut_table_entries);
sndev->nr_lut_mw = rounddown_pow_of_two(sndev->nr_lut_mw);
- dev_dbg(&sndev->stdev->dev, "MWs: %d direct, %d lut",
+ dev_dbg(&sndev->stdev->dev, "MWs: %d direct, %d lut\n",
sndev->nr_direct_mw, sndev->nr_lut_mw);
sndev->peer_nr_direct_mw = map_bars(sndev->peer_direct_mw_to_bar,
@@ -839,7 +1228,7 @@ static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev)
ioread16(&sndev->mmio_peer_ctrl->lut_table_entries);
sndev->peer_nr_lut_mw = rounddown_pow_of_two(sndev->peer_nr_lut_mw);
- dev_dbg(&sndev->stdev->dev, "Peer MWs: %d direct, %d lut",
+ dev_dbg(&sndev->stdev->dev, "Peer MWs: %d direct, %d lut\n",
sndev->peer_nr_direct_mw, sndev->peer_nr_lut_mw);
}
@@ -849,24 +1238,35 @@ static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev)
* shared among all partitions. So we must split them in half
* (32 for each partition). However, the message interrupts are
* also shared with the top 4 doorbells so we just limit this to
- * 28 doorbells per partition
+ * 28 doorbells per partition.
+ *
+ * In crosslink mode, each side has it's own dbmsg register so
+ * they can each use all 60 of the available doorbells.
*/
static void switchtec_ntb_init_db(struct switchtec_ntb *sndev)
{
- sndev->db_valid_mask = 0x0FFFFFFF;
+ sndev->db_mask = 0x0FFFFFFFFFFFFFFFULL;
- if (sndev->self_partition < sndev->peer_partition) {
+ if (sndev->mmio_peer_dbmsg != sndev->mmio_self_dbmsg) {
+ sndev->db_shift = 0;
+ sndev->db_peer_shift = 0;
+ sndev->db_valid_mask = sndev->db_mask;
+ } else if (sndev->self_partition < sndev->peer_partition) {
sndev->db_shift = 0;
sndev->db_peer_shift = 32;
+ sndev->db_valid_mask = 0x0FFFFFFF;
} else {
sndev->db_shift = 32;
sndev->db_peer_shift = 0;
+ sndev->db_valid_mask = 0x0FFFFFFF;
}
- sndev->db_mask = 0x0FFFFFFFFFFFFFFFULL;
iowrite64(~sndev->db_mask, &sndev->mmio_self_dbmsg->idb_mask);
iowrite64(sndev->db_valid_mask << sndev->db_peer_shift,
- &sndev->mmio_self_dbmsg->odb_mask);
+ &sndev->mmio_peer_dbmsg->odb_mask);
+
+ dev_dbg(&sndev->stdev->dev, "dbs: shift %d/%d, mask %016llx\n",
+ sndev->db_shift, sndev->db_peer_shift, sndev->db_valid_mask);
}
static void switchtec_ntb_init_msgs(struct switchtec_ntb *sndev)
@@ -887,52 +1287,23 @@ static void switchtec_ntb_init_msgs(struct switchtec_ntb *sndev)
&sndev->mmio_self_dbmsg->imsg[i]);
}
-static int switchtec_ntb_init_req_id_table(struct switchtec_ntb *sndev)
+static int
+switchtec_ntb_init_req_id_table(struct switchtec_ntb *sndev)
{
- int rc = 0;
- u16 req_id;
- u32 error;
-
- req_id = ioread16(&sndev->mmio_ntb->requester_id);
-
- if (ioread32(&sndev->mmio_self_ctrl->req_id_table_size) < 2) {
- dev_err(&sndev->stdev->dev,
- "Not enough requester IDs available.");
- return -EFAULT;
- }
-
- rc = switchtec_ntb_part_op(sndev, sndev->mmio_self_ctrl,
- NTB_CTRL_PART_OP_LOCK,
- NTB_CTRL_PART_STATUS_LOCKED);
- if (rc)
- return rc;
-
- iowrite32(NTB_PART_CTRL_ID_PROT_DIS,
- &sndev->mmio_self_ctrl->partition_ctrl);
+ int req_ids[2];
/*
* Root Complex Requester ID (which is 0:00.0)
*/
- iowrite32(0 << 16 | NTB_CTRL_REQ_ID_EN,
- &sndev->mmio_self_ctrl->req_id_table[0]);
+ req_ids[0] = 0;
/*
* Host Bridge Requester ID (as read from the mmap address)
*/
- iowrite32(req_id << 16 | NTB_CTRL_REQ_ID_EN,
- &sndev->mmio_self_ctrl->req_id_table[1]);
-
- rc = switchtec_ntb_part_op(sndev, sndev->mmio_self_ctrl,
- NTB_CTRL_PART_OP_CFG,
- NTB_CTRL_PART_STATUS_NORMAL);
- if (rc == -EIO) {
- error = ioread32(&sndev->mmio_self_ctrl->req_id_error);
- dev_err(&sndev->stdev->dev,
- "Error setting up the requester ID table: %08x",
- error);
- }
+ req_ids[1] = ioread16(&sndev->mmio_ntb->requester_id);
- return rc;
+ return config_req_id_table(sndev, sndev->mmio_self_ctrl, req_ids,
+ ARRAY_SIZE(req_ids));
}
static void switchtec_ntb_init_shared(struct switchtec_ntb *sndev)
@@ -963,59 +1334,35 @@ static void switchtec_ntb_init_shared(struct switchtec_ntb *sndev)
static int switchtec_ntb_init_shared_mw(struct switchtec_ntb *sndev)
{
- struct ntb_ctrl_regs __iomem *ctl = sndev->mmio_peer_ctrl;
- int bar = sndev->direct_mw_to_bar[0];
- u32 ctl_val;
+ int self_bar = sndev->direct_mw_to_bar[0];
int rc;
+ sndev->nr_rsvd_luts++;
sndev->self_shared = dma_zalloc_coherent(&sndev->stdev->pdev->dev,
LUT_SIZE,
&sndev->self_shared_dma,
GFP_KERNEL);
if (!sndev->self_shared) {
dev_err(&sndev->stdev->dev,
- "unable to allocate memory for shared mw");
+ "unable to allocate memory for shared mw\n");
return -ENOMEM;
}
switchtec_ntb_init_shared(sndev);
- rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_LOCK,
- NTB_CTRL_PART_STATUS_LOCKED);
+ rc = config_rsvd_lut_win(sndev, sndev->mmio_peer_ctrl, 0,
+ sndev->self_partition,
+ sndev->self_shared_dma);
if (rc)
goto unalloc_and_exit;
- ctl_val = ioread32(&ctl->bar_entry[bar].ctl);
- ctl_val &= 0xFF;
- ctl_val |= NTB_CTRL_BAR_LUT_WIN_EN;
- ctl_val |= ilog2(LUT_SIZE) << 8;
- ctl_val |= (sndev->nr_lut_mw - 1) << 14;
- iowrite32(ctl_val, &ctl->bar_entry[bar].ctl);
-
- iowrite64((NTB_CTRL_LUT_EN | (sndev->self_partition << 1) |
- sndev->self_shared_dma),
- &ctl->lut_entry[0]);
-
- rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_CFG,
- NTB_CTRL_PART_STATUS_NORMAL);
- if (rc) {
- u32 bar_error, lut_error;
-
- bar_error = ioread32(&ctl->bar_error);
- lut_error = ioread32(&ctl->lut_error);
- dev_err(&sndev->stdev->dev,
- "Error setting up shared MW: %08x / %08x",
- bar_error, lut_error);
- goto unalloc_and_exit;
- }
-
- sndev->peer_shared = pci_iomap(sndev->stdev->pdev, bar, LUT_SIZE);
+ sndev->peer_shared = pci_iomap(sndev->stdev->pdev, self_bar, LUT_SIZE);
if (!sndev->peer_shared) {
rc = -ENOMEM;
goto unalloc_and_exit;
}
- dev_dbg(&sndev->stdev->dev, "Shared MW Ready");
+ dev_dbg(&sndev->stdev->dev, "Shared MW Ready\n");
return 0;
unalloc_and_exit:
@@ -1034,6 +1381,7 @@ static void switchtec_ntb_deinit_shared_mw(struct switchtec_ntb *sndev)
dma_free_coherent(&sndev->stdev->pdev->dev, LUT_SIZE,
sndev->self_shared,
sndev->self_shared_dma);
+ sndev->nr_rsvd_luts--;
}
static irqreturn_t switchtec_ntb_doorbell_isr(int irq, void *dev)
@@ -1056,12 +1404,12 @@ static irqreturn_t switchtec_ntb_message_isr(int irq, void *dev)
u64 msg = ioread64(&sndev->mmio_self_dbmsg->imsg[i]);
if (msg & NTB_DBMSG_IMSG_STATUS) {
- dev_dbg(&sndev->stdev->dev, "message: %d %08x\n", i,
- (u32)msg);
+ dev_dbg(&sndev->stdev->dev, "message: %d %08x\n",
+ i, (u32)msg);
iowrite8(1, &sndev->mmio_self_dbmsg->imsg[i].status);
if (i == LINK_MESSAGE)
- switchtec_ntb_check_link(sndev);
+ switchtec_ntb_check_link(sndev, msg);
}
}
@@ -1085,7 +1433,7 @@ static int switchtec_ntb_init_db_msg_irq(struct switchtec_ntb *sndev)
message_irq == event_irq)
message_irq++;
- dev_dbg(&sndev->stdev->dev, "irqs - event: %d, db: %d, msgs: %d",
+ dev_dbg(&sndev->stdev->dev, "irqs - event: %d, db: %d, msgs: %d\n",
event_irq, doorbell_irq, message_irq);
for (i = 0; i < idb_vecs - 4; i++)
@@ -1122,6 +1470,14 @@ static void switchtec_ntb_deinit_db_msg_irq(struct switchtec_ntb *sndev)
free_irq(sndev->message_irq, sndev);
}
+static int switchtec_ntb_reinit_peer(struct switchtec_ntb *sndev)
+{
+ dev_info(&sndev->stdev->dev, "peer reinitialized\n");
+ switchtec_ntb_deinit_shared_mw(sndev);
+ switchtec_ntb_init_mw(sndev);
+ return switchtec_ntb_init_shared_mw(sndev);
+}
+
static int switchtec_ntb_add(struct device *dev,
struct class_interface *class_intf)
{
@@ -1134,38 +1490,50 @@ static int switchtec_ntb_add(struct device *dev,
if (stdev->pdev->class != MICROSEMI_NTB_CLASSCODE)
return -ENODEV;
- if (stdev->partition_count != 2)
- dev_warn(dev, "ntb driver only supports 2 partitions");
-
sndev = kzalloc_node(sizeof(*sndev), GFP_KERNEL, dev_to_node(dev));
if (!sndev)
return -ENOMEM;
sndev->stdev = stdev;
- switchtec_ntb_init_sndev(sndev);
+ rc = switchtec_ntb_init_sndev(sndev);
+ if (rc)
+ goto free_and_exit;
+
switchtec_ntb_init_mw(sndev);
- switchtec_ntb_init_db(sndev);
- switchtec_ntb_init_msgs(sndev);
rc = switchtec_ntb_init_req_id_table(sndev);
if (rc)
goto free_and_exit;
- rc = switchtec_ntb_init_shared_mw(sndev);
+ rc = switchtec_ntb_init_crosslink(sndev);
if (rc)
goto free_and_exit;
+ switchtec_ntb_init_db(sndev);
+ switchtec_ntb_init_msgs(sndev);
+
+ rc = switchtec_ntb_init_shared_mw(sndev);
+ if (rc)
+ goto deinit_crosslink;
+
rc = switchtec_ntb_init_db_msg_irq(sndev);
if (rc)
goto deinit_shared_and_exit;
+ /*
+ * If this host crashed, the other host may think the link is
+ * still up. Tell them to force it down (it will go back up
+ * once we register the ntb device).
+ */
+ switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_FORCE_DOWN);
+
rc = ntb_register_device(&sndev->ntb);
if (rc)
goto deinit_and_exit;
stdev->sndev = sndev;
stdev->link_notifier = switchtec_ntb_link_notification;
- dev_info(dev, "NTB device registered");
+ dev_info(dev, "NTB device registered\n");
return 0;
@@ -1173,14 +1541,16 @@ deinit_and_exit:
switchtec_ntb_deinit_db_msg_irq(sndev);
deinit_shared_and_exit:
switchtec_ntb_deinit_shared_mw(sndev);
+deinit_crosslink:
+ switchtec_ntb_deinit_crosslink(sndev);
free_and_exit:
kfree(sndev);
- dev_err(dev, "failed to register ntb device: %d", rc);
+ dev_err(dev, "failed to register ntb device: %d\n", rc);
return rc;
}
-void switchtec_ntb_remove(struct device *dev,
- struct class_interface *class_intf)
+static void switchtec_ntb_remove(struct device *dev,
+ struct class_interface *class_intf)
{
struct switchtec_dev *stdev = to_stdev(dev);
struct switchtec_ntb *sndev = stdev->sndev;
@@ -1193,8 +1563,9 @@ void switchtec_ntb_remove(struct device *dev,
ntb_unregister_device(&sndev->ntb);
switchtec_ntb_deinit_db_msg_irq(sndev);
switchtec_ntb_deinit_shared_mw(sndev);
+ switchtec_ntb_deinit_crosslink(sndev);
kfree(sndev);
- dev_info(dev, "ntb device unregistered");
+ dev_info(dev, "ntb device unregistered\n");
}
static struct class_interface switchtec_interface = {
diff --git a/drivers/ntb/ntb.c b/drivers/ntb/ntb.c
index 03b80d89b980..2581ab724c34 100644
--- a/drivers/ntb/ntb.c
+++ b/drivers/ntb/ntb.c
@@ -63,12 +63,11 @@
#define DRIVER_NAME "ntb"
#define DRIVER_DESCRIPTION "PCIe NTB Driver Framework"
-#define DRIVER_LICENSE "Dual BSD/GPL"
#define DRIVER_VERSION "1.0"
#define DRIVER_RELDATE "24 March 2015"
#define DRIVER_AUTHOR "Allen Hubbe <Allen.Hubbe@emc.com>"
-MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
@@ -112,7 +111,6 @@ int ntb_register_device(struct ntb_dev *ntb)
init_completion(&ntb->released);
- memset(&ntb->dev, 0, sizeof(ntb->dev));
ntb->dev.bus = &ntb_bus;
ntb->dev.parent = &ntb->pdev->dev;
ntb->dev.release = ntb_dev_release;
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 045e3dd4750e..9878c48826e3 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1003,6 +1003,9 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
mw_base = nt->mw_vec[mw_num].phys_addr;
mw_size = nt->mw_vec[mw_num].phys_size;
+ if (max_mw_size && mw_size > max_mw_size)
+ mw_size = max_mw_size;
+
tx_size = (unsigned int)mw_size / num_qps_mw;
qp_offset = tx_size * (qp_num / mw_count);
diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c
index 427112cf101a..2a9d6b0d1f19 100644
--- a/drivers/ntb/test/ntb_perf.c
+++ b/drivers/ntb/test/ntb_perf.c
@@ -5,6 +5,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2017 T-Platforms. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -13,6 +14,7 @@
* BSD LICENSE
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2017 T-Platforms. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,860 +42,1474 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * PCIe NTB Perf Linux driver
+ * PCIe NTB Perf Linux driver
+ */
+
+/*
+ * How to use this tool, by example.
+ *
+ * Assuming $DBG_DIR is something like:
+ * '/sys/kernel/debug/ntb_perf/0000:00:03.0'
+ * Suppose aside from local device there is at least one remote device
+ * connected to NTB with index 0.
+ *-----------------------------------------------------------------------------
+ * Eg: install driver with specified chunk/total orders and dma-enabled flag
+ *
+ * root@self# insmod ntb_perf.ko chunk_order=19 total_order=28 use_dma
+ *-----------------------------------------------------------------------------
+ * Eg: check NTB ports (index) and MW mapping information
+ *
+ * root@self# cat $DBG_DIR/info
+ *-----------------------------------------------------------------------------
+ * Eg: start performance test with peer (index 0) and get the test metrics
+ *
+ * root@self# echo 0 > $DBG_DIR/run
+ * root@self# cat $DBG_DIR/run
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/time.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/pci.h>
+#include <linux/ktime.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/dmaengine.h>
#include <linux/delay.h>
#include <linux/sizes.h>
+#include <linux/workqueue.h>
+#include <linux/debugfs.h>
+#include <linux/random.h>
#include <linux/ntb.h>
-#include <linux/mutex.h>
#define DRIVER_NAME "ntb_perf"
-#define DRIVER_DESCRIPTION "PCIe NTB Performance Measurement Tool"
-
-#define DRIVER_LICENSE "Dual BSD/GPL"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_AUTHOR "Dave Jiang <dave.jiang@intel.com>"
-
-#define PERF_LINK_DOWN_TIMEOUT 10
-#define PERF_VERSION 0xffff0001
-#define MAX_THREADS 32
-#define MAX_TEST_SIZE SZ_1M
-#define MAX_SRCS 32
-#define DMA_OUT_RESOURCE_TO msecs_to_jiffies(50)
-#define DMA_RETRIES 20
-#define SZ_4G (1ULL << 32)
-#define MAX_SEG_ORDER 20 /* no larger than 1M for kmalloc buffer */
-#define PIDX NTB_DEF_PEER_IDX
-
-MODULE_LICENSE(DRIVER_LICENSE);
+#define DRIVER_VERSION "2.0"
+
+MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+MODULE_AUTHOR("Dave Jiang <dave.jiang@intel.com>");
+MODULE_DESCRIPTION("PCIe NTB Performance Measurement Tool");
+
+#define MAX_THREADS_CNT 32
+#define DEF_THREADS_CNT 1
+#define MAX_CHUNK_SIZE SZ_1M
+#define MAX_CHUNK_ORDER 20 /* no larger than 1M */
-static struct dentry *perf_debugfs_dir;
+#define DMA_TRIES 100
+#define DMA_MDELAY 10
+
+#define MSG_TRIES 500
+#define MSG_UDELAY_LOW 1000
+#define MSG_UDELAY_HIGH 2000
+
+#define PERF_BUF_LEN 1024
static unsigned long max_mw_size;
module_param(max_mw_size, ulong, 0644);
-MODULE_PARM_DESC(max_mw_size, "Limit size of large memory windows");
+MODULE_PARM_DESC(max_mw_size, "Upper limit of memory window size");
-static unsigned int seg_order = 19; /* 512K */
-module_param(seg_order, uint, 0644);
-MODULE_PARM_DESC(seg_order, "size order [2^n] of buffer segment for testing");
+static unsigned char chunk_order = 19; /* 512K */
+module_param(chunk_order, byte, 0644);
+MODULE_PARM_DESC(chunk_order, "Data chunk order [2^n] to transfer");
-static unsigned int run_order = 32; /* 4G */
-module_param(run_order, uint, 0644);
-MODULE_PARM_DESC(run_order, "size order [2^n] of total data to transfer");
+static unsigned char total_order = 30; /* 1G */
+module_param(total_order, byte, 0644);
+MODULE_PARM_DESC(total_order, "Total data order [2^n] to transfer");
static bool use_dma; /* default to 0 */
module_param(use_dma, bool, 0644);
-MODULE_PARM_DESC(use_dma, "Using DMA engine to measure performance");
-
-static bool on_node = true; /* default to 1 */
-module_param(on_node, bool, 0644);
-MODULE_PARM_DESC(on_node, "Run threads only on NTB device node (default: true)");
-
-struct perf_mw {
- phys_addr_t phys_addr;
- resource_size_t phys_size;
- void __iomem *vbase;
- size_t xlat_size;
- size_t buf_size;
- void *virt_addr;
- dma_addr_t dma_addr;
+MODULE_PARM_DESC(use_dma, "Use DMA engine to measure performance");
+
+/*==============================================================================
+ * Perf driver data definition
+ *==============================================================================
+ */
+
+enum perf_cmd {
+ PERF_CMD_INVAL = -1,/* invalid spad command */
+ PERF_CMD_SSIZE = 0, /* send out buffer size */
+ PERF_CMD_RSIZE = 1, /* recv in buffer size */
+ PERF_CMD_SXLAT = 2, /* send in buffer xlat */
+ PERF_CMD_RXLAT = 3, /* recv out buffer xlat */
+ PERF_CMD_CLEAR = 4, /* clear allocated memory */
+ PERF_STS_DONE = 5, /* init is done */
+ PERF_STS_LNKUP = 6, /* link up state flag */
};
struct perf_ctx;
-struct pthr_ctx {
- struct task_struct *thread;
- struct perf_ctx *perf;
- atomic_t dma_sync;
- struct dma_chan *dma_chan;
- int dma_prep_err;
- int src_idx;
- void *srcs[MAX_SRCS];
- wait_queue_head_t *wq;
- int status;
- u64 copied;
- u64 diff_us;
+struct perf_peer {
+ struct perf_ctx *perf;
+ int pidx;
+ int gidx;
+
+ /* Outbound MW params */
+ u64 outbuf_xlat;
+ resource_size_t outbuf_size;
+ void __iomem *outbuf;
+
+ /* Inbound MW params */
+ dma_addr_t inbuf_xlat;
+ resource_size_t inbuf_size;
+ void *inbuf;
+
+ /* NTB connection setup service */
+ struct work_struct service;
+ unsigned long sts;
};
+#define to_peer_service(__work) \
+ container_of(__work, struct perf_peer, service)
-struct perf_ctx {
- struct ntb_dev *ntb;
- spinlock_t db_lock;
- struct perf_mw mw;
- bool link_is_up;
- struct delayed_work link_work;
- wait_queue_head_t link_wq;
- u8 perf_threads;
- /* mutex ensures only one set of threads run at once */
- struct mutex run_mutex;
- struct pthr_ctx pthr_ctx[MAX_THREADS];
- atomic_t tsync;
- atomic_t tdone;
+struct perf_thread {
+ struct perf_ctx *perf;
+ int tidx;
+
+ /* DMA-based test sync parameters */
+ atomic_t dma_sync;
+ wait_queue_head_t dma_wait;
+ struct dma_chan *dma_chan;
+
+ /* Data source and measured statistics */
+ void *src;
+ u64 copied;
+ ktime_t duration;
+ int status;
+ struct work_struct work;
};
+#define to_thread_work(__work) \
+ container_of(__work, struct perf_thread, work)
-enum {
- VERSION = 0,
- MW_SZ_HIGH,
- MW_SZ_LOW,
- MAX_SPAD
+struct perf_ctx {
+ struct ntb_dev *ntb;
+
+ /* Global device index and peers descriptors */
+ int gidx;
+ int pcnt;
+ struct perf_peer *peers;
+
+ /* Performance measuring work-threads interface */
+ unsigned long busy_flag;
+ wait_queue_head_t twait;
+ atomic_t tsync;
+ u8 tcnt;
+ struct perf_peer *test_peer;
+ struct perf_thread threads[MAX_THREADS_CNT];
+
+ /* Scratchpad/Message IO operations */
+ int (*cmd_send)(struct perf_peer *peer, enum perf_cmd cmd, u64 data);
+ int (*cmd_recv)(struct perf_ctx *perf, int *pidx, enum perf_cmd *cmd,
+ u64 *data);
+
+ struct dentry *dbgfs_dir;
};
+/*
+ * Scratchpads-base commands interface
+ */
+#define PERF_SPAD_CNT(_pcnt) \
+ (3*((_pcnt) + 1))
+#define PERF_SPAD_CMD(_gidx) \
+ (3*(_gidx))
+#define PERF_SPAD_LDATA(_gidx) \
+ (3*(_gidx) + 1)
+#define PERF_SPAD_HDATA(_gidx) \
+ (3*(_gidx) + 2)
+#define PERF_SPAD_NOTIFY(_gidx) \
+ (BIT_ULL(_gidx))
+
+/*
+ * Messages-base commands interface
+ */
+#define PERF_MSG_CNT 3
+#define PERF_MSG_CMD 0
+#define PERF_MSG_LDATA 1
+#define PERF_MSG_HDATA 2
+
+/*==============================================================================
+ * Static data declarations
+ *==============================================================================
+ */
+
+static struct dentry *perf_dbgfs_topdir;
+
+static struct workqueue_struct *perf_wq __read_mostly;
+
+/*==============================================================================
+ * NTB cross-link commands execution service
+ *==============================================================================
+ */
+
+static void perf_terminate_test(struct perf_ctx *perf);
+
+static inline bool perf_link_is_up(struct perf_peer *peer)
+{
+ u64 link;
+
+ link = ntb_link_is_up(peer->perf->ntb, NULL, NULL);
+ return !!(link & BIT_ULL_MASK(peer->pidx));
+}
+
+static int perf_spad_cmd_send(struct perf_peer *peer, enum perf_cmd cmd,
+ u64 data)
+{
+ struct perf_ctx *perf = peer->perf;
+ int try;
+ u32 sts;
+
+ dev_dbg(&perf->ntb->dev, "CMD send: %d 0x%llx\n", cmd, data);
+
+ /*
+ * Perform predefined number of attempts before give up.
+ * We are sending the data to the port specific scratchpad, so
+ * to prevent a multi-port access race-condition. Additionally
+ * there is no need in local locking since only thread-safe
+ * service work is using this method.
+ */
+ for (try = 0; try < MSG_TRIES; try++) {
+ if (!perf_link_is_up(peer))
+ return -ENOLINK;
+
+ sts = ntb_peer_spad_read(perf->ntb, peer->pidx,
+ PERF_SPAD_CMD(perf->gidx));
+ if (sts != PERF_CMD_INVAL) {
+ usleep_range(MSG_UDELAY_LOW, MSG_UDELAY_HIGH);
+ continue;
+ }
+
+ ntb_peer_spad_write(perf->ntb, peer->pidx,
+ PERF_SPAD_LDATA(perf->gidx),
+ lower_32_bits(data));
+ ntb_peer_spad_write(perf->ntb, peer->pidx,
+ PERF_SPAD_HDATA(perf->gidx),
+ upper_32_bits(data));
+ mmiowb();
+ ntb_peer_spad_write(perf->ntb, peer->pidx,
+ PERF_SPAD_CMD(perf->gidx),
+ cmd);
+ mmiowb();
+ ntb_peer_db_set(perf->ntb, PERF_SPAD_NOTIFY(peer->gidx));
+
+ dev_dbg(&perf->ntb->dev, "DB ring peer %#llx\n",
+ PERF_SPAD_NOTIFY(peer->gidx));
+
+ break;
+ }
+
+ return try < MSG_TRIES ? 0 : -EAGAIN;
+}
+
+static int perf_spad_cmd_recv(struct perf_ctx *perf, int *pidx,
+ enum perf_cmd *cmd, u64 *data)
+{
+ struct perf_peer *peer;
+ u32 val;
+
+ ntb_db_clear(perf->ntb, PERF_SPAD_NOTIFY(perf->gidx));
+
+ /*
+ * We start scanning all over, since cleared DB may have been set
+ * by any peer. Yes, it makes peer with smaller index being
+ * serviced with greater priority, but it's convenient for spad
+ * and message code unification and simplicity.
+ */
+ for (*pidx = 0; *pidx < perf->pcnt; (*pidx)++) {
+ peer = &perf->peers[*pidx];
+
+ if (!perf_link_is_up(peer))
+ continue;
+
+ val = ntb_spad_read(perf->ntb, PERF_SPAD_CMD(peer->gidx));
+ if (val == PERF_CMD_INVAL)
+ continue;
+
+ *cmd = val;
+
+ val = ntb_spad_read(perf->ntb, PERF_SPAD_LDATA(peer->gidx));
+ *data = val;
+
+ val = ntb_spad_read(perf->ntb, PERF_SPAD_HDATA(peer->gidx));
+ *data |= (u64)val << 32;
+
+ /* Next command can be retrieved from now */
+ ntb_spad_write(perf->ntb, PERF_SPAD_CMD(peer->gidx),
+ PERF_CMD_INVAL);
+
+ dev_dbg(&perf->ntb->dev, "CMD recv: %d 0x%llx\n", *cmd, *data);
+
+ return 0;
+ }
+
+ return -ENODATA;
+}
+
+static int perf_msg_cmd_send(struct perf_peer *peer, enum perf_cmd cmd,
+ u64 data)
+{
+ struct perf_ctx *perf = peer->perf;
+ int try, ret;
+ u64 outbits;
+
+ dev_dbg(&perf->ntb->dev, "CMD send: %d 0x%llx\n", cmd, data);
+
+ /*
+ * Perform predefined number of attempts before give up. Message
+ * registers are free of race-condition problem when accessed
+ * from different ports, so we don't need splitting registers
+ * by global device index. We also won't have local locking,
+ * since the method is used from service work only.
+ */
+ outbits = ntb_msg_outbits(perf->ntb);
+ for (try = 0; try < MSG_TRIES; try++) {
+ if (!perf_link_is_up(peer))
+ return -ENOLINK;
+
+ ret = ntb_msg_clear_sts(perf->ntb, outbits);
+ if (ret)
+ return ret;
+
+ ntb_peer_msg_write(perf->ntb, peer->pidx, PERF_MSG_LDATA,
+ lower_32_bits(data));
+
+ if (ntb_msg_read_sts(perf->ntb) & outbits) {
+ usleep_range(MSG_UDELAY_LOW, MSG_UDELAY_HIGH);
+ continue;
+ }
+
+ ntb_peer_msg_write(perf->ntb, peer->pidx, PERF_MSG_HDATA,
+ upper_32_bits(data));
+ mmiowb();
+
+ /* This call shall trigger peer message event */
+ ntb_peer_msg_write(perf->ntb, peer->pidx, PERF_MSG_CMD, cmd);
+
+ break;
+ }
+
+ return try < MSG_TRIES ? 0 : -EAGAIN;
+}
+
+static int perf_msg_cmd_recv(struct perf_ctx *perf, int *pidx,
+ enum perf_cmd *cmd, u64 *data)
+{
+ u64 inbits;
+ u32 val;
+
+ inbits = ntb_msg_inbits(perf->ntb);
+
+ if (hweight64(ntb_msg_read_sts(perf->ntb) & inbits) < 3)
+ return -ENODATA;
+
+ val = ntb_msg_read(perf->ntb, pidx, PERF_MSG_CMD);
+ *cmd = val;
+
+ val = ntb_msg_read(perf->ntb, pidx, PERF_MSG_LDATA);
+ *data = val;
+
+ val = ntb_msg_read(perf->ntb, pidx, PERF_MSG_HDATA);
+ *data |= (u64)val << 32;
+
+ /* Next command can be retrieved from now */
+ ntb_msg_clear_sts(perf->ntb, inbits);
+
+ dev_dbg(&perf->ntb->dev, "CMD recv: %d 0x%llx\n", *cmd, *data);
+
+ return 0;
+}
+
+static int perf_cmd_send(struct perf_peer *peer, enum perf_cmd cmd, u64 data)
+{
+ struct perf_ctx *perf = peer->perf;
+
+ if (cmd == PERF_CMD_SSIZE || cmd == PERF_CMD_SXLAT)
+ return perf->cmd_send(peer, cmd, data);
+
+ dev_err(&perf->ntb->dev, "Send invalid command\n");
+ return -EINVAL;
+}
+
+static int perf_cmd_exec(struct perf_peer *peer, enum perf_cmd cmd)
+{
+ switch (cmd) {
+ case PERF_CMD_SSIZE:
+ case PERF_CMD_RSIZE:
+ case PERF_CMD_SXLAT:
+ case PERF_CMD_RXLAT:
+ case PERF_CMD_CLEAR:
+ break;
+ default:
+ dev_err(&peer->perf->ntb->dev, "Exec invalid command\n");
+ return -EINVAL;
+ }
+
+ /* No need of memory barrier, since bit ops have invernal lock */
+ set_bit(cmd, &peer->sts);
+
+ dev_dbg(&peer->perf->ntb->dev, "CMD exec: %d\n", cmd);
+
+ (void)queue_work(system_highpri_wq, &peer->service);
+
+ return 0;
+}
+
+static int perf_cmd_recv(struct perf_ctx *perf)
+{
+ struct perf_peer *peer;
+ int ret, pidx, cmd;
+ u64 data;
+
+ while (!(ret = perf->cmd_recv(perf, &pidx, &cmd, &data))) {
+ peer = &perf->peers[pidx];
+
+ switch (cmd) {
+ case PERF_CMD_SSIZE:
+ peer->inbuf_size = data;
+ return perf_cmd_exec(peer, PERF_CMD_RSIZE);
+ case PERF_CMD_SXLAT:
+ peer->outbuf_xlat = data;
+ return perf_cmd_exec(peer, PERF_CMD_RXLAT);
+ default:
+ dev_err(&perf->ntb->dev, "Recv invalid command\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Return 0 if no data left to process, otherwise an error */
+ return ret == -ENODATA ? 0 : ret;
+}
+
static void perf_link_event(void *ctx)
{
struct perf_ctx *perf = ctx;
+ struct perf_peer *peer;
+ bool lnk_up;
+ int pidx;
- if (ntb_link_is_up(perf->ntb, NULL, NULL) == 1) {
- schedule_delayed_work(&perf->link_work, 2*HZ);
- } else {
- dev_dbg(&perf->ntb->pdev->dev, "link down\n");
+ for (pidx = 0; pidx < perf->pcnt; pidx++) {
+ peer = &perf->peers[pidx];
- if (!perf->link_is_up)
- cancel_delayed_work_sync(&perf->link_work);
+ lnk_up = perf_link_is_up(peer);
- perf->link_is_up = false;
+ if (lnk_up &&
+ !test_and_set_bit(PERF_STS_LNKUP, &peer->sts)) {
+ perf_cmd_exec(peer, PERF_CMD_SSIZE);
+ } else if (!lnk_up &&
+ test_and_clear_bit(PERF_STS_LNKUP, &peer->sts)) {
+ perf_cmd_exec(peer, PERF_CMD_CLEAR);
+ }
}
}
static void perf_db_event(void *ctx, int vec)
{
struct perf_ctx *perf = ctx;
- u64 db_bits, db_mask;
- db_mask = ntb_db_vector_mask(perf->ntb, vec);
- db_bits = ntb_db_read(perf->ntb);
+ dev_dbg(&perf->ntb->dev, "DB vec %d mask %#llx bits %#llx\n", vec,
+ ntb_db_vector_mask(perf->ntb, vec), ntb_db_read(perf->ntb));
+
+ /* Just receive all available commands */
+ (void)perf_cmd_recv(perf);
+}
+
+static void perf_msg_event(void *ctx)
+{
+ struct perf_ctx *perf = ctx;
+
+ dev_dbg(&perf->ntb->dev, "Msg status bits %#llx\n",
+ ntb_msg_read_sts(perf->ntb));
- dev_dbg(&perf->ntb->dev, "doorbell vec %d mask %#llx bits %#llx\n",
- vec, db_mask, db_bits);
+ /* Messages are only sent one-by-one */
+ (void)perf_cmd_recv(perf);
}
static const struct ntb_ctx_ops perf_ops = {
.link_event = perf_link_event,
.db_event = perf_db_event,
+ .msg_event = perf_msg_event
};
-static void perf_copy_callback(void *data)
+static void perf_free_outbuf(struct perf_peer *peer)
+{
+ (void)ntb_peer_mw_clear_trans(peer->perf->ntb, peer->pidx, peer->gidx);
+}
+
+static int perf_setup_outbuf(struct perf_peer *peer)
{
- struct pthr_ctx *pctx = data;
+ struct perf_ctx *perf = peer->perf;
+ int ret;
+
+ /* Outbuf size can be unaligned due to custom max_mw_size */
+ ret = ntb_peer_mw_set_trans(perf->ntb, peer->pidx, peer->gidx,
+ peer->outbuf_xlat, peer->outbuf_size);
+ if (ret) {
+ dev_err(&perf->ntb->dev, "Failed to set outbuf translation\n");
+ return ret;
+ }
- atomic_dec(&pctx->dma_sync);
+ /* Initialization is finally done */
+ set_bit(PERF_STS_DONE, &peer->sts);
+
+ return 0;
}
-static ssize_t perf_copy(struct pthr_ctx *pctx, char __iomem *dst,
- char *src, size_t size)
+static void perf_free_inbuf(struct perf_peer *peer)
{
- struct perf_ctx *perf = pctx->perf;
- struct dma_async_tx_descriptor *txd;
- struct dma_chan *chan = pctx->dma_chan;
- struct dma_device *device;
- struct dmaengine_unmap_data *unmap;
- dma_cookie_t cookie;
- size_t src_off, dst_off;
- struct perf_mw *mw = &perf->mw;
- void __iomem *vbase;
- void __iomem *dst_vaddr;
- dma_addr_t dst_phys;
- int retries = 0;
+ if (!peer->inbuf)
+ return;
- if (!use_dma) {
- memcpy_toio(dst, src, size);
- return size;
+ (void)ntb_mw_clear_trans(peer->perf->ntb, peer->pidx, peer->gidx);
+ dma_free_coherent(&peer->perf->ntb->dev, peer->inbuf_size,
+ peer->inbuf, peer->inbuf_xlat);
+ peer->inbuf = NULL;
+}
+
+static int perf_setup_inbuf(struct perf_peer *peer)
+{
+ resource_size_t xlat_align, size_align, size_max;
+ struct perf_ctx *perf = peer->perf;
+ int ret;
+
+ /* Get inbound MW parameters */
+ ret = ntb_mw_get_align(perf->ntb, peer->pidx, perf->gidx,
+ &xlat_align, &size_align, &size_max);
+ if (ret) {
+ dev_err(&perf->ntb->dev, "Couldn't get inbuf restrictions\n");
+ return ret;
}
- if (!chan) {
- dev_err(&perf->ntb->dev, "DMA engine does not exist\n");
+ if (peer->inbuf_size > size_max) {
+ dev_err(&perf->ntb->dev, "Too big inbuf size %pa > %pa\n",
+ &peer->inbuf_size, &size_max);
return -EINVAL;
}
- device = chan->device;
- src_off = (uintptr_t)src & ~PAGE_MASK;
- dst_off = (uintptr_t __force)dst & ~PAGE_MASK;
-
- if (!is_dma_copy_aligned(device, src_off, dst_off, size))
- return -ENODEV;
+ peer->inbuf_size = round_up(peer->inbuf_size, size_align);
- vbase = mw->vbase;
- dst_vaddr = dst;
- dst_phys = mw->phys_addr + (dst_vaddr - vbase);
+ perf_free_inbuf(peer);
- unmap = dmaengine_get_unmap_data(device->dev, 1, GFP_NOWAIT);
- if (!unmap)
+ peer->inbuf = dma_alloc_coherent(&perf->ntb->dev, peer->inbuf_size,
+ &peer->inbuf_xlat, GFP_KERNEL);
+ if (!peer->inbuf) {
+ dev_err(&perf->ntb->dev, "Failed to alloc inbuf of %pa\n",
+ &peer->inbuf_size);
return -ENOMEM;
+ }
+ if (!IS_ALIGNED(peer->inbuf_xlat, xlat_align)) {
+ dev_err(&perf->ntb->dev, "Unaligned inbuf allocated\n");
+ goto err_free_inbuf;
+ }
- unmap->len = size;
- unmap->addr[0] = dma_map_page(device->dev, virt_to_page(src),
- src_off, size, DMA_TO_DEVICE);
- if (dma_mapping_error(device->dev, unmap->addr[0]))
- goto err_get_unmap;
+ ret = ntb_mw_set_trans(perf->ntb, peer->pidx, peer->gidx,
+ peer->inbuf_xlat, peer->inbuf_size);
+ if (ret) {
+ dev_err(&perf->ntb->dev, "Failed to set inbuf translation\n");
+ goto err_free_inbuf;
+ }
- unmap->to_cnt = 1;
+ /*
+ * We submit inbuf xlat transmission cmd for execution here to follow
+ * the code architecture, even though this method is called from service
+ * work itself so the command will be executed right after it returns.
+ */
+ (void)perf_cmd_exec(peer, PERF_CMD_SXLAT);
- do {
- txd = device->device_prep_dma_memcpy(chan, dst_phys,
- unmap->addr[0],
- size, DMA_PREP_INTERRUPT);
- if (!txd) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(DMA_OUT_RESOURCE_TO);
- }
- } while (!txd && (++retries < DMA_RETRIES));
+ return 0;
- if (!txd) {
- pctx->dma_prep_err++;
- goto err_get_unmap;
- }
+err_free_inbuf:
+ perf_free_inbuf(peer);
- txd->callback = perf_copy_callback;
- txd->callback_param = pctx;
- dma_set_unmap(txd, unmap);
+ return ret;
+}
- cookie = dmaengine_submit(txd);
- if (dma_submit_error(cookie))
- goto err_set_unmap;
+static void perf_service_work(struct work_struct *work)
+{
+ struct perf_peer *peer = to_peer_service(work);
- dmaengine_unmap_put(unmap);
+ if (test_and_clear_bit(PERF_CMD_SSIZE, &peer->sts))
+ perf_cmd_send(peer, PERF_CMD_SSIZE, peer->outbuf_size);
- atomic_inc(&pctx->dma_sync);
- dma_async_issue_pending(chan);
+ if (test_and_clear_bit(PERF_CMD_RSIZE, &peer->sts))
+ perf_setup_inbuf(peer);
- return size;
+ if (test_and_clear_bit(PERF_CMD_SXLAT, &peer->sts))
+ perf_cmd_send(peer, PERF_CMD_SXLAT, peer->inbuf_xlat);
-err_set_unmap:
- dmaengine_unmap_put(unmap);
-err_get_unmap:
- dmaengine_unmap_put(unmap);
- return 0;
-}
+ if (test_and_clear_bit(PERF_CMD_RXLAT, &peer->sts))
+ perf_setup_outbuf(peer);
-static int perf_move_data(struct pthr_ctx *pctx, char __iomem *dst, char *src,
- u64 buf_size, u64 win_size, u64 total)
-{
- int chunks, total_chunks, i;
- int copied_chunks = 0;
- u64 copied = 0, result;
- char __iomem *tmp = dst;
- u64 perf, diff_us;
- ktime_t kstart, kstop, kdiff;
- unsigned long last_sleep = jiffies;
-
- chunks = div64_u64(win_size, buf_size);
- total_chunks = div64_u64(total, buf_size);
- kstart = ktime_get();
-
- for (i = 0; i < total_chunks; i++) {
- result = perf_copy(pctx, tmp, src, buf_size);
- copied += result;
- copied_chunks++;
- if (copied_chunks == chunks) {
- tmp = dst;
- copied_chunks = 0;
- } else
- tmp += buf_size;
-
- /* Probably should schedule every 5s to prevent soft hang. */
- if (unlikely((jiffies - last_sleep) > 5 * HZ)) {
- last_sleep = jiffies;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ if (test_and_clear_bit(PERF_CMD_CLEAR, &peer->sts)) {
+ clear_bit(PERF_STS_DONE, &peer->sts);
+ if (test_bit(0, &peer->perf->busy_flag) &&
+ peer == peer->perf->test_peer) {
+ dev_warn(&peer->perf->ntb->dev,
+ "Freeing while test on-fly\n");
+ perf_terminate_test(peer->perf);
}
+ perf_free_outbuf(peer);
+ perf_free_inbuf(peer);
+ }
+}
+
+static int perf_init_service(struct perf_ctx *perf)
+{
+ u64 mask;
- if (unlikely(kthread_should_stop()))
- break;
+ if (ntb_peer_mw_count(perf->ntb) < perf->pcnt + 1) {
+ dev_err(&perf->ntb->dev, "Not enough memory windows\n");
+ return -EINVAL;
}
- if (use_dma) {
- pr_debug("%s: All DMA descriptors submitted\n", current->comm);
- while (atomic_read(&pctx->dma_sync) != 0) {
- if (kthread_should_stop())
- break;
- msleep(20);
- }
+ if (ntb_msg_count(perf->ntb) >= PERF_MSG_CNT) {
+ perf->cmd_send = perf_msg_cmd_send;
+ perf->cmd_recv = perf_msg_cmd_recv;
+
+ dev_dbg(&perf->ntb->dev, "Message service initialized\n");
+
+ return 0;
}
- kstop = ktime_get();
- kdiff = ktime_sub(kstop, kstart);
- diff_us = ktime_to_us(kdiff);
+ dev_dbg(&perf->ntb->dev, "Message service unsupported\n");
- pr_debug("%s: copied %llu bytes\n", current->comm, copied);
+ mask = GENMASK_ULL(perf->pcnt, 0);
+ if (ntb_spad_count(perf->ntb) >= PERF_SPAD_CNT(perf->pcnt) &&
+ (ntb_db_valid_mask(perf->ntb) & mask) == mask) {
+ perf->cmd_send = perf_spad_cmd_send;
+ perf->cmd_recv = perf_spad_cmd_recv;
- pr_debug("%s: lasted %llu usecs\n", current->comm, diff_us);
+ dev_dbg(&perf->ntb->dev, "Scratchpad service initialized\n");
- perf = div64_u64(copied, diff_us);
+ return 0;
+ }
- pr_debug("%s: MBytes/s: %llu\n", current->comm, perf);
+ dev_dbg(&perf->ntb->dev, "Scratchpad service unsupported\n");
- pctx->copied = copied;
- pctx->diff_us = diff_us;
+ dev_err(&perf->ntb->dev, "Command services unsupported\n");
- return 0;
+ return -EINVAL;
}
-static bool perf_dma_filter_fn(struct dma_chan *chan, void *node)
+static int perf_enable_service(struct perf_ctx *perf)
{
- /* Is the channel required to be on the same node as the device? */
- if (!on_node)
- return true;
+ u64 mask, incmd_bit;
+ int ret, sidx, scnt;
- return dev_to_node(&chan->dev->device) == (int)(unsigned long)node;
-}
+ mask = ntb_db_valid_mask(perf->ntb);
+ (void)ntb_db_set_mask(perf->ntb, mask);
-static int ntb_perf_thread(void *data)
-{
- struct pthr_ctx *pctx = data;
- struct perf_ctx *perf = pctx->perf;
- struct pci_dev *pdev = perf->ntb->pdev;
- struct perf_mw *mw = &perf->mw;
- char __iomem *dst;
- u64 win_size, buf_size, total;
- void *src;
- int rc, node, i;
- struct dma_chan *dma_chan = NULL;
+ ret = ntb_set_ctx(perf->ntb, perf, &perf_ops);
+ if (ret)
+ return ret;
- pr_debug("kthread %s starting...\n", current->comm);
+ if (perf->cmd_send == perf_msg_cmd_send) {
+ u64 inbits, outbits;
- node = on_node ? dev_to_node(&pdev->dev) : NUMA_NO_NODE;
+ inbits = ntb_msg_inbits(perf->ntb);
+ outbits = ntb_msg_outbits(perf->ntb);
+ (void)ntb_msg_set_mask(perf->ntb, inbits | outbits);
- if (use_dma && !pctx->dma_chan) {
- dma_cap_mask_t dma_mask;
+ incmd_bit = BIT_ULL(__ffs64(inbits));
+ ret = ntb_msg_clear_mask(perf->ntb, incmd_bit);
- dma_cap_zero(dma_mask);
- dma_cap_set(DMA_MEMCPY, dma_mask);
- dma_chan = dma_request_channel(dma_mask, perf_dma_filter_fn,
- (void *)(unsigned long)node);
- if (!dma_chan) {
- pr_warn("%s: cannot acquire DMA channel, quitting\n",
- current->comm);
- return -ENODEV;
- }
- pctx->dma_chan = dma_chan;
+ dev_dbg(&perf->ntb->dev, "MSG sts unmasked %#llx\n", incmd_bit);
+ } else {
+ scnt = ntb_spad_count(perf->ntb);
+ for (sidx = 0; sidx < scnt; sidx++)
+ ntb_spad_write(perf->ntb, sidx, PERF_CMD_INVAL);
+ incmd_bit = PERF_SPAD_NOTIFY(perf->gidx);
+ ret = ntb_db_clear_mask(perf->ntb, incmd_bit);
+
+ dev_dbg(&perf->ntb->dev, "DB bits unmasked %#llx\n", incmd_bit);
+ }
+ if (ret) {
+ ntb_clear_ctx(perf->ntb);
+ return ret;
}
- for (i = 0; i < MAX_SRCS; i++) {
- pctx->srcs[i] = kmalloc_node(MAX_TEST_SIZE, GFP_KERNEL, node);
- if (!pctx->srcs[i]) {
- rc = -ENOMEM;
- goto err;
- }
+ ntb_link_enable(perf->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
+ /* Might be not necessary */
+ ntb_link_event(perf->ntb);
+
+ return 0;
+}
+
+static void perf_disable_service(struct perf_ctx *perf)
+{
+ int pidx;
+
+ ntb_link_disable(perf->ntb);
+
+ if (perf->cmd_send == perf_msg_cmd_send) {
+ u64 inbits;
+
+ inbits = ntb_msg_inbits(perf->ntb);
+ (void)ntb_msg_set_mask(perf->ntb, inbits);
+ } else {
+ (void)ntb_db_set_mask(perf->ntb, PERF_SPAD_NOTIFY(perf->gidx));
}
- win_size = mw->phys_size;
- buf_size = 1ULL << seg_order;
- total = 1ULL << run_order;
+ ntb_clear_ctx(perf->ntb);
- if (buf_size > MAX_TEST_SIZE)
- buf_size = MAX_TEST_SIZE;
+ for (pidx = 0; pidx < perf->pcnt; pidx++)
+ perf_cmd_exec(&perf->peers[pidx], PERF_CMD_CLEAR);
- dst = (char __iomem *)mw->vbase;
+ for (pidx = 0; pidx < perf->pcnt; pidx++)
+ flush_work(&perf->peers[pidx].service);
+}
- atomic_inc(&perf->tsync);
- while (atomic_read(&perf->tsync) != perf->perf_threads)
- schedule();
+/*==============================================================================
+ * Performance measuring work-thread
+ *==============================================================================
+ */
- src = pctx->srcs[pctx->src_idx];
- pctx->src_idx = (pctx->src_idx + 1) & (MAX_SRCS - 1);
+static void perf_dma_copy_callback(void *data)
+{
+ struct perf_thread *pthr = data;
- rc = perf_move_data(pctx, dst, src, buf_size, win_size, total);
+ atomic_dec(&pthr->dma_sync);
+ wake_up(&pthr->dma_wait);
+}
- atomic_dec(&perf->tsync);
+static int perf_copy_chunk(struct perf_thread *pthr,
+ void __iomem *dst, void *src, size_t len)
+{
+ struct dma_async_tx_descriptor *tx;
+ struct dmaengine_unmap_data *unmap;
+ struct device *dma_dev;
+ int try = 0, ret = 0;
- if (rc < 0) {
- pr_err("%s: failed\n", current->comm);
- rc = -ENXIO;
- goto err;
+ if (!use_dma) {
+ memcpy_toio(dst, src, len);
+ goto ret_check_tsync;
}
- for (i = 0; i < MAX_SRCS; i++) {
- kfree(pctx->srcs[i]);
- pctx->srcs[i] = NULL;
+ dma_dev = pthr->dma_chan->device->dev;
+
+ if (!is_dma_copy_aligned(pthr->dma_chan->device, offset_in_page(src),
+ offset_in_page(dst), len))
+ return -EIO;
+
+ unmap = dmaengine_get_unmap_data(dma_dev, 2, GFP_NOWAIT);
+ if (!unmap)
+ return -ENOMEM;
+
+ unmap->len = len;
+ unmap->addr[0] = dma_map_page(dma_dev, virt_to_page(src),
+ offset_in_page(src), len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dma_dev, unmap->addr[0])) {
+ ret = -EIO;
+ goto err_free_resource;
}
+ unmap->to_cnt = 1;
- atomic_inc(&perf->tdone);
- wake_up(pctx->wq);
- rc = 0;
- goto done;
+ unmap->addr[1] = dma_map_page(dma_dev, virt_to_page(dst),
+ offset_in_page(dst), len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma_dev, unmap->addr[1])) {
+ ret = -EIO;
+ goto err_free_resource;
+ }
+ unmap->from_cnt = 1;
-err:
- for (i = 0; i < MAX_SRCS; i++) {
- kfree(pctx->srcs[i]);
- pctx->srcs[i] = NULL;
+ do {
+ tx = dmaengine_prep_dma_memcpy(pthr->dma_chan, unmap->addr[1],
+ unmap->addr[0], len, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx)
+ msleep(DMA_MDELAY);
+ } while (!tx && (try++ < DMA_TRIES));
+
+ if (!tx) {
+ ret = -EIO;
+ goto err_free_resource;
}
- if (dma_chan) {
- dma_release_channel(dma_chan);
- pctx->dma_chan = NULL;
+ tx->callback = perf_dma_copy_callback;
+ tx->callback_param = pthr;
+ dma_set_unmap(tx, unmap);
+
+ ret = dma_submit_error(dmaengine_submit(tx));
+ if (ret) {
+ dmaengine_unmap_put(unmap);
+ goto err_free_resource;
}
-done:
- /* Wait until we are told to stop */
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (kthread_should_stop())
- break;
- schedule();
+ dmaengine_unmap_put(unmap);
+
+ atomic_inc(&pthr->dma_sync);
+ dma_async_issue_pending(pthr->dma_chan);
+
+ret_check_tsync:
+ return likely(atomic_read(&pthr->perf->tsync) > 0) ? 0 : -EINTR;
+
+err_free_resource:
+ dmaengine_unmap_put(unmap);
+
+ return ret;
+}
+
+static bool perf_dma_filter(struct dma_chan *chan, void *data)
+{
+ struct perf_ctx *perf = data;
+ int node;
+
+ node = dev_to_node(&perf->ntb->dev);
+
+ return node == NUMA_NO_NODE || node == dev_to_node(chan->device->dev);
+}
+
+static int perf_init_test(struct perf_thread *pthr)
+{
+ struct perf_ctx *perf = pthr->perf;
+ dma_cap_mask_t dma_mask;
+
+ pthr->src = kmalloc_node(perf->test_peer->outbuf_size, GFP_KERNEL,
+ dev_to_node(&perf->ntb->dev));
+ if (!pthr->src)
+ return -ENOMEM;
+
+ get_random_bytes(pthr->src, perf->test_peer->outbuf_size);
+
+ if (!use_dma)
+ return 0;
+
+ dma_cap_zero(dma_mask);
+ dma_cap_set(DMA_MEMCPY, dma_mask);
+ pthr->dma_chan = dma_request_channel(dma_mask, perf_dma_filter, perf);
+ if (!pthr->dma_chan) {
+ dev_err(&perf->ntb->dev, "%d: Failed to get DMA channel\n",
+ pthr->tidx);
+ atomic_dec(&perf->tsync);
+ wake_up(&perf->twait);
+ kfree(pthr->src);
+ return -ENODEV;
}
- __set_current_state(TASK_RUNNING);
- return rc;
+ atomic_set(&pthr->dma_sync, 0);
+
+ return 0;
}
-static void perf_free_mw(struct perf_ctx *perf)
+static int perf_run_test(struct perf_thread *pthr)
{
- struct perf_mw *mw = &perf->mw;
- struct pci_dev *pdev = perf->ntb->pdev;
+ struct perf_peer *peer = pthr->perf->test_peer;
+ struct perf_ctx *perf = pthr->perf;
+ void __iomem *flt_dst, *bnd_dst;
+ u64 total_size, chunk_size;
+ void *flt_src;
+ int ret = 0;
+
+ total_size = 1ULL << total_order;
+ chunk_size = 1ULL << chunk_order;
+ chunk_size = min_t(u64, peer->outbuf_size, chunk_size);
+
+ flt_src = pthr->src;
+ bnd_dst = peer->outbuf + peer->outbuf_size;
+ flt_dst = peer->outbuf;
+
+ pthr->duration = ktime_get();
+
+ /* Copied field is cleared on test launch stage */
+ while (pthr->copied < total_size) {
+ ret = perf_copy_chunk(pthr, flt_dst, flt_src, chunk_size);
+ if (ret) {
+ dev_err(&perf->ntb->dev, "%d: Got error %d on test\n",
+ pthr->tidx, ret);
+ return ret;
+ }
- if (!mw->virt_addr)
- return;
+ pthr->copied += chunk_size;
+
+ flt_dst += chunk_size;
+ flt_src += chunk_size;
+ if (flt_dst >= bnd_dst || flt_dst < peer->outbuf) {
+ flt_dst = peer->outbuf;
+ flt_src = pthr->src;
+ }
- ntb_mw_clear_trans(perf->ntb, PIDX, 0);
- dma_free_coherent(&pdev->dev, mw->buf_size,
- mw->virt_addr, mw->dma_addr);
- mw->xlat_size = 0;
- mw->buf_size = 0;
- mw->virt_addr = NULL;
+ /* Give up CPU to give a chance for other threads to use it */
+ schedule();
+ }
+
+ return 0;
}
-static int perf_set_mw(struct perf_ctx *perf, resource_size_t size)
+static int perf_sync_test(struct perf_thread *pthr)
{
- struct perf_mw *mw = &perf->mw;
- size_t xlat_size, buf_size;
- resource_size_t xlat_align;
- resource_size_t xlat_align_size;
- int rc;
+ struct perf_ctx *perf = pthr->perf;
- if (!size)
- return -EINVAL;
+ if (!use_dma)
+ goto no_dma_ret;
- rc = ntb_mw_get_align(perf->ntb, PIDX, 0, &xlat_align,
- &xlat_align_size, NULL);
- if (rc)
- return rc;
+ wait_event(pthr->dma_wait,
+ (atomic_read(&pthr->dma_sync) == 0 ||
+ atomic_read(&perf->tsync) < 0));
- xlat_size = round_up(size, xlat_align_size);
- buf_size = round_up(size, xlat_align);
+ if (atomic_read(&perf->tsync) < 0)
+ return -EINTR;
- if (mw->xlat_size == xlat_size)
- return 0;
+no_dma_ret:
+ pthr->duration = ktime_sub(ktime_get(), pthr->duration);
- if (mw->buf_size)
- perf_free_mw(perf);
+ dev_dbg(&perf->ntb->dev, "%d: copied %llu bytes\n",
+ pthr->tidx, pthr->copied);
- mw->xlat_size = xlat_size;
- mw->buf_size = buf_size;
+ dev_dbg(&perf->ntb->dev, "%d: lasted %llu usecs\n",
+ pthr->tidx, ktime_to_us(pthr->duration));
+
+ dev_dbg(&perf->ntb->dev, "%d: %llu MBytes/s\n", pthr->tidx,
+ div64_u64(pthr->copied, ktime_to_us(pthr->duration)));
+
+ return 0;
+}
+
+static void perf_clear_test(struct perf_thread *pthr)
+{
+ struct perf_ctx *perf = pthr->perf;
+
+ if (!use_dma)
+ goto no_dma_notify;
+
+ /*
+ * If test finished without errors, termination isn't needed.
+ * We call it anyway just to be sure of the transfers completion.
+ */
+ (void)dmaengine_terminate_sync(pthr->dma_chan);
+
+ dma_release_channel(pthr->dma_chan);
+
+no_dma_notify:
+ atomic_dec(&perf->tsync);
+ wake_up(&perf->twait);
+ kfree(pthr->src);
+}
- mw->virt_addr = dma_alloc_coherent(&perf->ntb->pdev->dev, buf_size,
- &mw->dma_addr, GFP_KERNEL);
- if (!mw->virt_addr) {
- mw->xlat_size = 0;
- mw->buf_size = 0;
+static void perf_thread_work(struct work_struct *work)
+{
+ struct perf_thread *pthr = to_thread_work(work);
+ int ret;
+
+ /*
+ * Perform stages in compliance with use_dma flag value.
+ * Test status is changed only if error happened, otherwise
+ * status -ENODATA is kept while test is on-fly. Results
+ * synchronization is performed only if test fininshed
+ * without an error or interruption.
+ */
+ ret = perf_init_test(pthr);
+ if (ret) {
+ pthr->status = ret;
+ return;
}
- rc = ntb_mw_set_trans(perf->ntb, PIDX, 0, mw->dma_addr, mw->xlat_size);
- if (rc) {
- dev_err(&perf->ntb->dev, "Unable to set mw0 translation\n");
- perf_free_mw(perf);
- return -EIO;
+ ret = perf_run_test(pthr);
+ if (ret) {
+ pthr->status = ret;
+ goto err_clear_test;
}
- return 0;
+ pthr->status = perf_sync_test(pthr);
+
+err_clear_test:
+ perf_clear_test(pthr);
}
-static void perf_link_work(struct work_struct *work)
+static int perf_set_tcnt(struct perf_ctx *perf, u8 tcnt)
{
- struct perf_ctx *perf =
- container_of(work, struct perf_ctx, link_work.work);
- struct ntb_dev *ndev = perf->ntb;
- struct pci_dev *pdev = ndev->pdev;
- u32 val;
- u64 size;
- int rc;
+ if (tcnt == 0 || tcnt > MAX_THREADS_CNT)
+ return -EINVAL;
- dev_dbg(&perf->ntb->pdev->dev, "%s called\n", __func__);
+ if (test_and_set_bit_lock(0, &perf->busy_flag))
+ return -EBUSY;
+
+ perf->tcnt = tcnt;
+
+ clear_bit_unlock(0, &perf->busy_flag);
- size = perf->mw.phys_size;
+ return 0;
+}
- if (max_mw_size && size > max_mw_size)
- size = max_mw_size;
+static void perf_terminate_test(struct perf_ctx *perf)
+{
+ int tidx;
- ntb_peer_spad_write(ndev, PIDX, MW_SZ_HIGH, upper_32_bits(size));
- ntb_peer_spad_write(ndev, PIDX, MW_SZ_LOW, lower_32_bits(size));
- ntb_peer_spad_write(ndev, PIDX, VERSION, PERF_VERSION);
+ atomic_set(&perf->tsync, -1);
+ wake_up(&perf->twait);
- /* now read what peer wrote */
- val = ntb_spad_read(ndev, VERSION);
- if (val != PERF_VERSION) {
- dev_dbg(&pdev->dev, "Remote version = %#x\n", val);
- goto out;
+ for (tidx = 0; tidx < MAX_THREADS_CNT; tidx++) {
+ wake_up(&perf->threads[tidx].dma_wait);
+ cancel_work_sync(&perf->threads[tidx].work);
}
+}
+
+static int perf_submit_test(struct perf_peer *peer)
+{
+ struct perf_ctx *perf = peer->perf;
+ struct perf_thread *pthr;
+ int tidx, ret;
- val = ntb_spad_read(ndev, MW_SZ_HIGH);
- size = (u64)val << 32;
+ if (!test_bit(PERF_STS_DONE, &peer->sts))
+ return -ENOLINK;
- val = ntb_spad_read(ndev, MW_SZ_LOW);
- size |= val;
+ if (test_and_set_bit_lock(0, &perf->busy_flag))
+ return -EBUSY;
- dev_dbg(&pdev->dev, "Remote MW size = %#llx\n", size);
+ perf->test_peer = peer;
+ atomic_set(&perf->tsync, perf->tcnt);
- rc = perf_set_mw(perf, size);
- if (rc)
- goto out1;
+ for (tidx = 0; tidx < MAX_THREADS_CNT; tidx++) {
+ pthr = &perf->threads[tidx];
- perf->link_is_up = true;
- wake_up(&perf->link_wq);
+ pthr->status = -ENODATA;
+ pthr->copied = 0;
+ pthr->duration = ktime_set(0, 0);
+ if (tidx < perf->tcnt)
+ (void)queue_work(perf_wq, &pthr->work);
+ }
- return;
+ ret = wait_event_interruptible(perf->twait,
+ atomic_read(&perf->tsync) <= 0);
+ if (ret == -ERESTARTSYS) {
+ perf_terminate_test(perf);
+ ret = -EINTR;
+ }
-out1:
- perf_free_mw(perf);
+ clear_bit_unlock(0, &perf->busy_flag);
-out:
- if (ntb_link_is_up(ndev, NULL, NULL) == 1)
- schedule_delayed_work(&perf->link_work,
- msecs_to_jiffies(PERF_LINK_DOWN_TIMEOUT));
+ return ret;
}
-static int perf_setup_mw(struct ntb_dev *ntb, struct perf_ctx *perf)
+static int perf_read_stats(struct perf_ctx *perf, char *buf,
+ size_t size, ssize_t *pos)
{
- struct perf_mw *mw;
- int rc;
+ struct perf_thread *pthr;
+ int tidx;
+
+ if (test_and_set_bit_lock(0, &perf->busy_flag))
+ return -EBUSY;
- mw = &perf->mw;
+ (*pos) += scnprintf(buf + *pos, size - *pos,
+ " Peer %d test statistics:\n", perf->test_peer->pidx);
- rc = ntb_peer_mw_get_addr(ntb, 0, &mw->phys_addr, &mw->phys_size);
- if (rc)
- return rc;
+ for (tidx = 0; tidx < MAX_THREADS_CNT; tidx++) {
+ pthr = &perf->threads[tidx];
- perf->mw.vbase = ioremap_wc(mw->phys_addr, mw->phys_size);
- if (!mw->vbase)
- return -ENOMEM;
+ if (pthr->status == -ENODATA)
+ continue;
+
+ if (pthr->status) {
+ (*pos) += scnprintf(buf + *pos, size - *pos,
+ "%d: error status %d\n", tidx, pthr->status);
+ continue;
+ }
+
+ (*pos) += scnprintf(buf + *pos, size - *pos,
+ "%d: copied %llu bytes in %llu usecs, %llu MBytes/s\n",
+ tidx, pthr->copied, ktime_to_us(pthr->duration),
+ div64_u64(pthr->copied, ktime_to_us(pthr->duration)));
+ }
+
+ clear_bit_unlock(0, &perf->busy_flag);
return 0;
}
-static ssize_t debugfs_run_read(struct file *filp, char __user *ubuf,
- size_t count, loff_t *offp)
+static void perf_init_threads(struct perf_ctx *perf)
{
- struct perf_ctx *perf = filp->private_data;
+ struct perf_thread *pthr;
+ int tidx;
+
+ perf->tcnt = DEF_THREADS_CNT;
+ perf->test_peer = &perf->peers[0];
+ init_waitqueue_head(&perf->twait);
+
+ for (tidx = 0; tidx < MAX_THREADS_CNT; tidx++) {
+ pthr = &perf->threads[tidx];
+
+ pthr->perf = perf;
+ pthr->tidx = tidx;
+ pthr->status = -ENODATA;
+ init_waitqueue_head(&pthr->dma_wait);
+ INIT_WORK(&pthr->work, perf_thread_work);
+ }
+}
+
+static void perf_clear_threads(struct perf_ctx *perf)
+{
+ perf_terminate_test(perf);
+}
+
+/*==============================================================================
+ * DebugFS nodes
+ *==============================================================================
+ */
+
+static ssize_t perf_dbgfs_read_info(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct perf_ctx *perf = filep->private_data;
+ struct perf_peer *peer;
+ size_t buf_size;
+ ssize_t pos = 0;
+ int ret, pidx;
char *buf;
- ssize_t ret, out_off = 0;
- struct pthr_ctx *pctx;
- int i;
- u64 rate;
- if (!perf)
- return 0;
+ buf_size = min_t(size_t, size, 0x1000U);
- buf = kmalloc(1024, GFP_KERNEL);
+ buf = kmalloc(buf_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- if (mutex_is_locked(&perf->run_mutex)) {
- out_off = scnprintf(buf, 64, "running\n");
- goto read_from_buf;
+ pos += scnprintf(buf + pos, buf_size - pos,
+ " Performance measuring tool info:\n\n");
+
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "Local port %d, Global index %d\n", ntb_port_number(perf->ntb),
+ perf->gidx);
+ pos += scnprintf(buf + pos, buf_size - pos, "Test status: ");
+ if (test_bit(0, &perf->busy_flag)) {
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "on-fly with port %d (%d)\n",
+ ntb_peer_port_number(perf->ntb, perf->test_peer->pidx),
+ perf->test_peer->pidx);
+ } else {
+ pos += scnprintf(buf + pos, buf_size - pos, "idle\n");
}
- for (i = 0; i < MAX_THREADS; i++) {
- pctx = &perf->pthr_ctx[i];
+ for (pidx = 0; pidx < perf->pcnt; pidx++) {
+ peer = &perf->peers[pidx];
+
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "Port %d (%d), Global index %d:\n",
+ ntb_peer_port_number(perf->ntb, peer->pidx), peer->pidx,
+ peer->gidx);
+
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tLink status: %s\n",
+ test_bit(PERF_STS_LNKUP, &peer->sts) ? "up" : "down");
+
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tOut buffer addr 0x%pK\n", peer->outbuf);
- if (pctx->status == -ENODATA)
- break;
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tOut buffer size %pa\n", &peer->outbuf_size);
- if (pctx->status) {
- out_off += scnprintf(buf + out_off, 1024 - out_off,
- "%d: error %d\n", i,
- pctx->status);
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tOut buffer xlat 0x%016llx[p]\n", peer->outbuf_xlat);
+
+ if (!peer->inbuf) {
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tIn buffer addr: unallocated\n");
continue;
}
- rate = div64_u64(pctx->copied, pctx->diff_us);
- out_off += scnprintf(buf + out_off, 1024 - out_off,
- "%d: copied %llu bytes in %llu usecs, %llu MBytes/s\n",
- i, pctx->copied, pctx->diff_us, rate);
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tIn buffer addr 0x%pK\n", peer->inbuf);
+
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tIn buffer size %pa\n", &peer->inbuf_size);
+
+ pos += scnprintf(buf + pos, buf_size - pos,
+ "\tIn buffer xlat %pad[p]\n", &peer->inbuf_xlat);
}
-read_from_buf:
- ret = simple_read_from_buffer(ubuf, count, offp, buf, out_off);
+ ret = simple_read_from_buffer(ubuf, size, offp, buf, pos);
kfree(buf);
return ret;
}
-static void threads_cleanup(struct perf_ctx *perf)
+static const struct file_operations perf_dbgfs_info = {
+ .open = simple_open,
+ .read = perf_dbgfs_read_info
+};
+
+static ssize_t perf_dbgfs_read_run(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct pthr_ctx *pctx;
- int i;
+ struct perf_ctx *perf = filep->private_data;
+ ssize_t ret, pos = 0;
+ char *buf;
- for (i = 0; i < MAX_THREADS; i++) {
- pctx = &perf->pthr_ctx[i];
- if (pctx->thread) {
- pctx->status = kthread_stop(pctx->thread);
- pctx->thread = NULL;
- }
- }
-}
+ buf = kmalloc(PERF_BUF_LEN, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
-static void perf_clear_thread_status(struct perf_ctx *perf)
-{
- int i;
+ ret = perf_read_stats(perf, buf, PERF_BUF_LEN, &pos);
+ if (ret)
+ goto err_free;
+
+ ret = simple_read_from_buffer(ubuf, size, offp, buf, pos);
+err_free:
+ kfree(buf);
- for (i = 0; i < MAX_THREADS; i++)
- perf->pthr_ctx[i].status = -ENODATA;
+ return ret;
}
-static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf,
- size_t count, loff_t *offp)
+static ssize_t perf_dbgfs_write_run(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct perf_ctx *perf = filp->private_data;
- int node, i;
- DECLARE_WAIT_QUEUE_HEAD(wq);
+ struct perf_ctx *perf = filep->private_data;
+ struct perf_peer *peer;
+ int pidx, ret;
- if (wait_event_interruptible(perf->link_wq, perf->link_is_up))
- return -ENOLINK;
+ ret = kstrtoint_from_user(ubuf, size, 0, &pidx);
+ if (ret)
+ return ret;
- if (perf->perf_threads == 0)
+ if (pidx < 0 || pidx >= perf->pcnt)
return -EINVAL;
- if (!mutex_trylock(&perf->run_mutex))
- return -EBUSY;
+ peer = &perf->peers[pidx];
- perf_clear_thread_status(perf);
+ ret = perf_submit_test(peer);
+ if (ret)
+ return ret;
- if (perf->perf_threads > MAX_THREADS) {
- perf->perf_threads = MAX_THREADS;
- pr_info("Reset total threads to: %u\n", MAX_THREADS);
- }
+ return size;
+}
- /* no greater than 1M */
- if (seg_order > MAX_SEG_ORDER) {
- seg_order = MAX_SEG_ORDER;
- pr_info("Fix seg_order to %u\n", seg_order);
- }
+static const struct file_operations perf_dbgfs_run = {
+ .open = simple_open,
+ .read = perf_dbgfs_read_run,
+ .write = perf_dbgfs_write_run
+};
- if (run_order < seg_order) {
- run_order = seg_order;
- pr_info("Fix run_order to %u\n", run_order);
- }
+static ssize_t perf_dbgfs_read_tcnt(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct perf_ctx *perf = filep->private_data;
+ char buf[8];
+ ssize_t pos;
- node = on_node ? dev_to_node(&perf->ntb->pdev->dev)
- : NUMA_NO_NODE;
- atomic_set(&perf->tdone, 0);
+ pos = scnprintf(buf, sizeof(buf), "%hhu\n", perf->tcnt);
- /* launch kernel thread */
- for (i = 0; i < perf->perf_threads; i++) {
- struct pthr_ctx *pctx;
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
+}
- pctx = &perf->pthr_ctx[i];
- atomic_set(&pctx->dma_sync, 0);
- pctx->perf = perf;
- pctx->wq = &wq;
- pctx->thread =
- kthread_create_on_node(ntb_perf_thread,
- (void *)pctx,
- node, "ntb_perf %d", i);
- if (IS_ERR(pctx->thread)) {
- pctx->thread = NULL;
- goto err;
- } else {
- wake_up_process(pctx->thread);
- }
- }
+static ssize_t perf_dbgfs_write_tcnt(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct perf_ctx *perf = filep->private_data;
+ int ret;
+ u8 val;
- wait_event_interruptible(wq,
- atomic_read(&perf->tdone) == perf->perf_threads);
+ ret = kstrtou8_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
- threads_cleanup(perf);
- mutex_unlock(&perf->run_mutex);
- return count;
+ ret = perf_set_tcnt(perf, val);
+ if (ret)
+ return ret;
-err:
- threads_cleanup(perf);
- mutex_unlock(&perf->run_mutex);
- return -ENXIO;
+ return size;
}
-static const struct file_operations ntb_perf_debugfs_run = {
- .owner = THIS_MODULE,
+static const struct file_operations perf_dbgfs_tcnt = {
.open = simple_open,
- .read = debugfs_run_read,
- .write = debugfs_run_write,
+ .read = perf_dbgfs_read_tcnt,
+ .write = perf_dbgfs_write_tcnt
};
-static int perf_debugfs_setup(struct perf_ctx *perf)
+static void perf_setup_dbgfs(struct perf_ctx *perf)
{
struct pci_dev *pdev = perf->ntb->pdev;
- struct dentry *debugfs_node_dir;
- struct dentry *debugfs_run;
- struct dentry *debugfs_threads;
- struct dentry *debugfs_seg_order;
- struct dentry *debugfs_run_order;
- struct dentry *debugfs_use_dma;
- struct dentry *debugfs_on_node;
-
- if (!debugfs_initialized())
- return -ENODEV;
- /* Assumpion: only one NTB device in the system */
- if (!perf_debugfs_dir) {
- perf_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!perf_debugfs_dir)
- return -ENODEV;
- }
-
- debugfs_node_dir = debugfs_create_dir(pci_name(pdev),
- perf_debugfs_dir);
- if (!debugfs_node_dir)
- goto err;
-
- debugfs_run = debugfs_create_file("run", S_IRUSR | S_IWUSR,
- debugfs_node_dir, perf,
- &ntb_perf_debugfs_run);
- if (!debugfs_run)
- goto err;
-
- debugfs_threads = debugfs_create_u8("threads", S_IRUSR | S_IWUSR,
- debugfs_node_dir,
- &perf->perf_threads);
- if (!debugfs_threads)
- goto err;
-
- debugfs_seg_order = debugfs_create_u32("seg_order", 0600,
- debugfs_node_dir,
- &seg_order);
- if (!debugfs_seg_order)
- goto err;
-
- debugfs_run_order = debugfs_create_u32("run_order", 0600,
- debugfs_node_dir,
- &run_order);
- if (!debugfs_run_order)
- goto err;
-
- debugfs_use_dma = debugfs_create_bool("use_dma", 0600,
- debugfs_node_dir,
- &use_dma);
- if (!debugfs_use_dma)
- goto err;
-
- debugfs_on_node = debugfs_create_bool("on_node", 0600,
- debugfs_node_dir,
- &on_node);
- if (!debugfs_on_node)
- goto err;
+ perf->dbgfs_dir = debugfs_create_dir(pci_name(pdev), perf_dbgfs_topdir);
+ if (!perf->dbgfs_dir) {
+ dev_warn(&perf->ntb->dev, "DebugFS unsupported\n");
+ return;
+ }
+
+ debugfs_create_file("info", 0600, perf->dbgfs_dir, perf,
+ &perf_dbgfs_info);
- return 0;
+ debugfs_create_file("run", 0600, perf->dbgfs_dir, perf,
+ &perf_dbgfs_run);
-err:
- debugfs_remove_recursive(perf_debugfs_dir);
- perf_debugfs_dir = NULL;
- return -ENODEV;
+ debugfs_create_file("threads_count", 0600, perf->dbgfs_dir, perf,
+ &perf_dbgfs_tcnt);
+
+ /* They are made read-only for test exec safety and integrity */
+ debugfs_create_u8("chunk_order", 0500, perf->dbgfs_dir, &chunk_order);
+
+ debugfs_create_u8("total_order", 0500, perf->dbgfs_dir, &total_order);
+
+ debugfs_create_bool("use_dma", 0500, perf->dbgfs_dir, &use_dma);
}
-static int perf_probe(struct ntb_client *client, struct ntb_dev *ntb)
+static void perf_clear_dbgfs(struct perf_ctx *perf)
+{
+ debugfs_remove_recursive(perf->dbgfs_dir);
+}
+
+/*==============================================================================
+ * Basic driver initialization
+ *==============================================================================
+ */
+
+static struct perf_ctx *perf_create_data(struct ntb_dev *ntb)
{
- struct pci_dev *pdev = ntb->pdev;
struct perf_ctx *perf;
- int node;
- int rc = 0;
- if (ntb_spad_count(ntb) < MAX_SPAD) {
- dev_err(&ntb->dev, "Not enough scratch pad registers for %s",
- DRIVER_NAME);
- return -EIO;
- }
+ perf = devm_kzalloc(&ntb->dev, sizeof(*perf), GFP_KERNEL);
+ if (!perf)
+ return ERR_PTR(-ENOMEM);
- if (!ntb->ops->mw_set_trans) {
- dev_err(&ntb->dev, "Need inbound MW based NTB API\n");
- return -EINVAL;
+ perf->pcnt = ntb_peer_port_count(ntb);
+ perf->peers = devm_kcalloc(&ntb->dev, perf->pcnt, sizeof(*perf->peers),
+ GFP_KERNEL);
+ if (!perf->peers)
+ return ERR_PTR(-ENOMEM);
+
+ perf->ntb = ntb;
+
+ return perf;
+}
+
+static int perf_setup_peer_mw(struct perf_peer *peer)
+{
+ struct perf_ctx *perf = peer->perf;
+ phys_addr_t phys_addr;
+ int ret;
+
+ /* Get outbound MW parameters and map it */
+ ret = ntb_peer_mw_get_addr(perf->ntb, peer->gidx, &phys_addr,
+ &peer->outbuf_size);
+ if (ret)
+ return ret;
+
+ peer->outbuf = devm_ioremap_wc(&perf->ntb->dev, phys_addr,
+ peer->outbuf_size);
+ if (!peer->outbuf)
+ return -ENOMEM;
+
+ if (max_mw_size && peer->outbuf_size > max_mw_size) {
+ peer->outbuf_size = max_mw_size;
+ dev_warn(&peer->perf->ntb->dev,
+ "Peer %d outbuf reduced to %pa\n", peer->pidx,
+ &peer->outbuf_size);
}
- if (ntb_peer_port_count(ntb) != NTB_DEF_PEER_CNT)
- dev_warn(&ntb->dev, "Multi-port NTB devices unsupported\n");
+ return 0;
+}
- node = on_node ? dev_to_node(&pdev->dev) : NUMA_NO_NODE;
- perf = kzalloc_node(sizeof(*perf), GFP_KERNEL, node);
- if (!perf) {
- rc = -ENOMEM;
- goto err_perf;
+static int perf_init_peers(struct perf_ctx *perf)
+{
+ struct perf_peer *peer;
+ int pidx, lport, ret;
+
+ lport = ntb_port_number(perf->ntb);
+ perf->gidx = -1;
+ for (pidx = 0; pidx < perf->pcnt; pidx++) {
+ peer = &perf->peers[pidx];
+
+ peer->perf = perf;
+ peer->pidx = pidx;
+ if (lport < ntb_peer_port_number(perf->ntb, pidx)) {
+ if (perf->gidx == -1)
+ perf->gidx = pidx;
+ peer->gidx = pidx + 1;
+ } else {
+ peer->gidx = pidx;
+ }
+ INIT_WORK(&peer->service, perf_service_work);
}
+ if (perf->gidx == -1)
+ perf->gidx = pidx;
- perf->ntb = ntb;
- perf->perf_threads = 1;
- atomic_set(&perf->tsync, 0);
- mutex_init(&perf->run_mutex);
- spin_lock_init(&perf->db_lock);
- perf_setup_mw(ntb, perf);
- init_waitqueue_head(&perf->link_wq);
- INIT_DELAYED_WORK(&perf->link_work, perf_link_work);
+ for (pidx = 0; pidx < perf->pcnt; pidx++) {
+ ret = perf_setup_peer_mw(&perf->peers[pidx]);
+ if (ret)
+ return ret;
+ }
+
+ dev_dbg(&perf->ntb->dev, "Global port index %d\n", perf->gidx);
+
+ return 0;
+}
- rc = ntb_set_ctx(ntb, perf, &perf_ops);
- if (rc)
- goto err_ctx;
+static int perf_probe(struct ntb_client *client, struct ntb_dev *ntb)
+{
+ struct perf_ctx *perf;
+ int ret;
- perf->link_is_up = false;
- ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
- ntb_link_event(ntb);
+ perf = perf_create_data(ntb);
+ if (IS_ERR(perf))
+ return PTR_ERR(perf);
- rc = perf_debugfs_setup(perf);
- if (rc)
- goto err_ctx;
+ ret = perf_init_peers(perf);
+ if (ret)
+ return ret;
- perf_clear_thread_status(perf);
+ perf_init_threads(perf);
- return 0;
+ ret = perf_init_service(perf);
+ if (ret)
+ return ret;
-err_ctx:
- cancel_delayed_work_sync(&perf->link_work);
- kfree(perf);
-err_perf:
- return rc;
+ ret = perf_enable_service(perf);
+ if (ret)
+ return ret;
+
+ perf_setup_dbgfs(perf);
+
+ return 0;
}
static void perf_remove(struct ntb_client *client, struct ntb_dev *ntb)
{
struct perf_ctx *perf = ntb->ctx;
- int i;
- dev_dbg(&perf->ntb->dev, "%s called\n", __func__);
+ perf_clear_dbgfs(perf);
- mutex_lock(&perf->run_mutex);
+ perf_disable_service(perf);
- cancel_delayed_work_sync(&perf->link_work);
+ perf_clear_threads(perf);
+}
- ntb_clear_ctx(ntb);
- ntb_link_disable(ntb);
+static struct ntb_client perf_client = {
+ .ops = {
+ .probe = perf_probe,
+ .remove = perf_remove
+ }
+};
- debugfs_remove_recursive(perf_debugfs_dir);
- perf_debugfs_dir = NULL;
+static int __init perf_init(void)
+{
+ int ret;
- if (use_dma) {
- for (i = 0; i < MAX_THREADS; i++) {
- struct pthr_ctx *pctx = &perf->pthr_ctx[i];
+ if (chunk_order > MAX_CHUNK_ORDER) {
+ chunk_order = MAX_CHUNK_ORDER;
+ pr_info("Chunk order reduced to %hhu\n", chunk_order);
+ }
- if (pctx->dma_chan)
- dma_release_channel(pctx->dma_chan);
- }
+ if (total_order < chunk_order) {
+ total_order = chunk_order;
+ pr_info("Total data order reduced to %hhu\n", total_order);
}
- kfree(perf);
+ perf_wq = alloc_workqueue("perf_wq", WQ_UNBOUND | WQ_SYSFS, 0);
+ if (!perf_wq)
+ return -ENOMEM;
+
+ if (debugfs_initialized())
+ perf_dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+ ret = ntb_register_client(&perf_client);
+ if (ret) {
+ debugfs_remove_recursive(perf_dbgfs_topdir);
+ destroy_workqueue(perf_wq);
+ }
+
+ return ret;
}
+module_init(perf_init);
+
+static void __exit perf_exit(void)
+{
+ ntb_unregister_client(&perf_client);
+ debugfs_remove_recursive(perf_dbgfs_topdir);
+ destroy_workqueue(perf_wq);
+}
+module_exit(perf_exit);
-static struct ntb_client perf_client = {
- .ops = {
- .probe = perf_probe,
- .remove = perf_remove,
- },
-};
-module_ntb_client(perf_client);
diff --git a/drivers/ntb/test/ntb_pingpong.c b/drivers/ntb/test/ntb_pingpong.c
index 3f5a92bae6f8..65865e460ab8 100644
--- a/drivers/ntb/test/ntb_pingpong.c
+++ b/drivers/ntb/test/ntb_pingpong.c
@@ -1,10 +1,11 @@
/*
- * This file is provided under a dual BSD/GPLv2 license. When using or
+ * This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright (C) 2015 EMC Corporation. All Rights Reserved.
+ * Copyright (C) 2017 T-Platforms. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -18,6 +19,7 @@
* BSD LICENSE
*
* Copyright (C) 2015 EMC Corporation. All Rights Reserved.
+ * Copyright (C) 2017 T-Platforms. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,37 +48,45 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* PCIe NTB Pingpong Linux driver
- *
- * Contact Information:
- * Allen Hubbe <Allen.Hubbe@emc.com>
*/
-/* Note: load this module with option 'dyndbg=+p' */
+/*
+ * How to use this tool, by example.
+ *
+ * Assuming $DBG_DIR is something like:
+ * '/sys/kernel/debug/ntb_perf/0000:00:03.0'
+ * Suppose aside from local device there is at least one remote device
+ * connected to NTB with index 0.
+ *-----------------------------------------------------------------------------
+ * Eg: install driver with specified delay between doorbell event and response
+ *
+ * root@self# insmod ntb_pingpong.ko delay_ms=1000
+ *-----------------------------------------------------------------------------
+ * Eg: get number of ping-pong cycles performed
+ *
+ * root@self# cat $DBG_DIR/count
+ */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
-#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
#include <linux/debugfs.h>
#include <linux/ntb.h>
-#define DRIVER_NAME "ntb_pingpong"
-#define DRIVER_DESCRIPTION "PCIe NTB Simple Pingpong Client"
-
-#define DRIVER_LICENSE "Dual BSD/GPL"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_RELDATE "24 March 2015"
-#define DRIVER_AUTHOR "Allen Hubbe <Allen.Hubbe@emc.com>"
+#define DRIVER_NAME "ntb_pingpong"
+#define DRIVER_VERSION "2.0"
-MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+MODULE_AUTHOR("Allen Hubbe <Allen.Hubbe@emc.com>");
+MODULE_DESCRIPTION("PCIe NTB Simple Pingpong Client");
static unsigned int unsafe;
module_param(unsafe, uint, 0644);
@@ -86,237 +96,343 @@ static unsigned int delay_ms = 1000;
module_param(delay_ms, uint, 0644);
MODULE_PARM_DESC(delay_ms, "Milliseconds to delay the response to peer");
-static unsigned long db_init = 0x7;
-module_param(db_init, ulong, 0644);
-MODULE_PARM_DESC(db_init, "Initial doorbell bits to ring on the peer");
-
-/* Only two-ports NTB devices are supported */
-#define PIDX NTB_DEF_PEER_IDX
-
struct pp_ctx {
- struct ntb_dev *ntb;
- u64 db_bits;
- /* synchronize access to db_bits by ping and pong */
- spinlock_t db_lock;
- struct timer_list db_timer;
- unsigned long db_delay;
- struct dentry *debugfs_node_dir;
- struct dentry *debugfs_count;
- atomic_t count;
+ struct ntb_dev *ntb;
+ struct hrtimer timer;
+ u64 in_db;
+ u64 out_db;
+ int out_pidx;
+ u64 nmask;
+ u64 pmask;
+ atomic_t count;
+ spinlock_t lock;
+ struct dentry *dbgfs_dir;
};
+#define to_pp_timer(__timer) \
+ container_of(__timer, struct pp_ctx, timer)
-static struct dentry *pp_debugfs_dir;
+static struct dentry *pp_dbgfs_topdir;
-static void pp_ping(struct timer_list *t)
+static int pp_find_next_peer(struct pp_ctx *pp)
{
- struct pp_ctx *pp = from_timer(pp, t, db_timer);
- unsigned long irqflags;
- u64 db_bits, db_mask;
- u32 spad_rd, spad_wr;
+ u64 link, out_db;
+ int pidx;
+
+ link = ntb_link_is_up(pp->ntb, NULL, NULL);
+
+ /* Find next available peer */
+ if (link & pp->nmask) {
+ pidx = __ffs64(link & pp->nmask);
+ out_db = BIT_ULL(pidx + 1);
+ } else if (link & pp->pmask) {
+ pidx = __ffs64(link & pp->pmask);
+ out_db = BIT_ULL(pidx);
+ } else {
+ return -ENODEV;
+ }
- spin_lock_irqsave(&pp->db_lock, irqflags);
- {
- db_mask = ntb_db_valid_mask(pp->ntb);
- db_bits = ntb_db_read(pp->ntb);
+ spin_lock(&pp->lock);
+ pp->out_pidx = pidx;
+ pp->out_db = out_db;
+ spin_unlock(&pp->lock);
- if (db_bits) {
- dev_dbg(&pp->ntb->dev,
- "Masked pongs %#llx\n",
- db_bits);
- ntb_db_clear(pp->ntb, db_bits);
- }
+ return 0;
+}
- db_bits = ((pp->db_bits | db_bits) << 1) & db_mask;
+static void pp_setup(struct pp_ctx *pp)
+{
+ int ret;
- if (!db_bits)
- db_bits = db_init;
+ ntb_db_set_mask(pp->ntb, pp->in_db);
- spad_rd = ntb_spad_read(pp->ntb, 0);
- spad_wr = spad_rd + 1;
+ hrtimer_cancel(&pp->timer);
- dev_dbg(&pp->ntb->dev,
- "Ping bits %#llx read %#x write %#x\n",
- db_bits, spad_rd, spad_wr);
+ ret = pp_find_next_peer(pp);
+ if (ret == -ENODEV) {
+ dev_dbg(&pp->ntb->dev, "Got no peers, so cancel\n");
+ return;
+ }
- ntb_peer_spad_write(pp->ntb, PIDX, 0, spad_wr);
- ntb_peer_db_set(pp->ntb, db_bits);
- ntb_db_clear_mask(pp->ntb, db_mask);
+ dev_dbg(&pp->ntb->dev, "Ping-pong started with port %d, db %#llx\n",
+ ntb_peer_port_number(pp->ntb, pp->out_pidx), pp->out_db);
- pp->db_bits = 0;
- }
- spin_unlock_irqrestore(&pp->db_lock, irqflags);
+ hrtimer_start(&pp->timer, ms_to_ktime(delay_ms), HRTIMER_MODE_REL);
}
-static void pp_link_event(void *ctx)
+static void pp_clear(struct pp_ctx *pp)
{
- struct pp_ctx *pp = ctx;
+ hrtimer_cancel(&pp->timer);
- if (ntb_link_is_up(pp->ntb, NULL, NULL) == 1) {
- dev_dbg(&pp->ntb->dev, "link is up\n");
- pp_ping(&pp->db_timer);
- } else {
- dev_dbg(&pp->ntb->dev, "link is down\n");
- del_timer(&pp->db_timer);
- }
+ ntb_db_set_mask(pp->ntb, pp->in_db);
+
+ dev_dbg(&pp->ntb->dev, "Ping-pong cancelled\n");
}
-static void pp_db_event(void *ctx, int vec)
+static void pp_ping(struct pp_ctx *pp)
{
- struct pp_ctx *pp = ctx;
- u64 db_bits, db_mask;
- unsigned long irqflags;
+ u32 count;
- spin_lock_irqsave(&pp->db_lock, irqflags);
- {
- db_mask = ntb_db_vector_mask(pp->ntb, vec);
- db_bits = db_mask & ntb_db_read(pp->ntb);
- ntb_db_set_mask(pp->ntb, db_mask);
- ntb_db_clear(pp->ntb, db_bits);
+ count = atomic_read(&pp->count);
- pp->db_bits |= db_bits;
+ spin_lock(&pp->lock);
+ ntb_peer_spad_write(pp->ntb, pp->out_pidx, 0, count);
+ ntb_peer_msg_write(pp->ntb, pp->out_pidx, 0, count);
- mod_timer(&pp->db_timer, jiffies + pp->db_delay);
+ dev_dbg(&pp->ntb->dev, "Ping port %d spad %#x, msg %#x\n",
+ ntb_peer_port_number(pp->ntb, pp->out_pidx), count, count);
- dev_dbg(&pp->ntb->dev,
- "Pong vec %d bits %#llx\n",
- vec, db_bits);
- atomic_inc(&pp->count);
- }
- spin_unlock_irqrestore(&pp->db_lock, irqflags);
+ ntb_peer_db_set(pp->ntb, pp->out_db);
+ ntb_db_clear_mask(pp->ntb, pp->in_db);
+ spin_unlock(&pp->lock);
}
-static int pp_debugfs_setup(struct pp_ctx *pp)
+static void pp_pong(struct pp_ctx *pp)
{
- struct pci_dev *pdev = pp->ntb->pdev;
+ u32 msg_data = -1, spad_data = -1;
+ int pidx = 0;
- if (!pp_debugfs_dir)
- return -ENODEV;
+ /* Read pong data */
+ spad_data = ntb_spad_read(pp->ntb, 0);
+ msg_data = ntb_msg_read(pp->ntb, &pidx, 0);
+ ntb_msg_clear_sts(pp->ntb, -1);
- pp->debugfs_node_dir = debugfs_create_dir(pci_name(pdev),
- pp_debugfs_dir);
- if (!pp->debugfs_node_dir)
- return -ENODEV;
+ /*
+ * Scratchpad and message data may differ, since message register can't
+ * be rewritten unless status is cleared. Additionally either of them
+ * might be unsupported
+ */
+ dev_dbg(&pp->ntb->dev, "Pong spad %#x, msg %#x (port %d)\n",
+ spad_data, msg_data, ntb_peer_port_number(pp->ntb, pidx));
- pp->debugfs_count = debugfs_create_atomic_t("count", S_IRUSR | S_IWUSR,
- pp->debugfs_node_dir,
- &pp->count);
- if (!pp->debugfs_count)
- return -ENODEV;
+ atomic_inc(&pp->count);
- return 0;
+ ntb_db_set_mask(pp->ntb, pp->in_db);
+ ntb_db_clear(pp->ntb, pp->in_db);
+
+ hrtimer_start(&pp->timer, ms_to_ktime(delay_ms), HRTIMER_MODE_REL);
+}
+
+static enum hrtimer_restart pp_timer_func(struct hrtimer *t)
+{
+ struct pp_ctx *pp = to_pp_timer(t);
+
+ pp_ping(pp);
+
+ return HRTIMER_NORESTART;
+}
+
+static void pp_link_event(void *ctx)
+{
+ struct pp_ctx *pp = ctx;
+
+ pp_setup(pp);
+}
+
+static void pp_db_event(void *ctx, int vec)
+{
+ struct pp_ctx *pp = ctx;
+
+ pp_pong(pp);
}
static const struct ntb_ctx_ops pp_ops = {
.link_event = pp_link_event,
- .db_event = pp_db_event,
+ .db_event = pp_db_event
};
-static int pp_probe(struct ntb_client *client,
- struct ntb_dev *ntb)
+static int pp_check_ntb(struct ntb_dev *ntb)
{
- struct pp_ctx *pp;
- int rc;
+ u64 pmask;
if (ntb_db_is_unsafe(ntb)) {
- dev_dbg(&ntb->dev, "doorbell is unsafe\n");
- if (!unsafe) {
- rc = -EINVAL;
- goto err_pp;
- }
- }
-
- if (ntb_spad_count(ntb) < 1) {
- dev_dbg(&ntb->dev, "no enough scratchpads\n");
- rc = -EINVAL;
- goto err_pp;
+ dev_dbg(&ntb->dev, "Doorbell is unsafe\n");
+ if (!unsafe)
+ return -EINVAL;
}
if (ntb_spad_is_unsafe(ntb)) {
- dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
- if (!unsafe) {
- rc = -EINVAL;
- goto err_pp;
- }
+ dev_dbg(&ntb->dev, "Scratchpad is unsafe\n");
+ if (!unsafe)
+ return -EINVAL;
}
- if (ntb_peer_port_count(ntb) != NTB_DEF_PEER_CNT)
- dev_warn(&ntb->dev, "multi-port NTB is unsupported\n");
+ pmask = GENMASK_ULL(ntb_peer_port_count(ntb), 0);
+ if ((ntb_db_valid_mask(ntb) & pmask) != pmask) {
+ dev_err(&ntb->dev, "Unsupported DB configuration\n");
+ return -EINVAL;
+ }
- pp = kmalloc(sizeof(*pp), GFP_KERNEL);
- if (!pp) {
- rc = -ENOMEM;
- goto err_pp;
+ if (ntb_spad_count(ntb) < 1 && ntb_msg_count(ntb) < 1) {
+ dev_err(&ntb->dev, "Scratchpads and messages unsupported\n");
+ return -EINVAL;
+ } else if (ntb_spad_count(ntb) < 1) {
+ dev_dbg(&ntb->dev, "Scratchpads unsupported\n");
+ } else if (ntb_msg_count(ntb) < 1) {
+ dev_dbg(&ntb->dev, "Messages unsupported\n");
}
+ return 0;
+}
+
+static struct pp_ctx *pp_create_data(struct ntb_dev *ntb)
+{
+ struct pp_ctx *pp;
+
+ pp = devm_kzalloc(&ntb->dev, sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return ERR_PTR(-ENOMEM);
+
pp->ntb = ntb;
- pp->db_bits = 0;
atomic_set(&pp->count, 0);
- spin_lock_init(&pp->db_lock);
- timer_setup(&pp->db_timer, pp_ping, 0);
- pp->db_delay = msecs_to_jiffies(delay_ms);
+ spin_lock_init(&pp->lock);
+ hrtimer_init(&pp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ pp->timer.function = pp_timer_func;
+
+ return pp;
+}
+
+static void pp_init_flds(struct pp_ctx *pp)
+{
+ int pidx, lport, pcnt;
+
+ /* Find global port index */
+ lport = ntb_port_number(pp->ntb);
+ pcnt = ntb_peer_port_count(pp->ntb);
+ for (pidx = 0; pidx < pcnt; pidx++) {
+ if (lport < ntb_peer_port_number(pp->ntb, pidx))
+ break;
+ }
- rc = ntb_set_ctx(ntb, pp, &pp_ops);
- if (rc)
- goto err_ctx;
+ pp->in_db = BIT_ULL(pidx);
+ pp->pmask = GENMASK_ULL(pidx, 0) >> 1;
+ pp->nmask = GENMASK_ULL(pcnt - 1, pidx);
- rc = pp_debugfs_setup(pp);
- if (rc)
- goto err_ctx;
+ dev_dbg(&pp->ntb->dev, "Inbound db %#llx, prev %#llx, next %#llx\n",
+ pp->in_db, pp->pmask, pp->nmask);
+}
+
+static int pp_mask_events(struct pp_ctx *pp)
+{
+ u64 db_mask, msg_mask;
+ int ret;
+
+ db_mask = ntb_db_valid_mask(pp->ntb);
+ ret = ntb_db_set_mask(pp->ntb, db_mask);
+ if (ret)
+ return ret;
- ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
- ntb_link_event(ntb);
+ /* Skip message events masking if unsupported */
+ if (ntb_msg_count(pp->ntb) < 1)
+ return 0;
+
+ msg_mask = ntb_msg_outbits(pp->ntb) | ntb_msg_inbits(pp->ntb);
+ return ntb_msg_set_mask(pp->ntb, msg_mask);
+}
+
+static int pp_setup_ctx(struct pp_ctx *pp)
+{
+ int ret;
+
+ ret = ntb_set_ctx(pp->ntb, pp, &pp_ops);
+ if (ret)
+ return ret;
+
+ ntb_link_enable(pp->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
+ /* Might be not necessary */
+ ntb_link_event(pp->ntb);
return 0;
+}
+
+static void pp_clear_ctx(struct pp_ctx *pp)
+{
+ ntb_link_disable(pp->ntb);
-err_ctx:
- kfree(pp);
-err_pp:
- return rc;
+ ntb_clear_ctx(pp->ntb);
}
-static void pp_remove(struct ntb_client *client,
- struct ntb_dev *ntb)
+static void pp_setup_dbgfs(struct pp_ctx *pp)
+{
+ struct pci_dev *pdev = pp->ntb->pdev;
+ void *ret;
+
+ pp->dbgfs_dir = debugfs_create_dir(pci_name(pdev), pp_dbgfs_topdir);
+
+ ret = debugfs_create_atomic_t("count", 0600, pp->dbgfs_dir, &pp->count);
+ if (!ret)
+ dev_warn(&pp->ntb->dev, "DebugFS unsupported\n");
+}
+
+static void pp_clear_dbgfs(struct pp_ctx *pp)
+{
+ debugfs_remove_recursive(pp->dbgfs_dir);
+}
+
+static int pp_probe(struct ntb_client *client, struct ntb_dev *ntb)
+{
+ struct pp_ctx *pp;
+ int ret;
+
+ ret = pp_check_ntb(ntb);
+ if (ret)
+ return ret;
+
+ pp = pp_create_data(ntb);
+ if (IS_ERR(pp))
+ return PTR_ERR(pp);
+
+ pp_init_flds(pp);
+
+ ret = pp_mask_events(pp);
+ if (ret)
+ return ret;
+
+ ret = pp_setup_ctx(pp);
+ if (ret)
+ return ret;
+
+ pp_setup_dbgfs(pp);
+
+ return 0;
+}
+
+static void pp_remove(struct ntb_client *client, struct ntb_dev *ntb)
{
struct pp_ctx *pp = ntb->ctx;
- debugfs_remove_recursive(pp->debugfs_node_dir);
+ pp_clear_dbgfs(pp);
- ntb_clear_ctx(ntb);
- del_timer_sync(&pp->db_timer);
- ntb_link_disable(ntb);
+ pp_clear_ctx(pp);
- kfree(pp);
+ pp_clear(pp);
}
static struct ntb_client pp_client = {
.ops = {
.probe = pp_probe,
- .remove = pp_remove,
- },
+ .remove = pp_remove
+ }
};
static int __init pp_init(void)
{
- int rc;
+ int ret;
if (debugfs_initialized())
- pp_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ pp_dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- rc = ntb_register_client(&pp_client);
- if (rc)
- goto err_client;
+ ret = ntb_register_client(&pp_client);
+ if (ret)
+ debugfs_remove_recursive(pp_dbgfs_topdir);
- return 0;
-
-err_client:
- debugfs_remove_recursive(pp_debugfs_dir);
- return rc;
+ return ret;
}
module_init(pp_init);
static void __exit pp_exit(void)
{
ntb_unregister_client(&pp_client);
- debugfs_remove_recursive(pp_debugfs_dir);
+ debugfs_remove_recursive(pp_dbgfs_topdir);
}
module_exit(pp_exit);
+
diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c
index 91526a986caa..d592c0ffbd19 100644
--- a/drivers/ntb/test/ntb_tool.c
+++ b/drivers/ntb/test/ntb_tool.c
@@ -5,6 +5,7 @@
* GPL LICENSE SUMMARY
*
* Copyright (C) 2015 EMC Corporation. All Rights Reserved.
+ * Copyright (C) 2017 T-Platforms All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -18,6 +19,7 @@
* BSD LICENSE
*
* Copyright (C) 2015 EMC Corporation. All Rights Reserved.
+ * Copyright (C) 2017 T-Platforms All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,9 +48,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* PCIe NTB Debugging Tool Linux driver
- *
- * Contact Information:
- * Allen Hubbe <Allen.Hubbe@emc.com>
*/
/*
@@ -56,42 +55,125 @@
*
* Assuming $DBG_DIR is something like:
* '/sys/kernel/debug/ntb_tool/0000:00:03.0'
+ * Suppose aside from local device there is at least one remote device
+ * connected to NTB with index 0.
+ *-----------------------------------------------------------------------------
+ * Eg: check local/peer device information.
+ *
+ * # Get local device port number
+ * root@self# cat $DBG_DIR/port
+ *
+ * # Check local device functionality
+ * root@self# ls $DBG_DIR
+ * db msg1 msg_sts peer4/ port
+ * db_event msg2 peer0/ peer5/ spad0
+ * db_mask msg3 peer1/ peer_db spad1
+ * link msg_event peer2/ peer_db_mask spad2
+ * msg0 msg_mask peer3/ peer_spad spad3
+ * # As one can see it supports:
+ * # 1) four inbound message registers
+ * # 2) four inbound scratchpads
+ * # 3) up to six peer devices
+ *
+ * # Check peer device port number
+ * root@self# cat $DBG_DIR/peer0/port
+ *
+ * # Check peer device(s) functionality to be used
+ * root@self# ls $DBG_DIR/peer0
+ * link mw_trans0 mw_trans6 port
+ * link_event mw_trans1 mw_trans7 spad0
+ * msg0 mw_trans2 peer_mw_trans0 spad1
+ * msg1 mw_trans3 peer_mw_trans1 spad2
+ * msg2 mw_trans4 peer_mw_trans2 spad3
+ * msg3 mw_trans5 peer_mw_trans3
+ * # As one can see we got:
+ * # 1) four outbound message registers
+ * # 2) four outbound scratchpads
+ * # 3) eight inbound memory windows
+ * # 4) four outbound memory windows
+ *-----------------------------------------------------------------------------
+ * Eg: NTB link tests
*
- * Eg: check if clearing the doorbell mask generates an interrupt.
+ * # Set local link up/down
+ * root@self# echo Y > $DBG_DIR/link
+ * root@self# echo N > $DBG_DIR/link
*
- * # Check the link status
- * root@self# cat $DBG_DIR/link
+ * # Check if link with peer device is up/down:
+ * root@self# cat $DBG_DIR/peer0/link
*
- * # Block until the link is up
- * root@self# echo Y > $DBG_DIR/link_event
+ * # Block until the link is up/down
+ * root@self# echo Y > $DBG_DIR/peer0/link_event
+ * root@self# echo N > $DBG_DIR/peer0/link_event
+ *-----------------------------------------------------------------------------
+ * Eg: Doorbell registers tests (some functionality might be absent)
*
- * # Set the doorbell mask
- * root@self# echo 's 1' > $DBG_DIR/mask
+ * # Set/clear/get local doorbell
+ * root@self# echo 's 1' > $DBG_DIR/db
+ * root@self# echo 'c 1' > $DBG_DIR/db
+ * root@self# cat $DBG_DIR/db
*
- * # Ring the doorbell from the peer
+ * # Set/clear/get local doorbell mask
+ * root@self# echo 's 1' > $DBG_DIR/db_mask
+ * root@self# echo 'c 1' > $DBG_DIR/db_mask
+ * root@self# cat $DBG_DIR/db_mask
+ *
+ * # Ring/clear/get peer doorbell
* root@peer# echo 's 1' > $DBG_DIR/peer_db
+ * root@peer# echo 'c 1' > $DBG_DIR/peer_db
+ * root@peer# cat $DBG_DIR/peer_db
+ *
+ * # Set/clear/get peer doorbell mask
+ * root@self# echo 's 1' > $DBG_DIR/peer_db_mask
+ * root@self# echo 'c 1' > $DBG_DIR/peer_db_mask
+ * root@self# cat $DBG_DIR/peer_db_mask
+ *
+ * # Block until local doorbell is set with specified value
+ * root@self# echo 1 > $DBG_DIR/db_event
+ *-----------------------------------------------------------------------------
+ * Eg: Message registers tests (functionality might be absent)
*
- * # Clear the doorbell mask
- * root@self# echo 'c 1' > $DBG_DIR/mask
+ * # Set/clear/get in/out message registers status
+ * root@self# echo 's 1' > $DBG_DIR/msg_sts
+ * root@self# echo 'c 1' > $DBG_DIR/msg_sts
+ * root@self# cat $DBG_DIR/msg_sts
*
- * Observe debugging output in dmesg or your console. You should see a
- * doorbell event triggered by clearing the mask. If not, this may indicate an
- * issue with the hardware that needs to be worked around in the driver.
+ * # Set/clear in/out message registers mask
+ * root@self# echo 's 1' > $DBG_DIR/msg_mask
+ * root@self# echo 'c 1' > $DBG_DIR/msg_mask
*
- * Eg: read and write scratchpad registers
+ * # Get inbound message register #0 value and source of port index
+ * root@self# cat $DBG_DIR/msg0
*
- * root@peer# echo '0 0x01010101 1 0x7f7f7f7f' > $DBG_DIR/peer_spad
+ * # Send some data to peer over outbound message register #0
+ * root@self# echo 0x01020304 > $DBG_DIR/peer0/msg0
+ *-----------------------------------------------------------------------------
+ * Eg: Scratchpad registers tests (functionality might be absent)
*
- * root@self# cat $DBG_DIR/spad
+ * # Write/read to/from local scratchpad register #0
+ * root@peer# echo 0x01020304 > $DBG_DIR/spad0
+ * root@peer# cat $DBG_DIR/spad0
*
- * Observe that spad 0 and 1 have the values set by the peer.
+ * # Write/read to/from peer scratchpad register #0
+ * root@peer# echo 0x01020304 > $DBG_DIR/peer0/spad0
+ * root@peer# cat $DBG_DIR/peer0/spad0
+ *-----------------------------------------------------------------------------
+ * Eg: Memory windows tests
*
- * # Check the memory window translation info
- * cat $DBG_DIR/peer_trans0
+ * # Create inbound memory window buffer of specified size/get its base address
+ * root@peer# echo 16384 > $DBG_DIR/peer0/mw_trans0
+ * root@peer# cat $DBG_DIR/peer0/mw_trans0
*
- * # Setup a 16k memory window buffer
- * echo 16384 > $DBG_DIR/peer_trans0
+ * # Write/read data to/from inbound memory window
+ * root@peer# echo Hello > $DBG_DIR/peer0/mw0
+ * root@peer# head -c 7 $DBG_DIR/peer0/mw0
*
+ * # Map outbound memory window/check it settings (on peer device)
+ * root@peer# echo 0xADD0BA5E:16384 > $DBG_DIR/peer0/peer_mw_trans0
+ * root@peer# cat $DBG_DIR/peer0/peer_mw_trans0
+ *
+ * # Write/read data to/from outbound memory window (on peer device)
+ * root@peer# echo olleH > $DBG_DIR/peer0/peer_mw0
+ * root@peer# head -c 7 $DBG_DIR/peer0/peer_mw0
*/
#include <linux/init.h>
@@ -106,49 +188,87 @@
#include <linux/ntb.h>
-#define DRIVER_NAME "ntb_tool"
-#define DRIVER_DESCRIPTION "PCIe NTB Debugging Tool"
-
-#define DRIVER_LICENSE "Dual BSD/GPL"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_RELDATE "22 April 2015"
-#define DRIVER_AUTHOR "Allen Hubbe <Allen.Hubbe@emc.com>"
+#define DRIVER_NAME "ntb_tool"
+#define DRIVER_VERSION "2.0"
-MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
-
-/* It is rare to have hadrware with greater than six MWs */
-#define MAX_MWS 6
-/* Only two-ports devices are supported */
-#define PIDX NTB_DEF_PEER_IDX
-
-static struct dentry *tool_dbgfs;
+MODULE_AUTHOR("Allen Hubbe <Allen.Hubbe@emc.com>");
+MODULE_DESCRIPTION("PCIe NTB Debugging Tool");
+/*
+ * Inbound and outbound memory windows descriptor. Union members selection
+ * depends on the MW type the structure describes. mm_base/dma_base are the
+ * virtual and DMA address of an inbound MW. io_base/tr_base are the MMIO
+ * mapped virtual and xlat addresses of an outbound MW respectively.
+ */
struct tool_mw {
- int idx;
+ int widx;
+ int pidx;
struct tool_ctx *tc;
- resource_size_t win_size;
+ union {
+ u8 *mm_base;
+ u8 __iomem *io_base;
+ };
+ union {
+ dma_addr_t dma_base;
+ u64 tr_base;
+ };
resource_size_t size;
- u8 __iomem *local;
- u8 *peer;
- dma_addr_t peer_dma;
- struct dentry *peer_dbg_file;
+ struct dentry *dbgfs_file;
+};
+
+/*
+ * Wrapper structure is used to distinguish the outbound MW peers reference
+ * within the corresponding DebugFS directory IO operation.
+ */
+struct tool_mw_wrap {
+ int pidx;
+ struct tool_mw *mw;
+};
+
+struct tool_msg {
+ int midx;
+ int pidx;
+ struct tool_ctx *tc;
+};
+
+struct tool_spad {
+ int sidx;
+ int pidx;
+ struct tool_ctx *tc;
+};
+
+struct tool_peer {
+ int pidx;
+ struct tool_ctx *tc;
+ int inmw_cnt;
+ struct tool_mw *inmws;
+ int outmw_cnt;
+ struct tool_mw_wrap *outmws;
+ int outmsg_cnt;
+ struct tool_msg *outmsgs;
+ int outspad_cnt;
+ struct tool_spad *outspads;
+ struct dentry *dbgfs_dir;
};
struct tool_ctx {
struct ntb_dev *ntb;
- struct dentry *dbgfs;
wait_queue_head_t link_wq;
- int mw_count;
- struct tool_mw mws[MAX_MWS];
+ wait_queue_head_t db_wq;
+ wait_queue_head_t msg_wq;
+ int outmw_cnt;
+ struct tool_mw *outmws;
+ int peer_cnt;
+ struct tool_peer *peers;
+ int inmsg_cnt;
+ struct tool_msg *inmsgs;
+ int inspad_cnt;
+ struct tool_spad *inspads;
+ struct dentry *dbgfs_dir;
};
-#define SPAD_FNAME_SIZE 0x10
-#define INT_PTR(x) ((void *)(unsigned long)x)
-#define PTR_INT(x) ((int)(unsigned long)x)
-
#define TOOL_FOPS_RDWR(__name, __read, __write) \
const struct file_operations __name = { \
.owner = THIS_MODULE, \
@@ -157,6 +277,15 @@ struct tool_ctx {
.write = __write, \
}
+#define TOOL_BUF_LEN 32
+
+static struct dentry *tool_dbgfs_topdir;
+
+/*==============================================================================
+ * NTB events handlers
+ *==============================================================================
+ */
+
static void tool_link_event(void *ctx)
{
struct tool_ctx *tc = ctx;
@@ -182,580 +311,578 @@ static void tool_db_event(void *ctx, int vec)
dev_dbg(&tc->ntb->dev, "doorbell vec %d mask %#llx bits %#llx\n",
vec, db_mask, db_bits);
+
+ wake_up(&tc->db_wq);
+}
+
+static void tool_msg_event(void *ctx)
+{
+ struct tool_ctx *tc = ctx;
+ u64 msg_sts;
+
+ msg_sts = ntb_msg_read_sts(tc->ntb);
+
+ dev_dbg(&tc->ntb->dev, "message bits %#llx\n", msg_sts);
+
+ wake_up(&tc->msg_wq);
}
static const struct ntb_ctx_ops tool_ops = {
.link_event = tool_link_event,
.db_event = tool_db_event,
+ .msg_event = tool_msg_event
};
-static ssize_t tool_dbfn_read(struct tool_ctx *tc, char __user *ubuf,
- size_t size, loff_t *offp,
- u64 (*db_read_fn)(struct ntb_dev *))
+/*==============================================================================
+ * Common read/write methods
+ *==============================================================================
+ */
+
+static ssize_t tool_fn_read(struct tool_ctx *tc, char __user *ubuf,
+ size_t size, loff_t *offp,
+ u64 (*fn_read)(struct ntb_dev *))
{
size_t buf_size;
- char *buf;
- ssize_t pos, rc;
+ char buf[TOOL_BUF_LEN];
+ ssize_t pos;
- if (!db_read_fn)
+ if (!fn_read)
return -EINVAL;
- buf_size = min_t(size_t, size, 0x20);
-
- buf = kmalloc(buf_size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- pos = scnprintf(buf, buf_size, "%#llx\n",
- db_read_fn(tc->ntb));
+ buf_size = min(size, sizeof(buf));
- rc = simple_read_from_buffer(ubuf, size, offp, buf, pos);
+ pos = scnprintf(buf, buf_size, "%#llx\n", fn_read(tc->ntb));
- kfree(buf);
-
- return rc;
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
}
-static ssize_t tool_dbfn_write(struct tool_ctx *tc,
- const char __user *ubuf,
- size_t size, loff_t *offp,
- int (*db_set_fn)(struct ntb_dev *, u64),
- int (*db_clear_fn)(struct ntb_dev *, u64))
+static ssize_t tool_fn_write(struct tool_ctx *tc,
+ const char __user *ubuf,
+ size_t size, loff_t *offp,
+ int (*fn_set)(struct ntb_dev *, u64),
+ int (*fn_clear)(struct ntb_dev *, u64))
{
- u64 db_bits;
char *buf, cmd;
- ssize_t rc;
+ ssize_t ret;
+ u64 bits;
int n;
buf = kmalloc(size + 1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- rc = simple_write_to_buffer(buf, size, offp, ubuf, size);
- if (rc < 0) {
+ ret = simple_write_to_buffer(buf, size, offp, ubuf, size);
+ if (ret < 0) {
kfree(buf);
- return rc;
+ return ret;
}
buf[size] = 0;
- n = sscanf(buf, "%c %lli", &cmd, &db_bits);
+ n = sscanf(buf, "%c %lli", &cmd, &bits);
kfree(buf);
if (n != 2) {
- rc = -EINVAL;
+ ret = -EINVAL;
} else if (cmd == 's') {
- if (!db_set_fn)
- rc = -EINVAL;
+ if (!fn_set)
+ ret = -EINVAL;
else
- rc = db_set_fn(tc->ntb, db_bits);
+ ret = fn_set(tc->ntb, bits);
} else if (cmd == 'c') {
- if (!db_clear_fn)
- rc = -EINVAL;
+ if (!fn_clear)
+ ret = -EINVAL;
else
- rc = db_clear_fn(tc->ntb, db_bits);
+ ret = fn_clear(tc->ntb, bits);
} else {
- rc = -EINVAL;
+ ret = -EINVAL;
}
- return rc ? : size;
+ return ret ? : size;
}
-static ssize_t tool_spadfn_read(struct tool_ctx *tc, char __user *ubuf,
- size_t size, loff_t *offp,
- u32 (*spad_read_fn)(struct ntb_dev *, int))
-{
- size_t buf_size;
- char *buf;
- ssize_t pos, rc;
- int i, spad_count;
-
- if (!spad_read_fn)
- return -EINVAL;
-
- spad_count = ntb_spad_count(tc->ntb);
+/*==============================================================================
+ * Port read/write methods
+ *==============================================================================
+ */
- /*
- * We multiply the number of spads by 15 to get the buffer size
- * this is from 3 for the %d, 10 for the largest hex value
- * (0x00000000) and 2 for the tab and line feed.
- */
- buf_size = min_t(size_t, size, spad_count * 15);
+static ssize_t tool_port_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+ char buf[TOOL_BUF_LEN];
+ int pos;
- buf = kmalloc(buf_size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ pos = scnprintf(buf, sizeof(buf), "%d\n", ntb_port_number(tc->ntb));
- pos = 0;
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
+}
- for (i = 0; i < spad_count; ++i) {
- pos += scnprintf(buf + pos, buf_size - pos, "%d\t%#x\n",
- i, spad_read_fn(tc->ntb, i));
- }
+static TOOL_FOPS_RDWR(tool_port_fops,
+ tool_port_read,
+ NULL);
- rc = simple_read_from_buffer(ubuf, size, offp, buf, pos);
+static ssize_t tool_peer_port_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_peer *peer = filep->private_data;
+ struct tool_ctx *tc = peer->tc;
+ char buf[TOOL_BUF_LEN];
+ int pos;
- kfree(buf);
+ pos = scnprintf(buf, sizeof(buf), "%d\n",
+ ntb_peer_port_number(tc->ntb, peer->pidx));
- return rc;
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
}
-static ssize_t tool_spadfn_write(struct tool_ctx *tc,
- const char __user *ubuf,
- size_t size, loff_t *offp,
- int (*spad_write_fn)(struct ntb_dev *,
- int, u32))
+static TOOL_FOPS_RDWR(tool_peer_port_fops,
+ tool_peer_port_read,
+ NULL);
+
+static int tool_init_peers(struct tool_ctx *tc)
{
- int spad_idx;
- u32 spad_val;
- char *buf, *buf_ptr;
- int pos, n;
- ssize_t rc;
-
- if (!spad_write_fn) {
- dev_dbg(&tc->ntb->dev, "no spad write fn\n");
- return -EINVAL;
- }
+ int pidx;
- buf = kmalloc(size + 1, GFP_KERNEL);
- if (!buf)
+ tc->peer_cnt = ntb_peer_port_count(tc->ntb);
+ tc->peers = devm_kcalloc(&tc->ntb->dev, tc->peer_cnt,
+ sizeof(*tc->peers), GFP_KERNEL);
+ if (tc->peers == NULL)
return -ENOMEM;
- rc = simple_write_to_buffer(buf, size, offp, ubuf, size);
- if (rc < 0) {
- kfree(buf);
- return rc;
+ for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
+ tc->peers[pidx].pidx = pidx;
+ tc->peers[pidx].tc = tc;
}
- buf[size] = 0;
- buf_ptr = buf;
- n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
- while (n == 2) {
- buf_ptr += pos;
- rc = spad_write_fn(tc->ntb, spad_idx, spad_val);
- if (rc)
- break;
-
- n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
- }
-
- if (n < 0)
- rc = n;
-
- kfree(buf);
-
- return rc ? : size;
+ return 0;
}
-static ssize_t tool_db_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
-
- return tool_dbfn_read(tc, ubuf, size, offp,
- tc->ntb->ops->db_read);
-}
+/*==============================================================================
+ * Link state read/write methods
+ *==============================================================================
+ */
-static ssize_t tool_db_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_link_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
{
struct tool_ctx *tc = filep->private_data;
+ bool val;
+ int ret;
- return tool_dbfn_write(tc, ubuf, size, offp,
- tc->ntb->ops->db_set,
- tc->ntb->ops->db_clear);
-}
+ ret = kstrtobool_from_user(ubuf, size, &val);
+ if (ret)
+ return ret;
-static TOOL_FOPS_RDWR(tool_db_fops,
- tool_db_read,
- tool_db_write);
+ if (val)
+ ret = ntb_link_enable(tc->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
+ else
+ ret = ntb_link_disable(tc->ntb);
-static ssize_t tool_mask_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
+ if (ret)
+ return ret;
- return tool_dbfn_read(tc, ubuf, size, offp,
- tc->ntb->ops->db_read_mask);
+ return size;
}
-static ssize_t tool_mask_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
+static TOOL_FOPS_RDWR(tool_link_fops,
+ NULL,
+ tool_link_write);
+
+static ssize_t tool_peer_link_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_ctx *tc = filep->private_data;
+ struct tool_peer *peer = filep->private_data;
+ struct tool_ctx *tc = peer->tc;
+ char buf[3];
- return tool_dbfn_write(tc, ubuf, size, offp,
- tc->ntb->ops->db_set_mask,
- tc->ntb->ops->db_clear_mask);
+ if (ntb_link_is_up(tc->ntb, NULL, NULL) & BIT(peer->pidx))
+ buf[0] = 'Y';
+ else
+ buf[0] = 'N';
+ buf[1] = '\n';
+ buf[2] = '\0';
+
+ return simple_read_from_buffer(ubuf, size, offp, buf, 3);
}
-static TOOL_FOPS_RDWR(tool_mask_fops,
- tool_mask_read,
- tool_mask_write);
+static TOOL_FOPS_RDWR(tool_peer_link_fops,
+ tool_peer_link_read,
+ NULL);
-static ssize_t tool_peer_db_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_peer_link_event_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_ctx *tc = filep->private_data;
+ struct tool_peer *peer = filep->private_data;
+ struct tool_ctx *tc = peer->tc;
+ u64 link_msk;
+ bool val;
+ int ret;
- return tool_dbfn_read(tc, ubuf, size, offp,
- tc->ntb->ops->peer_db_read);
-}
+ ret = kstrtobool_from_user(ubuf, size, &val);
+ if (ret)
+ return ret;
-static ssize_t tool_peer_db_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
+ link_msk = BIT_ULL_MASK(peer->pidx);
- return tool_dbfn_write(tc, ubuf, size, offp,
- tc->ntb->ops->peer_db_set,
- tc->ntb->ops->peer_db_clear);
+ if (wait_event_interruptible(tc->link_wq,
+ !!(ntb_link_is_up(tc->ntb, NULL, NULL) & link_msk) == val))
+ return -ERESTART;
+
+ return size;
}
-static TOOL_FOPS_RDWR(tool_peer_db_fops,
- tool_peer_db_read,
- tool_peer_db_write);
+static TOOL_FOPS_RDWR(tool_peer_link_event_fops,
+ NULL,
+ tool_peer_link_event_write);
-static ssize_t tool_peer_mask_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
+/*==============================================================================
+ * Memory windows read/write/setting methods
+ *==============================================================================
+ */
+
+static ssize_t tool_mw_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_ctx *tc = filep->private_data;
+ struct tool_mw *inmw = filep->private_data;
+
+ if (inmw->mm_base == NULL)
+ return -ENXIO;
- return tool_dbfn_read(tc, ubuf, size, offp,
- tc->ntb->ops->peer_db_read_mask);
+ return simple_read_from_buffer(ubuf, size, offp,
+ inmw->mm_base, inmw->size);
}
-static ssize_t tool_peer_mask_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_mw_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_ctx *tc = filep->private_data;
+ struct tool_mw *inmw = filep->private_data;
- return tool_dbfn_write(tc, ubuf, size, offp,
- tc->ntb->ops->peer_db_set_mask,
- tc->ntb->ops->peer_db_clear_mask);
+ if (inmw->mm_base == NULL)
+ return -ENXIO;
+
+ return simple_write_to_buffer(inmw->mm_base, inmw->size, offp,
+ ubuf, size);
}
-static TOOL_FOPS_RDWR(tool_peer_mask_fops,
- tool_peer_mask_read,
- tool_peer_mask_write);
+static TOOL_FOPS_RDWR(tool_mw_fops,
+ tool_mw_read,
+ tool_mw_write);
-static ssize_t tool_spad_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
+static int tool_setup_mw(struct tool_ctx *tc, int pidx, int widx,
+ size_t req_size)
{
- struct tool_ctx *tc = filep->private_data;
+ resource_size_t size, addr_align, size_align;
+ struct tool_mw *inmw = &tc->peers[pidx].inmws[widx];
+ char buf[TOOL_BUF_LEN];
+ int ret;
- return tool_spadfn_read(tc, ubuf, size, offp,
- tc->ntb->ops->spad_read);
-}
+ if (inmw->mm_base != NULL)
+ return 0;
-static ssize_t tool_spad_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
+ ret = ntb_mw_get_align(tc->ntb, pidx, widx, &addr_align,
+ &size_align, &size);
+ if (ret)
+ return ret;
+
+ inmw->size = min_t(resource_size_t, req_size, size);
+ inmw->size = round_up(inmw->size, addr_align);
+ inmw->size = round_up(inmw->size, size_align);
+ inmw->mm_base = dma_alloc_coherent(&tc->ntb->dev, inmw->size,
+ &inmw->dma_base, GFP_KERNEL);
+ if (!inmw->mm_base)
+ return -ENOMEM;
- return tool_spadfn_write(tc, ubuf, size, offp,
- tc->ntb->ops->spad_write);
-}
+ if (!IS_ALIGNED(inmw->dma_base, addr_align)) {
+ ret = -ENOMEM;
+ goto err_free_dma;
+ }
-static TOOL_FOPS_RDWR(tool_spad_fops,
- tool_spad_read,
- tool_spad_write);
+ ret = ntb_mw_set_trans(tc->ntb, pidx, widx, inmw->dma_base, inmw->size);
+ if (ret)
+ goto err_free_dma;
-static u32 ntb_tool_peer_spad_read(struct ntb_dev *ntb, int sidx)
-{
- return ntb_peer_spad_read(ntb, PIDX, sidx);
-}
+ snprintf(buf, sizeof(buf), "mw%d", widx);
+ inmw->dbgfs_file = debugfs_create_file(buf, 0600,
+ tc->peers[pidx].dbgfs_dir, inmw,
+ &tool_mw_fops);
-static ssize_t tool_peer_spad_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
+ return 0;
- return tool_spadfn_read(tc, ubuf, size, offp, ntb_tool_peer_spad_read);
-}
+err_free_dma:
+ dma_free_coherent(&tc->ntb->dev, inmw->size, inmw->mm_base,
+ inmw->dma_base);
+ inmw->mm_base = NULL;
+ inmw->dma_base = 0;
+ inmw->size = 0;
-static int ntb_tool_peer_spad_write(struct ntb_dev *ntb, int sidx, u32 val)
-{
- return ntb_peer_spad_write(ntb, PIDX, sidx, val);
+ return ret;
}
-static ssize_t tool_peer_spad_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
+static void tool_free_mw(struct tool_ctx *tc, int pidx, int widx)
{
- struct tool_ctx *tc = filep->private_data;
+ struct tool_mw *inmw = &tc->peers[pidx].inmws[widx];
- return tool_spadfn_write(tc, ubuf, size, offp,
- ntb_tool_peer_spad_write);
-}
+ debugfs_remove(inmw->dbgfs_file);
-static TOOL_FOPS_RDWR(tool_peer_spad_fops,
- tool_peer_spad_read,
- tool_peer_spad_write);
-
-static ssize_t tool_link_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
- char buf[3];
-
- buf[0] = ntb_link_is_up(tc->ntb, NULL, NULL) ? 'Y' : 'N';
- buf[1] = '\n';
- buf[2] = '\0';
+ if (inmw->mm_base != NULL) {
+ ntb_mw_clear_trans(tc->ntb, pidx, widx);
+ dma_free_coherent(&tc->ntb->dev, inmw->size,
+ inmw->mm_base, inmw->dma_base);
+ }
- return simple_read_from_buffer(ubuf, size, offp, buf, 2);
+ inmw->mm_base = NULL;
+ inmw->dma_base = 0;
+ inmw->size = 0;
+ inmw->dbgfs_file = NULL;
}
-static ssize_t tool_link_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_mw_trans_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_ctx *tc = filep->private_data;
- char buf[32];
+ struct tool_mw *inmw = filep->private_data;
+ resource_size_t addr_align;
+ resource_size_t size_align;
+ resource_size_t size_max;
+ ssize_t ret, off = 0;
size_t buf_size;
- bool val;
- int rc;
+ char *buf;
- buf_size = min(size, (sizeof(buf) - 1));
- if (copy_from_user(buf, ubuf, buf_size))
- return -EFAULT;
+ buf_size = min_t(size_t, size, 512);
- buf[buf_size] = '\0';
+ buf = kmalloc(buf_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- rc = strtobool(buf, &val);
- if (rc)
- return rc;
+ ret = ntb_mw_get_align(inmw->tc->ntb, inmw->pidx, inmw->widx,
+ &addr_align, &size_align, &size_max);
+ if (ret)
+ goto err;
- if (val)
- rc = ntb_link_enable(tc->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
- else
- rc = ntb_link_disable(tc->ntb);
+ off += scnprintf(buf + off, buf_size - off,
+ "Inbound MW \t%d\n",
+ inmw->widx);
- if (rc)
- return rc;
+ off += scnprintf(buf + off, buf_size - off,
+ "Port \t%d (%d)\n",
+ ntb_peer_port_number(inmw->tc->ntb, inmw->pidx),
+ inmw->pidx);
- return size;
-}
+ off += scnprintf(buf + off, buf_size - off,
+ "Window Address \t0x%pK\n", inmw->mm_base);
-static TOOL_FOPS_RDWR(tool_link_fops,
- tool_link_read,
- tool_link_write);
+ off += scnprintf(buf + off, buf_size - off,
+ "DMA Address \t%pad\n",
+ &inmw->dma_base);
-static ssize_t tool_link_event_write(struct file *filep,
- const char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_ctx *tc = filep->private_data;
- char buf[32];
- size_t buf_size;
- bool val;
- int rc;
+ off += scnprintf(buf + off, buf_size - off,
+ "Window Size \t%pa[p]\n",
+ &inmw->size);
- buf_size = min(size, (sizeof(buf) - 1));
- if (copy_from_user(buf, ubuf, buf_size))
- return -EFAULT;
+ off += scnprintf(buf + off, buf_size - off,
+ "Alignment \t%pa[p]\n",
+ &addr_align);
- buf[buf_size] = '\0';
+ off += scnprintf(buf + off, buf_size - off,
+ "Size Alignment \t%pa[p]\n",
+ &size_align);
- rc = strtobool(buf, &val);
- if (rc)
- return rc;
+ off += scnprintf(buf + off, buf_size - off,
+ "Size Max \t%pa[p]\n",
+ &size_max);
- if (wait_event_interruptible(tc->link_wq,
- ntb_link_is_up(tc->ntb, NULL, NULL) == val))
- return -ERESTART;
+ ret = simple_read_from_buffer(ubuf, size, offp, buf, off);
+
+err:
+ kfree(buf);
+
+ return ret;
+}
+
+static ssize_t tool_mw_trans_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *inmw = filep->private_data;
+ unsigned int val;
+ int ret;
+
+ ret = kstrtouint_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
+
+ tool_free_mw(inmw->tc, inmw->pidx, inmw->widx);
+ if (val) {
+ ret = tool_setup_mw(inmw->tc, inmw->pidx, inmw->widx, val);
+ if (ret)
+ return ret;
+ }
return size;
}
-static TOOL_FOPS_RDWR(tool_link_event_fops,
- NULL,
- tool_link_event_write);
+static TOOL_FOPS_RDWR(tool_mw_trans_fops,
+ tool_mw_trans_read,
+ tool_mw_trans_write);
-static ssize_t tool_mw_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_peer_mw_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_mw *mw = filep->private_data;
- ssize_t rc;
+ struct tool_mw *outmw = filep->private_data;
loff_t pos = *offp;
+ ssize_t ret;
void *buf;
- if (mw->local == NULL)
+ if (outmw->io_base == NULL)
return -EIO;
- if (pos < 0)
- return -EINVAL;
- if (pos >= mw->win_size || !size)
+
+ if (pos >= outmw->size || !size)
return 0;
- if (size > mw->win_size - pos)
- size = mw->win_size - pos;
+
+ if (size > outmw->size - pos)
+ size = outmw->size - pos;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- memcpy_fromio(buf, mw->local + pos, size);
- rc = copy_to_user(ubuf, buf, size);
- if (rc == size) {
- rc = -EFAULT;
+ memcpy_fromio(buf, outmw->io_base + pos, size);
+ ret = copy_to_user(ubuf, buf, size);
+ if (ret == size) {
+ ret = -EFAULT;
goto err_free;
}
- size -= rc;
+ size -= ret;
*offp = pos + size;
- rc = size;
+ ret = size;
err_free:
kfree(buf);
- return rc;
+ return ret;
}
-static ssize_t tool_mw_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_peer_mw_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_mw *mw = filep->private_data;
- ssize_t rc;
+ struct tool_mw *outmw = filep->private_data;
+ ssize_t ret;
loff_t pos = *offp;
void *buf;
- if (pos < 0)
- return -EINVAL;
- if (pos >= mw->win_size || !size)
+ if (outmw->io_base == NULL)
+ return -EIO;
+
+ if (pos >= outmw->size || !size)
return 0;
- if (size > mw->win_size - pos)
- size = mw->win_size - pos;
+ if (size > outmw->size - pos)
+ size = outmw->size - pos;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- rc = copy_from_user(buf, ubuf, size);
- if (rc == size) {
- rc = -EFAULT;
+ ret = copy_from_user(buf, ubuf, size);
+ if (ret == size) {
+ ret = -EFAULT;
goto err_free;
}
- size -= rc;
+ size -= ret;
*offp = pos + size;
- rc = size;
+ ret = size;
- memcpy_toio(mw->local + pos, buf, size);
+ memcpy_toio(outmw->io_base + pos, buf, size);
err_free:
kfree(buf);
- return rc;
-}
-
-static TOOL_FOPS_RDWR(tool_mw_fops,
- tool_mw_read,
- tool_mw_write);
-
-static ssize_t tool_peer_mw_read(struct file *filep, char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_mw *mw = filep->private_data;
-
- if (!mw->peer)
- return -ENXIO;
-
- return simple_read_from_buffer(ubuf, size, offp, mw->peer, mw->size);
-}
-
-static ssize_t tool_peer_mw_write(struct file *filep, const char __user *ubuf,
- size_t size, loff_t *offp)
-{
- struct tool_mw *mw = filep->private_data;
-
- if (!mw->peer)
- return -ENXIO;
-
- return simple_write_to_buffer(mw->peer, mw->size, offp, ubuf, size);
+ return ret;
}
static TOOL_FOPS_RDWR(tool_peer_mw_fops,
tool_peer_mw_read,
tool_peer_mw_write);
-static int tool_setup_mw(struct tool_ctx *tc, int idx, size_t req_size)
+static int tool_setup_peer_mw(struct tool_ctx *tc, int pidx, int widx,
+ u64 req_addr, size_t req_size)
{
- int rc;
- struct tool_mw *mw = &tc->mws[idx];
- resource_size_t size, align_addr, align_size;
- char buf[16];
+ struct tool_mw *outmw = &tc->outmws[widx];
+ resource_size_t map_size;
+ phys_addr_t map_base;
+ char buf[TOOL_BUF_LEN];
+ int ret;
- if (mw->peer)
+ if (outmw->io_base != NULL)
return 0;
- rc = ntb_mw_get_align(tc->ntb, PIDX, idx, &align_addr,
- &align_size, &size);
- if (rc)
- return rc;
+ ret = ntb_peer_mw_get_addr(tc->ntb, widx, &map_base, &map_size);
+ if (ret)
+ return ret;
- mw->size = min_t(resource_size_t, req_size, size);
- mw->size = round_up(mw->size, align_addr);
- mw->size = round_up(mw->size, align_size);
- mw->peer = dma_alloc_coherent(&tc->ntb->pdev->dev, mw->size,
- &mw->peer_dma, GFP_KERNEL);
+ ret = ntb_peer_mw_set_trans(tc->ntb, pidx, widx, req_addr, req_size);
+ if (ret)
+ return ret;
- if (!mw->peer || !IS_ALIGNED(mw->peer_dma, align_addr))
- return -ENOMEM;
+ outmw->io_base = ioremap_wc(map_base, map_size);
+ if (outmw->io_base == NULL) {
+ ret = -EFAULT;
+ goto err_clear_trans;
+ }
- rc = ntb_mw_set_trans(tc->ntb, PIDX, idx, mw->peer_dma, mw->size);
- if (rc)
- goto err_free_dma;
+ outmw->tr_base = req_addr;
+ outmw->size = req_size;
+ outmw->pidx = pidx;
- snprintf(buf, sizeof(buf), "peer_mw%d", idx);
- mw->peer_dbg_file = debugfs_create_file(buf, S_IRUSR | S_IWUSR,
- mw->tc->dbgfs, mw,
- &tool_peer_mw_fops);
+ snprintf(buf, sizeof(buf), "peer_mw%d", widx);
+ outmw->dbgfs_file = debugfs_create_file(buf, 0600,
+ tc->peers[pidx].dbgfs_dir, outmw,
+ &tool_peer_mw_fops);
return 0;
-err_free_dma:
- dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
- mw->peer,
- mw->peer_dma);
- mw->peer = NULL;
- mw->peer_dma = 0;
- mw->size = 0;
-
- return rc;
+err_clear_trans:
+ ntb_peer_mw_clear_trans(tc->ntb, pidx, widx);
+
+ return ret;
}
-static void tool_free_mw(struct tool_ctx *tc, int idx)
+static void tool_free_peer_mw(struct tool_ctx *tc, int widx)
{
- struct tool_mw *mw = &tc->mws[idx];
-
- if (mw->peer) {
- ntb_mw_clear_trans(tc->ntb, PIDX, idx);
- dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
- mw->peer,
- mw->peer_dma);
- }
+ struct tool_mw *outmw = &tc->outmws[widx];
- mw->peer = NULL;
- mw->peer_dma = 0;
+ debugfs_remove(outmw->dbgfs_file);
- debugfs_remove(mw->peer_dbg_file);
+ if (outmw->io_base != NULL) {
+ iounmap(tc->outmws[widx].io_base);
+ ntb_peer_mw_clear_trans(tc->ntb, outmw->pidx, widx);
+ }
- mw->peer_dbg_file = NULL;
+ outmw->io_base = NULL;
+ outmw->tr_base = 0;
+ outmw->size = 0;
+ outmw->pidx = -1;
+ outmw->dbgfs_file = NULL;
}
-static ssize_t tool_peer_mw_trans_read(struct file *filep,
- char __user *ubuf,
- size_t size, loff_t *offp)
+static ssize_t tool_peer_mw_trans_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_mw *mw = filep->private_data;
-
- char *buf;
+ struct tool_mw_wrap *outmw_wrap = filep->private_data;
+ struct tool_mw *outmw = outmw_wrap->mw;
+ resource_size_t map_size;
+ phys_addr_t map_base;
+ ssize_t off = 0;
size_t buf_size;
- ssize_t ret, off = 0;
+ char *buf;
+ int ret;
- phys_addr_t base;
- resource_size_t mw_size;
- resource_size_t align_addr = 0;
- resource_size_t align_size = 0;
- resource_size_t max_size = 0;
+ ret = ntb_peer_mw_get_addr(outmw->tc->ntb, outmw->widx,
+ &map_base, &map_size);
+ if (ret)
+ return ret;
buf_size = min_t(size_t, size, 512);
@@ -763,43 +890,37 @@ static ssize_t tool_peer_mw_trans_read(struct file *filep,
if (!buf)
return -ENOMEM;
- ntb_mw_get_align(mw->tc->ntb, PIDX, mw->idx,
- &align_addr, &align_size, &max_size);
- ntb_peer_mw_get_addr(mw->tc->ntb, mw->idx, &base, &mw_size);
-
off += scnprintf(buf + off, buf_size - off,
- "Peer MW %d Information:\n", mw->idx);
+ "Outbound MW: \t%d\n", outmw->widx);
- off += scnprintf(buf + off, buf_size - off,
- "Physical Address \t%pa[p]\n",
- &base);
-
- off += scnprintf(buf + off, buf_size - off,
- "Window Size \t%lld\n",
- (unsigned long long)mw_size);
+ if (outmw->io_base != NULL) {
+ off += scnprintf(buf + off, buf_size - off,
+ "Port attached \t%d (%d)\n",
+ ntb_peer_port_number(outmw->tc->ntb, outmw->pidx),
+ outmw->pidx);
+ } else {
+ off += scnprintf(buf + off, buf_size - off,
+ "Port attached \t-1 (-1)\n");
+ }
off += scnprintf(buf + off, buf_size - off,
- "Alignment \t%lld\n",
- (unsigned long long)align_addr);
+ "Virtual address \t0x%pK\n", outmw->io_base);
off += scnprintf(buf + off, buf_size - off,
- "Size Alignment \t%lld\n",
- (unsigned long long)align_size);
+ "Phys Address \t%pa[p]\n", &map_base);
off += scnprintf(buf + off, buf_size - off,
- "Size Max \t%lld\n",
- (unsigned long long)max_size);
+ "Mapping Size \t%pa[p]\n", &map_size);
off += scnprintf(buf + off, buf_size - off,
- "Ready \t%c\n",
- (mw->peer) ? 'Y' : 'N');
+ "Translation Address \t0x%016llx\n", outmw->tr_base);
off += scnprintf(buf + off, buf_size - off,
- "Allocated Size \t%zd\n",
- (mw->peer) ? (size_t)mw->size : 0);
+ "Window Size \t%pa[p]\n", &outmw->size);
ret = simple_read_from_buffer(ubuf, size, offp, buf, off);
kfree(buf);
+
return ret;
}
@@ -807,12 +928,12 @@ static ssize_t tool_peer_mw_trans_write(struct file *filep,
const char __user *ubuf,
size_t size, loff_t *offp)
{
- struct tool_mw *mw = filep->private_data;
-
- char buf[32];
- size_t buf_size;
- unsigned long long val;
- int rc;
+ struct tool_mw_wrap *outmw_wrap = filep->private_data;
+ struct tool_mw *outmw = outmw_wrap->mw;
+ size_t buf_size, wsize;
+ char buf[TOOL_BUF_LEN];
+ int ret, n;
+ u64 addr;
buf_size = min(size, (sizeof(buf) - 1));
if (copy_from_user(buf, ubuf, buf_size))
@@ -820,16 +941,17 @@ static ssize_t tool_peer_mw_trans_write(struct file *filep,
buf[buf_size] = '\0';
- rc = kstrtoull(buf, 0, &val);
- if (rc)
- return rc;
-
- tool_free_mw(mw->tc, mw->idx);
- if (val)
- rc = tool_setup_mw(mw->tc, mw->idx, val);
+ n = sscanf(buf, "%lli:%zi", &addr, &wsize);
+ if (n != 2)
+ return -EINVAL;
- if (rc)
- return rc;
+ tool_free_peer_mw(outmw->tc, outmw->widx);
+ if (wsize) {
+ ret = tool_setup_peer_mw(outmw->tc, outmw_wrap->pidx,
+ outmw->widx, addr, wsize);
+ if (ret)
+ return ret;
+ }
return size;
}
@@ -838,195 +960,734 @@ static TOOL_FOPS_RDWR(tool_peer_mw_trans_fops,
tool_peer_mw_trans_read,
tool_peer_mw_trans_write);
-static int tool_init_mw(struct tool_ctx *tc, int idx)
+static int tool_init_mws(struct tool_ctx *tc)
{
- struct tool_mw *mw = &tc->mws[idx];
- phys_addr_t base;
- int rc;
-
- rc = ntb_peer_mw_get_addr(tc->ntb, idx, &base, &mw->win_size);
- if (rc)
- return rc;
-
- mw->tc = tc;
- mw->idx = idx;
- mw->local = ioremap_wc(base, mw->win_size);
- if (!mw->local)
- return -EFAULT;
+ int widx, pidx;
+
+ /* Initialize outbound memory windows */
+ tc->outmw_cnt = ntb_peer_mw_count(tc->ntb);
+ tc->outmws = devm_kcalloc(&tc->ntb->dev, tc->outmw_cnt,
+ sizeof(*tc->outmws), GFP_KERNEL);
+ if (tc->outmws == NULL)
+ return -ENOMEM;
+
+ for (widx = 0; widx < tc->outmw_cnt; widx++) {
+ tc->outmws[widx].widx = widx;
+ tc->outmws[widx].pidx = -1;
+ tc->outmws[widx].tc = tc;
+ }
+
+ /* Initialize inbound memory windows and outbound MWs wrapper */
+ for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
+ tc->peers[pidx].inmw_cnt = ntb_mw_count(tc->ntb, pidx);
+ tc->peers[pidx].inmws =
+ devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].inmw_cnt,
+ sizeof(*tc->peers[pidx].inmws), GFP_KERNEL);
+ if (tc->peers[pidx].inmws == NULL)
+ return -ENOMEM;
+
+ for (widx = 0; widx < tc->peers[pidx].inmw_cnt; widx++) {
+ tc->peers[pidx].inmws[widx].widx = widx;
+ tc->peers[pidx].inmws[widx].pidx = pidx;
+ tc->peers[pidx].inmws[widx].tc = tc;
+ }
+
+ tc->peers[pidx].outmw_cnt = ntb_peer_mw_count(tc->ntb);
+ tc->peers[pidx].outmws =
+ devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmw_cnt,
+ sizeof(*tc->peers[pidx].outmws), GFP_KERNEL);
+
+ for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) {
+ tc->peers[pidx].outmws[widx].pidx = pidx;
+ tc->peers[pidx].outmws[widx].mw = &tc->outmws[widx];
+ }
+ }
return 0;
}
-static void tool_free_mws(struct tool_ctx *tc)
+static void tool_clear_mws(struct tool_ctx *tc)
{
- int i;
+ int widx, pidx;
+
+ /* Free outbound memory windows */
+ for (widx = 0; widx < tc->outmw_cnt; widx++)
+ tool_free_peer_mw(tc, widx);
- for (i = 0; i < tc->mw_count; i++) {
- tool_free_mw(tc, i);
+ /* Free outbound memory windows */
+ for (pidx = 0; pidx < tc->peer_cnt; pidx++)
+ for (widx = 0; widx < tc->peers[pidx].inmw_cnt; widx++)
+ tool_free_mw(tc, pidx, widx);
+}
- if (tc->mws[i].local)
- iounmap(tc->mws[i].local);
+/*==============================================================================
+ * Doorbell read/write methods
+ *==============================================================================
+ */
- tc->mws[i].local = NULL;
- }
+static ssize_t tool_db_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->db_read);
}
-static void tool_setup_dbgfs(struct tool_ctx *tc)
+static ssize_t tool_db_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
{
- int i;
+ struct tool_ctx *tc = filep->private_data;
- /* This modules is useless without dbgfs... */
- if (!tool_dbgfs) {
- tc->dbgfs = NULL;
- return;
+ return tool_fn_write(tc, ubuf, size, offp, tc->ntb->ops->db_set,
+ tc->ntb->ops->db_clear);
+}
+
+static TOOL_FOPS_RDWR(tool_db_fops,
+ tool_db_read,
+ tool_db_write);
+
+static ssize_t tool_db_valid_mask_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->db_valid_mask);
+}
+
+static TOOL_FOPS_RDWR(tool_db_valid_mask_fops,
+ tool_db_valid_mask_read,
+ NULL);
+
+static ssize_t tool_db_mask_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->db_read_mask);
+}
+
+static ssize_t tool_db_mask_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_write(tc, ubuf, size, offp, tc->ntb->ops->db_set_mask,
+ tc->ntb->ops->db_clear_mask);
+}
+
+static TOOL_FOPS_RDWR(tool_db_mask_fops,
+ tool_db_mask_read,
+ tool_db_mask_write);
+
+static ssize_t tool_peer_db_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->peer_db_read);
+}
+
+static ssize_t tool_peer_db_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_write(tc, ubuf, size, offp, tc->ntb->ops->peer_db_set,
+ tc->ntb->ops->peer_db_clear);
+}
+
+static TOOL_FOPS_RDWR(tool_peer_db_fops,
+ tool_peer_db_read,
+ tool_peer_db_write);
+
+static ssize_t tool_peer_db_mask_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp,
+ tc->ntb->ops->peer_db_read_mask);
+}
+
+static ssize_t tool_peer_db_mask_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_write(tc, ubuf, size, offp,
+ tc->ntb->ops->peer_db_set_mask,
+ tc->ntb->ops->peer_db_clear_mask);
+}
+
+static TOOL_FOPS_RDWR(tool_peer_db_mask_fops,
+ tool_peer_db_mask_read,
+ tool_peer_db_mask_write);
+
+static ssize_t tool_db_event_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+ u64 val;
+ int ret;
+
+ ret = kstrtou64_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
+
+ if (wait_event_interruptible(tc->db_wq, ntb_db_read(tc->ntb) == val))
+ return -ERESTART;
+
+ return size;
+}
+
+static TOOL_FOPS_RDWR(tool_db_event_fops,
+ NULL,
+ tool_db_event_write);
+
+/*==============================================================================
+ * Scratchpads read/write methods
+ *==============================================================================
+ */
+
+static ssize_t tool_spad_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_spad *spad = filep->private_data;
+ char buf[TOOL_BUF_LEN];
+ ssize_t pos;
+
+ if (!spad->tc->ntb->ops->spad_read)
+ return -EINVAL;
+
+ pos = scnprintf(buf, sizeof(buf), "%#x\n",
+ ntb_spad_read(spad->tc->ntb, spad->sidx));
+
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
+}
+
+static ssize_t tool_spad_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_spad *spad = filep->private_data;
+ u32 val;
+ int ret;
+
+ if (!spad->tc->ntb->ops->spad_write) {
+ dev_dbg(&spad->tc->ntb->dev, "no spad write fn\n");
+ return -EINVAL;
}
- tc->dbgfs = debugfs_create_dir(dev_name(&tc->ntb->dev),
- tool_dbgfs);
- if (!tc->dbgfs)
- return;
+ ret = kstrtou32_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
- debugfs_create_file("db", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_db_fops);
+ ret = ntb_spad_write(spad->tc->ntb, spad->sidx, val);
- debugfs_create_file("mask", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_mask_fops);
+ return ret ?: size;
+}
- debugfs_create_file("peer_db", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_peer_db_fops);
+static TOOL_FOPS_RDWR(tool_spad_fops,
+ tool_spad_read,
+ tool_spad_write);
- debugfs_create_file("peer_mask", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_peer_mask_fops);
+static ssize_t tool_peer_spad_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_spad *spad = filep->private_data;
+ char buf[TOOL_BUF_LEN];
+ ssize_t pos;
- debugfs_create_file("spad", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_spad_fops);
+ if (!spad->tc->ntb->ops->peer_spad_read)
+ return -EINVAL;
- debugfs_create_file("peer_spad", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_peer_spad_fops);
+ pos = scnprintf(buf, sizeof(buf), "%#x\n",
+ ntb_peer_spad_read(spad->tc->ntb, spad->pidx, spad->sidx));
- debugfs_create_file("link", S_IRUSR | S_IWUSR, tc->dbgfs,
- tc, &tool_link_fops);
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
+}
- debugfs_create_file("link_event", S_IWUSR, tc->dbgfs,
- tc, &tool_link_event_fops);
+static ssize_t tool_peer_spad_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_spad *spad = filep->private_data;
+ u32 val;
+ int ret;
+
+ if (!spad->tc->ntb->ops->peer_spad_write) {
+ dev_dbg(&spad->tc->ntb->dev, "no spad write fn\n");
+ return -EINVAL;
+ }
+
+ ret = kstrtou32_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = ntb_peer_spad_write(spad->tc->ntb, spad->pidx, spad->sidx, val);
+
+ return ret ?: size;
+}
- for (i = 0; i < tc->mw_count; i++) {
- char buf[30];
+static TOOL_FOPS_RDWR(tool_peer_spad_fops,
+ tool_peer_spad_read,
+ tool_peer_spad_write);
- snprintf(buf, sizeof(buf), "mw%d", i);
- debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
- &tc->mws[i], &tool_mw_fops);
+static int tool_init_spads(struct tool_ctx *tc)
+{
+ int sidx, pidx;
+
+ /* Initialize inbound scratchpad structures */
+ tc->inspad_cnt = ntb_spad_count(tc->ntb);
+ tc->inspads = devm_kcalloc(&tc->ntb->dev, tc->inspad_cnt,
+ sizeof(*tc->inspads), GFP_KERNEL);
+ if (tc->inspads == NULL)
+ return -ENOMEM;
+
+ for (sidx = 0; sidx < tc->inspad_cnt; sidx++) {
+ tc->inspads[sidx].sidx = sidx;
+ tc->inspads[sidx].pidx = -1;
+ tc->inspads[sidx].tc = tc;
+ }
- snprintf(buf, sizeof(buf), "peer_trans%d", i);
- debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
- &tc->mws[i], &tool_peer_mw_trans_fops);
+ /* Initialize outbound scratchpad structures */
+ for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
+ tc->peers[pidx].outspad_cnt = ntb_spad_count(tc->ntb);
+ tc->peers[pidx].outspads =
+ devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outspad_cnt,
+ sizeof(*tc->peers[pidx].outspads), GFP_KERNEL);
+ if (tc->peers[pidx].outspads == NULL)
+ return -ENOMEM;
+
+ for (sidx = 0; sidx < tc->peers[pidx].outspad_cnt; sidx++) {
+ tc->peers[pidx].outspads[sidx].sidx = sidx;
+ tc->peers[pidx].outspads[sidx].pidx = pidx;
+ tc->peers[pidx].outspads[sidx].tc = tc;
+ }
}
+
+ return 0;
}
-static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
+/*==============================================================================
+ * Messages read/write methods
+ *==============================================================================
+ */
+
+static ssize_t tool_inmsg_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
{
- struct tool_ctx *tc;
- int rc;
- int i;
+ struct tool_msg *msg = filep->private_data;
+ char buf[TOOL_BUF_LEN];
+ ssize_t pos;
+ u32 data;
+ int pidx;
+
+ data = ntb_msg_read(msg->tc->ntb, &pidx, msg->midx);
+
+ pos = scnprintf(buf, sizeof(buf), "0x%08x<-%d\n", data, pidx);
+
+ return simple_read_from_buffer(ubuf, size, offp, buf, pos);
+}
+
+static TOOL_FOPS_RDWR(tool_inmsg_fops,
+ tool_inmsg_read,
+ NULL);
+
+static ssize_t tool_outmsg_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_msg *msg = filep->private_data;
+ u32 val;
+ int ret;
+
+ ret = kstrtou32_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
+
+ ret = ntb_peer_msg_write(msg->tc->ntb, msg->pidx, msg->midx, val);
+
+ return ret ? : size;
+}
+
+static TOOL_FOPS_RDWR(tool_outmsg_fops,
+ NULL,
+ tool_outmsg_write);
+
+static ssize_t tool_msg_sts_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->msg_read_sts);
+}
+
+static ssize_t tool_msg_sts_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_write(tc, ubuf, size, offp, NULL,
+ tc->ntb->ops->msg_clear_sts);
+}
+
+static TOOL_FOPS_RDWR(tool_msg_sts_fops,
+ tool_msg_sts_read,
+ tool_msg_sts_write);
+
+static ssize_t tool_msg_inbits_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->msg_inbits);
+}
+
+static TOOL_FOPS_RDWR(tool_msg_inbits_fops,
+ tool_msg_inbits_read,
+ NULL);
- if (!ntb->ops->mw_set_trans) {
- dev_dbg(&ntb->dev, "need inbound MW based NTB API\n");
- rc = -EINVAL;
- goto err_tc;
+static ssize_t tool_msg_outbits_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_read(tc, ubuf, size, offp, tc->ntb->ops->msg_outbits);
+}
+
+static TOOL_FOPS_RDWR(tool_msg_outbits_fops,
+ tool_msg_outbits_read,
+ NULL);
+
+static ssize_t tool_msg_mask_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+
+ return tool_fn_write(tc, ubuf, size, offp,
+ tc->ntb->ops->msg_set_mask,
+ tc->ntb->ops->msg_clear_mask);
+}
+
+static TOOL_FOPS_RDWR(tool_msg_mask_fops,
+ NULL,
+ tool_msg_mask_write);
+
+static ssize_t tool_msg_event_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+ u64 val;
+ int ret;
+
+ ret = kstrtou64_from_user(ubuf, size, 0, &val);
+ if (ret)
+ return ret;
+
+ if (wait_event_interruptible(tc->msg_wq,
+ ntb_msg_read_sts(tc->ntb) == val))
+ return -ERESTART;
+
+ return size;
+}
+
+static TOOL_FOPS_RDWR(tool_msg_event_fops,
+ NULL,
+ tool_msg_event_write);
+
+static int tool_init_msgs(struct tool_ctx *tc)
+{
+ int midx, pidx;
+
+ /* Initialize inbound message structures */
+ tc->inmsg_cnt = ntb_msg_count(tc->ntb);
+ tc->inmsgs = devm_kcalloc(&tc->ntb->dev, tc->inmsg_cnt,
+ sizeof(*tc->inmsgs), GFP_KERNEL);
+ if (tc->inmsgs == NULL)
+ return -ENOMEM;
+
+ for (midx = 0; midx < tc->inmsg_cnt; midx++) {
+ tc->inmsgs[midx].midx = midx;
+ tc->inmsgs[midx].pidx = -1;
+ tc->inmsgs[midx].tc = tc;
}
- if (ntb_spad_count(ntb) < 1) {
- dev_dbg(&ntb->dev, "no enough scratchpads\n");
- rc = -EINVAL;
- goto err_tc;
+ /* Initialize outbound message structures */
+ for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
+ tc->peers[pidx].outmsg_cnt = ntb_msg_count(tc->ntb);
+ tc->peers[pidx].outmsgs =
+ devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmsg_cnt,
+ sizeof(*tc->peers[pidx].outmsgs), GFP_KERNEL);
+ if (tc->peers[pidx].outmsgs == NULL)
+ return -ENOMEM;
+
+ for (midx = 0; midx < tc->peers[pidx].outmsg_cnt; midx++) {
+ tc->peers[pidx].outmsgs[midx].midx = midx;
+ tc->peers[pidx].outmsgs[midx].pidx = pidx;
+ tc->peers[pidx].outmsgs[midx].tc = tc;
+ }
}
+ return 0;
+}
+
+/*==============================================================================
+ * Initialization methods
+ *==============================================================================
+ */
+
+static struct tool_ctx *tool_create_data(struct ntb_dev *ntb)
+{
+ struct tool_ctx *tc;
+
+ tc = devm_kzalloc(&ntb->dev, sizeof(*tc), GFP_KERNEL);
+ if (tc == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ tc->ntb = ntb;
+ init_waitqueue_head(&tc->link_wq);
+ init_waitqueue_head(&tc->db_wq);
+ init_waitqueue_head(&tc->msg_wq);
+
if (ntb_db_is_unsafe(ntb))
dev_dbg(&ntb->dev, "doorbell is unsafe\n");
if (ntb_spad_is_unsafe(ntb))
dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
- if (ntb_peer_port_count(ntb) != NTB_DEF_PEER_CNT)
- dev_warn(&ntb->dev, "multi-port NTB is unsupported\n");
+ return tc;
+}
+
+static void tool_clear_data(struct tool_ctx *tc)
+{
+ wake_up(&tc->link_wq);
+ wake_up(&tc->db_wq);
+ wake_up(&tc->msg_wq);
+}
+
+static int tool_init_ntb(struct tool_ctx *tc)
+{
+ return ntb_set_ctx(tc->ntb, tc, &tool_ops);
+}
- tc = kzalloc(sizeof(*tc), GFP_KERNEL);
- if (!tc) {
- rc = -ENOMEM;
- goto err_tc;
+static void tool_clear_ntb(struct tool_ctx *tc)
+{
+ ntb_clear_ctx(tc->ntb);
+ ntb_link_disable(tc->ntb);
+}
+
+static void tool_setup_dbgfs(struct tool_ctx *tc)
+{
+ int pidx, widx, sidx, midx;
+ char buf[TOOL_BUF_LEN];
+
+ /* This modules is useless without dbgfs... */
+ if (!tool_dbgfs_topdir) {
+ tc->dbgfs_dir = NULL;
+ return;
}
- tc->ntb = ntb;
- init_waitqueue_head(&tc->link_wq);
+ tc->dbgfs_dir = debugfs_create_dir(dev_name(&tc->ntb->dev),
+ tool_dbgfs_topdir);
+ if (!tc->dbgfs_dir)
+ return;
+
+ debugfs_create_file("port", 0600, tc->dbgfs_dir,
+ tc, &tool_port_fops);
+
+ debugfs_create_file("link", 0600, tc->dbgfs_dir,
+ tc, &tool_link_fops);
+
+ debugfs_create_file("db", 0600, tc->dbgfs_dir,
+ tc, &tool_db_fops);
+
+ debugfs_create_file("db_valid_mask", 0600, tc->dbgfs_dir,
+ tc, &tool_db_valid_mask_fops);
+
+ debugfs_create_file("db_mask", 0600, tc->dbgfs_dir,
+ tc, &tool_db_mask_fops);
- tc->mw_count = min(ntb_peer_mw_count(tc->ntb), MAX_MWS);
- for (i = 0; i < tc->mw_count; i++) {
- rc = tool_init_mw(tc, i);
- if (rc)
- goto err_ctx;
+ debugfs_create_file("db_event", 0600, tc->dbgfs_dir,
+ tc, &tool_db_event_fops);
+
+ debugfs_create_file("peer_db", 0600, tc->dbgfs_dir,
+ tc, &tool_peer_db_fops);
+
+ debugfs_create_file("peer_db_mask", 0600, tc->dbgfs_dir,
+ tc, &tool_peer_db_mask_fops);
+
+ if (tc->inspad_cnt != 0) {
+ for (sidx = 0; sidx < tc->inspad_cnt; sidx++) {
+ snprintf(buf, sizeof(buf), "spad%d", sidx);
+
+ debugfs_create_file(buf, 0600, tc->dbgfs_dir,
+ &tc->inspads[sidx], &tool_spad_fops);
+ }
}
- tool_setup_dbgfs(tc);
+ if (tc->inmsg_cnt != 0) {
+ for (midx = 0; midx < tc->inmsg_cnt; midx++) {
+ snprintf(buf, sizeof(buf), "msg%d", midx);
+ debugfs_create_file(buf, 0600, tc->dbgfs_dir,
+ &tc->inmsgs[midx], &tool_inmsg_fops);
+ }
+
+ debugfs_create_file("msg_sts", 0600, tc->dbgfs_dir,
+ tc, &tool_msg_sts_fops);
+
+ debugfs_create_file("msg_inbits", 0600, tc->dbgfs_dir,
+ tc, &tool_msg_inbits_fops);
- rc = ntb_set_ctx(ntb, tc, &tool_ops);
- if (rc)
- goto err_ctx;
+ debugfs_create_file("msg_outbits", 0600, tc->dbgfs_dir,
+ tc, &tool_msg_outbits_fops);
- ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
- ntb_link_event(ntb);
+ debugfs_create_file("msg_mask", 0600, tc->dbgfs_dir,
+ tc, &tool_msg_mask_fops);
+
+ debugfs_create_file("msg_event", 0600, tc->dbgfs_dir,
+ tc, &tool_msg_event_fops);
+ }
+
+ for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
+ snprintf(buf, sizeof(buf), "peer%d", pidx);
+ tc->peers[pidx].dbgfs_dir =
+ debugfs_create_dir(buf, tc->dbgfs_dir);
+
+ debugfs_create_file("port", 0600,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx], &tool_peer_port_fops);
+
+ debugfs_create_file("link", 0200,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx], &tool_peer_link_fops);
+
+ debugfs_create_file("link_event", 0200,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx], &tool_peer_link_event_fops);
+
+ for (widx = 0; widx < tc->peers[pidx].inmw_cnt; widx++) {
+ snprintf(buf, sizeof(buf), "mw_trans%d", widx);
+ debugfs_create_file(buf, 0600,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx].inmws[widx],
+ &tool_mw_trans_fops);
+ }
+
+ for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) {
+ snprintf(buf, sizeof(buf), "peer_mw_trans%d", widx);
+ debugfs_create_file(buf, 0600,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx].outmws[widx],
+ &tool_peer_mw_trans_fops);
+ }
+
+ for (sidx = 0; sidx < tc->peers[pidx].outspad_cnt; sidx++) {
+ snprintf(buf, sizeof(buf), "spad%d", sidx);
+
+ debugfs_create_file(buf, 0600,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx].outspads[sidx],
+ &tool_peer_spad_fops);
+ }
+
+ for (midx = 0; midx < tc->peers[pidx].outmsg_cnt; midx++) {
+ snprintf(buf, sizeof(buf), "msg%d", midx);
+ debugfs_create_file(buf, 0600,
+ tc->peers[pidx].dbgfs_dir,
+ &tc->peers[pidx].outmsgs[midx],
+ &tool_outmsg_fops);
+ }
+ }
+}
+
+static void tool_clear_dbgfs(struct tool_ctx *tc)
+{
+ debugfs_remove_recursive(tc->dbgfs_dir);
+}
+
+static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
+{
+ struct tool_ctx *tc;
+ int ret;
+
+ tc = tool_create_data(ntb);
+ if (IS_ERR(tc))
+ return PTR_ERR(tc);
+
+ ret = tool_init_peers(tc);
+ if (ret != 0)
+ goto err_clear_data;
+
+ ret = tool_init_mws(tc);
+ if (ret != 0)
+ goto err_clear_data;
+
+ ret = tool_init_spads(tc);
+ if (ret != 0)
+ goto err_clear_mws;
+
+ ret = tool_init_msgs(tc);
+ if (ret != 0)
+ goto err_clear_mws;
+
+ ret = tool_init_ntb(tc);
+ if (ret != 0)
+ goto err_clear_mws;
+
+ tool_setup_dbgfs(tc);
return 0;
-err_ctx:
- tool_free_mws(tc);
- debugfs_remove_recursive(tc->dbgfs);
- kfree(tc);
-err_tc:
- return rc;
+err_clear_mws:
+ tool_clear_mws(tc);
+
+err_clear_data:
+ tool_clear_data(tc);
+
+ return ret;
}
static void tool_remove(struct ntb_client *self, struct ntb_dev *ntb)
{
struct tool_ctx *tc = ntb->ctx;
- tool_free_mws(tc);
+ tool_clear_dbgfs(tc);
- ntb_clear_ctx(ntb);
- ntb_link_disable(ntb);
+ tool_clear_ntb(tc);
- debugfs_remove_recursive(tc->dbgfs);
- kfree(tc);
+ tool_clear_mws(tc);
+
+ tool_clear_data(tc);
}
static struct ntb_client tool_client = {
.ops = {
.probe = tool_probe,
.remove = tool_remove,
- },
+ }
};
static int __init tool_init(void)
{
- int rc;
+ int ret;
if (debugfs_initialized())
- tool_dbgfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ tool_dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- rc = ntb_register_client(&tool_client);
- if (rc)
- goto err_client;
+ ret = ntb_register_client(&tool_client);
+ if (ret)
+ debugfs_remove_recursive(tool_dbgfs_topdir);
- return 0;
-
-err_client:
- debugfs_remove_recursive(tool_dbgfs);
- return rc;
+ return ret;
}
module_init(tool_init);
static void __exit tool_exit(void)
{
ntb_unregister_client(&tool_client);
- debugfs_remove_recursive(tool_dbgfs);
+ debugfs_remove_recursive(tool_dbgfs_topdir);
}
module_exit(tool_exit);
+
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index a3449d717a99..fc01d7d807f3 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -27,6 +27,7 @@
#include <linux/mutex.h>
#include <asm/rtas.h>
#include <asm/vio.h>
+#include <linux/firmware.h>
#include "../pci.h"
#include "rpaphp.h"
@@ -44,15 +45,14 @@ static struct device_node *find_vio_slot_node(char *drc_name)
{
struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
struct device_node *dn = NULL;
- char *name;
int rc;
if (!parent)
return NULL;
while ((dn = of_get_next_child(parent, dn))) {
- rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
- if ((rc == 0) && (!strcmp(drc_name, name)))
+ rc = rpaphp_check_drc_props(dn, drc_name, NULL);
+ if (rc == 0)
break;
}
@@ -64,15 +64,12 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
char *drc_type)
{
struct device_node *np = NULL;
- char *name;
- char *type;
int rc;
while ((np = of_find_node_by_name(np, "pci"))) {
- rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL);
+ rc = rpaphp_check_drc_props(np, drc_name, drc_type);
if (rc == 0)
- if (!strcmp(drc_name, name) && !strcmp(drc_type, type))
- break;
+ break;
}
return np;
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index edb5d8a53020..b806314349cf 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
+#include "rpaphp.h"
#include "rpadlpar.h"
#include "../pci.h"
@@ -27,8 +28,6 @@
#define ADD_SLOT_ATTR_NAME add_slot
#define REMOVE_SLOT_ATTR_NAME remove_slot
-#define MAX_DRC_NAME_LEN 64
-
static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t nbytes)
{
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 7db024e68fe6..bdb844b01a3d 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -64,6 +64,10 @@ extern bool rpaphp_debug;
#define CONFIGURED 1
#define EMPTY 0
+/* DRC constants */
+
+#define MAX_DRC_NAME_LEN 64
+
/*
* struct slot - slot information for each *physical* slot
*/
@@ -91,8 +95,8 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state);
/* rpaphp_core.c */
int rpaphp_add_slot(struct device_node *dn);
-int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
- char **drc_name, char **drc_type, int *drc_power_domain);
+int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
+ char *drc_type);
/* rpaphp_slot.c */
void dealloc_slot_struct(struct slot *slot);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 1e29abaaea08..53902c7c38f2 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -30,6 +30,7 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
+#include <asm/firmware.h>
#include <asm/eeh.h> /* for eeh_add_device() */
#include <asm/rtas.h> /* rtas_call */
#include <asm/pci-bridge.h> /* for pci_controller */
@@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,
return 0;
}
-/* To get the DRC props describing the current node, first obtain it's
- * my-drc-index property. Next obtain the DRC list from it's parent. Use
- * the my-drc-index for correlation, and obtain the requested properties.
+
+/* Verify the existence of 'drc_name' and/or 'drc_type' within the
+ * current node. First obtain it's my-drc-index property. Next,
+ * obtain the DRC info from it's parent. Use the my-drc-index for
+ * correlation, and obtain/validate the requested properties.
*/
-int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
- char **drc_name, char **drc_type, int *drc_power_domain)
+
+static int rpaphp_check_drc_props_v1(struct device_node *dn, char *drc_name,
+ char *drc_type, unsigned int my_index)
{
+ char *name_tmp, *type_tmp;
const int *indexes, *names;
const int *types, *domains;
- const unsigned int *my_index;
- char *name_tmp, *type_tmp;
int i, rc;
- my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
- if (!my_index) {
- /* Node isn't DLPAR/hotplug capable */
- return -EINVAL;
- }
-
rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
if (rc < 0) {
return -EINVAL;
@@ -225,24 +222,84 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
/* Iterate through parent properties, looking for my-drc-index */
for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
- if ((unsigned int) indexes[i + 1] == *my_index) {
- if (drc_name)
- *drc_name = name_tmp;
- if (drc_type)
- *drc_type = type_tmp;
- if (drc_index)
- *drc_index = be32_to_cpu(*my_index);
- if (drc_power_domain)
- *drc_power_domain = be32_to_cpu(domains[i+1]);
- return 0;
- }
+ if ((unsigned int) indexes[i + 1] == my_index)
+ break;
+
name_tmp += (strlen(name_tmp) + 1);
type_tmp += (strlen(type_tmp) + 1);
}
+ if (((drc_name == NULL) || (drc_name && !strcmp(drc_name, name_tmp))) &&
+ ((drc_type == NULL) || (drc_type && !strcmp(drc_type, type_tmp))))
+ return 0;
+
return -EINVAL;
}
-EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
+
+static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
+ char *drc_type, unsigned int my_index)
+{
+ struct property *info;
+ unsigned int entries;
+ struct of_drc_info drc;
+ const __be32 *value;
+ char cell_drc_name[MAX_DRC_NAME_LEN];
+ int j, fndit;
+
+ info = of_find_property(dn->parent, "ibm,drc-info", NULL);
+ if (info == NULL)
+ return -EINVAL;
+
+ value = of_prop_next_u32(info, NULL, &entries);
+ if (!value)
+ return -EINVAL;
+
+ for (j = 0; j < entries; j++) {
+ of_read_drc_info_cell(&info, &value, &drc);
+
+ /* Should now know end of current entry */
+
+ if (my_index > drc.last_drc_index)
+ continue;
+
+ fndit = 1;
+ break;
+ }
+ /* Found it */
+
+ if (fndit)
+ sprintf(cell_drc_name, "%s%d", drc.drc_name_prefix,
+ my_index);
+
+ if (((drc_name == NULL) ||
+ (drc_name && !strcmp(drc_name, cell_drc_name))) &&
+ ((drc_type == NULL) ||
+ (drc_type && !strcmp(drc_type, drc.drc_type))))
+ return 0;
+
+ return -EINVAL;
+}
+
+int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
+ char *drc_type)
+{
+ const unsigned int *my_index;
+
+ my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
+ if (!my_index) {
+ /* Node isn't DLPAR/hotplug capable */
+ return -EINVAL;
+ }
+
+ if (firmware_has_feature(FW_FEATURE_DRC_INFO))
+ return rpaphp_check_drc_props_v2(dn, drc_name, drc_type,
+ *my_index);
+ else
+ return rpaphp_check_drc_props_v1(dn, drc_name, drc_type,
+ *my_index);
+}
+EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);
+
static int is_php_type(char *drc_type)
{
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 6bacb8995e96..0b7b5da63d4e 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -636,6 +636,17 @@ void pci_restore_iov_state(struct pci_dev *dev)
}
/**
+ * pci_vf_drivers_autoprobe - set PF property drivers_autoprobe for VFs
+ * @dev: the PCI device
+ * @auto_probe: set VF drivers auto probe flag
+ */
+void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool auto_probe)
+{
+ if (dev->is_physfn)
+ dev->sriov->drivers_autoprobe = auto_probe;
+}
+
+/**
* pci_iov_bus_range - find bus range used by Virtual Function
* @bus: the PCI bus
*
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 744805232155..8d7448063fd1 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -278,6 +278,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
} else {
err_handler = dev->driver->err_handler;
vote = err_handler->error_detected(dev, result_data->state);
+ pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
}
result_data->result = merge_result(result_data->result, vote);
@@ -341,6 +342,7 @@ static int report_resume(struct pci_dev *dev, void *data)
err_handler = dev->driver->err_handler;
err_handler->resume(dev);
+ pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
out:
device_unlock(&dev->dev);
return 0;
@@ -541,6 +543,7 @@ static void do_recovery(struct pci_dev *dev, int severity)
return;
failed:
+ pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
/* TODO: Should kernel panic here? */
dev_info(&dev->dev, "AER: Device recovery failed\n");
}
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ce126955212c..0f254b35c378 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -66,6 +66,10 @@ config PINCTRL_AS3722
config PINCTRL_AXP209
tristate "X-Powers AXP209 PMIC pinctrl and GPIO Support"
depends on MFD_AXP20X
+ depends on OF
+ select PINMUX
+ select GENERIC_PINCONF
+ select GPIOLIB
help
AXP PMICs provides multiple GPIOs that can be muxed for different
functions. This driver bundles a pinctrl driver to select the function
@@ -353,6 +357,17 @@ config PINCTRL_RK805
help
This selects the pinctrl driver for RK805.
+config PINCTRL_OCELOT
+ bool "Pinctrl driver for the Microsemi Ocelot SoCs"
+ default y
+ depends on OF
+ depends on MSCC_OCELOT || COMPILE_TEST
+ select GPIOLIB
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select REGMAP_MMIO
+
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"
source "drivers/pinctrl/berlin/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 4777f1595ce2..d3692633e9ed 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
+obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-y += bcm/
@@ -65,5 +66,5 @@ obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
-obj-$(CONFIG_PINCTRL_MTK) += mediatek/
+obj-y += mediatek/
obj-$(CONFIG_PINCTRL_ZX) += zte/
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 4c8d5b23e4d0..2c0dbfcff3e6 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1189,19 +1189,16 @@ struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,
EXPORT_SYMBOL_GPL(pinctrl_lookup_state);
/**
- * pinctrl_select_state() - select/activate/program a pinctrl state to HW
+ * pinctrl_commit_state() - select/activate/program a pinctrl state to HW
* @p: the pinctrl handle for the device that requests configuration
* @state: the state handle to select/activate/program
*/
-int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
+static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
{
struct pinctrl_setting *setting, *setting2;
struct pinctrl_state *old_state = p->state;
int ret;
- if (p->state == state)
- return 0;
-
if (p->state) {
/*
* For each pinmux setting in the old state, forget SW's record
@@ -1265,6 +1262,19 @@ unapply_new_state:
return ret;
}
+
+/**
+ * pinctrl_select_state() - select/activate/program a pinctrl state to HW
+ * @p: the pinctrl handle for the device that requests configuration
+ * @state: the state handle to select/activate/program
+ */
+int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
+{
+ if (p->state == state)
+ return 0;
+
+ return pinctrl_commit_state(p, state);
+}
EXPORT_SYMBOL_GPL(pinctrl_select_state);
static void devm_pinctrl_release(struct device *dev, void *res)
@@ -1430,7 +1440,7 @@ void pinctrl_unregister_map(const struct pinctrl_map *map)
int pinctrl_force_sleep(struct pinctrl_dev *pctldev)
{
if (!IS_ERR(pctldev->p) && !IS_ERR(pctldev->hog_sleep))
- return pinctrl_select_state(pctldev->p, pctldev->hog_sleep);
+ return pinctrl_commit_state(pctldev->p, pctldev->hog_sleep);
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_force_sleep);
@@ -1442,7 +1452,7 @@ EXPORT_SYMBOL_GPL(pinctrl_force_sleep);
int pinctrl_force_default(struct pinctrl_dev *pctldev)
{
if (!IS_ERR(pctldev->p) && !IS_ERR(pctldev->hog_default))
- return pinctrl_select_state(pctldev->p, pctldev->hog_default);
+ return pinctrl_commit_state(pctldev->p, pctldev->hog_default);
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_force_default);
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index 6e472691d8ee..24aaddd760a0 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -62,7 +62,6 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct pinctrl_map **map, unsigned *num_maps)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
const struct group_desc *grp;
struct pinctrl_map *new_map;
struct device_node *parent;
@@ -75,7 +74,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
*/
grp = imx_pinctrl_find_group_by_name(pctldev, np->name);
if (!grp) {
- dev_err(info->dev, "unable to find group for node %s\n",
+ dev_err(ipctl->dev, "unable to find group for node %s\n",
np->name);
return -EINVAL;
}
@@ -146,7 +145,7 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
unsigned int npins, pin_id;
int i;
@@ -174,7 +173,7 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
pin_id = pin->pin;
- pin_reg = &info->pin_regs[pin_id];
+ pin_reg = &ipctl->pin_regs[pin_id];
if (pin_reg->mux_reg == -1) {
dev_dbg(ipctl->dev, "Pin(%s) does not support mux function\n",
@@ -255,8 +254,8 @@ static u32 imx_pinconf_decode_generic_config(struct imx_pinctrl *ipctl,
unsigned long *configs,
unsigned int num_configs)
{
- struct imx_pinctrl_soc_info *info = ipctl->info;
- struct imx_cfg_params_decode *decode;
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_cfg_params_decode *decode;
enum pin_config_param param;
u32 raw_config = 0;
u32 param_val;
@@ -289,7 +288,7 @@ static u32 imx_pinconf_decode_generic_config(struct imx_pinctrl *ipctl,
static u32 imx_pinconf_parse_generic_config(struct device_node *np,
struct imx_pinctrl *ipctl)
{
- struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
struct pinctrl_dev *pctl = ipctl->pctl;
unsigned int num_configs;
unsigned long *configs;
@@ -310,11 +309,11 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long *config)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
- const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg = &ipctl->pin_regs[pin_id];
if (pin_reg->conf_reg == -1) {
- dev_err(info->dev, "Pin(%s) does not support config function\n",
+ dev_err(ipctl->dev, "Pin(%s) does not support config function\n",
info->pins[pin_id].name);
return -EINVAL;
}
@@ -332,12 +331,12 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
unsigned num_configs)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
- const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg = &ipctl->pin_regs[pin_id];
int i;
if (pin_reg->conf_reg == -1) {
- dev_err(info->dev, "Pin(%s) does not support config function\n",
+ dev_err(ipctl->dev, "Pin(%s) does not support config function\n",
info->pins[pin_id].name);
return -EINVAL;
}
@@ -368,8 +367,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
- const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
+ const struct imx_pin_reg *pin_reg = &ipctl->pin_regs[pin_id];
unsigned long config;
if (!pin_reg || pin_reg->conf_reg == -1) {
@@ -427,13 +425,13 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
struct imx_pinctrl *ipctl,
u32 index)
{
- struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
int size, pin_size;
const __be32 *list;
int i;
u32 config;
- dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+ dev_dbg(ipctl->dev, "group(%d): %s\n", index, np->name);
if (info->flags & SHARE_MUX_CONF_REG)
pin_size = SHARE_FSL_PIN_SIZE;
@@ -460,7 +458,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
if (!list) {
list = of_get_property(np, "pinmux", &size);
if (!list) {
- dev_err(info->dev,
+ dev_err(ipctl->dev,
"no fsl,pins and pins property in node %pOF\n", np);
return -EINVAL;
}
@@ -468,7 +466,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
/* we do not check return since it's safe node passed down */
if (!size || size % pin_size) {
- dev_err(info->dev, "Invalid fsl,pins or pins property in node %pOF\n", np);
+ dev_err(ipctl->dev, "Invalid fsl,pins or pins property in node %pOF\n", np);
return -EINVAL;
}
@@ -476,9 +474,9 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
config = imx_pinconf_parse_generic_config(np, ipctl);
grp->num_pins = size / pin_size;
- grp->data = devm_kzalloc(info->dev, grp->num_pins *
+ grp->data = devm_kzalloc(ipctl->dev, grp->num_pins *
sizeof(struct imx_pin), GFP_KERNEL);
- grp->pins = devm_kzalloc(info->dev, grp->num_pins *
+ grp->pins = devm_kzalloc(ipctl->dev, grp->num_pins *
sizeof(unsigned int), GFP_KERNEL);
if (!grp->pins || !grp->data)
return -ENOMEM;
@@ -502,7 +500,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
}
pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
- pin_reg = &info->pin_regs[pin_id];
+ pin_reg = &ipctl->pin_regs[pin_id];
pin->pin = pin_id;
grp->pins[i] = pin_id;
pin_reg->mux_reg = mux_reg;
@@ -524,7 +522,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
pin->config = config & ~IMX_PAD_SION;
}
- dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
+ dev_dbg(ipctl->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
pin->mux_mode, pin->config);
}
@@ -536,13 +534,12 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
u32 index)
{
struct pinctrl_dev *pctl = ipctl->pctl;
- struct imx_pinctrl_soc_info *info = ipctl->info;
struct device_node *child;
struct function_desc *func;
struct group_desc *grp;
u32 i = 0;
- dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+ dev_dbg(pctl->dev, "parse function(%d): %s\n", index, np->name);
func = pinmux_generic_get_function(pctl, index);
if (!func)
@@ -552,10 +549,10 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
func->name = np->name;
func->num_group_names = of_get_child_count(np);
if (func->num_group_names == 0) {
- dev_err(info->dev, "no groups defined in %pOF\n", np);
+ dev_err(ipctl->dev, "no groups defined in %pOF\n", np);
return -EINVAL;
}
- func->group_names = devm_kcalloc(info->dev, func->num_group_names,
+ func->group_names = devm_kcalloc(ipctl->dev, func->num_group_names,
sizeof(char *), GFP_KERNEL);
if (!func->group_names)
return -ENOMEM;
@@ -563,15 +560,15 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
for_each_child_of_node(np, child) {
func->group_names[i] = child->name;
- grp = devm_kzalloc(info->dev, sizeof(struct group_desc),
+ grp = devm_kzalloc(ipctl->dev, sizeof(struct group_desc),
GFP_KERNEL);
if (!grp)
return -ENOMEM;
- mutex_lock(&info->mutex);
+ mutex_lock(&ipctl->mutex);
radix_tree_insert(&pctl->pin_group_tree,
- info->group_index++, grp);
- mutex_unlock(&info->mutex);
+ ipctl->group_index++, grp);
+ mutex_unlock(&ipctl->mutex);
imx_pinctrl_parse_groups(child, grp, ipctl, i++);
}
@@ -608,7 +605,6 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
struct pinctrl_dev *pctl = ipctl->pctl;
- struct imx_pinctrl_soc_info *info = ipctl->info;
u32 nfuncs = 0;
u32 i = 0;
bool flat_funcs;
@@ -635,13 +631,13 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
if (!function)
return -ENOMEM;
- mutex_lock(&info->mutex);
+ mutex_lock(&ipctl->mutex);
radix_tree_insert(&pctl->pin_function_tree, i, function);
- mutex_unlock(&info->mutex);
+ mutex_unlock(&ipctl->mutex);
}
pctl->num_functions = nfuncs;
- info->group_index = 0;
+ ipctl->group_index = 0;
if (flat_funcs) {
pctl->num_groups = of_get_child_count(np);
} else {
@@ -672,7 +668,7 @@ static void imx_free_resources(struct imx_pinctrl *ipctl)
}
int imx_pinctrl_probe(struct platform_device *pdev,
- struct imx_pinctrl_soc_info *info)
+ const struct imx_pinctrl_soc_info *info)
{
struct regmap_config config = { .name = "gpr" };
struct device_node *dev_np = pdev->dev.of_node;
@@ -687,7 +683,6 @@ int imx_pinctrl_probe(struct platform_device *pdev,
dev_err(&pdev->dev, "wrong pinctrl info\n");
return -EINVAL;
}
- info->dev = &pdev->dev;
if (info->gpr_compatible) {
gpr = syscon_regmap_lookup_by_compatible(info->gpr_compatible);
@@ -700,14 +695,14 @@ int imx_pinctrl_probe(struct platform_device *pdev,
if (!ipctl)
return -ENOMEM;
- info->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*info->pin_regs) *
+ ipctl->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*ipctl->pin_regs) *
info->npins, GFP_KERNEL);
- if (!info->pin_regs)
+ if (!ipctl->pin_regs)
return -ENOMEM;
for (i = 0; i < info->npins; i++) {
- info->pin_regs[i].mux_reg = -1;
- info->pin_regs[i].conf_reg = -1;
+ ipctl->pin_regs[i].mux_reg = -1;
+ ipctl->pin_regs[i].conf_reg = -1;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -751,10 +746,10 @@ int imx_pinctrl_probe(struct platform_device *pdev,
/* platform specific callback */
imx_pmx_ops.gpio_set_direction = info->gpio_set_direction;
- mutex_init(&info->mutex);
+ mutex_init(&ipctl->mutex);
ipctl->info = info;
- ipctl->dev = info->dev;
+ ipctl->dev = &pdev->dev;
platform_set_drvdata(pdev, ipctl);
ret = devm_pinctrl_register_and_init(&pdev->dev,
imx_pinctrl_desc, ipctl,
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h b/drivers/pinctrl/freescale/pinctrl-imx.h
index 5aa22b52c1d4..038e8c0e5b96 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -58,14 +58,10 @@ struct imx_cfg_params_decode {
};
struct imx_pinctrl_soc_info {
- struct device *dev;
const struct pinctrl_pin_desc *pins;
unsigned int npins;
- struct imx_pin_reg *pin_regs;
- unsigned int group_index;
unsigned int flags;
const char *gpr_compatible;
- struct mutex mutex;
/* MUX_MODE shift and mask in case SHARE_MUX_CONF_REG */
unsigned int mux_mask;
@@ -75,7 +71,7 @@ struct imx_pinctrl_soc_info {
bool generic_pinconf;
const struct pinconf_generic_params *custom_params;
unsigned int num_custom_params;
- struct imx_cfg_params_decode *decodes;
+ const struct imx_cfg_params_decode *decodes;
unsigned int num_decodes;
void (*fixup)(unsigned long *configs, unsigned int num_configs,
u32 *raw_config);
@@ -95,7 +91,10 @@ struct imx_pinctrl {
struct pinctrl_dev *pctl;
void __iomem *base;
void __iomem *input_sel_base;
- struct imx_pinctrl_soc_info *info;
+ const struct imx_pinctrl_soc_info *info;
+ struct imx_pin_reg *pin_regs;
+ unsigned int group_index;
+ struct mutex mutex;
};
#define IMX_CFG_PARAMS_DECODE(p, m, o) \
@@ -117,5 +116,5 @@ struct imx_pinctrl {
#define IOMUXC_CONFIG_SION (0x1 << 4)
int imx_pinctrl_probe(struct platform_device *pdev,
- struct imx_pinctrl_soc_info *info);
+ const struct imx_pinctrl_soc_info *info);
#endif /* __DRIVERS_PINCTRL_IMX_H */
diff --git a/drivers/pinctrl/freescale/pinctrl-imx25.c b/drivers/pinctrl/freescale/pinctrl-imx25.c
index d7367fabe712..db6d9d1382f9 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx25.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx25.c
@@ -309,7 +309,7 @@ static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX25_PAD_BOOT_MODE1),
};
-static struct imx_pinctrl_soc_info imx25_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx25_pinctrl_info = {
.pins = imx25_pinctrl_pads,
.npins = ARRAY_SIZE(imx25_pinctrl_pads),
};
diff --git a/drivers/pinctrl/freescale/pinctrl-imx35.c b/drivers/pinctrl/freescale/pinctrl-imx35.c
index 6315ba6af431..6927946ae4b5 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx35.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx35.c
@@ -999,7 +999,7 @@ static const struct pinctrl_pin_desc imx35_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX35_PAD_TEST_MODE),
};
-static struct imx_pinctrl_soc_info imx35_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx35_pinctrl_info = {
.pins = imx35_pinctrl_pads,
.npins = ARRAY_SIZE(imx35_pinctrl_pads),
};
diff --git a/drivers/pinctrl/freescale/pinctrl-imx50.c b/drivers/pinctrl/freescale/pinctrl-imx50.c
index 8e3a17df5c5d..eb349b97290f 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx50.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx50.c
@@ -385,7 +385,7 @@ static const struct pinctrl_pin_desc imx50_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX50_PAD_EIM_CRE),
};
-static struct imx_pinctrl_soc_info imx50_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx50_pinctrl_info = {
.pins = imx50_pinctrl_pads,
.npins = ARRAY_SIZE(imx50_pinctrl_pads),
.gpr_compatible = "fsl,imx50-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx51.c b/drivers/pinctrl/freescale/pinctrl-imx51.c
index eeac64ba2709..49acd991b5fb 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx51.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx51.c
@@ -762,7 +762,7 @@ static const struct pinctrl_pin_desc imx51_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX51_PAD_CSI1_MCLK),
};
-static struct imx_pinctrl_soc_info imx51_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx51_pinctrl_info = {
.pins = imx51_pinctrl_pads,
.npins = ARRAY_SIZE(imx51_pinctrl_pads),
};
diff --git a/drivers/pinctrl/freescale/pinctrl-imx53.c b/drivers/pinctrl/freescale/pinctrl-imx53.c
index 46a9572f3473..6dd0c60eaea4 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx53.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx53.c
@@ -448,7 +448,7 @@ static const struct pinctrl_pin_desc imx53_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX53_PAD_GPIO_18),
};
-static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx53_pinctrl_info = {
.pins = imx53_pinctrl_pads,
.npins = ARRAY_SIZE(imx53_pinctrl_pads),
.gpr_compatible = "fsl,imx53-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6dl.c b/drivers/pinctrl/freescale/pinctrl-imx6dl.c
index 3f25ca5867cc..91b85fc01de8 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6dl.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6dl.c
@@ -457,7 +457,7 @@ static const struct pinctrl_pin_desc imx6dl_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT7),
};
-static struct imx_pinctrl_soc_info imx6dl_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx6dl_pinctrl_info = {
.pins = imx6dl_pinctrl_pads,
.npins = ARRAY_SIZE(imx6dl_pinctrl_pads),
.gpr_compatible = "fsl,imx6q-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6q.c b/drivers/pinctrl/freescale/pinctrl-imx6q.c
index d61651c40458..5f653d69d0f5 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6q.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6q.c
@@ -460,7 +460,7 @@ static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6Q_PAD_SD2_DAT3),
};
-static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
.pins = imx6q_pinctrl_pads,
.npins = ARRAY_SIZE(imx6q_pinctrl_pads),
.gpr_compatible = "fsl,imx6q-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6sl.c b/drivers/pinctrl/freescale/pinctrl-imx6sl.c
index d023f6b00623..1167dc273c04 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6sl.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6sl.c
@@ -363,7 +363,7 @@ static const struct pinctrl_pin_desc imx6sl_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6SL_PAD_WDOG_B),
};
-static struct imx_pinctrl_soc_info imx6sl_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx6sl_pinctrl_info = {
.pins = imx6sl_pinctrl_pads,
.npins = ARRAY_SIZE(imx6sl_pinctrl_pads),
.gpr_compatible = "fsl,imx6sl-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6sx.c b/drivers/pinctrl/freescale/pinctrl-imx6sx.c
index 898b781701e6..15ea56c75f68 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6sx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6sx.c
@@ -367,7 +367,7 @@ static const struct pinctrl_pin_desc imx6sx_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6SX_PAD_USB_H_STROBE),
};
-static struct imx_pinctrl_soc_info imx6sx_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx6sx_pinctrl_info = {
.pins = imx6sx_pinctrl_pads,
.npins = ARRAY_SIZE(imx6sx_pinctrl_pads),
.gpr_compatible = "fsl,imx6sx-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6ul.c b/drivers/pinctrl/freescale/pinctrl-imx6ul.c
index 1aeb840aae1d..4580717ade19 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6ul.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6ul.c
@@ -150,6 +150,21 @@ enum imx6ul_pads {
MX6UL_PAD_CSI_DATA07 = 128,
};
+enum imx6ull_lpsr_pads {
+ MX6ULL_PAD_BOOT_MODE0 = 0,
+ MX6ULL_PAD_BOOT_MODE1 = 1,
+ MX6ULL_PAD_SNVS_TAMPER0 = 2,
+ MX6ULL_PAD_SNVS_TAMPER1 = 3,
+ MX6ULL_PAD_SNVS_TAMPER2 = 4,
+ MX6ULL_PAD_SNVS_TAMPER3 = 5,
+ MX6ULL_PAD_SNVS_TAMPER4 = 6,
+ MX6ULL_PAD_SNVS_TAMPER5 = 7,
+ MX6ULL_PAD_SNVS_TAMPER6 = 8,
+ MX6ULL_PAD_SNVS_TAMPER7 = 9,
+ MX6ULL_PAD_SNVS_TAMPER8 = 10,
+ MX6ULL_PAD_SNVS_TAMPER9 = 11,
+};
+
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx6ul_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6UL_PAD_RESERVE0),
@@ -283,20 +298,49 @@ static const struct pinctrl_pin_desc imx6ul_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX6UL_PAD_CSI_DATA07),
};
-static struct imx_pinctrl_soc_info imx6ul_pinctrl_info = {
+/* pad for i.MX6ULL lpsr pinmux */
+static const struct pinctrl_pin_desc imx6ull_snvs_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX6ULL_PAD_BOOT_MODE0),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_BOOT_MODE1),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER0),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER1),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER2),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER3),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER4),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER5),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER6),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER7),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER8),
+ IMX_PINCTRL_PIN(MX6ULL_PAD_SNVS_TAMPER9),
+};
+
+static const struct imx_pinctrl_soc_info imx6ul_pinctrl_info = {
.pins = imx6ul_pinctrl_pads,
.npins = ARRAY_SIZE(imx6ul_pinctrl_pads),
.gpr_compatible = "fsl,imx6ul-iomuxc-gpr",
};
-static struct of_device_id imx6ul_pinctrl_of_match[] = {
- { .compatible = "fsl,imx6ul-iomuxc", },
+static const struct imx_pinctrl_soc_info imx6ull_snvs_pinctrl_info = {
+ .pins = imx6ull_snvs_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx6ull_snvs_pinctrl_pads),
+ .flags = ZERO_OFFSET_VALID,
+};
+
+static const struct of_device_id imx6ul_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx6ul-iomuxc", .data = &imx6ul_pinctrl_info, },
+ { .compatible = "fsl,imx6ull-iomuxc-snvs", .data = &imx6ull_snvs_pinctrl_info, },
{ /* sentinel */ }
};
static int imx6ul_pinctrl_probe(struct platform_device *pdev)
{
- return imx_pinctrl_probe(pdev, &imx6ul_pinctrl_info);
+ const struct imx_pinctrl_soc_info *pinctrl_info;
+
+ pinctrl_info = of_device_get_match_data(&pdev->dev);
+ if (!pinctrl_info)
+ return -ENODEV;
+
+ return imx_pinctrl_probe(pdev, pinctrl_info);
}
static struct platform_driver imx6ul_pinctrl_driver = {
diff --git a/drivers/pinctrl/freescale/pinctrl-imx7d.c b/drivers/pinctrl/freescale/pinctrl-imx7d.c
index 754159ee7b1e..0b0a2f33b06a 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx7d.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx7d.c
@@ -378,16 +378,12 @@ static const struct of_device_id imx7d_pinctrl_of_match[] = {
static int imx7d_pinctrl_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
- struct imx_pinctrl_soc_info *pinctrl_info;
+ const struct imx_pinctrl_soc_info *pinctrl_info;
- match = of_match_device(imx7d_pinctrl_of_match, &pdev->dev);
-
- if (!match)
+ pinctrl_info = of_device_get_match_data(&pdev->dev);
+ if (!pinctrl_info)
return -ENODEV;
- pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;
-
return imx_pinctrl_probe(pdev, pinctrl_info);
}
diff --git a/drivers/pinctrl/freescale/pinctrl-imx7ulp.c b/drivers/pinctrl/freescale/pinctrl-imx7ulp.c
index b7bebb292f37..f363e45fd246 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx7ulp.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx7ulp.c
@@ -266,7 +266,7 @@ static const struct pinctrl_pin_desc imx7ulp_pinctrl_pads[] = {
#define BP_MUX_MODE 8
#define BM_PULL_ENABLED BIT(1)
-struct imx_cfg_params_decode imx7ulp_cfg_decodes[] = {
+static const struct imx_cfg_params_decode imx7ulp_cfg_decodes[] = {
IMX_CFG_PARAMS_DECODE(PIN_CONFIG_DRIVE_STRENGTH, BIT(6), 6),
IMX_CFG_PARAMS_DECODE(PIN_CONFIG_DRIVE_PUSH_PULL, BIT(5), 5),
IMX_CFG_PARAMS_DECODE(PIN_CONFIG_SLEW_RATE, BIT(2), 2),
@@ -307,11 +307,10 @@ static int imx7ulp_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
unsigned offset, bool input)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
u32 reg;
- pin_reg = &info->pin_regs[offset];
+ pin_reg = &ipctl->pin_regs[offset];
if (pin_reg->mux_reg == -1)
return -EINVAL;
@@ -325,7 +324,7 @@ static int imx7ulp_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
return 0;
}
-static struct imx_pinctrl_soc_info imx7ulp_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx7ulp_pinctrl_info = {
.pins = imx7ulp_pinctrl_pads,
.npins = ARRAY_SIZE(imx7ulp_pinctrl_pads),
.flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG,
diff --git a/drivers/pinctrl/freescale/pinctrl-vf610.c b/drivers/pinctrl/freescale/pinctrl-vf610.c
index ac18bb6d6d5e..c078f859ae15 100644
--- a/drivers/pinctrl/freescale/pinctrl-vf610.c
+++ b/drivers/pinctrl/freescale/pinctrl-vf610.c
@@ -300,11 +300,10 @@ static int vf610_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
unsigned offset, bool input)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
u32 reg;
- pin_reg = &info->pin_regs[offset];
+ pin_reg = &ipctl->pin_regs[offset];
if (pin_reg->mux_reg == -1)
return -EINVAL;
@@ -319,7 +318,7 @@ static int vf610_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
return 0;
}
-static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
+static const struct imx_pinctrl_soc_info vf610_pinctrl_info = {
.pins = vf610_pinctrl_pads,
.npins = ARRAY_SIZE(vf610_pinctrl_pads),
.flags = SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID,
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 9c1ca29c60b7..6b52ea1440a6 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -46,6 +46,9 @@
#define BYT_TRIG_POS BIT(25)
#define BYT_TRIG_LVL BIT(24)
#define BYT_DEBOUNCE_EN BIT(20)
+#define BYT_GLITCH_FILTER_EN BIT(19)
+#define BYT_GLITCH_F_SLOW_CLK BIT(17)
+#define BYT_GLITCH_F_FAST_CLK BIT(16)
#define BYT_PULL_STR_SHIFT 9
#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT)
@@ -1579,6 +1582,9 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
*/
value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
BYT_TRIG_LVL);
+ /* Enable glitch filtering */
+ value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK |
+ BYT_GLITCH_F_FAST_CLK;
writel(value, reg);
diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c
index e130599be571..6243e7d95e7e 100644
--- a/drivers/pinctrl/intel/pinctrl-cannonlake.c
+++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c
@@ -23,13 +23,16 @@
#define CNL_HOSTSW_OWN 0x0b0
#define CNL_GPI_IE 0x120
-#define CNL_GPP(r, s, e) \
+#define CNL_GPP(r, s, e, g) \
{ \
.reg_num = (r), \
.base = (s), \
.size = ((e) - (s) + 1), \
+ .gpio_base = (g), \
}
+#define CNL_NO_GPIO -1
+
#define CNL_COMMUNITY(b, s, e, g) \
{ \
.barno = (b), \
@@ -363,32 +366,32 @@ static const struct pinctrl_pin_desc cnlh_pins[] = {
};
static const struct intel_padgroup cnlh_community0_gpps[] = {
- CNL_GPP(0, 0, 24), /* GPP_A */
- CNL_GPP(1, 25, 50), /* GPP_B */
+ CNL_GPP(0, 0, 24, 0), /* GPP_A */
+ CNL_GPP(1, 25, 50, 32), /* GPP_B */
};
static const struct intel_padgroup cnlh_community1_gpps[] = {
- CNL_GPP(0, 51, 74), /* GPP_C */
- CNL_GPP(1, 75, 98), /* GPP_D */
- CNL_GPP(2, 99, 106), /* GPP_G */
- CNL_GPP(3, 107, 114), /* AZA */
- CNL_GPP(4, 115, 146), /* vGPIO_0 */
- CNL_GPP(5, 147, 154), /* vGPIO_1 */
+ CNL_GPP(0, 51, 74, 64), /* GPP_C */
+ CNL_GPP(1, 75, 98, 96), /* GPP_D */
+ CNL_GPP(2, 99, 106, 128), /* GPP_G */
+ CNL_GPP(3, 107, 114, CNL_NO_GPIO), /* AZA */
+ CNL_GPP(4, 115, 146, 160), /* vGPIO_0 */
+ CNL_GPP(5, 147, 154, CNL_NO_GPIO), /* vGPIO_1 */
};
static const struct intel_padgroup cnlh_community3_gpps[] = {
- CNL_GPP(0, 155, 178), /* GPP_K */
- CNL_GPP(1, 179, 202), /* GPP_H */
- CNL_GPP(2, 203, 215), /* GPP_E */
- CNL_GPP(3, 216, 239), /* GPP_F */
- CNL_GPP(4, 240, 248), /* SPI */
+ CNL_GPP(0, 155, 178, 192), /* GPP_K */
+ CNL_GPP(1, 179, 202, 224), /* GPP_H */
+ CNL_GPP(2, 203, 215, 258), /* GPP_E */
+ CNL_GPP(3, 216, 239, 288), /* GPP_F */
+ CNL_GPP(4, 240, 248, CNL_NO_GPIO), /* SPI */
};
static const struct intel_padgroup cnlh_community4_gpps[] = {
- CNL_GPP(0, 249, 259), /* CPU */
- CNL_GPP(1, 260, 268), /* JTAG */
- CNL_GPP(2, 269, 286), /* GPP_I */
- CNL_GPP(3, 287, 298), /* GPP_J */
+ CNL_GPP(0, 249, 259, CNL_NO_GPIO), /* CPU */
+ CNL_GPP(1, 260, 268, CNL_NO_GPIO), /* JTAG */
+ CNL_GPP(2, 269, 286, 320), /* GPP_I */
+ CNL_GPP(3, 287, 298, 352), /* GPP_J */
};
static const unsigned int cnlh_spi0_pins[] = { 40, 41, 42, 43 };
@@ -785,25 +788,25 @@ static const struct intel_function cnllp_functions[] = {
};
static const struct intel_padgroup cnllp_community0_gpps[] = {
- CNL_GPP(0, 0, 24), /* GPP_A */
- CNL_GPP(1, 25, 50), /* GPP_B */
- CNL_GPP(2, 51, 58), /* GPP_G */
- CNL_GPP(3, 59, 67), /* SPI */
+ CNL_GPP(0, 0, 24, 0), /* GPP_A */
+ CNL_GPP(1, 25, 50, 32), /* GPP_B */
+ CNL_GPP(2, 51, 58, 64), /* GPP_G */
+ CNL_GPP(3, 59, 67, CNL_NO_GPIO), /* SPI */
};
static const struct intel_padgroup cnllp_community1_gpps[] = {
- CNL_GPP(0, 68, 92), /* GPP_D */
- CNL_GPP(1, 93, 116), /* GPP_F */
- CNL_GPP(2, 117, 140), /* GPP_H */
- CNL_GPP(3, 141, 172), /* vGPIO */
- CNL_GPP(4, 173, 180), /* vGPIO */
+ CNL_GPP(0, 68, 92, 96), /* GPP_D */
+ CNL_GPP(1, 93, 116, 128), /* GPP_F */
+ CNL_GPP(2, 117, 140, 160), /* GPP_H */
+ CNL_GPP(3, 141, 172, 192), /* vGPIO */
+ CNL_GPP(4, 173, 180, 224), /* vGPIO */
};
static const struct intel_padgroup cnllp_community4_gpps[] = {
- CNL_GPP(0, 181, 204), /* GPP_C */
- CNL_GPP(1, 205, 228), /* GPP_E */
- CNL_GPP(2, 229, 237), /* JTAG */
- CNL_GPP(3, 238, 243), /* HVCMOS */
+ CNL_GPP(0, 181, 204, 256), /* GPP_C */
+ CNL_GPP(1, 205, 228, 288), /* GPP_E */
+ CNL_GPP(2, 229, 237, CNL_NO_GPIO), /* JTAG */
+ CNL_GPP(3, 238, 243, CNL_NO_GPIO), /* HVCMOS */
};
static const struct intel_community cnllp_communities[] = {
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 4471fd94e1fe..b1ae1618fefe 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -131,10 +131,8 @@ struct chv_gpio_pinrange {
* @ngroups: Number of groups
* @functions: All functions in this community
* @nfunctions: Number of functions
- * @ngpios: Number of GPIOs in this community
* @gpio_ranges: An array of GPIO ranges in this community
* @ngpio_ranges: Number of GPIO ranges
- * @ngpios: Total number of GPIOs in this community
* @nirqs: Total number of IRQs this community can generate
*/
struct chv_community {
@@ -147,7 +145,6 @@ struct chv_community {
size_t nfunctions;
const struct chv_gpio_pinrange *gpio_ranges;
size_t ngpio_ranges;
- size_t ngpios;
size_t nirqs;
acpi_adr_space_type acpi_space_id;
};
@@ -399,7 +396,6 @@ static const struct chv_community southwest_community = {
.nfunctions = ARRAY_SIZE(southwest_functions),
.gpio_ranges = southwest_gpio_ranges,
.ngpio_ranges = ARRAY_SIZE(southwest_gpio_ranges),
- .ngpios = ARRAY_SIZE(southwest_pins),
/*
* Southwest community can benerate GPIO interrupts only for the
* first 8 interrupts. The upper half (8-15) can only be used to
@@ -489,7 +485,6 @@ static const struct chv_community north_community = {
.npins = ARRAY_SIZE(north_pins),
.gpio_ranges = north_gpio_ranges,
.ngpio_ranges = ARRAY_SIZE(north_gpio_ranges),
- .ngpios = ARRAY_SIZE(north_pins),
/*
* North community can generate GPIO interrupts only for the first
* 8 interrupts. The upper half (8-15) can only be used to trigger
@@ -538,7 +533,6 @@ static const struct chv_community east_community = {
.npins = ARRAY_SIZE(east_pins),
.gpio_ranges = east_gpio_ranges,
.ngpio_ranges = ARRAY_SIZE(east_gpio_ranges),
- .ngpios = ARRAY_SIZE(east_pins),
.nirqs = 16,
.acpi_space_id = 0x93,
};
@@ -665,7 +659,6 @@ static const struct chv_community southeast_community = {
.nfunctions = ARRAY_SIZE(southeast_functions),
.gpio_ranges = southeast_gpio_ranges,
.ngpio_ranges = ARRAY_SIZE(southeast_gpio_ranges),
- .ngpios = ARRAY_SIZE(southeast_pins),
.nirqs = 16,
.acpi_space_id = 0x94,
};
@@ -1253,21 +1246,14 @@ static struct pinctrl_desc chv_pinctrl_desc = {
.owner = THIS_MODULE,
};
-static unsigned chv_gpio_offset_to_pin(struct chv_pinctrl *pctrl,
- unsigned offset)
-{
- return pctrl->community->pins[offset].number;
-}
-
static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
- int pin = chv_gpio_offset_to_pin(pctrl, offset);
unsigned long flags;
u32 ctrl0, cfg;
raw_spin_lock_irqsave(&chv_lock, flags);
- ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
+ ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
raw_spin_unlock_irqrestore(&chv_lock, flags);
cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
@@ -1281,14 +1267,13 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
- unsigned pin = chv_gpio_offset_to_pin(pctrl, offset);
unsigned long flags;
void __iomem *reg;
u32 ctrl0;
raw_spin_lock_irqsave(&chv_lock, flags);
- reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
+ reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
ctrl0 = readl(reg);
if (value)
@@ -1304,12 +1289,11 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
- unsigned pin = chv_gpio_offset_to_pin(pctrl, offset);
u32 ctrl0, direction;
unsigned long flags;
raw_spin_lock_irqsave(&chv_lock, flags);
- ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
+ ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
raw_spin_unlock_irqrestore(&chv_lock, flags);
direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
@@ -1345,7 +1329,7 @@ static void chv_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
- int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
+ int pin = irqd_to_hwirq(d);
u32 intr_line;
raw_spin_lock(&chv_lock);
@@ -1362,7 +1346,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
- int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
+ int pin = irqd_to_hwirq(d);
u32 value, intr_line;
unsigned long flags;
@@ -1407,8 +1391,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) {
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
- unsigned offset = irqd_to_hwirq(d);
- int pin = chv_gpio_offset_to_pin(pctrl, offset);
+ unsigned pin = irqd_to_hwirq(d);
irq_flow_handler_t handler;
unsigned long flags;
u32 intsel, value;
@@ -1426,7 +1409,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
if (!pctrl->intr_lines[intsel]) {
irq_set_handler_locked(d, handler);
- pctrl->intr_lines[intsel] = offset;
+ pctrl->intr_lines[intsel] = pin;
}
raw_spin_unlock_irqrestore(&chv_lock, flags);
}
@@ -1439,8 +1422,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
- unsigned offset = irqd_to_hwirq(d);
- int pin = chv_gpio_offset_to_pin(pctrl, offset);
+ unsigned pin = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
@@ -1486,7 +1468,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
value &= CHV_PADCTRL0_INTSEL_MASK;
value >>= CHV_PADCTRL0_INTSEL_SHIFT;
- pctrl->intr_lines[value] = offset;
+ pctrl->intr_lines[value] = pin;
if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(d, handle_edge_irq);
@@ -1576,12 +1558,12 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
const struct chv_gpio_pinrange *range;
struct gpio_chip *chip = &pctrl->chip;
bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
- int ret, i, offset;
- int irq_base;
+ const struct chv_community *community = pctrl->community;
+ int ret, i, irq_base;
*chip = chv_gpio_chip;
- chip->ngpio = pctrl->community->ngpios;
+ chip->ngpio = community->pins[community->npins - 1].number + 1;
chip->label = dev_name(pctrl->dev);
chip->parent = pctrl->dev;
chip->base = -1;
@@ -1593,30 +1575,29 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
return ret;
}
- for (i = 0, offset = 0; i < pctrl->community->ngpio_ranges; i++) {
- range = &pctrl->community->gpio_ranges[i];
- ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev), offset,
- range->base, range->npins);
+ for (i = 0; i < community->ngpio_ranges; i++) {
+ range = &community->gpio_ranges[i];
+ ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev),
+ range->base, range->base,
+ range->npins);
if (ret) {
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
return ret;
}
-
- offset += range->npins;
}
/* Do not add GPIOs that can only generate GPEs to the IRQ domain */
- for (i = 0; i < pctrl->community->npins; i++) {
+ for (i = 0; i < community->npins; i++) {
const struct pinctrl_pin_desc *desc;
u32 intsel;
- desc = &pctrl->community->pins[i];
+ desc = &community->pins[i];
intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0));
intsel &= CHV_PADCTRL0_INTSEL_MASK;
intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
- if (need_valid_mask && intsel >= pctrl->community->nirqs)
+ if (need_valid_mask && intsel >= community->nirqs)
clear_bit(i, chip->irq.valid_mask);
}
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 12a1af45acb9..96e73e30204e 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -425,6 +425,18 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
writel(value, padcfg0);
}
+static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
+{
+ u32 value;
+
+ /* Put the pad into GPIO mode */
+ value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
+ /* Disable SCI/SMI/NMI generation */
+ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
+ value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
+ writel(value, padcfg0);
+}
+
static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin)
@@ -432,7 +444,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg0;
unsigned long flags;
- u32 value;
raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -442,13 +453,7 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
}
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
- /* Put the pad into GPIO mode */
- value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
- /* Disable SCI/SMI/NMI generation */
- value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
- value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
- writel(value, padcfg0);
-
+ intel_gpio_set_gpio_mode(padcfg0);
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(padcfg0, true);
@@ -806,22 +811,63 @@ static const struct gpio_chip intel_gpio_chip = {
.set_config = gpiochip_generic_config,
};
+/**
+ * intel_gpio_to_pin() - Translate from GPIO offset to pin number
+ * @pctrl: Pinctrl structure
+ * @offset: GPIO offset from gpiolib
+ * @commmunity: Community is filled here if not %NULL
+ * @padgrp: Pad group is filled here if not %NULL
+ *
+ * When coming through gpiolib irqchip, the GPIO offset is not
+ * automatically translated to pinctrl pin number. This function can be
+ * used to find out the corresponding pinctrl pin.
+ */
+static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
+ const struct intel_community **community,
+ const struct intel_padgroup **padgrp)
+{
+ int i;
+
+ for (i = 0; i < pctrl->ncommunities; i++) {
+ const struct intel_community *comm = &pctrl->communities[i];
+ int j;
+
+ for (j = 0; j < comm->ngpps; j++) {
+ const struct intel_padgroup *pgrp = &comm->gpps[j];
+
+ if (pgrp->gpio_base < 0)
+ continue;
+
+ if (offset >= pgrp->gpio_base &&
+ offset < pgrp->gpio_base + pgrp->size) {
+ int pin;
+
+ pin = pgrp->base + offset - pgrp->gpio_base;
+ if (community)
+ *community = comm;
+ if (padgrp)
+ *padgrp = pgrp;
+
+ return pin;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
static void intel_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
const struct intel_community *community;
- unsigned pin = irqd_to_hwirq(d);
+ const struct intel_padgroup *padgrp;
+ int pin;
- community = intel_get_community(pctrl, pin);
- if (community) {
- const struct intel_padgroup *padgrp;
+ pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+ if (pin >= 0) {
unsigned gpp, gpp_offset, is_offset;
- padgrp = intel_community_get_padgroup(community, pin);
- if (!padgrp)
- return;
-
gpp = padgrp->reg_num;
gpp_offset = padgroup_offset(padgrp, pin);
is_offset = community->is_offset + gpp * 4;
@@ -837,19 +883,15 @@ static void intel_gpio_irq_enable(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
const struct intel_community *community;
- unsigned pin = irqd_to_hwirq(d);
+ const struct intel_padgroup *padgrp;
+ int pin;
- community = intel_get_community(pctrl, pin);
- if (community) {
- const struct intel_padgroup *padgrp;
+ pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+ if (pin >= 0) {
unsigned gpp, gpp_offset, is_offset;
unsigned long flags;
u32 value;
- padgrp = intel_community_get_padgroup(community, pin);
- if (!padgrp)
- return;
-
gpp = padgrp->reg_num;
gpp_offset = padgroup_offset(padgrp, pin);
is_offset = community->is_offset + gpp * 4;
@@ -870,20 +912,16 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
const struct intel_community *community;
- unsigned pin = irqd_to_hwirq(d);
+ const struct intel_padgroup *padgrp;
+ int pin;
- community = intel_get_community(pctrl, pin);
- if (community) {
- const struct intel_padgroup *padgrp;
+ pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+ if (pin >= 0) {
unsigned gpp, gpp_offset;
unsigned long flags;
void __iomem *reg;
u32 value;
- padgrp = intel_community_get_padgroup(community, pin);
- if (!padgrp)
- return;
-
gpp = padgrp->reg_num;
gpp_offset = padgroup_offset(padgrp, pin);
@@ -914,7 +952,7 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- unsigned pin = irqd_to_hwirq(d);
+ unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
unsigned long flags;
void __iomem *reg;
u32 value;
@@ -935,6 +973,8 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ intel_gpio_set_gpio_mode(reg);
+
value = readl(reg);
value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
@@ -969,7 +1009,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- unsigned pin = irqd_to_hwirq(d);
+ unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
if (on)
enable_irq_wake(pctrl->irq);
@@ -1000,14 +1040,10 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
pending &= enabled;
for_each_set_bit(gpp_offset, &pending, padgrp->size) {
- unsigned padno, irq;
-
- padno = padgrp->base - community->pin_base + gpp_offset;
- if (padno >= community->npins)
- break;
+ unsigned irq;
irq = irq_find_mapping(gc->irq.domain,
- community->pin_base + padno);
+ padgrp->gpio_base + gpp_offset);
generic_handle_irq(irq);
ret |= IRQ_HANDLED;
@@ -1044,13 +1080,56 @@ static struct irq_chip intel_gpio_irqchip = {
.flags = IRQCHIP_MASK_ON_SUSPEND,
};
+static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
+ const struct intel_community *community)
+{
+ int ret = 0, i;
+
+ for (i = 0; i < community->ngpps; i++) {
+ const struct intel_padgroup *gpp = &community->gpps[i];
+
+ if (gpp->gpio_base < 0)
+ continue;
+
+ ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
+ gpp->gpio_base, gpp->base,
+ gpp->size);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
+{
+ const struct intel_community *community;
+ unsigned ngpio = 0;
+ int i, j;
+
+ for (i = 0; i < pctrl->ncommunities; i++) {
+ community = &pctrl->communities[i];
+ for (j = 0; j < community->ngpps; j++) {
+ const struct intel_padgroup *gpp = &community->gpps[j];
+
+ if (gpp->gpio_base < 0)
+ continue;
+
+ if (gpp->gpio_base + gpp->size > ngpio)
+ ngpio = gpp->gpio_base + gpp->size;
+ }
+ }
+
+ return ngpio;
+}
+
static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
{
- int ret;
+ int ret, i;
pctrl->chip = intel_gpio_chip;
- pctrl->chip.ngpio = pctrl->soc->npins;
+ pctrl->chip.ngpio = intel_gpio_ngpio(pctrl);
pctrl->chip.label = dev_name(pctrl->dev);
pctrl->chip.parent = pctrl->dev;
pctrl->chip.base = -1;
@@ -1062,11 +1141,14 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
return ret;
}
- ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
- 0, 0, pctrl->soc->npins);
- if (ret) {
- dev_err(pctrl->dev, "failed to add GPIO pin range\n");
- return ret;
+ for (i = 0; i < pctrl->ncommunities; i++) {
+ struct intel_community *community = &pctrl->communities[i];
+
+ ret = intel_gpio_add_pin_ranges(pctrl, community);
+ if (ret) {
+ dev_err(pctrl->dev, "failed to add GPIO pin range\n");
+ return ret;
+ }
}
/*
@@ -1126,6 +1208,9 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
if (gpps[i].size > 32)
return -EINVAL;
+ if (!gpps[i].gpio_base)
+ gpps[i].gpio_base = gpps[i].base;
+
gpps[i].padown_num = padown_num;
/*
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index 13b0bd6eb2a2..98fdf9adf623 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -51,6 +51,8 @@ struct intel_function {
* @reg_num: GPI_IS register number
* @base: Starting pin of this group
* @size: Size of this group (maximum is 32).
+ * @gpio_base: Starting GPIO base of this group (%0 if matches with @base,
+ * and %-1 if no GPIO mapping should be created)
* @padown_num: PAD_OWN register number (assigned by the core driver)
*
* If pad groups of a community are not the same size, use this structure
@@ -60,6 +62,7 @@ struct intel_padgroup {
unsigned reg_num;
unsigned base;
unsigned size;
+ int gpio_base;
unsigned padown_num;
};
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index 86c4b3fab7b0..d9357054d41d 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -931,10 +931,17 @@ static int mrfld_pinctrl_probe(struct platform_device *pdev)
return 0;
}
+static const struct acpi_device_id mrfld_acpi_table[] = {
+ { "INTC1002" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, mrfld_acpi_table);
+
static struct platform_driver mrfld_pinctrl_driver = {
.probe = mrfld_pinctrl_probe,
.driver = {
.name = "pinctrl-merrifield",
+ .acpi_match_table = mrfld_acpi_table,
},
};
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index fac9866311f3..3e598740b379 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -1,4 +1,5 @@
-if ARCH_MEDIATEK || COMPILE_TEST
+menu "MediaTek pinctrl drivers"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
config PINCTRL_MTK
bool
@@ -31,6 +32,16 @@ config PINCTRL_MT8127
select PINCTRL_MTK
# For ARMv8 SoCs
+config PINCTRL_MT7622
+ bool "MediaTek MT7622 pin control"
+ depends on OF
+ depends on ARM64 || COMPILE_TEST
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select OF_GPIO
+
config PINCTRL_MT8173
bool "Mediatek MT8173 pin control"
depends on OF
@@ -46,4 +57,4 @@ config PINCTRL_MT6397
default MFD_MT6397
select PINCTRL_MTK
-endif
+endmenu
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index 10d90140a38a..ed7d2b2cc6e9 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -1,10 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
# Core
-obj-y += pinctrl-mtk-common.o
+obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
# SoC Drivers
obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o
obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
+obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
new file mode 100644
index 000000000000..06e8406c4440
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
@@ -0,0 +1,1597 @@
+/*
+ * MediaTek MT7622 Pinctrl Driver
+ *
+ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
+#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
+#define PINCTRL_PIN_GROUP(name, id) \
+ { \
+ name, \
+ id##_pins, \
+ ARRAY_SIZE(id##_pins), \
+ id##_funcs, \
+ }
+
+#define MTK_GPIO_MODE 1
+#define MTK_INPUT 0
+#define MTK_OUTPUT 1
+#define MTK_DISABLE 0
+#define MTK_ENABLE 1
+
+/* Custom pinconf parameters */
+#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1)
+#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2)
+
+/* List these attributes which could be modified for the pin */
+enum {
+ PINCTRL_PIN_REG_MODE,
+ PINCTRL_PIN_REG_DIR,
+ PINCTRL_PIN_REG_DI,
+ PINCTRL_PIN_REG_DO,
+ PINCTRL_PIN_REG_SR,
+ PINCTRL_PIN_REG_SMT,
+ PINCTRL_PIN_REG_PD,
+ PINCTRL_PIN_REG_PU,
+ PINCTRL_PIN_REG_E4,
+ PINCTRL_PIN_REG_E8,
+ PINCTRL_PIN_REG_TDSEL,
+ PINCTRL_PIN_REG_RDSEL,
+ PINCTRL_PIN_REG_MAX,
+};
+
+/* struct mtk_pin_field - the structure that holds the information of the field
+ * used to describe the attribute for the pin
+ * @offset: the register offset relative to the base address
+ * @mask: the mask used to filter out the field from the register
+ * @bitpos: the start bit relative to the register
+ * @next: the indication that the field would be extended to the
+ next register
+ */
+struct mtk_pin_field {
+ u32 offset;
+ u32 mask;
+ u8 bitpos;
+ u8 next;
+};
+
+/* struct mtk_pin_field_calc - the structure that holds the range providing
+ * the guide used to look up the relevant field
+ * @s_pin: the start pin within the range
+ * @e_pin: the end pin within the range
+ * @s_addr: the start address for the range
+ * @x_addrs: the address distance between two consecutive registers
+ * within the range
+ * @s_bit: the start bit for the first register within the range
+ * @x_bits: the bit distance between two consecutive pins within
+ * the range
+ */
+struct mtk_pin_field_calc {
+ u16 s_pin;
+ u16 e_pin;
+ u32 s_addr;
+ u8 x_addrs;
+ u8 s_bit;
+ u8 x_bits;
+};
+
+/* struct mtk_pin_reg_calc - the structure that holds all ranges used to
+ * determine which register the pin would make use of
+ * for certain pin attribute.
+ * @range: the start address for the range
+ * @nranges: the number of items in the range
+ */
+struct mtk_pin_reg_calc {
+ const struct mtk_pin_field_calc *range;
+ unsigned int nranges;
+};
+
+/* struct mtk_pin_soc - the structure that holds SoC-specific data */
+struct mtk_pin_soc {
+ const struct mtk_pin_reg_calc *reg_cal;
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+ const struct group_desc *grps;
+ unsigned int ngrps;
+ const struct function_desc *funcs;
+ unsigned int nfuncs;
+};
+
+struct mtk_pinctrl {
+ struct pinctrl_dev *pctrl;
+ void __iomem *base;
+ struct device *dev;
+ struct gpio_chip chip;
+ const struct mtk_pin_soc *soc;
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = {
+ {0, 0, 0x320, 0x10, 16, 4},
+ {1, 4, 0x3a0, 0x10, 16, 4},
+ {5, 5, 0x320, 0x10, 0, 4},
+ {6, 6, 0x300, 0x10, 4, 4},
+ {7, 7, 0x300, 0x10, 4, 4},
+ {8, 9, 0x350, 0x10, 20, 4},
+ {10, 10, 0x300, 0x10, 8, 4},
+ {11, 11, 0x300, 0x10, 8, 4},
+ {12, 12, 0x300, 0x10, 8, 4},
+ {13, 13, 0x300, 0x10, 8, 4},
+ {14, 15, 0x320, 0x10, 4, 4},
+ {16, 17, 0x320, 0x10, 20, 4},
+ {18, 21, 0x310, 0x10, 16, 4},
+ {22, 22, 0x380, 0x10, 16, 4},
+ {23, 23, 0x300, 0x10, 24, 4},
+ {24, 24, 0x300, 0x10, 24, 4},
+ {25, 25, 0x300, 0x10, 12, 4},
+ {25, 25, 0x300, 0x10, 12, 4},
+ {26, 26, 0x300, 0x10, 12, 4},
+ {27, 27, 0x300, 0x10, 12, 4},
+ {28, 28, 0x300, 0x10, 12, 4},
+ {29, 29, 0x300, 0x10, 12, 4},
+ {30, 30, 0x300, 0x10, 12, 4},
+ {31, 31, 0x300, 0x10, 12, 4},
+ {32, 32, 0x300, 0x10, 12, 4},
+ {33, 33, 0x300, 0x10, 12, 4},
+ {34, 34, 0x300, 0x10, 12, 4},
+ {35, 35, 0x300, 0x10, 12, 4},
+ {36, 36, 0x300, 0x10, 12, 4},
+ {37, 37, 0x300, 0x10, 20, 4},
+ {38, 38, 0x300, 0x10, 20, 4},
+ {39, 39, 0x300, 0x10, 20, 4},
+ {40, 40, 0x300, 0x10, 20, 4},
+ {41, 41, 0x300, 0x10, 20, 4},
+ {42, 42, 0x300, 0x10, 20, 4},
+ {43, 43, 0x300, 0x10, 20, 4},
+ {44, 44, 0x300, 0x10, 20, 4},
+ {45, 46, 0x300, 0x10, 20, 4},
+ {47, 47, 0x300, 0x10, 20, 4},
+ {48, 48, 0x300, 0x10, 20, 4},
+ {49, 49, 0x300, 0x10, 20, 4},
+ {50, 50, 0x300, 0x10, 20, 4},
+ {51, 70, 0x330, 0x10, 4, 4},
+ {71, 71, 0x300, 0x10, 16, 4},
+ {72, 72, 0x300, 0x10, 16, 4},
+ {73, 76, 0x310, 0x10, 0, 4},
+ {77, 77, 0x320, 0x10, 28, 4},
+ {78, 78, 0x320, 0x10, 12, 4},
+ {79, 82, 0x3a0, 0x10, 0, 4},
+ {83, 83, 0x350, 0x10, 28, 4},
+ {84, 84, 0x330, 0x10, 0, 4},
+ {85, 90, 0x360, 0x10, 4, 4},
+ {91, 94, 0x390, 0x10, 16, 4},
+ {95, 97, 0x380, 0x10, 20, 4},
+ {98, 101, 0x390, 0x10, 0, 4},
+ {102, 102, 0x360, 0x10, 0, 4},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_dir_range[] = {
+ {0, 102, 0x0, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_di_range[] = {
+ {0, 102, 0x200, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_do_range[] = {
+ {0, 102, 0x100, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_sr_range[] = {
+ {0, 31, 0x910, 0x10, 0, 1},
+ {32, 50, 0xa10, 0x10, 0, 1},
+ {51, 70, 0x810, 0x10, 0, 1},
+ {71, 72, 0xb10, 0x10, 0, 1},
+ {73, 86, 0xb10, 0x10, 4, 1},
+ {87, 90, 0xc10, 0x10, 0, 1},
+ {91, 102, 0xb10, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_smt_range[] = {
+ {0, 31, 0x920, 0x10, 0, 1},
+ {32, 50, 0xa20, 0x10, 0, 1},
+ {51, 70, 0x820, 0x10, 0, 1},
+ {71, 72, 0xb20, 0x10, 0, 1},
+ {73, 86, 0xb20, 0x10, 4, 1},
+ {87, 90, 0xc20, 0x10, 0, 1},
+ {91, 102, 0xb20, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_pu_range[] = {
+ {0, 31, 0x930, 0x10, 0, 1},
+ {32, 50, 0xa30, 0x10, 0, 1},
+ {51, 70, 0x830, 0x10, 0, 1},
+ {71, 72, 0xb30, 0x10, 0, 1},
+ {73, 86, 0xb30, 0x10, 4, 1},
+ {87, 90, 0xc30, 0x10, 0, 1},
+ {91, 102, 0xb30, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_pd_range[] = {
+ {0, 31, 0x940, 0x10, 0, 1},
+ {32, 50, 0xa40, 0x10, 0, 1},
+ {51, 70, 0x840, 0x10, 0, 1},
+ {71, 72, 0xb40, 0x10, 0, 1},
+ {73, 86, 0xb40, 0x10, 4, 1},
+ {87, 90, 0xc40, 0x10, 0, 1},
+ {91, 102, 0xb40, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_e4_range[] = {
+ {0, 31, 0x960, 0x10, 0, 1},
+ {32, 50, 0xa60, 0x10, 0, 1},
+ {51, 70, 0x860, 0x10, 0, 1},
+ {71, 72, 0xb60, 0x10, 0, 1},
+ {73, 86, 0xb60, 0x10, 4, 1},
+ {87, 90, 0xc60, 0x10, 0, 1},
+ {91, 102, 0xb60, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_e8_range[] = {
+ {0, 31, 0x970, 0x10, 0, 1},
+ {32, 50, 0xa70, 0x10, 0, 1},
+ {51, 70, 0x870, 0x10, 0, 1},
+ {71, 72, 0xb70, 0x10, 0, 1},
+ {73, 86, 0xb70, 0x10, 4, 1},
+ {87, 90, 0xc70, 0x10, 0, 1},
+ {91, 102, 0xb70, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_tdsel_range[] = {
+ {0, 31, 0x980, 0x4, 0, 4},
+ {32, 50, 0xa80, 0x4, 0, 4},
+ {51, 70, 0x880, 0x4, 0, 4},
+ {71, 72, 0xb80, 0x4, 0, 4},
+ {73, 86, 0xb80, 0x4, 16, 4},
+ {87, 90, 0xc80, 0x4, 0, 4},
+ {91, 102, 0xb88, 0x4, 8, 4},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_rdsel_range[] = {
+ {0, 31, 0x990, 0x4, 0, 6},
+ {32, 50, 0xa90, 0x4, 0, 6},
+ {51, 58, 0x890, 0x4, 0, 6},
+ {59, 60, 0x894, 0x4, 28, 6},
+ {61, 62, 0x894, 0x4, 16, 6},
+ {63, 66, 0x898, 0x4, 8, 6},
+ {67, 68, 0x89c, 0x4, 12, 6},
+ {69, 70, 0x89c, 0x4, 0, 6},
+ {71, 72, 0xb90, 0x4, 0, 6},
+ {73, 86, 0xb90, 0x4, 24, 6},
+ {87, 90, 0xc90, 0x4, 0, 6},
+ {91, 102, 0xb9c, 0x4, 12, 6},
+};
+
+static const struct mtk_pin_reg_calc mt7622_reg_cals[PINCTRL_PIN_REG_MAX] = {
+ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7622_pin_mode_range),
+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7622_pin_dir_range),
+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7622_pin_di_range),
+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7622_pin_do_range),
+ [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt7622_pin_sr_range),
+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7622_pin_smt_range),
+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7622_pin_pu_range),
+ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7622_pin_pd_range),
+ [PINCTRL_PIN_REG_E4] = MTK_RANGE(mt7622_pin_e4_range),
+ [PINCTRL_PIN_REG_E8] = MTK_RANGE(mt7622_pin_e8_range),
+ [PINCTRL_PIN_REG_TDSEL] = MTK_RANGE(mt7622_pin_tdsel_range),
+ [PINCTRL_PIN_REG_RDSEL] = MTK_RANGE(mt7622_pin_rdsel_range),
+};
+
+static const struct pinctrl_pin_desc mt7622_pins[] = {
+ PINCTRL_PIN(0, "GPIO_A"),
+ PINCTRL_PIN(1, "I2S1_IN"),
+ PINCTRL_PIN(2, "I2S1_OUT"),
+ PINCTRL_PIN(3, "I2S_BCLK"),
+ PINCTRL_PIN(4, "I2S_WS"),
+ PINCTRL_PIN(5, "I2S_MCLK"),
+ PINCTRL_PIN(6, "TXD0"),
+ PINCTRL_PIN(7, "RXD0"),
+ PINCTRL_PIN(8, "SPI_WP"),
+ PINCTRL_PIN(9, "SPI_HOLD"),
+ PINCTRL_PIN(10, "SPI_CLK"),
+ PINCTRL_PIN(11, "SPI_MOSI"),
+ PINCTRL_PIN(12, "SPI_MISO"),
+ PINCTRL_PIN(13, "SPI_CS"),
+ PINCTRL_PIN(14, "I2C_SDA"),
+ PINCTRL_PIN(15, "I2C_SCL"),
+ PINCTRL_PIN(16, "I2S2_IN"),
+ PINCTRL_PIN(17, "I2S3_IN"),
+ PINCTRL_PIN(18, "I2S4_IN"),
+ PINCTRL_PIN(19, "I2S2_OUT"),
+ PINCTRL_PIN(20, "I2S3_OUT"),
+ PINCTRL_PIN(21, "I2S4_OUT"),
+ PINCTRL_PIN(22, "GPIO_B"),
+ PINCTRL_PIN(23, "MDC"),
+ PINCTRL_PIN(24, "MDIO"),
+ PINCTRL_PIN(25, "G2_TXD0"),
+ PINCTRL_PIN(26, "G2_TXD1"),
+ PINCTRL_PIN(27, "G2_TXD2"),
+ PINCTRL_PIN(28, "G2_TXD3"),
+ PINCTRL_PIN(29, "G2_TXEN"),
+ PINCTRL_PIN(30, "G2_TXC"),
+ PINCTRL_PIN(31, "G2_RXD0"),
+ PINCTRL_PIN(32, "G2_RXD1"),
+ PINCTRL_PIN(33, "G2_RXD2"),
+ PINCTRL_PIN(34, "G2_RXD3"),
+ PINCTRL_PIN(35, "G2_RXDV"),
+ PINCTRL_PIN(36, "G2_RXC"),
+ PINCTRL_PIN(37, "NCEB"),
+ PINCTRL_PIN(38, "NWEB"),
+ PINCTRL_PIN(39, "NREB"),
+ PINCTRL_PIN(40, "NDL4"),
+ PINCTRL_PIN(41, "NDL5"),
+ PINCTRL_PIN(42, "NDL6"),
+ PINCTRL_PIN(43, "NDL7"),
+ PINCTRL_PIN(44, "NRB"),
+ PINCTRL_PIN(45, "NCLE"),
+ PINCTRL_PIN(46, "NALE"),
+ PINCTRL_PIN(47, "NDL0"),
+ PINCTRL_PIN(48, "NDL1"),
+ PINCTRL_PIN(49, "NDL2"),
+ PINCTRL_PIN(50, "NDL3"),
+ PINCTRL_PIN(51, "MDI_TP_P0"),
+ PINCTRL_PIN(52, "MDI_TN_P0"),
+ PINCTRL_PIN(53, "MDI_RP_P0"),
+ PINCTRL_PIN(54, "MDI_RN_P0"),
+ PINCTRL_PIN(55, "MDI_TP_P1"),
+ PINCTRL_PIN(56, "MDI_TN_P1"),
+ PINCTRL_PIN(57, "MDI_RP_P1"),
+ PINCTRL_PIN(58, "MDI_RN_P1"),
+ PINCTRL_PIN(59, "MDI_RP_P2"),
+ PINCTRL_PIN(60, "MDI_RN_P2"),
+ PINCTRL_PIN(61, "MDI_TP_P2"),
+ PINCTRL_PIN(62, "MDI_TN_P2"),
+ PINCTRL_PIN(63, "MDI_TP_P3"),
+ PINCTRL_PIN(64, "MDI_TN_P3"),
+ PINCTRL_PIN(65, "MDI_RP_P3"),
+ PINCTRL_PIN(66, "MDI_RN_P3"),
+ PINCTRL_PIN(67, "MDI_RP_P4"),
+ PINCTRL_PIN(68, "MDI_RN_P4"),
+ PINCTRL_PIN(69, "MDI_TP_P4"),
+ PINCTRL_PIN(70, "MDI_TN_P4"),
+ PINCTRL_PIN(71, "PMIC_SCL"),
+ PINCTRL_PIN(72, "PMIC_SDA"),
+ PINCTRL_PIN(73, "SPIC1_CLK"),
+ PINCTRL_PIN(74, "SPIC1_MOSI"),
+ PINCTRL_PIN(75, "SPIC1_MISO"),
+ PINCTRL_PIN(76, "SPIC1_CS"),
+ PINCTRL_PIN(77, "GPIO_D"),
+ PINCTRL_PIN(78, "WATCHDOG"),
+ PINCTRL_PIN(79, "RTS3_N"),
+ PINCTRL_PIN(80, "CTS3_N"),
+ PINCTRL_PIN(81, "TXD3"),
+ PINCTRL_PIN(82, "RXD3"),
+ PINCTRL_PIN(83, "PERST0_N"),
+ PINCTRL_PIN(84, "PERST1_N"),
+ PINCTRL_PIN(85, "WLED_N"),
+ PINCTRL_PIN(86, "EPHY_LED0_N"),
+ PINCTRL_PIN(87, "AUXIN0"),
+ PINCTRL_PIN(88, "AUXIN1"),
+ PINCTRL_PIN(89, "AUXIN2"),
+ PINCTRL_PIN(90, "AUXIN3"),
+ PINCTRL_PIN(91, "TXD4"),
+ PINCTRL_PIN(92, "RXD4"),
+ PINCTRL_PIN(93, "RTS4_N"),
+ PINCTRL_PIN(94, "CTS4_N"),
+ PINCTRL_PIN(95, "PWM1"),
+ PINCTRL_PIN(96, "PWM2"),
+ PINCTRL_PIN(97, "PWM3"),
+ PINCTRL_PIN(98, "PWM4"),
+ PINCTRL_PIN(99, "PWM5"),
+ PINCTRL_PIN(100, "PWM6"),
+ PINCTRL_PIN(101, "PWM7"),
+ PINCTRL_PIN(102, "GPIO_E"),
+};
+
+/* List all groups consisting of these pins dedicated to the enablement of
+ * certain hardware block and the corresponding mode for all of the pins. The
+ * hardware probably has multiple combinations of these pinouts.
+ */
+
+/* EMMC */
+static int mt7622_emmc_pins[] = { 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, };
+static int mt7622_emmc_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+static int mt7622_emmc_rst_pins[] = { 37, };
+static int mt7622_emmc_rst_funcs[] = { 1, };
+
+/* LED for EPHY */
+static int mt7622_ephy_leds_pins[] = { 86, 91, 92, 93, 94, };
+static int mt7622_ephy_leds_funcs[] = { 0, 0, 0, 0, 0, };
+static int mt7622_ephy0_led_pins[] = { 86, };
+static int mt7622_ephy0_led_funcs[] = { 0, };
+static int mt7622_ephy1_led_pins[] = { 91, };
+static int mt7622_ephy1_led_funcs[] = { 2, };
+static int mt7622_ephy2_led_pins[] = { 92, };
+static int mt7622_ephy2_led_funcs[] = { 2, };
+static int mt7622_ephy3_led_pins[] = { 93, };
+static int mt7622_ephy3_led_funcs[] = { 2, };
+static int mt7622_ephy4_led_pins[] = { 94, };
+static int mt7622_ephy4_led_funcs[] = { 2, };
+
+/* Embedded Switch */
+static int mt7622_esw_pins[] = { 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, };
+static int mt7622_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+static int mt7622_esw_p0_p1_pins[] = { 51, 52, 53, 54, 55, 56, 57, 58, };
+static int mt7622_esw_p0_p1_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static int mt7622_esw_p2_p3_p4_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, };
+static int mt7622_esw_p2_p3_p4_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, };
+/* RGMII via ESW */
+static int mt7622_rgmii_via_esw_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, };
+static int mt7622_rgmii_via_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* RGMII via GMAC1 */
+static int mt7622_rgmii_via_gmac1_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, };
+static int mt7622_rgmii_via_gmac1_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, };
+
+/* RGMII via GMAC2 */
+static int mt7622_rgmii_via_gmac2_pins[] = { 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, };
+static int mt7622_rgmii_via_gmac2_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* I2C */
+static int mt7622_i2c0_pins[] = { 14, 15, };
+static int mt7622_i2c0_funcs[] = { 0, 0, };
+static int mt7622_i2c1_0_pins[] = { 55, 56, };
+static int mt7622_i2c1_0_funcs[] = { 0, 0, };
+static int mt7622_i2c1_1_pins[] = { 73, 74, };
+static int mt7622_i2c1_1_funcs[] = { 3, 3, };
+static int mt7622_i2c1_2_pins[] = { 87, 88, };
+static int mt7622_i2c1_2_funcs[] = { 0, 0, };
+static int mt7622_i2c2_0_pins[] = { 57, 58, };
+static int mt7622_i2c2_0_funcs[] = { 0, 0, };
+static int mt7622_i2c2_1_pins[] = { 75, 76, };
+static int mt7622_i2c2_1_funcs[] = { 3, 3, };
+static int mt7622_i2c2_2_pins[] = { 89, 90, };
+static int mt7622_i2c2_2_funcs[] = { 0, 0, };
+
+/* I2S */
+static int mt7622_i2s_in_mclk_bclk_ws_pins[] = { 3, 4, 5, };
+static int mt7622_i2s_in_mclk_bclk_ws_funcs[] = { 3, 3, 0, };
+static int mt7622_i2s1_in_data_pins[] = { 1, };
+static int mt7622_i2s1_in_data_funcs[] = { 0, };
+static int mt7622_i2s2_in_data_pins[] = { 16, };
+static int mt7622_i2s2_in_data_funcs[] = { 0, };
+static int mt7622_i2s3_in_data_pins[] = { 17, };
+static int mt7622_i2s3_in_data_funcs[] = { 0, };
+static int mt7622_i2s4_in_data_pins[] = { 18, };
+static int mt7622_i2s4_in_data_funcs[] = { 0, };
+static int mt7622_i2s_out_mclk_bclk_ws_pins[] = { 3, 4, 5, };
+static int mt7622_i2s_out_mclk_bclk_ws_funcs[] = { 0, 0, 0, };
+static int mt7622_i2s1_out_data_pins[] = { 2, };
+static int mt7622_i2s1_out_data_funcs[] = { 0, };
+static int mt7622_i2s2_out_data_pins[] = { 19, };
+static int mt7622_i2s2_out_data_funcs[] = { 0, };
+static int mt7622_i2s3_out_data_pins[] = { 20, };
+static int mt7622_i2s3_out_data_funcs[] = { 0, };
+static int mt7622_i2s4_out_data_pins[] = { 21, };
+static int mt7622_i2s4_out_data_funcs[] = { 0, };
+
+/* IR */
+static int mt7622_ir_0_tx_pins[] = { 16, };
+static int mt7622_ir_0_tx_funcs[] = { 4, };
+static int mt7622_ir_1_tx_pins[] = { 59, };
+static int mt7622_ir_1_tx_funcs[] = { 5, };
+static int mt7622_ir_2_tx_pins[] = { 99, };
+static int mt7622_ir_2_tx_funcs[] = { 3, };
+static int mt7622_ir_0_rx_pins[] = { 17, };
+static int mt7622_ir_0_rx_funcs[] = { 4, };
+static int mt7622_ir_1_rx_pins[] = { 60, };
+static int mt7622_ir_1_rx_funcs[] = { 5, };
+static int mt7622_ir_2_rx_pins[] = { 100, };
+static int mt7622_ir_2_rx_funcs[] = { 3, };
+
+/* MDIO */
+static int mt7622_mdc_mdio_pins[] = { 23, 24, };
+static int mt7622_mdc_mdio_funcs[] = { 0, 0, };
+
+/* PCIE */
+static int mt7622_pcie0_0_waken_pins[] = { 14, };
+static int mt7622_pcie0_0_waken_funcs[] = { 2, };
+static int mt7622_pcie0_0_clkreq_pins[] = { 15, };
+static int mt7622_pcie0_0_clkreq_funcs[] = { 2, };
+static int mt7622_pcie0_1_waken_pins[] = { 79, };
+static int mt7622_pcie0_1_waken_funcs[] = { 4, };
+static int mt7622_pcie0_1_clkreq_pins[] = { 80, };
+static int mt7622_pcie0_1_clkreq_funcs[] = { 4, };
+static int mt7622_pcie1_0_waken_pins[] = { 14, };
+static int mt7622_pcie1_0_waken_funcs[] = { 3, };
+static int mt7622_pcie1_0_clkreq_pins[] = { 15, };
+static int mt7622_pcie1_0_clkreq_funcs[] = { 3, };
+
+static int mt7622_pcie0_pad_perst_pins[] = { 83, };
+static int mt7622_pcie0_pad_perst_funcs[] = { 0, };
+static int mt7622_pcie1_pad_perst_pins[] = { 84, };
+static int mt7622_pcie1_pad_perst_funcs[] = { 0, };
+
+/* PMIC bus */
+static int mt7622_pmic_bus_pins[] = { 71, 72, };
+static int mt7622_pmic_bus_funcs[] = { 0, 0, };
+
+/* Parallel NAND */
+static int mt7622_pnand_pins[] = { 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, };
+static int mt7622_pnand_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* PWM */
+static int mt7622_pwm_ch1_0_pins[] = { 51, };
+static int mt7622_pwm_ch1_0_funcs[] = { 3, };
+static int mt7622_pwm_ch1_1_pins[] = { 73, };
+static int mt7622_pwm_ch1_1_funcs[] = { 4, };
+static int mt7622_pwm_ch1_2_pins[] = { 95, };
+static int mt7622_pwm_ch1_2_funcs[] = { 0, };
+static int mt7622_pwm_ch2_0_pins[] = { 52, };
+static int mt7622_pwm_ch2_0_funcs[] = { 3, };
+static int mt7622_pwm_ch2_1_pins[] = { 74, };
+static int mt7622_pwm_ch2_1_funcs[] = { 4, };
+static int mt7622_pwm_ch2_2_pins[] = { 96, };
+static int mt7622_pwm_ch2_2_funcs[] = { 0, };
+static int mt7622_pwm_ch3_0_pins[] = { 53, };
+static int mt7622_pwm_ch3_0_funcs[] = { 3, };
+static int mt7622_pwm_ch3_1_pins[] = { 75, };
+static int mt7622_pwm_ch3_1_funcs[] = { 4, };
+static int mt7622_pwm_ch3_2_pins[] = { 97, };
+static int mt7622_pwm_ch3_2_funcs[] = { 0, };
+static int mt7622_pwm_ch4_0_pins[] = { 54, };
+static int mt7622_pwm_ch4_0_funcs[] = { 3, };
+static int mt7622_pwm_ch4_1_pins[] = { 67, };
+static int mt7622_pwm_ch4_1_funcs[] = { 3, };
+static int mt7622_pwm_ch4_2_pins[] = { 76, };
+static int mt7622_pwm_ch4_2_funcs[] = { 4, };
+static int mt7622_pwm_ch4_3_pins[] = { 98, };
+static int mt7622_pwm_ch4_3_funcs[] = { 0, };
+static int mt7622_pwm_ch5_0_pins[] = { 68, };
+static int mt7622_pwm_ch5_0_funcs[] = { 3, };
+static int mt7622_pwm_ch5_1_pins[] = { 77, };
+static int mt7622_pwm_ch5_1_funcs[] = { 4, };
+static int mt7622_pwm_ch5_2_pins[] = { 99, };
+static int mt7622_pwm_ch5_2_funcs[] = { 0, };
+static int mt7622_pwm_ch6_0_pins[] = { 69, };
+static int mt7622_pwm_ch6_0_funcs[] = { 3, };
+static int mt7622_pwm_ch6_1_pins[] = { 78, };
+static int mt7622_pwm_ch6_1_funcs[] = { 4, };
+static int mt7622_pwm_ch6_2_pins[] = { 81, };
+static int mt7622_pwm_ch6_2_funcs[] = { 4, };
+static int mt7622_pwm_ch6_3_pins[] = { 100, };
+static int mt7622_pwm_ch6_3_funcs[] = { 0, };
+static int mt7622_pwm_ch7_0_pins[] = { 70, };
+static int mt7622_pwm_ch7_0_funcs[] = { 3, };
+static int mt7622_pwm_ch7_1_pins[] = { 82, };
+static int mt7622_pwm_ch7_1_funcs[] = { 4, };
+static int mt7622_pwm_ch7_2_pins[] = { 101, };
+static int mt7622_pwm_ch7_2_funcs[] = { 0, };
+
+/* SD */
+static int mt7622_sd_0_pins[] = { 16, 17, 18, 19, 20, 21, };
+static int mt7622_sd_0_funcs[] = { 2, 2, 2, 2, 2, 2, };
+static int mt7622_sd_1_pins[] = { 25, 26, 27, 28, 29, 30, };
+static int mt7622_sd_1_funcs[] = { 2, 2, 2, 2, 2, 2, };
+
+/* Serial NAND */
+static int mt7622_snfi_pins[] = { 8, 9, 10, 11, 12, 13, };
+static int mt7622_snfi_funcs[] = { 2, 2, 2, 2, 2, 2, };
+
+/* SPI NOR */
+static int mt7622_spi_pins[] = { 8, 9, 10, 11, 12, 13 };
+static int mt7622_spi_funcs[] = { 0, 0, 0, 0, 0, 0, };
+
+/* SPIC */
+static int mt7622_spic0_0_pins[] = { 63, 64, 65, 66, };
+static int mt7622_spic0_0_funcs[] = { 4, 4, 4, 4, };
+static int mt7622_spic0_1_pins[] = { 79, 80, 81, 82, };
+static int mt7622_spic0_1_funcs[] = { 3, 3, 3, 3, };
+static int mt7622_spic1_0_pins[] = { 67, 68, 69, 70, };
+static int mt7622_spic1_0_funcs[] = { 4, 4, 4, 4, };
+static int mt7622_spic1_1_pins[] = { 73, 74, 75, 76, };
+static int mt7622_spic1_1_funcs[] = { 0, 0, 0, 0, };
+static int mt7622_spic2_0_pins[] = { 10, 11, 12, 13, };
+static int mt7622_spic2_0_funcs[] = { 0, 0, 0, 0, };
+static int mt7622_spic2_0_wp_hold_pins[] = { 8, 9, };
+static int mt7622_spic2_0_wp_hold_funcs[] = { 0, 0, };
+
+/* TDM */
+static int mt7622_tdm_0_out_mclk_bclk_ws_pins[] = { 8, 9, 10, };
+static int mt7622_tdm_0_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_0_in_mclk_bclk_ws_pins[] = { 11, 12, 13, };
+static int mt7622_tdm_0_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_0_out_data_pins[] = { 20, };
+static int mt7622_tdm_0_out_data_funcs[] = { 3, };
+static int mt7622_tdm_0_in_data_pins[] = { 21, };
+static int mt7622_tdm_0_in_data_funcs[] = { 3, };
+static int mt7622_tdm_1_out_mclk_bclk_ws_pins[] = { 57, 58, 59, };
+static int mt7622_tdm_1_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_1_in_mclk_bclk_ws_pins[] = { 60, 61, 62, };
+static int mt7622_tdm_1_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_1_out_data_pins[] = { 55, };
+static int mt7622_tdm_1_out_data_funcs[] = { 3, };
+static int mt7622_tdm_1_in_data_pins[] = { 56, };
+static int mt7622_tdm_1_in_data_funcs[] = { 3, };
+
+/* UART */
+static int mt7622_uart0_0_tx_rx_pins[] = { 6, 7, };
+static int mt7622_uart0_0_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart1_0_tx_rx_pins[] = { 55, 56, };
+static int mt7622_uart1_0_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart1_0_rts_cts_pins[] = { 57, 58, };
+static int mt7622_uart1_0_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart1_1_tx_rx_pins[] = { 73, 74, };
+static int mt7622_uart1_1_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart1_1_rts_cts_pins[] = { 75, 76, };
+static int mt7622_uart1_1_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart2_0_tx_rx_pins[] = { 3, 4, };
+static int mt7622_uart2_0_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart2_0_rts_cts_pins[] = { 1, 2, };
+static int mt7622_uart2_0_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart2_1_tx_rx_pins[] = { 51, 52, };
+static int mt7622_uart2_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart2_1_rts_cts_pins[] = { 53, 54, };
+static int mt7622_uart2_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart2_2_tx_rx_pins[] = { 59, 60, };
+static int mt7622_uart2_2_tx_rx_funcs[] = { 4, 4, };
+static int mt7622_uart2_2_rts_cts_pins[] = { 61, 62, };
+static int mt7622_uart2_2_rts_cts_funcs[] = { 4, 4, };
+static int mt7622_uart2_3_tx_rx_pins[] = { 95, 96, };
+static int mt7622_uart2_3_tx_rx_funcs[] = { 3, 3, };
+static int mt7622_uart3_0_tx_rx_pins[] = { 57, 58, };
+static int mt7622_uart3_0_tx_rx_funcs[] = { 5, 5, };
+static int mt7622_uart3_1_tx_rx_pins[] = { 81, 82, };
+static int mt7622_uart3_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart3_1_rts_cts_pins[] = { 79, 80, };
+static int mt7622_uart3_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart4_0_tx_rx_pins[] = { 61, 62, };
+static int mt7622_uart4_0_tx_rx_funcs[] = { 5, 5, };
+static int mt7622_uart4_1_tx_rx_pins[] = { 91, 92, };
+static int mt7622_uart4_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart4_1_rts_cts_pins[] = { 93, 94 };
+static int mt7622_uart4_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart4_2_tx_rx_pins[] = { 97, 98, };
+static int mt7622_uart4_2_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart4_2_rts_cts_pins[] = { 95, 96 };
+static int mt7622_uart4_2_rts_cts_funcs[] = { 2, 2, };
+
+/* Watchdog */
+static int mt7622_watchdog_pins[] = { 78, };
+static int mt7622_watchdog_funcs[] = { 0, };
+
+/* WLAN LED */
+static int mt7622_wled_pins[] = { 85, };
+static int mt7622_wled_funcs[] = { 0, };
+
+static const struct group_desc mt7622_groups[] = {
+ PINCTRL_PIN_GROUP("emmc", mt7622_emmc),
+ PINCTRL_PIN_GROUP("emmc_rst", mt7622_emmc_rst),
+ PINCTRL_PIN_GROUP("ephy_leds", mt7622_ephy_leds),
+ PINCTRL_PIN_GROUP("ephy0_led", mt7622_ephy0_led),
+ PINCTRL_PIN_GROUP("ephy1_led", mt7622_ephy1_led),
+ PINCTRL_PIN_GROUP("ephy2_led", mt7622_ephy2_led),
+ PINCTRL_PIN_GROUP("ephy3_led", mt7622_ephy3_led),
+ PINCTRL_PIN_GROUP("ephy4_led", mt7622_ephy4_led),
+ PINCTRL_PIN_GROUP("esw", mt7622_esw),
+ PINCTRL_PIN_GROUP("esw_p0_p1", mt7622_esw_p0_p1),
+ PINCTRL_PIN_GROUP("esw_p2_p3_p4", mt7622_esw_p2_p3_p4),
+ PINCTRL_PIN_GROUP("rgmii_via_esw", mt7622_rgmii_via_esw),
+ PINCTRL_PIN_GROUP("rgmii_via_gmac1", mt7622_rgmii_via_gmac1),
+ PINCTRL_PIN_GROUP("rgmii_via_gmac2", mt7622_rgmii_via_gmac2),
+ PINCTRL_PIN_GROUP("i2c0", mt7622_i2c0),
+ PINCTRL_PIN_GROUP("i2c1_0", mt7622_i2c1_0),
+ PINCTRL_PIN_GROUP("i2c1_1", mt7622_i2c1_1),
+ PINCTRL_PIN_GROUP("i2c1_2", mt7622_i2c1_2),
+ PINCTRL_PIN_GROUP("i2c2_0", mt7622_i2c2_0),
+ PINCTRL_PIN_GROUP("i2c2_1", mt7622_i2c2_1),
+ PINCTRL_PIN_GROUP("i2c2_2", mt7622_i2c2_2),
+ PINCTRL_PIN_GROUP("i2s_out_mclk_bclk_ws", mt7622_i2s_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("i2s_in_mclk_bclk_ws", mt7622_i2s_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("i2s1_in_data", mt7622_i2s1_in_data),
+ PINCTRL_PIN_GROUP("i2s2_in_data", mt7622_i2s2_in_data),
+ PINCTRL_PIN_GROUP("i2s3_in_data", mt7622_i2s3_in_data),
+ PINCTRL_PIN_GROUP("i2s4_in_data", mt7622_i2s4_in_data),
+ PINCTRL_PIN_GROUP("i2s1_out_data", mt7622_i2s1_out_data),
+ PINCTRL_PIN_GROUP("i2s2_out_data", mt7622_i2s2_out_data),
+ PINCTRL_PIN_GROUP("i2s3_out_data", mt7622_i2s3_out_data),
+ PINCTRL_PIN_GROUP("i2s4_out_data", mt7622_i2s4_out_data),
+ PINCTRL_PIN_GROUP("ir_0_tx", mt7622_ir_0_tx),
+ PINCTRL_PIN_GROUP("ir_1_tx", mt7622_ir_1_tx),
+ PINCTRL_PIN_GROUP("ir_2_tx", mt7622_ir_2_tx),
+ PINCTRL_PIN_GROUP("ir_0_rx", mt7622_ir_0_rx),
+ PINCTRL_PIN_GROUP("ir_1_rx", mt7622_ir_1_rx),
+ PINCTRL_PIN_GROUP("ir_2_rx", mt7622_ir_2_rx),
+ PINCTRL_PIN_GROUP("mdc_mdio", mt7622_mdc_mdio),
+ PINCTRL_PIN_GROUP("pcie0_0_waken", mt7622_pcie0_0_waken),
+ PINCTRL_PIN_GROUP("pcie0_0_clkreq", mt7622_pcie0_0_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_1_waken", mt7622_pcie0_1_waken),
+ PINCTRL_PIN_GROUP("pcie0_1_clkreq", mt7622_pcie0_1_clkreq),
+ PINCTRL_PIN_GROUP("pcie1_0_waken", mt7622_pcie1_0_waken),
+ PINCTRL_PIN_GROUP("pcie1_0_clkreq", mt7622_pcie1_0_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_pad_perst", mt7622_pcie0_pad_perst),
+ PINCTRL_PIN_GROUP("pcie1_pad_perst", mt7622_pcie1_pad_perst),
+ PINCTRL_PIN_GROUP("par_nand", mt7622_pnand),
+ PINCTRL_PIN_GROUP("pmic_bus", mt7622_pmic_bus),
+ PINCTRL_PIN_GROUP("pwm_ch1_0", mt7622_pwm_ch1_0),
+ PINCTRL_PIN_GROUP("pwm_ch1_1", mt7622_pwm_ch1_1),
+ PINCTRL_PIN_GROUP("pwm_ch1_2", mt7622_pwm_ch1_2),
+ PINCTRL_PIN_GROUP("pwm_ch2_0", mt7622_pwm_ch2_0),
+ PINCTRL_PIN_GROUP("pwm_ch2_1", mt7622_pwm_ch2_1),
+ PINCTRL_PIN_GROUP("pwm_ch2_2", mt7622_pwm_ch2_2),
+ PINCTRL_PIN_GROUP("pwm_ch3_0", mt7622_pwm_ch3_0),
+ PINCTRL_PIN_GROUP("pwm_ch3_1", mt7622_pwm_ch3_1),
+ PINCTRL_PIN_GROUP("pwm_ch3_2", mt7622_pwm_ch3_2),
+ PINCTRL_PIN_GROUP("pwm_ch4_0", mt7622_pwm_ch4_0),
+ PINCTRL_PIN_GROUP("pwm_ch4_1", mt7622_pwm_ch4_1),
+ PINCTRL_PIN_GROUP("pwm_ch4_2", mt7622_pwm_ch4_2),
+ PINCTRL_PIN_GROUP("pwm_ch4_3", mt7622_pwm_ch4_3),
+ PINCTRL_PIN_GROUP("pwm_ch5_0", mt7622_pwm_ch5_0),
+ PINCTRL_PIN_GROUP("pwm_ch5_1", mt7622_pwm_ch5_1),
+ PINCTRL_PIN_GROUP("pwm_ch5_2", mt7622_pwm_ch5_2),
+ PINCTRL_PIN_GROUP("pwm_ch6_0", mt7622_pwm_ch6_0),
+ PINCTRL_PIN_GROUP("pwm_ch6_1", mt7622_pwm_ch6_1),
+ PINCTRL_PIN_GROUP("pwm_ch6_2", mt7622_pwm_ch6_2),
+ PINCTRL_PIN_GROUP("pwm_ch6_3", mt7622_pwm_ch6_3),
+ PINCTRL_PIN_GROUP("pwm_ch7_0", mt7622_pwm_ch7_0),
+ PINCTRL_PIN_GROUP("pwm_ch7_1", mt7622_pwm_ch7_1),
+ PINCTRL_PIN_GROUP("pwm_ch7_2", mt7622_pwm_ch7_2),
+ PINCTRL_PIN_GROUP("sd_0", mt7622_sd_0),
+ PINCTRL_PIN_GROUP("sd_1", mt7622_sd_1),
+ PINCTRL_PIN_GROUP("snfi", mt7622_snfi),
+ PINCTRL_PIN_GROUP("spi_nor", mt7622_spi),
+ PINCTRL_PIN_GROUP("spic0_0", mt7622_spic0_0),
+ PINCTRL_PIN_GROUP("spic0_1", mt7622_spic0_1),
+ PINCTRL_PIN_GROUP("spic1_0", mt7622_spic1_0),
+ PINCTRL_PIN_GROUP("spic1_1", mt7622_spic1_1),
+ PINCTRL_PIN_GROUP("spic2_0", mt7622_spic2_0),
+ PINCTRL_PIN_GROUP("spic2_0_wp_hold", mt7622_spic2_0_wp_hold),
+ PINCTRL_PIN_GROUP("tdm_0_out_mclk_bclk_ws",
+ mt7622_tdm_0_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_0_in_mclk_bclk_ws",
+ mt7622_tdm_0_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_0_out_data", mt7622_tdm_0_out_data),
+ PINCTRL_PIN_GROUP("tdm_0_in_data", mt7622_tdm_0_in_data),
+ PINCTRL_PIN_GROUP("tdm_1_out_mclk_bclk_ws",
+ mt7622_tdm_1_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_1_in_mclk_bclk_ws",
+ mt7622_tdm_1_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_1_out_data", mt7622_tdm_1_out_data),
+ PINCTRL_PIN_GROUP("tdm_1_in_data", mt7622_tdm_1_in_data),
+ PINCTRL_PIN_GROUP("uart0_0_tx_rx", mt7622_uart0_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_0_tx_rx", mt7622_uart1_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_0_rts_cts", mt7622_uart1_0_rts_cts),
+ PINCTRL_PIN_GROUP("uart1_1_tx_rx", mt7622_uart1_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_1_rts_cts", mt7622_uart1_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7622_uart2_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_0_rts_cts", mt7622_uart2_0_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_1_tx_rx", mt7622_uart2_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_1_rts_cts", mt7622_uart2_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_2_tx_rx", mt7622_uart2_2_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_2_rts_cts", mt7622_uart2_2_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_3_tx_rx", mt7622_uart2_3_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_0_tx_rx", mt7622_uart3_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_1_tx_rx", mt7622_uart3_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_1_rts_cts", mt7622_uart3_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart4_0_tx_rx", mt7622_uart4_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_1_tx_rx", mt7622_uart4_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_1_rts_cts", mt7622_uart4_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart4_2_tx_rx", mt7622_uart4_2_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_2_rts_cts", mt7622_uart4_2_rts_cts),
+ PINCTRL_PIN_GROUP("watchdog", mt7622_watchdog),
+ PINCTRL_PIN_GROUP("wled", mt7622_wled),
+};
+
+/* Joint those groups owning the same capability in user point of view which
+ * allows that people tend to use through the device tree.
+ */
+static const char *mt7622_emmc_groups[] = { "emmc", "emmc_rst", };
+static const char *mt7622_ethernet_groups[] = { "esw", "esw_p0_p1",
+ "esw_p2_p3_p4", "mdc_mdio",
+ "rgmii_via_gmac1",
+ "rgmii_via_gmac2",
+ "rgmii_via_esw", };
+static const char *mt7622_i2c_groups[] = { "i2c0", "i2c1_0", "i2c1_1",
+ "i2c1_2", "i2c2_0", "i2c2_1",
+ "i2c2_2", };
+static const char *mt7622_i2s_groups[] = { "i2s_out_mclk_bclk_ws",
+ "i2s_in_mclk_bclk_ws",
+ "i2s1_in_data", "i2s2_in_data",
+ "i2s3_in_data", "i2s4_in_data",
+ "i2s1_out_data", "i2s2_out_data",
+ "i2s3_out_data", "i2s4_out_data", };
+static const char *mt7622_ir_groups[] = { "ir_0_tx", "ir_1_tx", "ir_2_tx",
+ "ir_0_rx", "ir_1_rx", "ir_2_rx"};
+static const char *mt7622_led_groups[] = { "ephy_leds", "ephy0_led",
+ "ephy1_led", "ephy2_led",
+ "ephy3_led", "ephy4_led",
+ "wled", };
+static const char *mt7622_flash_groups[] = { "par_nand", "snfi", "spi_nor"};
+static const char *mt7622_pcie_groups[] = { "pcie0_0_waken", "pcie0_0_clkreq",
+ "pcie0_1_waken", "pcie0_1_clkreq",
+ "pcie1_0_waken", "pcie1_0_clkreq",
+ "pcie0_pad_perst",
+ "pcie1_pad_perst", };
+static const char *mt7622_pmic_bus_groups[] = { "pmic_bus", };
+static const char *mt7622_pwm_groups[] = { "pwm_ch1_0", "pwm_ch1_1",
+ "pwm_ch1_2", "pwm_ch2_0",
+ "pwm_ch2_1", "pwm_ch2_2",
+ "pwm_ch3_0", "pwm_ch3_1",
+ "pwm_ch3_2", "pwm_ch4_0",
+ "pwm_ch4_1", "pwm_ch4_2",
+ "pwm_ch4_3", "pwm_ch5_0",
+ "pwm_ch5_1", "pwm_ch5_2",
+ "pwm_ch6_0", "pwm_ch6_1",
+ "pwm_ch6_2", "pwm_ch6_3",
+ "pwm_ch7_0", "pwm_ch7_1",
+ "pwm_ch7_2", };
+static const char *mt7622_sd_groups[] = { "sd_0", "sd_1", };
+static const char *mt7622_spic_groups[] = { "spic0_0", "spic0_1", "spic1_0",
+ "spic1_1", "spic2_0",
+ "spic2_0_wp_hold", };
+static const char *mt7622_tdm_groups[] = { "tdm_0_out_mclk_bclk_ws",
+ "tdm_0_in_mclk_bclk_ws",
+ "tdm_0_out_data",
+ "tdm_0_in_data",
+ "tdm_1_out_mclk_bclk_ws",
+ "tdm_1_in_mclk_bclk_ws",
+ "tdm_1_out_data",
+ "tdm_1_in_data", };
+
+static const char *mt7622_uart_groups[] = { "uart0_0_tx_rx",
+ "uart1_0_tx_rx", "uart1_0_rts_cts",
+ "uart1_1_tx_rx", "uart1_1_rts_cts",
+ "uart2_0_tx_rx", "uart2_0_rts_cts",
+ "uart2_1_tx_rx", "uart2_1_rts_cts",
+ "uart2_2_tx_rx", "uart2_2_rts_cts",
+ "uart2_3_tx_rx",
+ "uart3_0_tx_rx",
+ "uart3_1_tx_rx", "uart3_1_rts_cts",
+ "uart4_0_tx_rx",
+ "uart4_1_tx_rx", "uart4_1_rts_cts",
+ "uart4_2_tx_rx",
+ "uart4_2_rts_cts",};
+static const char *mt7622_wdt_groups[] = { "watchdog", };
+
+static const struct function_desc mt7622_functions[] = {
+ {"emmc", mt7622_emmc_groups, ARRAY_SIZE(mt7622_emmc_groups)},
+ {"eth", mt7622_ethernet_groups, ARRAY_SIZE(mt7622_ethernet_groups)},
+ {"i2c", mt7622_i2c_groups, ARRAY_SIZE(mt7622_i2c_groups)},
+ {"i2s", mt7622_i2s_groups, ARRAY_SIZE(mt7622_i2s_groups)},
+ {"ir", mt7622_ir_groups, ARRAY_SIZE(mt7622_ir_groups)},
+ {"led", mt7622_led_groups, ARRAY_SIZE(mt7622_led_groups)},
+ {"flash", mt7622_flash_groups, ARRAY_SIZE(mt7622_flash_groups)},
+ {"pcie", mt7622_pcie_groups, ARRAY_SIZE(mt7622_pcie_groups)},
+ {"pmic", mt7622_pmic_bus_groups, ARRAY_SIZE(mt7622_pmic_bus_groups)},
+ {"pwm", mt7622_pwm_groups, ARRAY_SIZE(mt7622_pwm_groups)},
+ {"sd", mt7622_sd_groups, ARRAY_SIZE(mt7622_sd_groups)},
+ {"spi", mt7622_spic_groups, ARRAY_SIZE(mt7622_spic_groups)},
+ {"tdm", mt7622_tdm_groups, ARRAY_SIZE(mt7622_tdm_groups)},
+ {"uart", mt7622_uart_groups, ARRAY_SIZE(mt7622_uart_groups)},
+ {"watchdog", mt7622_wdt_groups, ARRAY_SIZE(mt7622_wdt_groups)},
+};
+
+static const struct pinconf_generic_params mtk_custom_bindings[] = {
+ {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0},
+ {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0},
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct pin_config_item mtk_conf_items[] = {
+ PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
+ PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
+};
+#endif
+
+static const struct mtk_pin_soc mt7622_data = {
+ .reg_cal = mt7622_reg_cals,
+ .pins = mt7622_pins,
+ .npins = ARRAY_SIZE(mt7622_pins),
+ .grps = mt7622_groups,
+ .ngrps = ARRAY_SIZE(mt7622_groups),
+ .funcs = mt7622_functions,
+ .nfuncs = ARRAY_SIZE(mt7622_functions),
+};
+
+static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
+{
+ writel_relaxed(val, pctl->base + reg);
+}
+
+static u32 mtk_r32(struct mtk_pinctrl *pctl, u32 reg)
+{
+ return readl_relaxed(pctl->base + reg);
+}
+
+static void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set)
+{
+ u32 val;
+
+ val = mtk_r32(pctl, reg);
+ val &= ~mask;
+ val |= set;
+ mtk_w32(pctl, reg, val);
+}
+
+static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, int pin,
+ const struct mtk_pin_reg_calc *rc,
+ struct mtk_pin_field *pfd)
+{
+ const struct mtk_pin_field_calc *c, *e;
+ u32 bits;
+
+ c = rc->range;
+ e = c + rc->nranges;
+
+ while (c < e) {
+ if (pin >= c->s_pin && pin <= c->e_pin)
+ break;
+ c++;
+ }
+
+ if (c >= e) {
+ dev_err(hw->dev, "Out of range for pin = %d\n", pin);
+ return -EINVAL;
+ }
+
+ /* Caculated bits as the overall offset the pin is located at */
+ bits = c->s_bit + (pin - c->s_pin) * (c->x_bits);
+
+ /* Fill pfd from bits and 32-bit register applied is assumed */
+ pfd->offset = c->s_addr + c->x_addrs * (bits / 32);
+ pfd->bitpos = bits % 32;
+ pfd->mask = (1 << c->x_bits) - 1;
+
+ /* pfd->next is used for indicating that bit wrapping-around happens
+ * which requires the manipulation for bit 0 starting in the next
+ * register to form the complete field read/write.
+ */
+ pfd->next = pfd->bitpos + c->x_bits - 1 > 31 ? c->x_addrs : 0;
+
+ return 0;
+}
+
+static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw, int pin,
+ int field, struct mtk_pin_field *pfd)
+{
+ const struct mtk_pin_reg_calc *rc;
+
+ if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
+ dev_err(hw->dev, "Invalid Field %d\n", field);
+ return -EINVAL;
+ }
+
+ if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
+ rc = &hw->soc->reg_cal[field];
+ } else {
+ dev_err(hw->dev, "Undefined range for field %d\n", field);
+ return -EINVAL;
+ }
+
+ return mtk_hw_pin_field_lookup(hw, pin, rc, pfd);
+}
+
+static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
+{
+ *l = 32 - pf->bitpos;
+ *h = get_count_order(pf->mask) - *l;
+}
+
+static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
+ struct mtk_pin_field *pf, int value)
+{
+ int nbits_l, nbits_h;
+
+ mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+ mtk_rmw(hw, pf->offset, pf->mask << pf->bitpos,
+ (value & pf->mask) << pf->bitpos);
+
+ mtk_rmw(hw, pf->offset + pf->next, BIT(nbits_h) - 1,
+ (value & pf->mask) >> nbits_l);
+}
+
+static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
+ struct mtk_pin_field *pf, int *value)
+{
+ int nbits_l, nbits_h, h, l;
+
+ mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+ l = (mtk_r32(hw, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
+ h = (mtk_r32(hw, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
+
+ *value = (h << nbits_l) | l;
+}
+
+static int mtk_hw_set_value(struct mtk_pinctrl *hw, int pin, int field,
+ int value)
+{
+ struct mtk_pin_field pf;
+ int err;
+
+ err = mtk_hw_pin_field_get(hw, pin, field, &pf);
+ if (err)
+ return err;
+
+ if (!pf.next)
+ mtk_rmw(hw, pf.offset, pf.mask << pf.bitpos,
+ (value & pf.mask) << pf.bitpos);
+ else
+ mtk_hw_write_cross_field(hw, &pf, value);
+
+ return 0;
+}
+
+static int mtk_hw_get_value(struct mtk_pinctrl *hw, int pin, int field,
+ int *value)
+{
+ struct mtk_pin_field pf;
+ int err;
+
+ err = mtk_hw_pin_field_get(hw, pin, field, &pf);
+ if (err)
+ return err;
+
+ if (!pf.next)
+ *value = (mtk_r32(hw, pf.offset) >> pf.bitpos) & pf.mask;
+ else
+ mtk_hw_read_cross_field(hw, &pf, value);
+
+ return 0;
+}
+
+static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int selector, unsigned int group)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ struct function_desc *func;
+ struct group_desc *grp;
+ int i;
+
+ func = pinmux_generic_get_function(pctldev, selector);
+ if (!func)
+ return -EINVAL;
+
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ return -EINVAL;
+
+ dev_dbg(pctldev->dev, "enable function %s group %s\n",
+ func->name, grp->name);
+
+ for (i = 0; i < grp->num_pins; i++) {
+ int *pin_modes = grp->data;
+
+ mtk_hw_set_value(hw, grp->pins[i], PINCTRL_PIN_REG_MODE,
+ pin_modes[i]);
+ }
+
+ return 0;
+}
+
+static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+
+ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_MODE, MTK_GPIO_MODE);
+}
+
+static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin, bool input)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+
+ /* hardware would take 0 as input direction */
+ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR, !input);
+}
+
+static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ u32 param = pinconf_to_config_param(*config);
+ int val, val2, err, reg, ret = 1;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PU, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PD, &val2);
+ if (err)
+ return err;
+
+ if (val || val2)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_SLEW_RATE:
+ reg = (param == PIN_CONFIG_BIAS_PULL_UP) ?
+ PINCTRL_PIN_REG_PU :
+ (param == PIN_CONFIG_BIAS_PULL_DOWN) ?
+ PINCTRL_PIN_REG_PD : PINCTRL_PIN_REG_SR;
+
+ err = mtk_hw_get_value(hw, pin, reg, &val);
+ if (err)
+ return err;
+
+ if (!val)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val);
+ if (err)
+ return err;
+
+ /* HW takes input mode as zero; output mode as non-zero */
+ if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
+ (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_SMT, &val2);
+ if (err)
+ return err;
+
+ if (val || !val2)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E4, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E8, &val2);
+ if (err)
+ return err;
+
+ /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
+ * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
+ */
+ ret = ((val2 << 1) + val + 1) * 4;
+
+ break;
+ case MTK_PIN_CONFIG_TDSEL:
+ case MTK_PIN_CONFIG_RDSEL:
+ reg = (param == MTK_PIN_CONFIG_TDSEL) ?
+ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
+
+ err = mtk_hw_get_value(hw, pin, reg, &val);
+ if (err)
+ return err;
+
+ ret = val;
+
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, ret);
+
+ return 0;
+}
+
+static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ u32 reg, param, arg;
+ int cfg, err = 0;
+
+ for (cfg = 0; cfg < num_configs; cfg++) {
+ param = pinconf_to_config_param(configs[cfg]);
+ arg = pinconf_to_config_argument(configs[cfg]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
+ (param == PIN_CONFIG_BIAS_PULL_UP) ? 1 : 2;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PU,
+ arg & 1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PD,
+ !!(arg & 2));
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT,
+ MTK_DISABLE);
+ if (err)
+ goto err;
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_SLEW_RATE:
+ reg = (param == PIN_CONFIG_SLEW_RATE) ?
+ PINCTRL_PIN_REG_SR : PINCTRL_PIN_REG_DIR;
+
+ arg = (param == PIN_CONFIG_INPUT_ENABLE) ? 0 :
+ (param == PIN_CONFIG_OUTPUT_ENABLE) ? 1 : arg;
+ err = mtk_hw_set_value(hw, pin, reg, arg);
+ if (err)
+ goto err;
+
+ break;
+ case PIN_CONFIG_OUTPUT:
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR,
+ MTK_OUTPUT);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DO,
+ arg);
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ /* arg = 1: Input mode & SMT enable ;
+ * arg = 0: Output mode & SMT disable
+ */
+ arg = arg ? 2 : 1;
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR,
+ arg & 1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT,
+ !!(arg & 2));
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ /* 4mA when (e8, e4) = (0, 0);
+ * 8mA when (e8, e4) = (0, 1);
+ * 12mA when (e8, e4) = (1, 0);
+ * 16mA when (e8, e4) = (1, 1)
+ */
+ if (!(arg % 4) && (arg >= 4 && arg <= 16)) {
+ arg = arg / 4 - 1;
+ err = mtk_hw_set_value(hw, pin,
+ PINCTRL_PIN_REG_E4,
+ arg & 0x1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin,
+ PINCTRL_PIN_REG_E8,
+ (arg & 0x2) >> 1);
+ if (err)
+ goto err;
+ } else {
+ err = -ENOTSUPP;
+ }
+ break;
+ case MTK_PIN_CONFIG_TDSEL:
+ case MTK_PIN_CONFIG_RDSEL:
+ reg = (param == MTK_PIN_CONFIG_TDSEL) ?
+ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
+
+ err = mtk_hw_set_value(hw, pin, reg, arg);
+ if (err)
+ goto err;
+ break;
+ default:
+ err = -ENOTSUPP;
+ }
+ }
+err:
+ return err;
+}
+
+static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int i, npins, old = 0;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ if (mtk_pinconf_get(pctldev, pins[i], config))
+ return -ENOTSUPP;
+
+ /* configs do not match between two pins */
+ if (i && old != *config)
+ return -ENOTSUPP;
+
+ old = *config;
+ }
+
+ return 0;
+}
+
+static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int i, npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinctrl_ops mtk_pctlops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static const struct pinmux_ops mtk_pmxops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = mtk_pinmux_set_mux,
+ .gpio_request_enable = mtk_pinmux_gpio_request_enable,
+ .gpio_set_direction = mtk_pinmux_gpio_set_direction,
+ .strict = true,
+};
+
+static const struct pinconf_ops mtk_confops = {
+ .is_generic = true,
+ .pin_config_get = mtk_pinconf_get,
+ .pin_config_set = mtk_pinconf_set,
+ .pin_config_group_get = mtk_pinconf_group_get,
+ .pin_config_group_set = mtk_pinconf_group_set,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+static struct pinctrl_desc mtk_desc = {
+ .name = PINCTRL_PINCTRL_DEV,
+ .pctlops = &mtk_pctlops,
+ .pmxops = &mtk_pmxops,
+ .confops = &mtk_confops,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent);
+ int value, err;
+
+ err = mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value);
+ if (err)
+ return err;
+
+ return !!value;
+}
+
+static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
+{
+ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent);
+
+ mtk_hw_set_value(hw, gpio, PINCTRL_PIN_REG_DO, !!value);
+}
+
+static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
+{
+ return pinctrl_gpio_direction_input(chip->base + gpio);
+}
+
+static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
+ int value)
+{
+ mtk_gpio_set(chip, gpio, value);
+
+ return pinctrl_gpio_direction_output(chip->base + gpio);
+}
+
+static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
+{
+ struct gpio_chip *chip = &hw->chip;
+ int ret;
+
+ chip->label = PINCTRL_PINCTRL_DEV;
+ chip->parent = hw->dev;
+ chip->request = gpiochip_generic_request;
+ chip->free = gpiochip_generic_free;
+ chip->direction_input = mtk_gpio_direction_input;
+ chip->direction_output = mtk_gpio_direction_output;
+ chip->get = mtk_gpio_get;
+ chip->set = mtk_gpio_set;
+ chip->base = -1;
+ chip->ngpio = hw->soc->npins;
+ chip->of_node = np;
+ chip->of_gpio_n_cells = 2;
+
+ ret = gpiochip_add_data(chip, hw);
+ if (ret < 0)
+ return ret;
+
+ ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
+ chip->ngpio);
+ if (ret < 0) {
+ gpiochip_remove(chip);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_build_groups(struct mtk_pinctrl *hw)
+{
+ int err, i;
+
+ for (i = 0; i < hw->soc->ngrps; i++) {
+ const struct group_desc *group = hw->soc->grps + i;
+
+ err = pinctrl_generic_add_group(hw->pctrl, group->name,
+ group->pins, group->num_pins,
+ group->data);
+ if (err) {
+ dev_err(hw->dev, "Failed to register group %s\n",
+ group->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int mtk_build_functions(struct mtk_pinctrl *hw)
+{
+ int i, err;
+
+ for (i = 0; i < hw->soc->nfuncs ; i++) {
+ const struct function_desc *func = hw->soc->funcs + i;
+
+ err = pinmux_generic_add_function(hw->pctrl, func->name,
+ func->group_names,
+ func->num_group_names,
+ func->data);
+ if (err) {
+ dev_err(hw->dev, "Failed to register function %s\n",
+ func->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pinctrl_of_match[] = {
+ { .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data},
+ { }
+};
+
+static int mtk_pinctrl_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mtk_pinctrl *hw;
+ const struct of_device_id *of_id =
+ of_match_device(mtk_pinctrl_of_match, &pdev->dev);
+ int err;
+
+ hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ hw->soc = of_id->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "missing IO resource\n");
+ return -ENXIO;
+ }
+
+ hw->dev = &pdev->dev;
+ hw->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hw->base))
+ return PTR_ERR(hw->base);
+
+ /* Setup pins descriptions per SoC types */
+ mtk_desc.pins = hw->soc->pins;
+ mtk_desc.npins = hw->soc->npins;
+ mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
+ mtk_desc.custom_params = mtk_custom_bindings;
+#ifdef CONFIG_DEBUG_FS
+ mtk_desc.custom_conf_items = mtk_conf_items;
+#endif
+
+ hw->pctrl = devm_pinctrl_register(&pdev->dev, &mtk_desc, hw);
+ if (IS_ERR(hw->pctrl))
+ return PTR_ERR(hw->pctrl);
+
+ /* Setup groups descriptions per SoC types */
+ err = mtk_build_groups(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to build groups\n");
+ return 0;
+ }
+
+ /* Setup functions descriptions per SoC types */
+ err = mtk_build_functions(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to build functions\n");
+ return err;
+ }
+
+ err = mtk_build_gpiochip(hw, pdev->dev.of_node);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add gpio_chip\n");
+ return err;
+ }
+
+ platform_set_drvdata(pdev, hw);
+
+ return 0;
+}
+
+static struct platform_driver mtk_pinctrl_driver = {
+ .driver = {
+ .name = "mtk-pinctrl",
+ .of_match_table = mtk_pinctrl_of_match,
+ },
+ .probe = mtk_pinctrl_probe,
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+ return platform_driver_register(&mtk_pinctrl_driver);
+}
+arch_initcall(mtk_pinctrl_init);
diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
index 1a51778759ea..c80951d6caff 100644
--- a/drivers/pinctrl/meson/Kconfig
+++ b/drivers/pinctrl/meson/Kconfig
@@ -38,4 +38,13 @@ config PINCTRL_MESON_GXL
config PINCTRL_MESON8_PMX
bool
+config PINCTRL_MESON_AXG
+ bool "Meson axg Soc pinctrl driver"
+ depends on ARM64
+ select PINCTRL_MESON_AXG_PMX
+ default y
+
+config PINCTRL_MESON_AXG_PMX
+ bool
+
endif
diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
index cbd47bb74549..3c6580c2d9d7 100644
--- a/drivers/pinctrl/meson/Makefile
+++ b/drivers/pinctrl/meson/Makefile
@@ -4,3 +4,5 @@ obj-$(CONFIG_PINCTRL_MESON8) += pinctrl-meson8.o
obj-$(CONFIG_PINCTRL_MESON8B) += pinctrl-meson8b.o
obj-$(CONFIG_PINCTRL_MESON_GXBB) += pinctrl-meson-gxbb.o
obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
+obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
+obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
new file mode 100644
index 000000000000..e8931d9cf863
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
@@ -0,0 +1,118 @@
+/*
+ * Second generation of pinmux driver for Amlogic Meson-AXG SoC.
+ *
+ * Copyright (c) 2017 Baylibre SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
+ * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen <xingyu.chen@amlogic.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ or MIT)
+ */
+
+/*
+ * This new generation of pinctrl IP is mainly adopted by the
+ * Meson-AXG SoC and later series, which use 4-width continuous
+ * register bit to select the function for each pin.
+ *
+ * The value 0 is always selecting the GPIO mode, while other
+ * values (start from 1) for selecting the function mode.
+ */
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-meson.h"
+#include "pinctrl-meson-axg-pmx.h"
+
+static int meson_axg_pmx_get_bank(struct meson_pinctrl *pc,
+ unsigned int pin,
+ struct meson_pmx_bank **bank)
+{
+ int i;
+ struct meson_axg_pmx_data *pmx = pc->data->pmx_data;
+
+ for (i = 0; i < pmx->num_pmx_banks; i++)
+ if (pin >= pmx->pmx_banks[i].first &&
+ pin <= pmx->pmx_banks[i].last) {
+ *bank = &pmx->pmx_banks[i];
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int meson_pmx_calc_reg_and_offset(struct meson_pmx_bank *bank,
+ unsigned int pin, unsigned int *reg,
+ unsigned int *offset)
+{
+ int shift;
+
+ shift = pin - bank->first;
+
+ *reg = bank->reg + (bank->offset + (shift << 2)) / 32;
+ *offset = (bank->offset + (shift << 2)) % 32;
+
+ return 0;
+}
+
+static int meson_axg_pmx_update_function(struct meson_pinctrl *pc,
+ unsigned int pin, unsigned int func)
+{
+ int ret;
+ int reg;
+ int offset;
+ struct meson_pmx_bank *bank;
+
+ ret = meson_axg_pmx_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_pmx_calc_reg_and_offset(bank, pin, &reg, &offset);
+
+ ret = regmap_update_bits(pc->reg_mux, reg << 2,
+ 0xf << offset, (func & 0xf) << offset);
+
+ return ret;
+}
+
+static int meson_axg_pmx_set_mux(struct pinctrl_dev *pcdev,
+ unsigned int func_num, unsigned int group_num)
+{
+ int i;
+ int ret;
+ struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
+ struct meson_pmx_func *func = &pc->data->funcs[func_num];
+ struct meson_pmx_group *group = &pc->data->groups[group_num];
+ struct meson_pmx_axg_data *pmx_data =
+ (struct meson_pmx_axg_data *)group->data;
+
+ dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
+ group->name);
+
+ for (i = 0; i < group->num_pins; i++) {
+ ret = meson_axg_pmx_update_function(pc, group->pins[i],
+ pmx_data->func);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_axg_pmx_request_gpio(struct pinctrl_dev *pcdev,
+ struct pinctrl_gpio_range *range, unsigned int offset)
+{
+ struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
+
+ return meson_axg_pmx_update_function(pc, offset, 0);
+}
+
+const struct pinmux_ops meson_axg_pmx_ops = {
+ .set_mux = meson_axg_pmx_set_mux,
+ .get_functions_count = meson_pmx_get_funcs_count,
+ .get_function_name = meson_pmx_get_func_name,
+ .get_function_groups = meson_pmx_get_groups,
+ .gpio_request_enable = meson_axg_pmx_request_gpio,
+};
diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.h b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.h
new file mode 100644
index 000000000000..8ff88bf2e849
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 Baylibre SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
+ * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen <xingyu.chen@amlogic.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ or MIT)
+ */
+
+struct meson_pmx_bank {
+ const char *name;
+ unsigned int first;
+ unsigned int last;
+ unsigned int reg;
+ unsigned int offset;
+};
+
+struct meson_axg_pmx_data {
+ struct meson_pmx_bank *pmx_banks;
+ unsigned int num_pmx_banks;
+};
+
+#define BANK_PMX(n, f, l, r, o) \
+ { \
+ .name = n, \
+ .first = f, \
+ .last = l, \
+ .reg = r, \
+ .offset = o, \
+ }
+
+struct meson_pmx_axg_data {
+ unsigned int func;
+};
+
+#define PMX_DATA(f) \
+ { \
+ .func = f, \
+ }
+
+#define GROUP(grp, f) \
+ { \
+ .name = #grp, \
+ .pins = grp ## _pins, \
+ .num_pins = ARRAY_SIZE(grp ## _pins), \
+ .data = (const struct meson_pmx_axg_data[]){ \
+ PMX_DATA(f), \
+ }, \
+ }
+
+#define GPIO_GROUP(gpio) \
+ { \
+ .name = #gpio, \
+ .pins = (const unsigned int[]){ gpio }, \
+ .num_pins = 1, \
+ .data = (const struct meson_pmx_axg_data[]){ \
+ PMX_DATA(0), \
+ }, \
+ }
+
+extern const struct pinmux_ops meson_axg_pmx_ops;
diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg.c b/drivers/pinctrl/meson/pinctrl-meson-axg.c
new file mode 100644
index 000000000000..1fda9d6c7ea3
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-axg.c
@@ -0,0 +1,975 @@
+/*
+ * Pin controller and GPIO driver for Amlogic Meson AXG SoC.
+ *
+ * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen <xingyu.chen@amlogic.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ or MIT)
+ */
+
+#include <dt-bindings/gpio/meson-axg-gpio.h>
+#include "pinctrl-meson.h"
+#include "pinctrl-meson-axg-pmx.h"
+
+static const struct pinctrl_pin_desc meson_axg_periphs_pins[] = {
+ MESON_PIN(GPIOZ_0),
+ MESON_PIN(GPIOZ_1),
+ MESON_PIN(GPIOZ_2),
+ MESON_PIN(GPIOZ_3),
+ MESON_PIN(GPIOZ_4),
+ MESON_PIN(GPIOZ_5),
+ MESON_PIN(GPIOZ_6),
+ MESON_PIN(GPIOZ_7),
+ MESON_PIN(GPIOZ_8),
+ MESON_PIN(GPIOZ_9),
+ MESON_PIN(GPIOZ_10),
+ MESON_PIN(BOOT_0),
+ MESON_PIN(BOOT_1),
+ MESON_PIN(BOOT_2),
+ MESON_PIN(BOOT_3),
+ MESON_PIN(BOOT_4),
+ MESON_PIN(BOOT_5),
+ MESON_PIN(BOOT_6),
+ MESON_PIN(BOOT_7),
+ MESON_PIN(BOOT_8),
+ MESON_PIN(BOOT_9),
+ MESON_PIN(BOOT_10),
+ MESON_PIN(BOOT_11),
+ MESON_PIN(BOOT_12),
+ MESON_PIN(BOOT_13),
+ MESON_PIN(BOOT_14),
+ MESON_PIN(GPIOA_0),
+ MESON_PIN(GPIOA_1),
+ MESON_PIN(GPIOA_2),
+ MESON_PIN(GPIOA_3),
+ MESON_PIN(GPIOA_4),
+ MESON_PIN(GPIOA_5),
+ MESON_PIN(GPIOA_6),
+ MESON_PIN(GPIOA_7),
+ MESON_PIN(GPIOA_8),
+ MESON_PIN(GPIOA_9),
+ MESON_PIN(GPIOA_10),
+ MESON_PIN(GPIOA_11),
+ MESON_PIN(GPIOA_12),
+ MESON_PIN(GPIOA_13),
+ MESON_PIN(GPIOA_14),
+ MESON_PIN(GPIOA_15),
+ MESON_PIN(GPIOA_16),
+ MESON_PIN(GPIOA_17),
+ MESON_PIN(GPIOA_18),
+ MESON_PIN(GPIOA_19),
+ MESON_PIN(GPIOA_20),
+ MESON_PIN(GPIOX_0),
+ MESON_PIN(GPIOX_1),
+ MESON_PIN(GPIOX_2),
+ MESON_PIN(GPIOX_3),
+ MESON_PIN(GPIOX_4),
+ MESON_PIN(GPIOX_5),
+ MESON_PIN(GPIOX_6),
+ MESON_PIN(GPIOX_7),
+ MESON_PIN(GPIOX_8),
+ MESON_PIN(GPIOX_9),
+ MESON_PIN(GPIOX_10),
+ MESON_PIN(GPIOX_11),
+ MESON_PIN(GPIOX_12),
+ MESON_PIN(GPIOX_13),
+ MESON_PIN(GPIOX_14),
+ MESON_PIN(GPIOX_15),
+ MESON_PIN(GPIOX_16),
+ MESON_PIN(GPIOX_17),
+ MESON_PIN(GPIOX_18),
+ MESON_PIN(GPIOX_19),
+ MESON_PIN(GPIOX_20),
+ MESON_PIN(GPIOX_21),
+ MESON_PIN(GPIOX_22),
+ MESON_PIN(GPIOY_0),
+ MESON_PIN(GPIOY_1),
+ MESON_PIN(GPIOY_2),
+ MESON_PIN(GPIOY_3),
+ MESON_PIN(GPIOY_4),
+ MESON_PIN(GPIOY_5),
+ MESON_PIN(GPIOY_6),
+ MESON_PIN(GPIOY_7),
+ MESON_PIN(GPIOY_8),
+ MESON_PIN(GPIOY_9),
+ MESON_PIN(GPIOY_10),
+ MESON_PIN(GPIOY_11),
+ MESON_PIN(GPIOY_12),
+ MESON_PIN(GPIOY_13),
+ MESON_PIN(GPIOY_14),
+ MESON_PIN(GPIOY_15),
+};
+
+static const struct pinctrl_pin_desc meson_axg_aobus_pins[] = {
+ MESON_PIN(GPIOAO_0),
+ MESON_PIN(GPIOAO_1),
+ MESON_PIN(GPIOAO_2),
+ MESON_PIN(GPIOAO_3),
+ MESON_PIN(GPIOAO_4),
+ MESON_PIN(GPIOAO_5),
+ MESON_PIN(GPIOAO_6),
+ MESON_PIN(GPIOAO_7),
+ MESON_PIN(GPIOAO_8),
+ MESON_PIN(GPIOAO_9),
+ MESON_PIN(GPIOAO_10),
+ MESON_PIN(GPIOAO_11),
+ MESON_PIN(GPIOAO_12),
+ MESON_PIN(GPIOAO_13),
+ MESON_PIN(GPIO_TEST_N),
+};
+
+/* emmc */
+static const unsigned int emmc_nand_d0_pins[] = {BOOT_0};
+static const unsigned int emmc_nand_d1_pins[] = {BOOT_1};
+static const unsigned int emmc_nand_d2_pins[] = {BOOT_2};
+static const unsigned int emmc_nand_d3_pins[] = {BOOT_3};
+static const unsigned int emmc_nand_d4_pins[] = {BOOT_4};
+static const unsigned int emmc_nand_d5_pins[] = {BOOT_5};
+static const unsigned int emmc_nand_d6_pins[] = {BOOT_6};
+static const unsigned int emmc_nand_d7_pins[] = {BOOT_7};
+
+static const unsigned int emmc_clk_pins[] = {BOOT_8};
+static const unsigned int emmc_cmd_pins[] = {BOOT_10};
+static const unsigned int emmc_ds_pins[] = {BOOT_13};
+
+/* nand */
+static const unsigned int nand_ce0_pins[] = {BOOT_8};
+static const unsigned int nand_ale_pins[] = {BOOT_9};
+static const unsigned int nand_cle_pins[] = {BOOT_10};
+static const unsigned int nand_wen_clk_pins[] = {BOOT_11};
+static const unsigned int nand_ren_wr_pins[] = {BOOT_12};
+static const unsigned int nand_rb0_pins[] = {BOOT_13};
+
+/* nor */
+static const unsigned int nor_hold_pins[] = {BOOT_3};
+static const unsigned int nor_d_pins[] = {BOOT_4};
+static const unsigned int nor_q_pins[] = {BOOT_5};
+static const unsigned int nor_c_pins[] = {BOOT_6};
+static const unsigned int nor_wp_pins[] = {BOOT_9};
+static const unsigned int nor_cs_pins[] = {BOOT_14};
+
+/* sdio */
+static const unsigned int sdio_d0_pins[] = {GPIOX_0};
+static const unsigned int sdio_d1_pins[] = {GPIOX_1};
+static const unsigned int sdio_d2_pins[] = {GPIOX_2};
+static const unsigned int sdio_d3_pins[] = {GPIOX_3};
+static const unsigned int sdio_clk_pins[] = {GPIOX_4};
+static const unsigned int sdio_cmd_pins[] = {GPIOX_5};
+
+/* spi0 */
+static const unsigned int spi0_clk_pins[] = {GPIOZ_0};
+static const unsigned int spi0_mosi_pins[] = {GPIOZ_1};
+static const unsigned int spi0_miso_pins[] = {GPIOZ_2};
+static const unsigned int spi0_ss0_pins[] = {GPIOZ_3};
+static const unsigned int spi0_ss1_pins[] = {GPIOZ_4};
+static const unsigned int spi0_ss2_pins[] = {GPIOZ_5};
+
+/* spi1 */
+static const unsigned int spi1_clk_x_pins[] = {GPIOX_19};
+static const unsigned int spi1_mosi_x_pins[] = {GPIOX_17};
+static const unsigned int spi1_miso_x_pins[] = {GPIOX_18};
+static const unsigned int spi1_ss0_x_pins[] = {GPIOX_16};
+
+static const unsigned int spi1_clk_a_pins[] = {GPIOA_4};
+static const unsigned int spi1_mosi_a_pins[] = {GPIOA_2};
+static const unsigned int spi1_miso_a_pins[] = {GPIOA_3};
+static const unsigned int spi1_ss0_a_pins[] = {GPIOA_5};
+static const unsigned int spi1_ss1_pins[] = {GPIOA_6};
+
+/* i2c0 */
+static const unsigned int i2c0_sck_pins[] = {GPIOZ_6};
+static const unsigned int i2c0_sda_pins[] = {GPIOZ_7};
+
+/* i2c1 */
+static const unsigned int i2c1_sck_z_pins[] = {GPIOZ_8};
+static const unsigned int i2c1_sda_z_pins[] = {GPIOZ_9};
+
+static const unsigned int i2c1_sck_x_pins[] = {GPIOX_16};
+static const unsigned int i2c1_sda_x_pins[] = {GPIOX_17};
+
+/* i2c2 */
+static const unsigned int i2c2_sck_x_pins[] = {GPIOX_18};
+static const unsigned int i2c2_sda_x_pins[] = {GPIOX_19};
+
+static const unsigned int i2c2_sda_a_pins[] = {GPIOA_17};
+static const unsigned int i2c2_sck_a_pins[] = {GPIOA_18};
+
+/* i2c3 */
+static const unsigned int i2c3_sda_a6_pins[] = {GPIOA_6};
+static const unsigned int i2c3_sck_a7_pins[] = {GPIOA_7};
+
+static const unsigned int i2c3_sda_a12_pins[] = {GPIOA_12};
+static const unsigned int i2c3_sck_a13_pins[] = {GPIOA_13};
+
+static const unsigned int i2c3_sda_a19_pins[] = {GPIOA_19};
+static const unsigned int i2c3_sck_a20_pins[] = {GPIOA_20};
+
+/* uart_a */
+static const unsigned int uart_rts_a_pins[] = {GPIOX_11};
+static const unsigned int uart_cts_a_pins[] = {GPIOX_10};
+static const unsigned int uart_tx_a_pins[] = {GPIOX_8};
+static const unsigned int uart_rx_a_pins[] = {GPIOX_9};
+
+/* uart_b */
+static const unsigned int uart_rts_b_z_pins[] = {GPIOZ_0};
+static const unsigned int uart_cts_b_z_pins[] = {GPIOZ_1};
+static const unsigned int uart_tx_b_z_pins[] = {GPIOZ_2};
+static const unsigned int uart_rx_b_z_pins[] = {GPIOZ_3};
+
+static const unsigned int uart_rts_b_x_pins[] = {GPIOX_18};
+static const unsigned int uart_cts_b_x_pins[] = {GPIOX_19};
+static const unsigned int uart_tx_b_x_pins[] = {GPIOX_16};
+static const unsigned int uart_rx_b_x_pins[] = {GPIOX_17};
+
+/* uart_ao_b */
+static const unsigned int uart_ao_tx_b_z_pins[] = {GPIOZ_8};
+static const unsigned int uart_ao_rx_b_z_pins[] = {GPIOZ_9};
+static const unsigned int uart_ao_cts_b_z_pins[] = {GPIOZ_6};
+static const unsigned int uart_ao_rts_b_z_pins[] = {GPIOZ_7};
+
+/* pwm_a */
+static const unsigned int pwm_a_z_pins[] = {GPIOZ_5};
+
+static const unsigned int pwm_a_x18_pins[] = {GPIOX_18};
+static const unsigned int pwm_a_x20_pins[] = {GPIOX_20};
+
+static const unsigned int pwm_a_a_pins[] = {GPIOA_14};
+
+/* pwm_b */
+static const unsigned int pwm_b_z_pins[] = {GPIOZ_4};
+
+static const unsigned int pwm_b_x_pins[] = {GPIOX_19};
+
+static const unsigned int pwm_b_a_pins[] = {GPIOA_15};
+
+/* pwm_c */
+static const unsigned int pwm_c_x10_pins[] = {GPIOX_10};
+static const unsigned int pwm_c_x17_pins[] = {GPIOX_17};
+
+static const unsigned int pwm_c_a_pins[] = {GPIOA_16};
+
+/* pwm_d */
+static const unsigned int pwm_d_x11_pins[] = {GPIOX_11};
+static const unsigned int pwm_d_x16_pins[] = {GPIOX_16};
+
+/* pwm_vs */
+static const unsigned int pwm_vs_pins[] = {GPIOA_0};
+
+/* spdif_in */
+static const unsigned int spdif_in_z_pins[] = {GPIOZ_4};
+
+static const unsigned int spdif_in_a1_pins[] = {GPIOA_1};
+static const unsigned int spdif_in_a7_pins[] = {GPIOA_7};
+static const unsigned int spdif_in_a19_pins[] = {GPIOA_19};
+static const unsigned int spdif_in_a20_pins[] = {GPIOA_20};
+
+/* spdif_out */
+static const unsigned int spdif_out_z_pins[] = {GPIOZ_5};
+
+static const unsigned int spdif_out_a1_pins[] = {GPIOA_1};
+static const unsigned int spdif_out_a11_pins[] = {GPIOA_11};
+static const unsigned int spdif_out_a19_pins[] = {GPIOA_19};
+static const unsigned int spdif_out_a20_pins[] = {GPIOA_20};
+
+/* jtag_ee */
+static const unsigned int jtag_tdo_x_pins[] = {GPIOX_0};
+static const unsigned int jtag_tdi_x_pins[] = {GPIOX_1};
+static const unsigned int jtag_clk_x_pins[] = {GPIOX_4};
+static const unsigned int jtag_tms_x_pins[] = {GPIOX_5};
+
+/* eth */
+static const unsigned int eth_txd0_x_pins[] = {GPIOX_8};
+static const unsigned int eth_txd1_x_pins[] = {GPIOX_9};
+static const unsigned int eth_txen_x_pins[] = {GPIOX_10};
+static const unsigned int eth_rgmii_rx_clk_x_pins[] = {GPIOX_12};
+static const unsigned int eth_rxd0_x_pins[] = {GPIOX_13};
+static const unsigned int eth_rxd1_x_pins[] = {GPIOX_14};
+static const unsigned int eth_rx_dv_x_pins[] = {GPIOX_15};
+static const unsigned int eth_mdio_x_pins[] = {GPIOX_21};
+static const unsigned int eth_mdc_x_pins[] = {GPIOX_22};
+
+static const unsigned int eth_txd0_y_pins[] = {GPIOY_10};
+static const unsigned int eth_txd1_y_pins[] = {GPIOY_11};
+static const unsigned int eth_txen_y_pins[] = {GPIOY_9};
+static const unsigned int eth_rgmii_rx_clk_y_pins[] = {GPIOY_2};
+static const unsigned int eth_rxd0_y_pins[] = {GPIOY_4};
+static const unsigned int eth_rxd1_y_pins[] = {GPIOY_5};
+static const unsigned int eth_rx_dv_y_pins[] = {GPIOY_3};
+static const unsigned int eth_mdio_y_pins[] = {GPIOY_0};
+static const unsigned int eth_mdc_y_pins[] = {GPIOY_1};
+
+static const unsigned int eth_rxd2_rgmii_pins[] = {GPIOY_6};
+static const unsigned int eth_rxd3_rgmii_pins[] = {GPIOY_7};
+static const unsigned int eth_rgmii_tx_clk_pins[] = {GPIOY_8};
+static const unsigned int eth_txd2_rgmii_pins[] = {GPIOY_12};
+static const unsigned int eth_txd3_rgmii_pins[] = {GPIOY_13};
+
+/* pdm */
+static const unsigned int pdm_dclk_a14_pins[] = {GPIOA_14};
+static const unsigned int pdm_dclk_a19_pins[] = {GPIOA_19};
+static const unsigned int pdm_din0_pins[] = {GPIOA_15};
+static const unsigned int pdm_din1_pins[] = {GPIOA_16};
+static const unsigned int pdm_din2_pins[] = {GPIOA_17};
+static const unsigned int pdm_din3_pins[] = {GPIOA_18};
+
+static struct meson_pmx_group meson_axg_periphs_groups[] = {
+ GPIO_GROUP(GPIOZ_0),
+ GPIO_GROUP(GPIOZ_1),
+ GPIO_GROUP(GPIOZ_2),
+ GPIO_GROUP(GPIOZ_3),
+ GPIO_GROUP(GPIOZ_4),
+ GPIO_GROUP(GPIOZ_5),
+ GPIO_GROUP(GPIOZ_6),
+ GPIO_GROUP(GPIOZ_7),
+ GPIO_GROUP(GPIOZ_8),
+ GPIO_GROUP(GPIOZ_9),
+ GPIO_GROUP(GPIOZ_10),
+
+ GPIO_GROUP(BOOT_0),
+ GPIO_GROUP(BOOT_1),
+ GPIO_GROUP(BOOT_2),
+ GPIO_GROUP(BOOT_3),
+ GPIO_GROUP(BOOT_4),
+ GPIO_GROUP(BOOT_5),
+ GPIO_GROUP(BOOT_6),
+ GPIO_GROUP(BOOT_7),
+ GPIO_GROUP(BOOT_8),
+ GPIO_GROUP(BOOT_9),
+ GPIO_GROUP(BOOT_10),
+ GPIO_GROUP(BOOT_11),
+ GPIO_GROUP(BOOT_12),
+ GPIO_GROUP(BOOT_13),
+ GPIO_GROUP(BOOT_14),
+
+ GPIO_GROUP(GPIOA_0),
+ GPIO_GROUP(GPIOA_1),
+ GPIO_GROUP(GPIOA_2),
+ GPIO_GROUP(GPIOA_3),
+ GPIO_GROUP(GPIOA_4),
+ GPIO_GROUP(GPIOA_5),
+ GPIO_GROUP(GPIOA_6),
+ GPIO_GROUP(GPIOA_7),
+ GPIO_GROUP(GPIOA_8),
+ GPIO_GROUP(GPIOA_9),
+ GPIO_GROUP(GPIOA_10),
+ GPIO_GROUP(GPIOA_11),
+ GPIO_GROUP(GPIOA_12),
+ GPIO_GROUP(GPIOA_13),
+ GPIO_GROUP(GPIOA_14),
+ GPIO_GROUP(GPIOA_15),
+ GPIO_GROUP(GPIOA_16),
+ GPIO_GROUP(GPIOA_17),
+ GPIO_GROUP(GPIOA_19),
+ GPIO_GROUP(GPIOA_20),
+
+ GPIO_GROUP(GPIOX_0),
+ GPIO_GROUP(GPIOX_1),
+ GPIO_GROUP(GPIOX_2),
+ GPIO_GROUP(GPIOX_3),
+ GPIO_GROUP(GPIOX_4),
+ GPIO_GROUP(GPIOX_5),
+ GPIO_GROUP(GPIOX_6),
+ GPIO_GROUP(GPIOX_7),
+ GPIO_GROUP(GPIOX_8),
+ GPIO_GROUP(GPIOX_9),
+ GPIO_GROUP(GPIOX_10),
+ GPIO_GROUP(GPIOX_11),
+ GPIO_GROUP(GPIOX_12),
+ GPIO_GROUP(GPIOX_13),
+ GPIO_GROUP(GPIOX_14),
+ GPIO_GROUP(GPIOX_15),
+ GPIO_GROUP(GPIOX_16),
+ GPIO_GROUP(GPIOX_17),
+ GPIO_GROUP(GPIOX_18),
+ GPIO_GROUP(GPIOX_19),
+ GPIO_GROUP(GPIOX_20),
+ GPIO_GROUP(GPIOX_21),
+ GPIO_GROUP(GPIOX_22),
+
+ GPIO_GROUP(GPIOY_0),
+ GPIO_GROUP(GPIOY_1),
+ GPIO_GROUP(GPIOY_2),
+ GPIO_GROUP(GPIOY_3),
+ GPIO_GROUP(GPIOY_4),
+ GPIO_GROUP(GPIOY_5),
+ GPIO_GROUP(GPIOY_6),
+ GPIO_GROUP(GPIOY_7),
+ GPIO_GROUP(GPIOY_8),
+ GPIO_GROUP(GPIOY_9),
+ GPIO_GROUP(GPIOY_10),
+ GPIO_GROUP(GPIOY_11),
+ GPIO_GROUP(GPIOY_12),
+ GPIO_GROUP(GPIOY_13),
+ GPIO_GROUP(GPIOY_14),
+ GPIO_GROUP(GPIOY_15),
+
+ /* bank BOOT */
+ GROUP(emmc_nand_d0, 1),
+ GROUP(emmc_nand_d1, 1),
+ GROUP(emmc_nand_d2, 1),
+ GROUP(emmc_nand_d3, 1),
+ GROUP(emmc_nand_d4, 1),
+ GROUP(emmc_nand_d5, 1),
+ GROUP(emmc_nand_d6, 1),
+ GROUP(emmc_nand_d7, 1),
+ GROUP(emmc_clk, 1),
+ GROUP(emmc_cmd, 1),
+ GROUP(emmc_ds, 1),
+ GROUP(nand_ce0, 2),
+ GROUP(nand_ale, 2),
+ GROUP(nand_cle, 2),
+ GROUP(nand_wen_clk, 2),
+ GROUP(nand_ren_wr, 2),
+ GROUP(nand_rb0, 2),
+ GROUP(nor_hold, 3),
+ GROUP(nor_d, 3),
+ GROUP(nor_q, 3),
+ GROUP(nor_c, 3),
+ GROUP(nor_wp, 3),
+ GROUP(nor_cs, 3),
+
+ /* bank GPIOZ */
+ GROUP(spi0_clk, 1),
+ GROUP(spi0_mosi, 1),
+ GROUP(spi0_miso, 1),
+ GROUP(spi0_ss0, 1),
+ GROUP(spi0_ss1, 1),
+ GROUP(spi0_ss2, 1),
+ GROUP(i2c0_sck, 1),
+ GROUP(i2c0_sda, 1),
+ GROUP(i2c1_sck_z, 1),
+ GROUP(i2c1_sda_z, 1),
+ GROUP(uart_rts_b_z, 2),
+ GROUP(uart_cts_b_z, 2),
+ GROUP(uart_tx_b_z, 2),
+ GROUP(uart_rx_b_z, 2),
+ GROUP(pwm_a_z, 2),
+ GROUP(pwm_b_z, 2),
+ GROUP(spdif_in_z, 3),
+ GROUP(spdif_out_z, 3),
+ GROUP(uart_ao_tx_b_z, 2),
+ GROUP(uart_ao_rx_b_z, 2),
+ GROUP(uart_ao_cts_b_z, 2),
+ GROUP(uart_ao_rts_b_z, 2),
+
+ /* bank GPIOX */
+ GROUP(sdio_d0, 1),
+ GROUP(sdio_d1, 1),
+ GROUP(sdio_d2, 1),
+ GROUP(sdio_d3, 1),
+ GROUP(sdio_clk, 1),
+ GROUP(sdio_cmd, 1),
+ GROUP(i2c1_sck_x, 1),
+ GROUP(i2c1_sda_x, 1),
+ GROUP(i2c2_sck_x, 1),
+ GROUP(i2c2_sda_x, 1),
+ GROUP(uart_rts_a, 1),
+ GROUP(uart_cts_a, 1),
+ GROUP(uart_tx_a, 1),
+ GROUP(uart_rx_a, 1),
+ GROUP(uart_rts_b_x, 2),
+ GROUP(uart_cts_b_x, 2),
+ GROUP(uart_tx_b_x, 2),
+ GROUP(uart_rx_b_x, 2),
+ GROUP(jtag_tdo_x, 2),
+ GROUP(jtag_tdi_x, 2),
+ GROUP(jtag_clk_x, 2),
+ GROUP(jtag_tms_x, 2),
+ GROUP(spi1_clk_x, 4),
+ GROUP(spi1_mosi_x, 4),
+ GROUP(spi1_miso_x, 4),
+ GROUP(spi1_ss0_x, 4),
+ GROUP(pwm_a_x18, 3),
+ GROUP(pwm_a_x20, 1),
+ GROUP(pwm_b_x, 3),
+ GROUP(pwm_c_x10, 3),
+ GROUP(pwm_c_x17, 3),
+ GROUP(pwm_d_x11, 3),
+ GROUP(pwm_d_x16, 3),
+ GROUP(eth_txd0_x, 4),
+ GROUP(eth_txd1_x, 4),
+ GROUP(eth_txen_x, 4),
+ GROUP(eth_rgmii_rx_clk_x, 4),
+ GROUP(eth_rxd0_x, 4),
+ GROUP(eth_rxd1_x, 4),
+ GROUP(eth_rx_dv_x, 4),
+ GROUP(eth_mdio_x, 4),
+ GROUP(eth_mdc_x, 4),
+
+ /* bank GPIOY */
+ GROUP(eth_txd0_y, 1),
+ GROUP(eth_txd1_y, 1),
+ GROUP(eth_txen_y, 1),
+ GROUP(eth_rgmii_rx_clk_y, 1),
+ GROUP(eth_rxd0_y, 1),
+ GROUP(eth_rxd1_y, 1),
+ GROUP(eth_rx_dv_y, 1),
+ GROUP(eth_mdio_y, 1),
+ GROUP(eth_mdc_y, 1),
+ GROUP(eth_rxd2_rgmii, 1),
+ GROUP(eth_rxd3_rgmii, 1),
+ GROUP(eth_rgmii_tx_clk, 1),
+ GROUP(eth_txd2_rgmii, 1),
+ GROUP(eth_txd3_rgmii, 1),
+
+ /* bank GPIOA */
+ GROUP(spdif_out_a1, 4),
+ GROUP(spdif_out_a11, 3),
+ GROUP(spdif_out_a19, 2),
+ GROUP(spdif_out_a20, 1),
+ GROUP(spdif_in_a1, 3),
+ GROUP(spdif_in_a7, 3),
+ GROUP(spdif_in_a19, 1),
+ GROUP(spdif_in_a20, 2),
+ GROUP(spi1_clk_a, 3),
+ GROUP(spi1_mosi_a, 3),
+ GROUP(spi1_miso_a, 3),
+ GROUP(spi1_ss0_a, 3),
+ GROUP(spi1_ss1, 3),
+ GROUP(pwm_a_a, 3),
+ GROUP(pwm_b_a, 3),
+ GROUP(pwm_c_a, 3),
+ GROUP(pwm_vs, 2),
+ GROUP(i2c2_sda_a, 3),
+ GROUP(i2c2_sck_a, 3),
+ GROUP(i2c3_sda_a6, 4),
+ GROUP(i2c3_sck_a7, 4),
+ GROUP(i2c3_sda_a12, 4),
+ GROUP(i2c3_sck_a13, 4),
+ GROUP(i2c3_sda_a19, 4),
+ GROUP(i2c3_sck_a20, 4),
+ GROUP(pdm_dclk_a14, 1),
+ GROUP(pdm_dclk_a19, 3),
+ GROUP(pdm_din0, 1),
+ GROUP(pdm_din1, 1),
+ GROUP(pdm_din2, 1),
+ GROUP(pdm_din3, 1),
+};
+
+/* uart_ao_a */
+static const unsigned int uart_ao_tx_a_pins[] = {GPIOAO_0};
+static const unsigned int uart_ao_rx_a_pins[] = {GPIOAO_1};
+static const unsigned int uart_ao_cts_a_pins[] = {GPIOAO_2};
+static const unsigned int uart_ao_rts_a_pins[] = {GPIOAO_3};
+
+/* uart_ao_b */
+static const unsigned int uart_ao_tx_b_pins[] = {GPIOAO_4};
+static const unsigned int uart_ao_rx_b_pins[] = {GPIOAO_5};
+static const unsigned int uart_ao_cts_b_pins[] = {GPIOAO_2};
+static const unsigned int uart_ao_rts_b_pins[] = {GPIOAO_3};
+
+/* i2c_ao */
+static const unsigned int i2c_ao_sck_4_pins[] = {GPIOAO_4};
+static const unsigned int i2c_ao_sda_5_pins[] = {GPIOAO_5};
+static const unsigned int i2c_ao_sck_8_pins[] = {GPIOAO_8};
+static const unsigned int i2c_ao_sda_9_pins[] = {GPIOAO_9};
+static const unsigned int i2c_ao_sck_10_pins[] = {GPIOAO_10};
+static const unsigned int i2c_ao_sda_11_pins[] = {GPIOAO_11};
+
+/* i2c_ao_slave */
+static const unsigned int i2c_ao_slave_sck_pins[] = {GPIOAO_10};
+static const unsigned int i2c_ao_slave_sda_pins[] = {GPIOAO_11};
+
+/* ir_in */
+static const unsigned int remote_input_ao_pins[] = {GPIOAO_6};
+
+/* ir_out */
+static const unsigned int remote_out_ao_pins[] = {GPIOAO_7};
+
+/* pwm_ao_a */
+static const unsigned int pwm_ao_a_pins[] = {GPIOAO_3};
+
+/* pwm_ao_b */
+static const unsigned int pwm_ao_b_ao2_pins[] = {GPIOAO_2};
+static const unsigned int pwm_ao_b_ao12_pins[] = {GPIOAO_12};
+
+/* pwm_ao_c */
+static const unsigned int pwm_ao_c_ao8_pins[] = {GPIOAO_8};
+static const unsigned int pwm_ao_c_ao13_pins[] = {GPIOAO_13};
+
+/* pwm_ao_d */
+static const unsigned int pwm_ao_d_pins[] = {GPIOAO_9};
+
+/* jtag_ao */
+static const unsigned int jtag_ao_tdi_pins[] = {GPIOAO_3};
+static const unsigned int jtag_ao_tdo_pins[] = {GPIOAO_4};
+static const unsigned int jtag_ao_clk_pins[] = {GPIOAO_5};
+static const unsigned int jtag_ao_tms_pins[] = {GPIOAO_7};
+
+static struct meson_pmx_group meson_axg_aobus_groups[] = {
+ GPIO_GROUP(GPIOAO_0),
+ GPIO_GROUP(GPIOAO_1),
+ GPIO_GROUP(GPIOAO_2),
+ GPIO_GROUP(GPIOAO_3),
+ GPIO_GROUP(GPIOAO_4),
+ GPIO_GROUP(GPIOAO_5),
+ GPIO_GROUP(GPIOAO_6),
+ GPIO_GROUP(GPIOAO_7),
+ GPIO_GROUP(GPIOAO_8),
+ GPIO_GROUP(GPIOAO_9),
+ GPIO_GROUP(GPIOAO_10),
+ GPIO_GROUP(GPIOAO_11),
+ GPIO_GROUP(GPIOAO_12),
+ GPIO_GROUP(GPIOAO_13),
+ GPIO_GROUP(GPIO_TEST_N),
+
+ /* bank AO */
+ GROUP(uart_ao_tx_a, 1),
+ GROUP(uart_ao_rx_a, 1),
+ GROUP(uart_ao_cts_a, 2),
+ GROUP(uart_ao_rts_a, 2),
+ GROUP(uart_ao_tx_b, 1),
+ GROUP(uart_ao_rx_b, 1),
+ GROUP(uart_ao_cts_b, 1),
+ GROUP(uart_ao_rts_b, 1),
+ GROUP(i2c_ao_sck_4, 2),
+ GROUP(i2c_ao_sda_5, 2),
+ GROUP(i2c_ao_sck_8, 2),
+ GROUP(i2c_ao_sda_9, 2),
+ GROUP(i2c_ao_sck_10, 2),
+ GROUP(i2c_ao_sda_11, 2),
+ GROUP(i2c_ao_slave_sck, 1),
+ GROUP(i2c_ao_slave_sda, 1),
+ GROUP(remote_input_ao, 1),
+ GROUP(remote_out_ao, 1),
+ GROUP(pwm_ao_a, 3),
+ GROUP(pwm_ao_b_ao2, 3),
+ GROUP(pwm_ao_b_ao12, 3),
+ GROUP(pwm_ao_c_ao8, 3),
+ GROUP(pwm_ao_c_ao13, 3),
+ GROUP(pwm_ao_d, 3),
+ GROUP(jtag_ao_tdi, 4),
+ GROUP(jtag_ao_tdo, 4),
+ GROUP(jtag_ao_clk, 4),
+ GROUP(jtag_ao_tms, 4),
+};
+
+static const char * const gpio_periphs_groups[] = {
+ "GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4",
+ "GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9",
+ "GPIOZ_10",
+
+ "BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4",
+ "BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
+ "BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
+
+ "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
+ "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
+ "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14",
+ "GPIOA_15", "GPIOA_16", "GPIOA_17", "GPIOA_18", "GPIOA_19",
+ "GPIOA_20",
+
+ "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+ "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+ "GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+ "GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19",
+ "GPIOX_20", "GPIOX_21", "GPIOX_22",
+
+ "GPIOY_0", "GPIOY_1", "GPIOY_2", "GPIOY_3", "GPIOY_4",
+ "GPIOY_5", "GPIOY_6", "GPIOY_7", "GPIOY_8", "GPIOY_9",
+ "GPIOY_10", "GPIOY_11", "GPIOY_12", "GPIOY_13", "GPIOY_14",
+ "GPIOY_15",
+};
+
+static const char * const emmc_groups[] = {
+ "emmc_nand_d0", "emmc_nand_d1", "emmc_nand_d2",
+ "emmc_nand_d3", "emmc_nand_d4", "emmc_nand_d5",
+ "emmc_nand_d6", "emmc_nand_d7",
+ "emmc_clk", "emmc_cmd", "emmc_ds",
+};
+
+static const char * const nand_groups[] = {
+ "emmc_nand_d0", "emmc_nand_d1", "emmc_nand_d2",
+ "emmc_nand_d3", "emmc_nand_d4", "emmc_nand_d5",
+ "emmc_nand_d6", "emmc_nand_d7",
+ "nand_ce0", "nand_ale", "nand_cle",
+ "nand_wen_clk", "nand_ren_wr", "nand_rb0",
+};
+
+static const char * const nor_groups[] = {
+ "nor_d", "nor_q", "nor_c", "nor_cs",
+ "nor_hold", "nor_wp",
+};
+
+static const char * const sdio_groups[] = {
+ "sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3",
+ "sdio_cmd", "sdio_clk",
+};
+
+static const char * const spi0_groups[] = {
+ "spi0_clk", "spi0_mosi", "spi0_miso", "spi0_ss0",
+ "spi0_ss1", "spi0_ss2"
+};
+
+static const char * const spi1_groups[] = {
+ "spi1_clk_x", "spi1_mosi_x", "spi1_miso_x", "spi1_ss0_x",
+ "spi1_clk_a", "spi1_mosi_a", "spi1_miso_a", "spi1_ss0_a",
+ "spi1_ss1"
+};
+
+static const char * const uart_a_groups[] = {
+ "uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a",
+};
+
+static const char * const uart_b_groups[] = {
+ "uart_tx_b_z", "uart_rx_b_z", "uart_cts_b_z", "uart_rts_b_z",
+ "uart_tx_b_x", "uart_rx_b_x", "uart_cts_b_x", "uart_rts_b_x",
+};
+
+static const char * const uart_ao_b_gpioz_groups[] = {
+ "uart_ao_tx_b_z", "uart_ao_rx_b_z",
+ "uart_ao_cts_b_z", "uart_ao_rts_b_z",
+};
+
+static const char * const i2c0_groups[] = {
+ "i2c0_sck", "i2c0_sda",
+};
+
+static const char * const i2c1_groups[] = {
+ "i2c1_sck_z", "i2c1_sda_z",
+ "i2c1_sck_x", "i2c1_sda_x",
+};
+
+static const char * const i2c2_groups[] = {
+ "i2c2_sck_x", "i2c2_sda_x",
+ "i2c2_sda_a", "i2c2_sck_a",
+};
+
+static const char * const i2c3_groups[] = {
+ "i2c3_sda_a6", "i2c3_sck_a7",
+ "i2c3_sda_a12", "i2c3_sck_a13",
+ "i2c3_sda_a19", "i2c3_sck_a20",
+};
+
+static const char * const eth_groups[] = {
+ "eth_rxd2_rgmii", "eth_rxd3_rgmii", "eth_rgmii_tx_clk",
+ "eth_txd2_rgmii", "eth_txd3_rgmii",
+ "eth_txd0_x", "eth_txd1_x", "eth_txen_x", "eth_rgmii_rx_clk_x",
+ "eth_rxd0_x", "eth_rxd1_x", "eth_rx_dv_x", "eth_mdio_x",
+ "eth_mdc_x",
+ "eth_txd0_y", "eth_txd1_y", "eth_txen_y", "eth_rgmii_rx_clk_y",
+ "eth_rxd0_y", "eth_rxd1_y", "eth_rx_dv_y", "eth_mdio_y",
+ "eth_mdc_y",
+};
+
+static const char * const pwm_a_groups[] = {
+ "pwm_a_z", "pwm_a_x18", "pwm_a_x20", "pwm_a_a",
+};
+
+static const char * const pwm_b_groups[] = {
+ "pwm_b_z", "pwm_b_x", "pwm_b_a",
+};
+
+static const char * const pwm_c_groups[] = {
+ "pwm_c_x10", "pwm_c_x17", "pwm_c_a",
+};
+
+static const char * const pwm_d_groups[] = {
+ "pwm_d_x11", "pwm_d_x16",
+};
+
+static const char * const pwm_vs_groups[] = {
+ "pwm_vs",
+};
+
+static const char * const spdif_out_groups[] = {
+ "spdif_out_z", "spdif_out_a1", "spdif_out_a11",
+ "spdif_out_a19", "spdif_out_a20",
+};
+
+static const char * const spdif_in_groups[] = {
+ "spdif_in_z", "spdif_in_a1", "spdif_in_a7",
+ "spdif_in_a19", "spdif_in_a20",
+};
+
+static const char * const jtag_ee_groups[] = {
+ "jtag_tdo_x", "jtag_tdi_x", "jtag_clk_x",
+ "jtag_tms_x",
+};
+
+static const char * const pdm_groups[] = {
+ "pdm_din0", "pdm_din1", "pdm_din2", "pdm_din3",
+ "pdm_dclk_a14", "pdm_dclk_a19",
+};
+
+static const char * const gpio_aobus_groups[] = {
+ "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
+ "GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
+ "GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13",
+ "GPIO_TEST_N",
+};
+
+static const char * const uart_ao_a_groups[] = {
+ "uart_ao_tx_a", "uart_ao_rx_a", "uart_ao_cts_a", "uart_ao_rts_a",
+};
+
+static const char * const uart_ao_b_groups[] = {
+ "uart_ao_tx_b", "uart_ao_rx_b", "uart_ao_cts_b", "uart_ao_rts_b",
+};
+
+static const char * const i2c_ao_groups[] = {
+ "i2c_ao_sck_4", "i2c_ao_sda_5",
+ "i2c_ao_sck_8", "i2c_ao_sda_9",
+ "i2c_ao_sck_10", "i2c_ao_sda_11",
+};
+
+static const char * const i2c_ao_slave_groups[] = {
+ "i2c_ao_slave_sck", "i2c_ao_slave_sda",
+};
+
+static const char * const remote_input_ao_groups[] = {
+ "remote_input_ao",
+};
+
+static const char * const remote_out_ao_groups[] = {
+ "remote_out_ao",
+};
+
+static const char * const pwm_ao_a_groups[] = {
+ "pwm_ao_a",
+};
+
+static const char * const pwm_ao_b_groups[] = {
+ "pwm_ao_b_ao2", "pwm_ao_b_ao12",
+};
+
+static const char * const pwm_ao_c_groups[] = {
+ "pwm_ao_c_ao8", "pwm_ao_c_ao13",
+};
+
+static const char * const pwm_ao_d_groups[] = {
+ "pwm_ao_d",
+};
+
+static const char * const jtag_ao_groups[] = {
+ "jtag_ao_tdi", "jtag_ao_tdo", "jtag_ao_clk", "jtag_ao_tms",
+};
+
+static struct meson_pmx_func meson_axg_periphs_functions[] = {
+ FUNCTION(gpio_periphs),
+ FUNCTION(emmc),
+ FUNCTION(nor),
+ FUNCTION(spi0),
+ FUNCTION(spi1),
+ FUNCTION(sdio),
+ FUNCTION(nand),
+ FUNCTION(uart_a),
+ FUNCTION(uart_b),
+ FUNCTION(uart_ao_b_gpioz),
+ FUNCTION(i2c0),
+ FUNCTION(i2c1),
+ FUNCTION(i2c2),
+ FUNCTION(i2c3),
+ FUNCTION(eth),
+ FUNCTION(pwm_a),
+ FUNCTION(pwm_b),
+ FUNCTION(pwm_c),
+ FUNCTION(pwm_d),
+ FUNCTION(pwm_vs),
+ FUNCTION(spdif_out),
+ FUNCTION(spdif_in),
+ FUNCTION(jtag_ee),
+ FUNCTION(pdm),
+};
+
+static struct meson_pmx_func meson_axg_aobus_functions[] = {
+ FUNCTION(gpio_aobus),
+ FUNCTION(uart_ao_a),
+ FUNCTION(uart_ao_b),
+ FUNCTION(i2c_ao),
+ FUNCTION(i2c_ao_slave),
+ FUNCTION(remote_input_ao),
+ FUNCTION(remote_out_ao),
+ FUNCTION(pwm_ao_a),
+ FUNCTION(pwm_ao_b),
+ FUNCTION(pwm_ao_c),
+ FUNCTION(pwm_ao_d),
+ FUNCTION(jtag_ao),
+};
+
+static struct meson_bank meson_axg_periphs_banks[] = {
+ /* name first last irq pullen pull dir out in */
+ BANK("Z", GPIOZ_0, GPIOZ_10, 14, 24, 3, 0, 3, 0, 9, 0, 10, 0, 11, 0),
+ BANK("BOOT", BOOT_0, BOOT_14, 25, 39, 4, 0, 4, 0, 12, 0, 13, 0, 14, 0),
+ BANK("A", GPIOA_0, GPIOA_20, 40, 60, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0),
+ BANK("X", GPIOX_0, GPIOX_22, 61, 83, 2, 0, 2, 0, 6, 0, 7, 0, 8, 0),
+ BANK("Y", GPIOY_0, GPIOY_15, 84, 99, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0),
+};
+
+static struct meson_bank meson_axg_aobus_banks[] = {
+ /* name first last irq pullen pull dir out in */
+ BANK("AO", GPIOAO_0, GPIOAO_9, 0, 13, 0, 16, 0, 0, 0, 0, 0, 16, 1, 0),
+};
+
+static struct meson_pmx_bank meson_axg_periphs_pmx_banks[] = {
+ /* name first lask reg offset */
+ BANK_PMX("Z", GPIOZ_0, GPIOZ_10, 0x2, 0),
+ BANK_PMX("BOOT", BOOT_0, BOOT_14, 0x0, 0),
+ BANK_PMX("A", GPIOA_0, GPIOA_20, 0xb, 0),
+ BANK_PMX("X", GPIOX_0, GPIOX_22, 0x4, 0),
+ BANK_PMX("Y", GPIOY_0, GPIOY_15, 0x8, 0),
+};
+
+static struct meson_axg_pmx_data meson_axg_periphs_pmx_banks_data = {
+ .pmx_banks = meson_axg_periphs_pmx_banks,
+ .num_pmx_banks = ARRAY_SIZE(meson_axg_periphs_pmx_banks),
+};
+
+static struct meson_pmx_bank meson_axg_aobus_pmx_banks[] = {
+ BANK_PMX("AO", GPIOAO_0, GPIOAO_13, 0x0, 0),
+};
+
+static struct meson_axg_pmx_data meson_axg_aobus_pmx_banks_data = {
+ .pmx_banks = meson_axg_aobus_pmx_banks,
+ .num_pmx_banks = ARRAY_SIZE(meson_axg_aobus_pmx_banks),
+};
+
+static struct meson_pinctrl_data meson_axg_periphs_pinctrl_data = {
+ .name = "periphs-banks",
+ .pins = meson_axg_periphs_pins,
+ .groups = meson_axg_periphs_groups,
+ .funcs = meson_axg_periphs_functions,
+ .banks = meson_axg_periphs_banks,
+ .num_pins = ARRAY_SIZE(meson_axg_periphs_pins),
+ .num_groups = ARRAY_SIZE(meson_axg_periphs_groups),
+ .num_funcs = ARRAY_SIZE(meson_axg_periphs_functions),
+ .num_banks = ARRAY_SIZE(meson_axg_periphs_banks),
+ .pmx_ops = &meson_axg_pmx_ops,
+ .pmx_data = &meson_axg_periphs_pmx_banks_data,
+};
+
+static struct meson_pinctrl_data meson_axg_aobus_pinctrl_data = {
+ .name = "aobus-banks",
+ .pins = meson_axg_aobus_pins,
+ .groups = meson_axg_aobus_groups,
+ .funcs = meson_axg_aobus_functions,
+ .banks = meson_axg_aobus_banks,
+ .num_pins = ARRAY_SIZE(meson_axg_aobus_pins),
+ .num_groups = ARRAY_SIZE(meson_axg_aobus_groups),
+ .num_funcs = ARRAY_SIZE(meson_axg_aobus_functions),
+ .num_banks = ARRAY_SIZE(meson_axg_aobus_banks),
+ .pmx_ops = &meson_axg_pmx_ops,
+ .pmx_data = &meson_axg_aobus_pmx_banks_data,
+};
+
+static const struct of_device_id meson_axg_pinctrl_dt_match[] = {
+ {
+ .compatible = "amlogic,meson-axg-periphs-pinctrl",
+ .data = &meson_axg_periphs_pinctrl_data,
+ },
+ {
+ .compatible = "amlogic,meson-axg-aobus-pinctrl",
+ .data = &meson_axg_aobus_pinctrl_data,
+ },
+ { },
+};
+
+static struct platform_driver meson_axg_pinctrl_driver = {
+ .probe = meson_pinctrl_probe,
+ .driver = {
+ .name = "meson-axg-pinctrl",
+ .of_match_table = meson_axg_pinctrl_dt_match,
+ },
+};
+
+builtin_platform_driver(meson_axg_pinctrl_driver);
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index 183b6e471635..12a391109329 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -108,6 +108,7 @@ struct meson_pinctrl_data {
struct meson_bank *banks;
unsigned int num_banks;
const struct pinmux_ops *pmx_ops;
+ void *pmx_data;
};
struct meson_pinctrl {
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index bdb8d174efef..5b63248c8209 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -1006,11 +1006,11 @@ static int armada_37xx_pinctrl_register(struct platform_device *pdev,
static const struct of_device_id armada_37xx_pinctrl_of_match[] = {
{
.compatible = "marvell,armada3710-sb-pinctrl",
- .data = (void *)&armada_37xx_pin_sb,
+ .data = &armada_37xx_pin_sb,
},
{
.compatible = "marvell,armada3710-nb-pinctrl",
- .data = (void *)&armada_37xx_pin_nb,
+ .data = &armada_37xx_pin_nb,
},
{ },
};
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 163d4614b0f8..9e05cfaf75f0 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -636,10 +636,9 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
*/
size = pctl->num_groups * sizeof(*pctl->groups) + noname * 8;
p = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
- if (!p) {
- dev_err(&pdev->dev, "failed to alloc group data\n");
+ if (!p)
return -ENOMEM;
- }
+
pctl->groups = p;
noname_buf = p + pctl->num_groups * sizeof(*pctl->groups);
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index b32c0d602024..d56a49e53f56 100644
--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -633,7 +633,7 @@ static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++, gpio++) {
/* On AB8500, there is no GPIO0, the first is the GPIO 1 */
abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio);
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
}
@@ -1155,13 +1155,9 @@ static int abx500_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl),
- GFP_KERNEL);
- if (pct == NULL) {
- dev_err(&pdev->dev,
- "failed to allocate memory for pct\n");
+ pct = devm_kzalloc(&pdev->dev, sizeof(*pct), GFP_KERNEL);
+ if (!pct)
return -ENOMEM;
- }
pct->dev = &pdev->dev;
pct->parent = dev_get_drvdata(pdev->dev.parent);
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index 56aa181084ac..094a451db2a2 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -827,13 +827,10 @@ static int adi_gpio_pint_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
- struct gpio_pint *pint;
+ struct gpio_pint *pint = devm_kzalloc(dev, sizeof(*pint), GFP_KERNEL);
- pint = devm_kzalloc(dev, sizeof(struct gpio_pint), GFP_KERNEL);
- if (!pint) {
- dev_err(dev, "Memory alloc failed\n");
+ if (!pint)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pint->base = devm_ioremap_resource(dev, res);
@@ -945,11 +942,9 @@ static int adi_gpio_probe(struct platform_device *pdev)
if (!pdata)
return -EINVAL;
- port = devm_kzalloc(dev, sizeof(struct gpio_port), GFP_KERNEL);
- if (!port) {
- dev_err(dev, "Memory alloc failed\n");
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->base = devm_ioremap_resource(dev, res);
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index b1ca838dd80a..4b57a13758a4 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -910,7 +910,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
int i, ret;
struct resource *res;
struct atmel_pioctrl *atmel_pioctrl;
- struct atmel_pioctrl_data *atmel_pioctrl_data;
+ const struct atmel_pioctrl_data *atmel_pioctrl_data;
atmel_pioctrl = devm_kzalloc(dev, sizeof(*atmel_pioctrl), GFP_KERNEL);
if (!atmel_pioctrl)
@@ -924,7 +924,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
dev_err(dev, "unknown compatible string\n");
return -ENODEV;
}
- atmel_pioctrl_data = (struct atmel_pioctrl_data *)match->data;
+ atmel_pioctrl_data = match->data;
atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks;
atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK;
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 03492e3c09fa..297f1d161211 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1050,10 +1050,8 @@ static int at91_pinctrl_mux_mask(struct at91_pinctrl *info,
info->nmux = size / gpio_banks;
info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL);
- if (!info->mux_mask) {
- dev_err(info->dev, "could not alloc mux_mask\n");
+ if (!info->mux_mask)
return -ENOMEM;
- }
ret = of_property_read_u32_array(np, "atmel,mux-mask",
info->mux_mask, size);
diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c
index 22d3bb0bf927..1231bbbfa744 100644
--- a/drivers/pinctrl/pinctrl-axp209.c
+++ b/drivers/pinctrl/pinctrl-axp209.c
@@ -413,9 +413,11 @@ static int axp20x_pctl_probe(struct platform_device *pdev)
pctl->chip.set = axp20x_gpio_set;
pctl->chip.direction_input = axp20x_gpio_input;
pctl->chip.direction_output = axp20x_gpio_output;
+
+ pctl->desc = of_device_get_match_data(dev);
+
pctl->chip.ngpio = pctl->desc->npins;
- pctl->desc = (struct axp20x_pctrl_desc *)of_device_get_match_data(dev);
pctl->regmap = axp20x->regmap;
pctl->dev = &pdev->dev;
diff --git a/drivers/pinctrl/pinctrl-gemini.c b/drivers/pinctrl/pinctrl-gemini.c
index c11b8f14d841..8c9970ae8505 100644
--- a/drivers/pinctrl/pinctrl-gemini.c
+++ b/drivers/pinctrl/pinctrl-gemini.c
@@ -67,6 +67,9 @@ struct gemini_pmx {
* elements in .pins so we can iterate over that array
* @mask: bits to clear to enable this when doing pin muxing
* @value: bits to set to enable this when doing pin muxing
+ * @driving_mask: bitmask for the IO Pad driving register for this
+ * group, if it supports altering the driving strength of
+ * its lines.
*/
struct gemini_pin_group {
const char *name;
@@ -74,12 +77,14 @@ struct gemini_pin_group {
const unsigned int num_pins;
u32 mask;
u32 value;
+ u32 driving_mask;
};
/* Some straight-forward control registers */
#define GLOBAL_WORD_ID 0x00
#define GLOBAL_STATUS 0x04
#define GLOBAL_STATUS_FLPIN BIT(20)
+#define GLOBAL_IODRIVE 0x10
#define GLOBAL_GMAC_CTRL_SKEW 0x1c
#define GLOBAL_GMAC0_DATA_SKEW 0x20
#define GLOBAL_GMAC1_DATA_SKEW 0x24
@@ -738,6 +743,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
/* Conflict with all flash usage */
.value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
+ .driving_mask = GENMASK(21, 20),
},
{
.name = "satagrp",
@@ -753,6 +759,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
.name = "gmii_gmac0_grp",
.pins = gmii_gmac0_3512_pins,
.num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins),
+ .driving_mask = GENMASK(17, 16),
},
{
.name = "gmii_gmac1_grp",
@@ -760,6 +767,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
.num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins),
/* Bring out RGMII on the GMAC1 pins */
.value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
+ .driving_mask = GENMASK(19, 18),
},
{
.name = "pcigrp",
@@ -767,6 +775,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
.num_pins = ARRAY_SIZE(pci_3512_pins),
/* Conflict only with GPIO2 */
.value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
+ .driving_mask = GENMASK(23, 22),
},
{
.name = "lpcgrp",
@@ -1671,6 +1680,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
/* Conflict with all flash usage */
.value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
+ .driving_mask = GENMASK(21, 20),
},
{
.name = "satagrp",
@@ -1686,6 +1696,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
.name = "gmii_gmac0_grp",
.pins = gmii_gmac0_3516_pins,
.num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins),
+ .driving_mask = GENMASK(17, 16),
},
{
.name = "gmii_gmac1_grp",
@@ -1693,6 +1704,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
.num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins),
/* Bring out RGMII on the GMAC1 pins */
.value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
+ .driving_mask = GENMASK(19, 18),
},
{
.name = "pcigrp",
@@ -1700,6 +1712,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
.num_pins = ARRAY_SIZE(pci_3516_pins),
/* Conflict only with GPIO2 */
.value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
+ .driving_mask = GENMASK(23, 22),
},
{
.name = "lpcgrp",
@@ -2015,7 +2028,8 @@ static const char * const sflashgrps[] = { "sflashgrp" };
static const char * const gpio0grps[] = { "gpio0agrp", "gpio0bgrp", "gpio0cgrp",
"gpio0dgrp", "gpio0egrp", "gpio0fgrp",
"gpio0ggrp", "gpio0hgrp", "gpio0igrp",
- "gpio0jgrp", "gpio0kgrp" };
+ "gpio0jgrp", "gpio0kgrp", "gpio0lgrp",
+ "gpio0mgrp" };
static const char * const gpio1grps[] = { "gpio1agrp", "gpio1bgrp", "gpio1cgrp",
"gpio1dgrp" };
static const char * const gpio2grps[] = { "gpio2agrp", "gpio2bgrp", "gpio2cgrp" };
@@ -2393,9 +2407,77 @@ static int gemini_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
return ret;
}
+static int gemini_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ unsigned long *configs,
+ unsigned num_configs)
+{
+ struct gemini_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ const struct gemini_pin_group *grp = NULL;
+ enum pin_config_param param;
+ u32 arg;
+ u32 val;
+ int i;
+
+ if (pmx->is_3512)
+ grp = &gemini_3512_pin_groups[selector];
+ if (pmx->is_3516)
+ grp = &gemini_3516_pin_groups[selector];
+
+ /* First figure out if this group supports configs */
+ if (!grp->driving_mask) {
+ dev_err(pmx->dev, "pin config group \"%s\" does "
+ "not support drive strength setting\n",
+ grp->name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ switch (arg) {
+ case 4:
+ val = 0;
+ break;
+ case 8:
+ val = 1;
+ break;
+ case 12:
+ val = 2;
+ break;
+ case 16:
+ val = 3;
+ break;
+ default:
+ dev_err(pmx->dev,
+ "invalid drive strength %d mA\n",
+ arg);
+ return -ENOTSUPP;
+ }
+ val <<= (ffs(grp->driving_mask) - 1);
+ regmap_update_bits(pmx->map, GLOBAL_IODRIVE,
+ grp->driving_mask,
+ val);
+ dev_info(pmx->dev,
+ "set group %s to %d mA drive strength mask %08x val %08x\n",
+ grp->name, arg, grp->driving_mask, val);
+ break;
+ default:
+ dev_err(pmx->dev, "invalid config param %04x\n", param);
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
static const struct pinconf_ops gemini_pinconf_ops = {
.pin_config_get = gemini_pinconf_get,
.pin_config_set = gemini_pinconf_set,
+ .pin_config_group_set = gemini_pinconf_group_set,
.is_generic = true,
};
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index 372ddf386bdb..ac38a3f9f86b 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -736,10 +736,8 @@ static int ingenic_pinctrl_probe(struct platform_device *pdev)
base = devm_ioremap_resource(dev,
platform_get_resource(pdev, IORESOURCE_MEM, 0));
- if (IS_ERR(base)) {
- dev_err(dev, "Failed to ioremap registers\n");
+ if (IS_ERR(base))
return PTR_ERR(base);
- }
jzpc->map = devm_regmap_init_mmio(dev, base,
&ingenic_pinctrl_regmap_config);
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index 4a6ea159c65d..644c5beb05cb 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -455,31 +455,22 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
defval_changed, gpio_set;
mutex_lock(&mcp->lock);
- if (mcp_read(mcp, MCP_INTF, &intf) < 0) {
- mutex_unlock(&mcp->lock);
- return IRQ_HANDLED;
- }
+ if (mcp_read(mcp, MCP_INTF, &intf))
+ goto unlock;
- if (mcp_read(mcp, MCP_INTCAP, &intcap) < 0) {
- mutex_unlock(&mcp->lock);
- return IRQ_HANDLED;
- }
+ if (mcp_read(mcp, MCP_INTCAP, &intcap))
+ goto unlock;
- if (mcp_read(mcp, MCP_INTCON, &intcon) < 0) {
- mutex_unlock(&mcp->lock);
- return IRQ_HANDLED;
- }
+ if (mcp_read(mcp, MCP_INTCON, &intcon))
+ goto unlock;
- if (mcp_read(mcp, MCP_DEFVAL, &defval) < 0) {
- mutex_unlock(&mcp->lock);
- return IRQ_HANDLED;
- }
+ if (mcp_read(mcp, MCP_DEFVAL, &defval))
+ goto unlock;
/* This clears the interrupt(configurable on S18) */
- if (mcp_read(mcp, MCP_GPIO, &gpio) < 0) {
- mutex_unlock(&mcp->lock);
- return IRQ_HANDLED;
- }
+ if (mcp_read(mcp, MCP_GPIO, &gpio))
+ goto unlock;
+
gpio_orig = mcp->cached_gpio;
mcp->cached_gpio = gpio;
mutex_unlock(&mcp->lock);
@@ -541,6 +532,10 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
}
return IRQ_HANDLED;
+
+unlock:
+ mutex_unlock(&mcp->lock);
+ return IRQ_HANDLED;
}
static void mcp23s08_irq_mask(struct irq_data *data)
@@ -753,13 +748,12 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
if (!label)
continue;
- seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
- chip->base + t, bank, t, label,
- (iodir & mask) ? "in " : "out",
- (gpio & mask) ? "hi" : "lo",
- (gppu & mask) ? "up" : " ");
+ seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s\n",
+ chip->base + t, bank, t, label,
+ (iodir & mask) ? "in " : "out",
+ (gpio & mask) ? "hi" : "lo",
+ (gppu & mask) ? "up" : " ");
/* NOTE: ignoring the irq-related registers */
- seq_puts(s, "\n");
}
done:
mutex_unlock(&mcp->lock);
@@ -896,16 +890,16 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
goto fail;
}
- ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
- if (ret < 0)
- goto fail;
-
if (mcp->irq && mcp->irq_controller) {
ret = mcp23s08_irq_setup(mcp);
if (ret)
goto fail;
}
+ ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
+ if (ret < 0)
+ goto fail;
+
mcp->pinctrl_desc.name = "mcp23xxx-pinctrl";
mcp->pinctrl_desc.pctlops = &mcp_pinctrl_ops;
mcp->pinctrl_desc.confops = &mcp_pinconf_ops;
diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
new file mode 100644
index 000000000000..01a50d969111
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -0,0 +1,511 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <alexandre.belloni@free-electrons.com>
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinmux.h"
+
+#define OCELOT_GPIO_OUT_SET 0x0
+#define OCELOT_GPIO_OUT_CLR 0x4
+#define OCELOT_GPIO_OUT 0x8
+#define OCELOT_GPIO_IN 0xc
+#define OCELOT_GPIO_OE 0x10
+#define OCELOT_GPIO_INTR 0x14
+#define OCELOT_GPIO_INTR_ENA 0x18
+#define OCELOT_GPIO_INTR_IDENT 0x1c
+#define OCELOT_GPIO_ALT0 0x20
+#define OCELOT_GPIO_ALT1 0x24
+#define OCELOT_GPIO_SD_MAP 0x28
+
+#define OCELOT_PINS 22
+#define OCELOT_FUNC_PER_PIN 4
+
+enum {
+ FUNC_NONE,
+ FUNC_GPIO,
+ FUNC_IRQ0_IN,
+ FUNC_IRQ0_OUT,
+ FUNC_IRQ1_IN,
+ FUNC_IRQ1_OUT,
+ FUNC_MIIM1,
+ FUNC_PCI_WAKE,
+ FUNC_PTP0,
+ FUNC_PTP1,
+ FUNC_PTP2,
+ FUNC_PTP3,
+ FUNC_PWM,
+ FUNC_RECO_CLK0,
+ FUNC_RECO_CLK1,
+ FUNC_SFP0,
+ FUNC_SFP1,
+ FUNC_SFP2,
+ FUNC_SFP3,
+ FUNC_SFP4,
+ FUNC_SFP5,
+ FUNC_SG0,
+ FUNC_SI,
+ FUNC_TACHO,
+ FUNC_TWI,
+ FUNC_TWI_SCL_M,
+ FUNC_UART,
+ FUNC_UART2,
+ FUNC_MAX
+};
+
+static const char *const ocelot_function_names[] = {
+ [FUNC_NONE] = "none",
+ [FUNC_GPIO] = "gpio",
+ [FUNC_IRQ0_IN] = "irq0_in",
+ [FUNC_IRQ0_OUT] = "irq0_out",
+ [FUNC_IRQ1_IN] = "irq1_in",
+ [FUNC_IRQ1_OUT] = "irq1_out",
+ [FUNC_MIIM1] = "miim1",
+ [FUNC_PCI_WAKE] = "pci_wake",
+ [FUNC_PTP0] = "ptp0",
+ [FUNC_PTP1] = "ptp1",
+ [FUNC_PTP2] = "ptp2",
+ [FUNC_PTP3] = "ptp3",
+ [FUNC_PWM] = "pwm",
+ [FUNC_RECO_CLK0] = "reco_clk0",
+ [FUNC_RECO_CLK1] = "reco_clk1",
+ [FUNC_SFP0] = "sfp0",
+ [FUNC_SFP1] = "sfp1",
+ [FUNC_SFP2] = "sfp2",
+ [FUNC_SFP3] = "sfp3",
+ [FUNC_SFP4] = "sfp4",
+ [FUNC_SFP5] = "sfp5",
+ [FUNC_SG0] = "sg0",
+ [FUNC_SI] = "si",
+ [FUNC_TACHO] = "tacho",
+ [FUNC_TWI] = "twi",
+ [FUNC_TWI_SCL_M] = "twi_scl_m",
+ [FUNC_UART] = "uart",
+ [FUNC_UART2] = "uart2",
+};
+
+struct ocelot_pmx_func {
+ const char **groups;
+ unsigned int ngroups;
+};
+
+struct ocelot_pin_caps {
+ unsigned int pin;
+ unsigned char functions[OCELOT_FUNC_PER_PIN];
+};
+
+struct ocelot_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ struct gpio_chip gpio_chip;
+ struct regmap *map;
+ struct ocelot_pmx_func func[FUNC_MAX];
+};
+
+#define OCELOT_P(p, f0, f1, f2) \
+static struct ocelot_pin_caps ocelot_pin_##p = { \
+ .pin = p, \
+ .functions = { \
+ FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2, \
+ }, \
+}
+
+OCELOT_P(0, SG0, NONE, NONE);
+OCELOT_P(1, SG0, NONE, NONE);
+OCELOT_P(2, SG0, NONE, NONE);
+OCELOT_P(3, SG0, NONE, NONE);
+OCELOT_P(4, IRQ0_IN, IRQ0_OUT, TWI);
+OCELOT_P(5, IRQ1_IN, IRQ1_OUT, PCI_WAKE);
+OCELOT_P(6, UART, TWI_SCL_M, NONE);
+OCELOT_P(7, UART, TWI_SCL_M, NONE);
+OCELOT_P(8, SI, TWI_SCL_M, IRQ0_OUT);
+OCELOT_P(9, SI, TWI_SCL_M, IRQ1_OUT);
+OCELOT_P(10, PTP2, TWI_SCL_M, SFP0);
+OCELOT_P(11, PTP3, TWI_SCL_M, SFP1);
+OCELOT_P(12, UART2, TWI_SCL_M, SFP2);
+OCELOT_P(13, UART2, TWI_SCL_M, SFP3);
+OCELOT_P(14, MIIM1, TWI_SCL_M, SFP4);
+OCELOT_P(15, MIIM1, TWI_SCL_M, SFP5);
+OCELOT_P(16, TWI, NONE, SI);
+OCELOT_P(17, TWI, TWI_SCL_M, SI);
+OCELOT_P(18, PTP0, TWI_SCL_M, NONE);
+OCELOT_P(19, PTP1, TWI_SCL_M, NONE);
+OCELOT_P(20, RECO_CLK0, TACHO, NONE);
+OCELOT_P(21, RECO_CLK1, PWM, NONE);
+
+#define OCELOT_PIN(n) { \
+ .number = n, \
+ .name = "GPIO_"#n, \
+ .drv_data = &ocelot_pin_##n \
+}
+
+static const struct pinctrl_pin_desc ocelot_pins[] = {
+ OCELOT_PIN(0),
+ OCELOT_PIN(1),
+ OCELOT_PIN(2),
+ OCELOT_PIN(3),
+ OCELOT_PIN(4),
+ OCELOT_PIN(5),
+ OCELOT_PIN(6),
+ OCELOT_PIN(7),
+ OCELOT_PIN(8),
+ OCELOT_PIN(9),
+ OCELOT_PIN(10),
+ OCELOT_PIN(11),
+ OCELOT_PIN(12),
+ OCELOT_PIN(13),
+ OCELOT_PIN(14),
+ OCELOT_PIN(15),
+ OCELOT_PIN(16),
+ OCELOT_PIN(17),
+ OCELOT_PIN(18),
+ OCELOT_PIN(19),
+ OCELOT_PIN(20),
+ OCELOT_PIN(21),
+};
+
+static int ocelot_get_functions_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(ocelot_function_names);
+}
+
+static const char *ocelot_get_function_name(struct pinctrl_dev *pctldev,
+ unsigned int function)
+{
+ return ocelot_function_names[function];
+}
+
+static int ocelot_get_function_groups(struct pinctrl_dev *pctldev,
+ unsigned int function,
+ const char *const **groups,
+ unsigned *const num_groups)
+{
+ struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = info->func[function].groups;
+ *num_groups = info->func[function].ngroups;
+
+ return 0;
+}
+
+static int ocelot_pin_function_idx(unsigned int pin, unsigned int function)
+{
+ struct ocelot_pin_caps *p = ocelot_pins[pin].drv_data;
+ int i;
+
+ for (i = 0; i < OCELOT_FUNC_PER_PIN; i++) {
+ if (function == p->functions[i])
+ return i;
+ }
+
+ return -1;
+}
+
+static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int selector, unsigned int group)
+{
+ struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct ocelot_pin_caps *pin = ocelot_pins[group].drv_data;
+ int f;
+
+ f = ocelot_pin_function_idx(group, selector);
+ if (f < 0)
+ return -EINVAL;
+
+ /*
+ * f is encoded on two bits.
+ * bit 0 of f goes in BIT(pin) of ALT0, bit 1 of f goes in BIT(pin) of
+ * ALT1
+ * This is racy because both registers can't be updated at the same time
+ * but it doesn't matter much for now.
+ */
+ regmap_update_bits(info->map, OCELOT_GPIO_ALT0, BIT(pin->pin),
+ f << pin->pin);
+ regmap_update_bits(info->map, OCELOT_GPIO_ALT1, BIT(pin->pin),
+ f << (pin->pin - 1));
+
+ return 0;
+}
+
+static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin, bool input)
+{
+ struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ regmap_update_bits(info->map, OCELOT_GPIO_OE, BIT(pin),
+ input ? BIT(pin) : 0);
+
+ return 0;
+}
+
+static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ regmap_update_bits(info->map, OCELOT_GPIO_ALT0, BIT(offset), 0);
+ regmap_update_bits(info->map, OCELOT_GPIO_ALT1, BIT(offset), 0);
+
+ return 0;
+}
+
+static const struct pinmux_ops ocelot_pmx_ops = {
+ .get_functions_count = ocelot_get_functions_count,
+ .get_function_name = ocelot_get_function_name,
+ .get_function_groups = ocelot_get_function_groups,
+ .set_mux = ocelot_pinmux_set_mux,
+ .gpio_set_direction = ocelot_gpio_set_direction,
+ .gpio_request_enable = ocelot_gpio_request_enable,
+};
+
+static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(ocelot_pins);
+}
+
+static const char *ocelot_pctl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int group)
+{
+ return ocelot_pins[group].name;
+}
+
+static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int group,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ *pins = &ocelot_pins[group].number;
+ *num_pins = 1;
+
+ return 0;
+}
+
+static const struct pinctrl_ops ocelot_pctl_ops = {
+ .get_groups_count = ocelot_pctl_get_groups_count,
+ .get_group_name = ocelot_pctl_get_group_name,
+ .get_group_pins = ocelot_pctl_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static struct pinctrl_desc ocelot_desc = {
+ .name = "ocelot-pinctrl",
+ .pins = ocelot_pins,
+ .npins = ARRAY_SIZE(ocelot_pins),
+ .pctlops = &ocelot_pctl_ops,
+ .pmxops = &ocelot_pmx_ops,
+ .owner = THIS_MODULE,
+};
+
+static int ocelot_create_group_func_map(struct device *dev,
+ struct ocelot_pinctrl *info)
+{
+ u16 pins[ARRAY_SIZE(ocelot_pins)];
+ int f, npins, i;
+
+ for (f = 0; f < FUNC_MAX; f++) {
+ for (npins = 0, i = 0; i < ARRAY_SIZE(ocelot_pins); i++) {
+ if (ocelot_pin_function_idx(i, f) >= 0)
+ pins[npins++] = i;
+ }
+
+ info->func[f].ngroups = npins;
+ info->func[f].groups = devm_kzalloc(dev, npins *
+ sizeof(char *),
+ GFP_KERNEL);
+ if (!info->func[f].groups)
+ return -ENOMEM;
+
+ for (i = 0; i < npins; i++)
+ info->func[f].groups[i] = ocelot_pins[pins[i]].name;
+ }
+
+ return 0;
+}
+
+static int ocelot_pinctrl_register(struct platform_device *pdev,
+ struct ocelot_pinctrl *info)
+{
+ int ret;
+
+ ret = ocelot_create_group_func_map(&pdev->dev, info);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to create group func map.\n");
+ return ret;
+ }
+
+ info->pctl = devm_pinctrl_register(&pdev->dev, &ocelot_desc, info);
+ if (IS_ERR(info->pctl)) {
+ dev_err(&pdev->dev, "Failed to register pinctrl\n");
+ return PTR_ERR(info->pctl);
+ }
+
+ return 0;
+}
+
+static int ocelot_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct ocelot_pinctrl *info = gpiochip_get_data(chip);
+ unsigned int val;
+
+ regmap_read(info->map, OCELOT_GPIO_IN, &val);
+
+ return !!(val & BIT(offset));
+}
+
+static void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct ocelot_pinctrl *info = gpiochip_get_data(chip);
+
+ if (value)
+ regmap_write(info->map, OCELOT_GPIO_OUT_SET, BIT(offset));
+ else
+ regmap_write(info->map, OCELOT_GPIO_OUT_CLR, BIT(offset));
+}
+
+static int ocelot_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct ocelot_pinctrl *info = gpiochip_get_data(chip);
+ unsigned int val;
+
+ regmap_read(info->map, OCELOT_GPIO_OE, &val);
+
+ return !(val & BIT(offset));
+}
+
+static int ocelot_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int ocelot_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct ocelot_pinctrl *info = gpiochip_get_data(chip);
+ unsigned int pin = BIT(offset);
+
+ if (value)
+ regmap_write(info->map, OCELOT_GPIO_OUT_SET, pin);
+ else
+ regmap_write(info->map, OCELOT_GPIO_OUT_CLR, pin);
+
+ return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static const struct gpio_chip ocelot_gpiolib_chip = {
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
+ .set = ocelot_gpio_set,
+ .get = ocelot_gpio_get,
+ .get_direction = ocelot_gpio_get_direction,
+ .direction_input = ocelot_gpio_direction_input,
+ .direction_output = ocelot_gpio_direction_output,
+ .owner = THIS_MODULE,
+};
+
+static int ocelot_gpiochip_register(struct platform_device *pdev,
+ struct ocelot_pinctrl *info)
+{
+ struct gpio_chip *gc;
+ int ret;
+
+ info->gpio_chip = ocelot_gpiolib_chip;
+
+ gc = &info->gpio_chip;
+ gc->ngpio = OCELOT_PINS;
+ gc->parent = &pdev->dev;
+ gc->base = 0;
+ gc->of_node = info->dev->of_node;
+ gc->label = "ocelot-gpio";
+
+ ret = devm_gpiochip_add_data(&pdev->dev, gc, info);
+ if (ret)
+ return ret;
+
+ /* TODO: this can be used as an irqchip but no board is using that */
+
+ return 0;
+}
+
+static const struct regmap_config ocelot_pinctrl_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x64,
+};
+
+static const struct of_device_id ocelot_pinctrl_of_match[] = {
+ { .compatible = "mscc,ocelot-pinctrl" },
+ {},
+};
+
+int ocelot_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ocelot_pinctrl *info;
+ void __iomem *base;
+ int ret;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ base = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (IS_ERR(base)) {
+ dev_err(dev, "Failed to ioremap registers\n");
+ return PTR_ERR(base);
+ }
+
+ info->map = devm_regmap_init_mmio(dev, base,
+ &ocelot_pinctrl_regmap_config);
+ if (IS_ERR(info->map)) {
+ dev_err(dev, "Failed to create regmap\n");
+ return PTR_ERR(info->map);
+ }
+ dev_set_drvdata(dev, info->map);
+ info->dev = dev;
+
+ ret = ocelot_pinctrl_register(pdev, info);
+ if (ret)
+ return ret;
+
+ ret = ocelot_gpiochip_register(pdev, info);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct platform_driver ocelot_pinctrl_driver = {
+ .driver = {
+ .name = "pinctrl-ocelot",
+ .of_match_table = of_match_ptr(ocelot_pinctrl_of_match),
+ .suppress_bind_attrs = true,
+ },
+ .probe = ocelot_pinctrl_probe,
+};
+builtin_platform_driver(ocelot_pinctrl_driver);
diff --git a/drivers/pinctrl/pinctrl-palmas.c b/drivers/pinctrl/pinctrl-palmas.c
index 4d6a5015b927..d42f18cb1bc7 100644
--- a/drivers/pinctrl/pinctrl-palmas.c
+++ b/drivers/pinctrl/pinctrl-palmas.c
@@ -1012,10 +1012,8 @@ static int palmas_pinctrl_probe(struct platform_device *pdev)
}
pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL);
- if (!pci) {
- dev_err(&pdev->dev, "Malloc for pci failed\n");
+ if (!pci)
return -ENOMEM;
- }
pci->dev = &pdev->dev;
pci->palmas = dev_get_drvdata(pdev->dev.parent);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 2ba17548ad5b..3924779f5578 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -136,7 +136,7 @@ struct rockchip_drv {
* @iomux: array describing the 4 iomux sources of the bank
* @drv: array describing the 4 drive strength sources of the bank
* @pull_type: array describing the 4 pull type sources of the bank
- * @valid: are all necessary informations present
+ * @valid: is all necessary information present
* @of_node: dt node of this bank
* @drvdata: common pinctrl basedata
* @domain: irqdomain of the gpio bank
@@ -1988,7 +1988,7 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
info->functions[selector].name, info->groups[group].name);
/*
- * for each pin in the pin group selected, program the correspoding pin
+ * for each pin in the pin group selected, program the corresponding
* pin function number in the config register.
*/
for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
@@ -2014,8 +2014,16 @@ static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct rockchip_pin_bank *bank = gpiochip_get_data(chip);
u32 data;
+ int ret;
+ ret = clk_enable(bank->clk);
+ if (ret < 0) {
+ dev_err(bank->drvdata->dev,
+ "failed to enable clock for bank %s\n", bank->name);
+ return ret;
+ }
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
+ clk_disable(bank->clk);
return !(data & BIT(offset));
}
@@ -2400,18 +2408,14 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev,
info->functions = devm_kzalloc(dev, info->nfunctions *
sizeof(struct rockchip_pmx_func),
GFP_KERNEL);
- if (!info->functions) {
- dev_err(dev, "failed to allocate memory for function list\n");
+ if (!info->functions)
return -EINVAL;
- }
info->groups = devm_kzalloc(dev, info->ngroups *
sizeof(struct rockchip_pin_group),
GFP_KERNEL);
- if (!info->groups) {
- dev_err(dev, "failed allocate memory for ping group list\n");
+ if (!info->groups)
return -EINVAL;
- }
i = 0;
@@ -2447,10 +2451,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
info->ctrl->nr_pins, GFP_KERNEL);
- if (!pindesc) {
- dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
+ if (!pindesc)
return -ENOMEM;
- }
+
ctrldesc->pins = pindesc;
ctrldesc->npins = info->ctrl->nr_pins;
@@ -2532,7 +2535,7 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
/*
* gpiolib gpio_direction_input callback function. The setting of the pin
- * mux function as 'gpio input' will be handled by the pinctrl susbsystem
+ * mux function as 'gpio input' will be handled by the pinctrl subsystem
* interface.
*/
static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
@@ -2542,7 +2545,7 @@ static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
/*
* gpiolib gpio_direction_output callback function. The setting of the pin
- * mux function as 'gpio output' will be handled by the pinctrl susbsystem
+ * mux function as 'gpio output' will be handled by the pinctrl subsystem
* interface.
*/
static int rockchip_gpio_direction_output(struct gpio_chip *gc,
@@ -3163,7 +3166,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
return -ENODEV;
}
- info = devm_kzalloc(dev, sizeof(struct rockchip_pinctrl), GFP_KERNEL);
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 3501491e5bfc..cec75379f936 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1462,8 +1462,6 @@ static void pcs_irq_chain_handler(struct irq_desc *desc)
pcs_irq_handle(pcs_soc);
/* REVISIT: export and add handle_bad_irq(irq, desc)? */
chained_irq_exit(chip, desc);
-
- return;
}
static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq,
@@ -1649,10 +1647,9 @@ static int pcs_probe(struct platform_device *pdev)
return -EINVAL;
pcs = devm_kzalloc(&pdev->dev, sizeof(*pcs), GFP_KERNEL);
- if (!pcs) {
- dev_err(&pdev->dev, "could not allocate\n");
+ if (!pcs)
return -ENOMEM;
- }
+
pcs->dev = &pdev->dev;
pcs->np = np;
raw_spin_lock_init(&pcs->lock);
@@ -1777,8 +1774,7 @@ static int pcs_probe(struct platform_device *pdev)
dev_warn(pcs->dev, "initialized with no interrupts\n");
}
- dev_info(pcs->dev, "%i pins at pa %p size %u\n",
- pcs->desc.npins, pcs->base, pcs->size);
+ dev_info(pcs->dev, "%i pins, size %u\n", pcs->desc.npins, pcs->size);
return pinctrl_enable(pcs->pctl);
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index fb242c542dc9..cbf58a10113d 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -1144,6 +1144,27 @@ static int sx150x_probe(struct i2c_client *client,
if (ret)
return ret;
+ /* Pinctrl_desc */
+ pctl->pinctrl_desc.name = "sx150x-pinctrl";
+ pctl->pinctrl_desc.pctlops = &sx150x_pinctrl_ops;
+ pctl->pinctrl_desc.confops = &sx150x_pinconf_ops;
+ pctl->pinctrl_desc.pins = pctl->data->pins;
+ pctl->pinctrl_desc.npins = pctl->data->npins;
+ pctl->pinctrl_desc.owner = THIS_MODULE;
+
+ ret = devm_pinctrl_register_and_init(dev, &pctl->pinctrl_desc,
+ pctl, &pctl->pctldev);
+ if (ret) {
+ dev_err(dev, "Failed to register pinctrl device\n");
+ return ret;
+ }
+
+ ret = pinctrl_enable(pctl->pctldev);
+ if (ret) {
+ dev_err(dev, "Failed to enable pinctrl device\n");
+ return ret;
+ }
+
/* Register GPIO controller */
pctl->gpio.label = devm_kstrdup(dev, client->name, GFP_KERNEL);
pctl->gpio.base = -1;
@@ -1172,6 +1193,11 @@ static int sx150x_probe(struct i2c_client *client,
if (ret)
return ret;
+ ret = gpiochip_add_pin_range(&pctl->gpio, dev_name(dev),
+ 0, 0, pctl->data->npins);
+ if (ret)
+ return ret;
+
/* Add Interrupt support if an irq is specified */
if (client->irq > 0) {
pctl->irq_chip.name = devm_kstrdup(dev, client->name,
@@ -1217,20 +1243,6 @@ static int sx150x_probe(struct i2c_client *client,
client->irq);
}
- /* Pinctrl_desc */
- pctl->pinctrl_desc.name = "sx150x-pinctrl";
- pctl->pinctrl_desc.pctlops = &sx150x_pinctrl_ops;
- pctl->pinctrl_desc.confops = &sx150x_pinconf_ops;
- pctl->pinctrl_desc.pins = pctl->data->pins;
- pctl->pinctrl_desc.npins = pctl->data->npins;
- pctl->pinctrl_desc.owner = THIS_MODULE;
-
- pctl->pctldev = pinctrl_register(&pctl->pinctrl_desc, dev, pctl);
- if (IS_ERR(pctl->pctldev)) {
- dev_err(dev, "Failed to register pinctrl device\n");
- return PTR_ERR(pctl->pctldev);
- }
-
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c
index 5cfa93cecf73..b16d1c96b7eb 100644
--- a/drivers/pinctrl/pinctrl-tz1090-pdc.c
+++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c
@@ -357,10 +357,8 @@ static int add_map_configs(struct device *dev,
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
GFP_KERNEL);
- if (!dup_configs) {
- dev_err(dev, "kmemdup(configs) failed\n");
+ if (!dup_configs)
return -ENOMEM;
- }
/*
* We support both pins and pin groups, but we need to figure out which
@@ -931,10 +929,9 @@ static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev)
struct resource *res;
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
- if (!pmx) {
- dev_err(&pdev->dev, "Can't alloc tz1090_pdc_pmx\n");
+ if (!pmx)
return -ENOMEM;
- }
+
pmx->dev = &pdev->dev;
spin_lock_init(&pmx->lock);
diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c
index 74d1ffcc2199..2379ce2be365 100644
--- a/drivers/pinctrl/pinctrl-tz1090.c
+++ b/drivers/pinctrl/pinctrl-tz1090.c
@@ -1082,10 +1082,8 @@ static int add_map_configs(struct device *dev,
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
GFP_KERNEL);
- if (!dup_configs) {
- dev_err(dev, "kmemdup(configs) failed\n");
+ if (!dup_configs)
return -ENOMEM;
- }
(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
(*map)[*num_maps].data.configs.group_or_pin = group;
@@ -1946,10 +1944,9 @@ static int tz1090_pinctrl_probe(struct platform_device *pdev)
struct resource *res;
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
- if (!pmx) {
- dev_err(&pdev->dev, "Can't alloc tz1090_pmx\n");
+ if (!pmx)
return -ENOMEM;
- }
+
pmx->dev = &pdev->dev;
spin_lock_init(&pmx->lock);
diff --git a/drivers/pinctrl/pinctrl-utils.c b/drivers/pinctrl/pinctrl-utils.c
index 9189fbafb102..f2bcbf62c03d 100644
--- a/drivers/pinctrl/pinctrl-utils.c
+++ b/drivers/pinctrl/pinctrl-utils.c
@@ -83,10 +83,8 @@ int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev,
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
GFP_KERNEL);
- if (!dup_configs) {
- dev_err(pctldev->dev, "kmemdup(configs) failed\n");
+ if (!dup_configs)
return -ENOMEM;
- }
(*map)[*num_maps].type = type;
(*map)[*num_maps].data.configs.group_or_pin = group;
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index f9e98a7d4f0c..cd0f402c1164 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -1730,18 +1730,16 @@ static int pinmux_xway_probe(struct platform_device *pdev)
xway_info.pads = devm_kzalloc(&pdev->dev,
sizeof(struct pinctrl_pin_desc) * xway_chip.ngpio,
GFP_KERNEL);
- if (!xway_info.pads) {
- dev_err(&pdev->dev, "Failed to allocate pads\n");
+ if (!xway_info.pads)
return -ENOMEM;
- }
+
for (i = 0; i < xway_chip.ngpio; i++) {
/* strlen("ioXY") + 1 = 5 */
char *name = devm_kzalloc(&pdev->dev, 5, GFP_KERNEL);
- if (!name) {
- dev_err(&pdev->dev, "Failed to allocate pad name\n");
+ if (!name)
return -ENOMEM;
- }
+
snprintf(name, 5, "io%d", i);
xway_info.pads[i].number = GPIO0 + i;
xway_info.pads[i].name = name;
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 55502fc4479c..b8e9bda8ec98 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -493,8 +493,6 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)
continue;
}
if (desc->mux_setting == &(setting->data.mux)) {
- desc->mux_setting = NULL;
- /* And release the pin */
pin_free(pctldev, pins[i], NULL);
} else {
const char *gname;
@@ -619,7 +617,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
pctlops->get_group_name(pctldev,
desc->mux_setting->group));
else
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
mutex_unlock(&pctldev->mutex);
diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c
index 866aa3ce1ac9..6cf0006d4c8d 100644
--- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c
+++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c
@@ -436,3 +436,7 @@ int pxa2xx_pinctrl_exit(struct platform_device *pdev)
return 0;
}
EXPORT_SYMBOL_GPL(pxa2xx_pinctrl_exit);
+
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_DESCRIPTION("Marvell PXA2xx pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 9e504dbc7fb5..fcaaa92d76df 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -106,6 +106,14 @@ config PINCTRL_MSM8996
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm MSM8996 platform.
+config PINCTRL_MSM8998
+ tristate "Qualcomm MSM8998 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm MSM8998 platform.
+
config PINCTRL_QDF2XXX
tristate "Qualcomm Technologies QDF2xxx pin controller driver"
depends on GPIOLIB && ACPI
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index a1db345ded1c..8cb45bbd2e7f 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
obj-$(CONFIG_PINCTRL_MSM8994) += pinctrl-msm8994.o
obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
+obj-$(CONFIG_PINCTRL_MSM8998) += pinctrl-msm8998.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 7a960590ecaa..495432f3341b 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -898,10 +898,9 @@ int msm_pinctrl_probe(struct platform_device *pdev,
int ret;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
- if (!pctrl) {
- dev_err(&pdev->dev, "Can't allocate msm_pinctrl\n");
+ if (!pctrl)
return -ENOMEM;
- }
+
pctrl->dev = &pdev->dev;
pctrl->soc = soc_data;
pctrl->chip = msm_gpio_template;
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c
new file mode 100644
index 000000000000..c33953183013
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c
@@ -0,0 +1,1590 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define NORTH 0x500000
+#define WEST 0x100000
+#define EAST 0x900000
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = base + 0x1000 * id, \
+ .io_reg = base + 0x4 + 0x1000 * id, \
+ .intr_cfg_reg = base + 0x8 + 0x1000 * id, \
+ .intr_status_reg = base + 0xc + 0x1000 * id, \
+ .intr_target_reg = base + 0x8 + 0x1000 * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define UFS_RESET(pg_name, offset) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc msm8998_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "SDC2_CLK"),
+ PINCTRL_PIN(151, "SDC2_CMD"),
+ PINCTRL_PIN(152, "SDC2_DATA"),
+ PINCTRL_PIN(153, "UFS_RESET"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+
+static const unsigned int sdc2_clk_pins[] = { 150 };
+static const unsigned int sdc2_cmd_pins[] = { 151 };
+static const unsigned int sdc2_data_pins[] = { 152 };
+static const unsigned int ufs_reset_pins[] = { 153 };
+
+enum msm8998_functions {
+ msm_mux_adsp_ext,
+ msm_mux_agera_pll,
+ msm_mux_atest_char,
+ msm_mux_atest_gpsadc0,
+ msm_mux_atest_gpsadc1,
+ msm_mux_atest_tsens,
+ msm_mux_atest_tsens2,
+ msm_mux_atest_usb1,
+ msm_mux_atest_usb10,
+ msm_mux_atest_usb11,
+ msm_mux_atest_usb12,
+ msm_mux_atest_usb13,
+ msm_mux_audio_ref,
+ msm_mux_bimc_dte0,
+ msm_mux_bimc_dte1,
+ msm_mux_blsp10_spi,
+ msm_mux_blsp10_spi_a,
+ msm_mux_blsp10_spi_b,
+ msm_mux_blsp11_i2c,
+ msm_mux_blsp1_spi,
+ msm_mux_blsp1_spi_a,
+ msm_mux_blsp1_spi_b,
+ msm_mux_blsp2_spi,
+ msm_mux_blsp9_spi,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c10,
+ msm_mux_blsp_i2c11,
+ msm_mux_blsp_i2c12,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_i2c6,
+ msm_mux_blsp_i2c7,
+ msm_mux_blsp_i2c8,
+ msm_mux_blsp_i2c9,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi10,
+ msm_mux_blsp_spi11,
+ msm_mux_blsp_spi12,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_spi7,
+ msm_mux_blsp_spi8,
+ msm_mux_blsp_spi9,
+ msm_mux_blsp_uart1_a,
+ msm_mux_blsp_uart1_b,
+ msm_mux_blsp_uart2_a,
+ msm_mux_blsp_uart2_b,
+ msm_mux_blsp_uart3_a,
+ msm_mux_blsp_uart3_b,
+ msm_mux_blsp_uart7_a,
+ msm_mux_blsp_uart7_b,
+ msm_mux_blsp_uart8,
+ msm_mux_blsp_uart8_a,
+ msm_mux_blsp_uart8_b,
+ msm_mux_blsp_uart9_a,
+ msm_mux_blsp_uart9_b,
+ msm_mux_blsp_uim1_a,
+ msm_mux_blsp_uim1_b,
+ msm_mux_blsp_uim2_a,
+ msm_mux_blsp_uim2_b,
+ msm_mux_blsp_uim3_a,
+ msm_mux_blsp_uim3_b,
+ msm_mux_blsp_uim7_a,
+ msm_mux_blsp_uim7_b,
+ msm_mux_blsp_uim8_a,
+ msm_mux_blsp_uim8_b,
+ msm_mux_blsp_uim9_a,
+ msm_mux_blsp_uim9_b,
+ msm_mux_bt_reset,
+ msm_mux_btfm_slimbus,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cci_timer2,
+ msm_mux_cci_timer3,
+ msm_mux_cci_timer4,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_dbg_out,
+ msm_mux_ddr_bist,
+ msm_mux_edp_hot,
+ msm_mux_edp_lcd,
+ msm_mux_gcc_gp1_a,
+ msm_mux_gcc_gp1_b,
+ msm_mux_gcc_gp2_a,
+ msm_mux_gcc_gp2_b,
+ msm_mux_gcc_gp3_a,
+ msm_mux_gcc_gp3_b,
+ msm_mux_gpio,
+ msm_mux_hdmi_cec,
+ msm_mux_hdmi_ddc,
+ msm_mux_hdmi_hot,
+ msm_mux_hdmi_rcv,
+ msm_mux_isense_dbg,
+ msm_mux_jitter_bist,
+ msm_mux_ldo_en,
+ msm_mux_ldo_update,
+ msm_mux_lpass_slimbus,
+ msm_mux_m_voc,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync0,
+ msm_mux_mdp_vsync1,
+ msm_mux_mdp_vsync2,
+ msm_mux_mdp_vsync3,
+ msm_mux_mdp_vsync_a,
+ msm_mux_mdp_vsync_b,
+ msm_mux_modem_tsync,
+ msm_mux_mss_lte,
+ msm_mux_nav_dr,
+ msm_mux_nav_pps,
+ msm_mux_pa_indicator,
+ msm_mux_pci_e0,
+ msm_mux_phase_flag,
+ msm_mux_pll_bypassnl,
+ msm_mux_pll_reset,
+ msm_mux_pri_mi2s,
+ msm_mux_pri_mi2s_ws,
+ msm_mux_prng_rosc,
+ msm_mux_pwr_crypto,
+ msm_mux_pwr_modem,
+ msm_mux_pwr_nav,
+ msm_mux_qdss_cti0_a,
+ msm_mux_qdss_cti0_b,
+ msm_mux_qdss_cti1_a,
+ msm_mux_qdss_cti1_b,
+ msm_mux_qdss,
+ msm_mux_qlink_enable,
+ msm_mux_qlink_request,
+ msm_mux_qua_mi2s,
+ msm_mux_sd_card,
+ msm_mux_sd_write,
+ msm_mux_sdc40,
+ msm_mux_sdc41,
+ msm_mux_sdc42,
+ msm_mux_sdc43,
+ msm_mux_sdc4_clk,
+ msm_mux_sdc4_cmd,
+ msm_mux_sec_mi2s,
+ msm_mux_sp_cmu,
+ msm_mux_spkr_i2s,
+ msm_mux_ssbi1,
+ msm_mux_ssc_irq,
+ msm_mux_ter_mi2s,
+ msm_mux_tgu_ch0,
+ msm_mux_tgu_ch1,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_tsif1_clk,
+ msm_mux_tsif1_data,
+ msm_mux_tsif1_en,
+ msm_mux_tsif1_error,
+ msm_mux_tsif1_sync,
+ msm_mux_tsif2_clk,
+ msm_mux_tsif2_data,
+ msm_mux_tsif2_en,
+ msm_mux_tsif2_error,
+ msm_mux_tsif2_sync,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_data,
+ msm_mux_uim1_present,
+ msm_mux_uim1_reset,
+ msm_mux_uim2_clk,
+ msm_mux_uim2_data,
+ msm_mux_uim2_present,
+ msm_mux_uim2_reset,
+ msm_mux_uim_batt,
+ msm_mux_usb_phy,
+ msm_mux_vfr_1,
+ msm_mux_vsense_clkout,
+ msm_mux_vsense_data0,
+ msm_mux_vsense_data1,
+ msm_mux_vsense_mode,
+ msm_mux_wlan1_adc0,
+ msm_mux_wlan1_adc1,
+ msm_mux_wlan2_adc0,
+ msm_mux_wlan2_adc1,
+ msm_mux__,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+ "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+ "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+ "gpio147", "gpio148", "gpio149",
+};
+static const char * const blsp_spi1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const blsp_uim1_a_groups[] = {
+ "gpio0", "gpio1",
+};
+static const char * const blsp_uart1_a_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio2", "gpio3",
+};
+static const char * const blsp_spi8_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart8_a_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uim8_a_groups[] = {
+ "gpio4", "gpio5",
+};
+static const char * const qdss_cti0_b_groups[] = {
+ "gpio4", "gpio5",
+};
+static const char * const blsp_i2c8_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const ddr_bist_groups[] = {
+ "gpio7", "gpio8", "gpio9", "gpio10",
+};
+static const char * const atest_tsens2_groups[] = {
+ "gpio7",
+};
+static const char * const atest_usb1_groups[] = {
+ "gpio7",
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uart1_b_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uim1_b_groups[] = {
+ "gpio8", "gpio9",
+};
+static const char * const wlan1_adc1_groups[] = {
+ "gpio8",
+};
+static const char * const atest_usb13_groups[] = {
+ "gpio8",
+};
+static const char * const bimc_dte1_groups[] = {
+ "gpio8", "gpio10",
+};
+static const char * const tsif1_sync_groups[] = {
+ "gpio9",
+};
+static const char * const wlan1_adc0_groups[] = {
+ "gpio9",
+};
+static const char * const atest_usb12_groups[] = {
+ "gpio9",
+};
+static const char * const bimc_dte0_groups[] = {
+ "gpio9", "gpio11",
+};
+static const char * const mdp_vsync_a_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const atest_gpsadc1_groups[] = {
+ "gpio10",
+};
+static const char * const wlan2_adc1_groups[] = {
+ "gpio10",
+};
+static const char * const atest_usb11_groups[] = {
+ "gpio10",
+};
+static const char * const edp_lcd_groups[] = {
+ "gpio11",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio11",
+};
+static const char * const atest_gpsadc0_groups[] = {
+ "gpio11",
+};
+static const char * const wlan2_adc0_groups[] = {
+ "gpio11",
+};
+static const char * const atest_usb10_groups[] = {
+ "gpio11",
+};
+static const char * const mdp_vsync_groups[] = {
+ "gpio12",
+};
+static const char * const m_voc_groups[] = {
+ "gpio12",
+};
+static const char * const cam_mclk_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16",
+};
+static const char * const pll_bypassnl_groups[] = {
+ "gpio13",
+};
+static const char * const qdss_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26",
+ "gpio27", "gpio28", "gpio29", "gpio30", "gpio41", "gpio42", "gpio43",
+ "gpio44", "gpio75", "gpio76", "gpio77", "gpio79", "gpio80", "gpio93",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124",
+};
+static const char * const pll_reset_groups[] = {
+ "gpio14",
+};
+static const char * const cci_i2c_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20",
+};
+static const char * const phase_flag_groups[] = {
+ "gpio18", "gpio19", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio89", "gpio91", "gpio92", "gpio96", "gpio114", "gpio115",
+ "gpio116", "gpio117", "gpio118", "gpio119", "gpio120", "gpio121",
+ "gpio122", "gpio123", "gpio124", "gpio125", "gpio126", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+};
+static const char * const cci_timer4_groups[] = {
+ "gpio25",
+};
+static const char * const blsp2_spi_groups[] = {
+ "gpio25", "gpio29", "gpio30",
+};
+static const char * const cci_timer0_groups[] = {
+ "gpio21",
+};
+static const char * const vsense_data0_groups[] = {
+ "gpio21",
+};
+static const char * const cci_timer1_groups[] = {
+ "gpio22",
+};
+static const char * const vsense_data1_groups[] = {
+ "gpio22",
+};
+static const char * const cci_timer2_groups[] = {
+ "gpio23",
+};
+static const char * const blsp1_spi_b_groups[] = {
+ "gpio23", "gpio28",
+};
+static const char * const vsense_mode_groups[] = {
+ "gpio23",
+};
+static const char * const cci_timer3_groups[] = {
+ "gpio24",
+};
+static const char * const cci_async_groups[] = {
+ "gpio24", "gpio25", "gpio26",
+};
+static const char * const blsp1_spi_a_groups[] = {
+ "gpio24", "gpio27",
+};
+static const char * const vsense_clkout_groups[] = {
+ "gpio24",
+};
+static const char * const hdmi_rcv_groups[] = {
+ "gpio30",
+};
+static const char * const hdmi_cec_groups[] = {
+ "gpio31",
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio31", "gpio32", "gpio33", "gpio34",
+};
+static const char * const blsp_uart2_a_groups[] = {
+ "gpio31", "gpio32", "gpio33", "gpio34",
+};
+static const char * const blsp_uim2_a_groups[] = {
+ "gpio31", "gpio34",
+};
+static const char * const pwr_modem_groups[] = {
+ "gpio31",
+};
+static const char * const hdmi_ddc_groups[] = {
+ "gpio32", "gpio33",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio32", "gpio33",
+};
+static const char * const pwr_nav_groups[] = {
+ "gpio32",
+};
+static const char * const pwr_crypto_groups[] = {
+ "gpio33",
+};
+static const char * const hdmi_hot_groups[] = {
+ "gpio34",
+};
+static const char * const edp_hot_groups[] = {
+ "gpio34",
+};
+static const char * const pci_e0_groups[] = {
+ "gpio35", "gpio36", "gpio37",
+};
+static const char * const jitter_bist_groups[] = {
+ "gpio35",
+};
+static const char * const agera_pll_groups[] = {
+ "gpio36", "gpio37",
+};
+static const char * const atest_tsens_groups[] = {
+ "gpio36",
+};
+static const char * const usb_phy_groups[] = {
+ "gpio38",
+};
+static const char * const lpass_slimbus_groups[] = {
+ "gpio39", "gpio70", "gpio71", "gpio72",
+};
+static const char * const sd_write_groups[] = {
+ "gpio40",
+};
+static const char * const tsif1_error_groups[] = {
+ "gpio40",
+};
+static const char * const blsp_spi6_groups[] = {
+ "gpio41", "gpio42", "gpio43", "gpio44",
+};
+static const char * const blsp_uart3_b_groups[] = {
+ "gpio41", "gpio42", "gpio43", "gpio44",
+};
+static const char * const blsp_uim3_b_groups[] = {
+ "gpio41", "gpio42",
+};
+static const char * const blsp_i2c6_groups[] = {
+ "gpio43", "gpio44",
+};
+static const char * const bt_reset_groups[] = {
+ "gpio45",
+};
+static const char * const blsp_spi3_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+static const char * const blsp_uart3_a_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+static const char * const blsp_uim3_a_groups[] = {
+ "gpio45", "gpio46",
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio47", "gpio48",
+};
+static const char * const blsp_spi9_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const blsp_uart9_a_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const blsp_uim9_a_groups[] = {
+ "gpio49", "gpio50",
+};
+static const char * const blsp10_spi_b_groups[] = {
+ "gpio49", "gpio50",
+};
+static const char * const qdss_cti0_a_groups[] = {
+ "gpio49", "gpio50",
+};
+static const char * const blsp_i2c9_groups[] = {
+ "gpio51", "gpio52",
+};
+static const char * const blsp10_spi_a_groups[] = {
+ "gpio51", "gpio52",
+};
+static const char * const blsp_spi7_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const blsp_uart7_a_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const blsp_uim7_a_groups[] = {
+ "gpio53", "gpio54",
+};
+static const char * const blsp_i2c7_groups[] = {
+ "gpio55", "gpio56",
+};
+static const char * const qua_mi2s_groups[] = {
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+};
+static const char * const blsp10_spi_groups[] = {
+ "gpio57",
+};
+static const char * const gcc_gp1_a_groups[] = {
+ "gpio57",
+};
+static const char * const ssc_irq_groups[] = {
+ "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", "gpio78",
+ "gpio79", "gpio80", "gpio117", "gpio118", "gpio119", "gpio120",
+ "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
+};
+static const char * const blsp_spi11_groups[] = {
+ "gpio58", "gpio59", "gpio60", "gpio61",
+};
+static const char * const blsp_uart8_b_groups[] = {
+ "gpio58", "gpio59", "gpio60", "gpio61",
+};
+static const char * const blsp_uim8_b_groups[] = {
+ "gpio58", "gpio59",
+};
+static const char * const gcc_gp2_a_groups[] = {
+ "gpio58",
+};
+static const char * const qdss_cti1_a_groups[] = {
+ "gpio58", "gpio59",
+};
+static const char * const gcc_gp3_a_groups[] = {
+ "gpio59",
+};
+static const char * const blsp_i2c11_groups[] = {
+ "gpio60", "gpio61",
+};
+static const char * const cri_trng0_groups[] = {
+ "gpio60",
+};
+static const char * const cri_trng1_groups[] = {
+ "gpio61",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio62",
+};
+static const char * const pri_mi2s_groups[] = {
+ "gpio64", "gpio65", "gpio67", "gpio68",
+};
+static const char * const sp_cmu_groups[] = {
+ "gpio64",
+};
+static const char * const blsp_spi10_groups[] = {
+ "gpio65", "gpio66", "gpio67", "gpio68",
+};
+static const char * const blsp_uart7_b_groups[] = {
+ "gpio65", "gpio66", "gpio67", "gpio68",
+};
+static const char * const blsp_uim7_b_groups[] = {
+ "gpio65", "gpio66",
+};
+static const char * const pri_mi2s_ws_groups[] = {
+ "gpio66",
+};
+static const char * const blsp_i2c10_groups[] = {
+ "gpio67", "gpio68",
+};
+static const char * const spkr_i2s_groups[] = {
+ "gpio69", "gpio70", "gpio71", "gpio72",
+};
+static const char * const audio_ref_groups[] = {
+ "gpio69",
+};
+static const char * const blsp9_spi_groups[] = {
+ "gpio70", "gpio71", "gpio72",
+};
+static const char * const tsense_pwm1_groups[] = {
+ "gpio71",
+};
+static const char * const tsense_pwm2_groups[] = {
+ "gpio71",
+};
+static const char * const btfm_slimbus_groups[] = {
+ "gpio73", "gpio74",
+};
+static const char * const ter_mi2s_groups[] = {
+ "gpio74", "gpio75", "gpio76", "gpio77", "gpio78",
+};
+static const char * const gcc_gp1_b_groups[] = {
+ "gpio78",
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+};
+static const char * const blsp_spi12_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio84",
+};
+static const char * const blsp_uart9_b_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio84",
+};
+static const char * const blsp_uim9_b_groups[] = {
+ "gpio81", "gpio82",
+};
+static const char * const gcc_gp2_b_groups[] = {
+ "gpio81",
+};
+static const char * const gcc_gp3_b_groups[] = {
+ "gpio82",
+};
+static const char * const blsp_i2c12_groups[] = {
+ "gpio83", "gpio84",
+};
+static const char * const blsp_spi5_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const blsp_uart2_b_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const blsp_uim2_b_groups[] = {
+ "gpio85", "gpio86",
+};
+static const char * const blsp_i2c5_groups[] = {
+ "gpio87", "gpio88",
+};
+static const char * const tsif1_clk_groups[] = {
+ "gpio89",
+};
+static const char * const tsif1_en_groups[] = {
+ "gpio90",
+};
+static const char * const mdp_vsync0_groups[] = {
+ "gpio90",
+};
+static const char * const mdp_vsync1_groups[] = {
+ "gpio90",
+};
+static const char * const mdp_vsync2_groups[] = {
+ "gpio90",
+};
+static const char * const mdp_vsync3_groups[] = {
+ "gpio90",
+};
+static const char * const blsp1_spi_groups[] = {
+ "gpio90",
+};
+static const char * const tgu_ch0_groups[] = {
+ "gpio90",
+};
+static const char * const qdss_cti1_b_groups[] = {
+ "gpio90", "gpio91",
+};
+static const char * const tsif1_data_groups[] = {
+ "gpio91",
+};
+static const char * const sdc4_cmd_groups[] = {
+ "gpio91",
+};
+static const char * const tgu_ch1_groups[] = {
+ "gpio91",
+};
+static const char * const tsif2_error_groups[] = {
+ "gpio92",
+};
+static const char * const sdc43_groups[] = {
+ "gpio92",
+};
+static const char * const vfr_1_groups[] = {
+ "gpio92",
+};
+static const char * const tsif2_clk_groups[] = {
+ "gpio93",
+};
+static const char * const sdc4_clk_groups[] = {
+ "gpio93",
+};
+static const char * const tsif2_en_groups[] = {
+ "gpio94",
+};
+static const char * const sdc42_groups[] = {
+ "gpio94",
+};
+static const char * const sd_card_groups[] = {
+ "gpio95",
+};
+static const char * const tsif2_data_groups[] = {
+ "gpio95",
+};
+static const char * const sdc41_groups[] = {
+ "gpio95",
+};
+static const char * const tsif2_sync_groups[] = {
+ "gpio96",
+};
+static const char * const sdc40_groups[] = {
+ "gpio96",
+};
+static const char * const mdp_vsync_b_groups[] = {
+ "gpio97", "gpio98",
+};
+static const char * const ldo_en_groups[] = {
+ "gpio97",
+};
+static const char * const ldo_update_groups[] = {
+ "gpio98",
+};
+static const char * const blsp_uart8_groups[] = {
+ "gpio100", "gpio101",
+};
+static const char * const blsp11_i2c_groups[] = {
+ "gpio102", "gpio103",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio102",
+};
+static const char * const uim2_data_groups[] = {
+ "gpio105",
+};
+static const char * const uim2_clk_groups[] = {
+ "gpio106",
+};
+static const char * const uim2_reset_groups[] = {
+ "gpio107",
+};
+static const char * const uim2_present_groups[] = {
+ "gpio108",
+};
+static const char * const uim1_data_groups[] = {
+ "gpio109",
+};
+static const char * const uim1_clk_groups[] = {
+ "gpio110",
+};
+static const char * const uim1_reset_groups[] = {
+ "gpio111",
+};
+static const char * const uim1_present_groups[] = {
+ "gpio112",
+};
+static const char * const uim_batt_groups[] = {
+ "gpio113",
+};
+static const char * const nav_dr_groups[] = {
+ "gpio115",
+};
+static const char * const atest_char_groups[] = {
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio118",
+};
+static const char * const modem_tsync_groups[] = {
+ "gpio128",
+};
+static const char * const nav_pps_groups[] = {
+ "gpio128",
+};
+static const char * const qlink_request_groups[] = {
+ "gpio130",
+};
+static const char * const qlink_enable_groups[] = {
+ "gpio131",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio135",
+};
+static const char * const ssbi1_groups[] = {
+ "gpio142",
+};
+static const char * const isense_dbg_groups[] = {
+ "gpio143",
+};
+static const char * const mss_lte_groups[] = {
+ "gpio144", "gpio145",
+};
+
+static const struct msm_function msm8998_functions[] = {
+ FUNCTION(gpio),
+ FUNCTION(adsp_ext),
+ FUNCTION(agera_pll),
+ FUNCTION(atest_char),
+ FUNCTION(atest_gpsadc0),
+ FUNCTION(atest_gpsadc1),
+ FUNCTION(atest_tsens),
+ FUNCTION(atest_tsens2),
+ FUNCTION(atest_usb1),
+ FUNCTION(atest_usb10),
+ FUNCTION(atest_usb11),
+ FUNCTION(atest_usb12),
+ FUNCTION(atest_usb13),
+ FUNCTION(audio_ref),
+ FUNCTION(bimc_dte0),
+ FUNCTION(bimc_dte1),
+ FUNCTION(blsp10_spi),
+ FUNCTION(blsp10_spi_a),
+ FUNCTION(blsp10_spi_b),
+ FUNCTION(blsp11_i2c),
+ FUNCTION(blsp1_spi),
+ FUNCTION(blsp1_spi_a),
+ FUNCTION(blsp1_spi_b),
+ FUNCTION(blsp2_spi),
+ FUNCTION(blsp9_spi),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(blsp_i2c5),
+ FUNCTION(blsp_i2c6),
+ FUNCTION(blsp_i2c7),
+ FUNCTION(blsp_i2c8),
+ FUNCTION(blsp_i2c9),
+ FUNCTION(blsp_i2c10),
+ FUNCTION(blsp_i2c11),
+ FUNCTION(blsp_i2c12),
+ FUNCTION(blsp_spi1),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_spi3),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_spi5),
+ FUNCTION(blsp_spi6),
+ FUNCTION(blsp_spi7),
+ FUNCTION(blsp_spi8),
+ FUNCTION(blsp_spi9),
+ FUNCTION(blsp_spi10),
+ FUNCTION(blsp_spi11),
+ FUNCTION(blsp_spi12),
+ FUNCTION(blsp_uart1_a),
+ FUNCTION(blsp_uart1_b),
+ FUNCTION(blsp_uart2_a),
+ FUNCTION(blsp_uart2_b),
+ FUNCTION(blsp_uart3_a),
+ FUNCTION(blsp_uart3_b),
+ FUNCTION(blsp_uart7_a),
+ FUNCTION(blsp_uart7_b),
+ FUNCTION(blsp_uart8),
+ FUNCTION(blsp_uart8_a),
+ FUNCTION(blsp_uart8_b),
+ FUNCTION(blsp_uart9_a),
+ FUNCTION(blsp_uart9_b),
+ FUNCTION(blsp_uim1_a),
+ FUNCTION(blsp_uim1_b),
+ FUNCTION(blsp_uim2_a),
+ FUNCTION(blsp_uim2_b),
+ FUNCTION(blsp_uim3_a),
+ FUNCTION(blsp_uim3_b),
+ FUNCTION(blsp_uim7_a),
+ FUNCTION(blsp_uim7_b),
+ FUNCTION(blsp_uim8_a),
+ FUNCTION(blsp_uim8_b),
+ FUNCTION(blsp_uim9_a),
+ FUNCTION(blsp_uim9_b),
+ FUNCTION(bt_reset),
+ FUNCTION(btfm_slimbus),
+ FUNCTION(cam_mclk),
+ FUNCTION(cci_async),
+ FUNCTION(cci_i2c),
+ FUNCTION(cci_timer0),
+ FUNCTION(cci_timer1),
+ FUNCTION(cci_timer2),
+ FUNCTION(cci_timer3),
+ FUNCTION(cci_timer4),
+ FUNCTION(cri_trng),
+ FUNCTION(cri_trng0),
+ FUNCTION(cri_trng1),
+ FUNCTION(dbg_out),
+ FUNCTION(ddr_bist),
+ FUNCTION(edp_hot),
+ FUNCTION(edp_lcd),
+ FUNCTION(gcc_gp1_a),
+ FUNCTION(gcc_gp1_b),
+ FUNCTION(gcc_gp2_a),
+ FUNCTION(gcc_gp2_b),
+ FUNCTION(gcc_gp3_a),
+ FUNCTION(gcc_gp3_b),
+ FUNCTION(hdmi_cec),
+ FUNCTION(hdmi_ddc),
+ FUNCTION(hdmi_hot),
+ FUNCTION(hdmi_rcv),
+ FUNCTION(isense_dbg),
+ FUNCTION(jitter_bist),
+ FUNCTION(ldo_en),
+ FUNCTION(ldo_update),
+ FUNCTION(lpass_slimbus),
+ FUNCTION(m_voc),
+ FUNCTION(mdp_vsync),
+ FUNCTION(mdp_vsync0),
+ FUNCTION(mdp_vsync1),
+ FUNCTION(mdp_vsync2),
+ FUNCTION(mdp_vsync3),
+ FUNCTION(mdp_vsync_a),
+ FUNCTION(mdp_vsync_b),
+ FUNCTION(modem_tsync),
+ FUNCTION(mss_lte),
+ FUNCTION(nav_dr),
+ FUNCTION(nav_pps),
+ FUNCTION(pa_indicator),
+ FUNCTION(pci_e0),
+ FUNCTION(phase_flag),
+ FUNCTION(pll_bypassnl),
+ FUNCTION(pll_reset),
+ FUNCTION(pri_mi2s),
+ FUNCTION(pri_mi2s_ws),
+ FUNCTION(prng_rosc),
+ FUNCTION(pwr_crypto),
+ FUNCTION(pwr_modem),
+ FUNCTION(pwr_nav),
+ FUNCTION(qdss_cti0_a),
+ FUNCTION(qdss_cti0_b),
+ FUNCTION(qdss_cti1_a),
+ FUNCTION(qdss_cti1_b),
+ FUNCTION(qdss),
+ FUNCTION(qlink_enable),
+ FUNCTION(qlink_request),
+ FUNCTION(qua_mi2s),
+ FUNCTION(sd_card),
+ FUNCTION(sd_write),
+ FUNCTION(sdc40),
+ FUNCTION(sdc41),
+ FUNCTION(sdc42),
+ FUNCTION(sdc43),
+ FUNCTION(sdc4_clk),
+ FUNCTION(sdc4_cmd),
+ FUNCTION(sec_mi2s),
+ FUNCTION(sp_cmu),
+ FUNCTION(spkr_i2s),
+ FUNCTION(ssbi1),
+ FUNCTION(ssc_irq),
+ FUNCTION(ter_mi2s),
+ FUNCTION(tgu_ch0),
+ FUNCTION(tgu_ch1),
+ FUNCTION(tsense_pwm1),
+ FUNCTION(tsense_pwm2),
+ FUNCTION(tsif1_clk),
+ FUNCTION(tsif1_data),
+ FUNCTION(tsif1_en),
+ FUNCTION(tsif1_error),
+ FUNCTION(tsif1_sync),
+ FUNCTION(tsif2_clk),
+ FUNCTION(tsif2_data),
+ FUNCTION(tsif2_en),
+ FUNCTION(tsif2_error),
+ FUNCTION(tsif2_sync),
+ FUNCTION(uim1_clk),
+ FUNCTION(uim1_data),
+ FUNCTION(uim1_present),
+ FUNCTION(uim1_reset),
+ FUNCTION(uim2_clk),
+ FUNCTION(uim2_data),
+ FUNCTION(uim2_present),
+ FUNCTION(uim2_reset),
+ FUNCTION(uim_batt),
+ FUNCTION(usb_phy),
+ FUNCTION(vfr_1),
+ FUNCTION(vsense_clkout),
+ FUNCTION(vsense_data0),
+ FUNCTION(vsense_data1),
+ FUNCTION(vsense_mode),
+ FUNCTION(wlan1_adc0),
+ FUNCTION(wlan1_adc1),
+ FUNCTION(wlan2_adc0),
+ FUNCTION(wlan2_adc1),
+};
+
+static const struct msm_pingroup msm8998_groups[] = {
+ PINGROUP(0, EAST, blsp_spi1, blsp_uart1_a, blsp_uim1_a, _, _, _, _, _, _),
+ PINGROUP(1, EAST, blsp_spi1, blsp_uart1_a, blsp_uim1_a, _, _, _, _, _, _),
+ PINGROUP(2, EAST, blsp_spi1, blsp_uart1_a, blsp_i2c1, _, _, _, _, _, _),
+ PINGROUP(3, EAST, blsp_spi1, blsp_uart1_a, blsp_i2c1, _, _, _, _, _, _),
+ PINGROUP(4, WEST, blsp_spi8, blsp_uart8_a, blsp_uim8_a, _, qdss_cti0_b, _, _, _, _),
+ PINGROUP(5, WEST, blsp_spi8, blsp_uart8_a, blsp_uim8_a, _, qdss_cti0_b, _, _, _, _),
+ PINGROUP(6, WEST, blsp_spi8, blsp_uart8_a, blsp_i2c8, _, _, _, _, _, _),
+ PINGROUP(7, WEST, blsp_spi8, blsp_uart8_a, blsp_i2c8, ddr_bist, _, atest_tsens2, atest_usb1, _, _),
+ PINGROUP(8, EAST, blsp_spi4, blsp_uart1_b, blsp_uim1_b, _, ddr_bist, _, wlan1_adc1, atest_usb13, bimc_dte1),
+ PINGROUP(9, EAST, blsp_spi4, blsp_uart1_b, blsp_uim1_b, tsif1_sync, ddr_bist, _, wlan1_adc0, atest_usb12, bimc_dte0),
+ PINGROUP(10, EAST, mdp_vsync_a, blsp_spi4, blsp_uart1_b, blsp_i2c4, ddr_bist, atest_gpsadc1, wlan2_adc1, atest_usb11, bimc_dte1),
+ PINGROUP(11, EAST, mdp_vsync_a, edp_lcd, blsp_spi4, blsp_uart1_b, blsp_i2c4, dbg_out, atest_gpsadc0, wlan2_adc0, atest_usb10),
+ PINGROUP(12, EAST, mdp_vsync, m_voc, _, _, _, _, _, _, _),
+ PINGROUP(13, EAST, cam_mclk, pll_bypassnl, qdss, _, _, _, _, _, _),
+ PINGROUP(14, EAST, cam_mclk, pll_reset, qdss, _, _, _, _, _, _),
+ PINGROUP(15, EAST, cam_mclk, qdss, _, _, _, _, _, _, _),
+ PINGROUP(16, EAST, cam_mclk, qdss, _, _, _, _, _, _, _),
+ PINGROUP(17, EAST, cci_i2c, qdss, _, _, _, _, _, _, _),
+ PINGROUP(18, EAST, cci_i2c, phase_flag, qdss, _, _, _, _, _, _),
+ PINGROUP(19, EAST, cci_i2c, phase_flag, qdss, _, _, _, _, _, _),
+ PINGROUP(20, EAST, cci_i2c, qdss, _, _, _, _, _, _, _),
+ PINGROUP(21, EAST, cci_timer0, _, qdss, vsense_data0, _, _, _, _, _),
+ PINGROUP(22, EAST, cci_timer1, _, qdss, vsense_data1, _, _, _, _, _),
+ PINGROUP(23, EAST, cci_timer2, blsp1_spi_b, qdss, vsense_mode, _, _, _, _, _),
+ PINGROUP(24, EAST, cci_timer3, cci_async, blsp1_spi_a, _, qdss, vsense_clkout, _, _, _),
+ PINGROUP(25, EAST, cci_timer4, cci_async, blsp2_spi, _, qdss, _, _, _, _),
+ PINGROUP(26, EAST, cci_async, qdss, _, _, _, _, _, _, _),
+ PINGROUP(27, EAST, blsp1_spi_a, qdss, _, _, _, _, _, _, _),
+ PINGROUP(28, EAST, blsp1_spi_b, qdss, _, _, _, _, _, _, _),
+ PINGROUP(29, EAST, blsp2_spi, _, qdss, _, _, _, _, _, _),
+ PINGROUP(30, EAST, hdmi_rcv, blsp2_spi, qdss, _, _, _, _, _, _),
+ PINGROUP(31, EAST, hdmi_cec, blsp_spi2, blsp_uart2_a, blsp_uim2_a, pwr_modem, _, _, _, _),
+ PINGROUP(32, EAST, hdmi_ddc, blsp_spi2, blsp_uart2_a, blsp_i2c2, pwr_nav, _, _, _, _),
+ PINGROUP(33, EAST, hdmi_ddc, blsp_spi2, blsp_uart2_a, blsp_i2c2, pwr_crypto, _, _, _, _),
+ PINGROUP(34, EAST, hdmi_hot, edp_hot, blsp_spi2, blsp_uart2_a, blsp_uim2_a, _, _, _, _),
+ PINGROUP(35, NORTH, pci_e0, jitter_bist, _, _, _, _, _, _, _),
+ PINGROUP(36, NORTH, pci_e0, agera_pll, _, atest_tsens, _, _, _, _, _),
+ PINGROUP(37, NORTH, agera_pll, _, _, _, _, _, _, _, _),
+ PINGROUP(38, WEST, usb_phy, _, _, _, _, _, _, _, _),
+ PINGROUP(39, WEST, lpass_slimbus, _, _, _, _, _, _, _, _),
+ PINGROUP(40, EAST, sd_write, tsif1_error, _, _, _, _, _, _, _),
+ PINGROUP(41, EAST, blsp_spi6, blsp_uart3_b, blsp_uim3_b, _, qdss, _, _, _, _),
+ PINGROUP(42, EAST, blsp_spi6, blsp_uart3_b, blsp_uim3_b, _, qdss, _, _, _, _),
+ PINGROUP(43, EAST, blsp_spi6, blsp_uart3_b, blsp_i2c6, _, qdss, _, _, _, _),
+ PINGROUP(44, EAST, blsp_spi6, blsp_uart3_b, blsp_i2c6, _, qdss, _, _, _, _),
+ PINGROUP(45, EAST, blsp_spi3, blsp_uart3_a, blsp_uim3_a, _, _, _, _, _, _),
+ PINGROUP(46, EAST, blsp_spi3, blsp_uart3_a, blsp_uim3_a, _, _, _, _, _, _),
+ PINGROUP(47, EAST, blsp_spi3, blsp_uart3_a, blsp_i2c3, _, _, _, _, _, _),
+ PINGROUP(48, EAST, blsp_spi3, blsp_uart3_a, blsp_i2c3, _, _, _, _, _, _),
+ PINGROUP(49, NORTH, blsp_spi9, blsp_uart9_a, blsp_uim9_a, blsp10_spi_b, qdss_cti0_a, _, _, _, _),
+ PINGROUP(50, NORTH, blsp_spi9, blsp_uart9_a, blsp_uim9_a, blsp10_spi_b, qdss_cti0_a, _, _, _, _),
+ PINGROUP(51, NORTH, blsp_spi9, blsp_uart9_a, blsp_i2c9, blsp10_spi_a, _, _, _, _, _),
+ PINGROUP(52, NORTH, blsp_spi9, blsp_uart9_a, blsp_i2c9, blsp10_spi_a, _, _, _, _, _),
+ PINGROUP(53, WEST, blsp_spi7, blsp_uart7_a, blsp_uim7_a, _, _, _, _, _, _),
+ PINGROUP(54, WEST, blsp_spi7, blsp_uart7_a, blsp_uim7_a, _, _, _, _, _, _),
+ PINGROUP(55, WEST, blsp_spi7, blsp_uart7_a, blsp_i2c7, _, _, _, _, _, _),
+ PINGROUP(56, WEST, blsp_spi7, blsp_uart7_a, blsp_i2c7, _, _, _, _, _, _),
+ PINGROUP(57, WEST, qua_mi2s, blsp10_spi, gcc_gp1_a, _, _, _, _, _, _),
+ PINGROUP(58, WEST, qua_mi2s, blsp_spi11, blsp_uart8_b, blsp_uim8_b, gcc_gp2_a, _, qdss_cti1_a, _, _),
+ PINGROUP(59, WEST, qua_mi2s, blsp_spi11, blsp_uart8_b, blsp_uim8_b, gcc_gp3_a, _, qdss_cti1_a, _, _),
+ PINGROUP(60, WEST, qua_mi2s, blsp_spi11, blsp_uart8_b, blsp_i2c11, cri_trng0, _, _, _, _),
+ PINGROUP(61, WEST, qua_mi2s, blsp_spi11, blsp_uart8_b, blsp_i2c11, cri_trng1, _, _, _, _),
+ PINGROUP(62, WEST, qua_mi2s, cri_trng, _, _, _, _, _, _, _),
+ PINGROUP(63, WEST, qua_mi2s, _, _, _, _, _, _, _, _),
+ PINGROUP(64, WEST, pri_mi2s, sp_cmu, _, _, _, _, _, _, _),
+ PINGROUP(65, WEST, pri_mi2s, blsp_spi10, blsp_uart7_b, blsp_uim7_b, _, _, _, _, _),
+ PINGROUP(66, WEST, pri_mi2s_ws, blsp_spi10, blsp_uart7_b, blsp_uim7_b, _, _, _, _, _),
+ PINGROUP(67, WEST, pri_mi2s, blsp_spi10, blsp_uart7_b, blsp_i2c10, _, _, _, _, _),
+ PINGROUP(68, WEST, pri_mi2s, blsp_spi10, blsp_uart7_b, blsp_i2c10, _, _, _, _, _),
+ PINGROUP(69, WEST, spkr_i2s, audio_ref, _, _, _, _, _, _, _),
+ PINGROUP(70, WEST, lpass_slimbus, spkr_i2s, blsp9_spi, _, _, _, _, _, _),
+ PINGROUP(71, WEST, lpass_slimbus, spkr_i2s, blsp9_spi, tsense_pwm1, tsense_pwm2, _, _, _, _),
+ PINGROUP(72, WEST, lpass_slimbus, spkr_i2s, blsp9_spi, _, _, _, _, _, _),
+ PINGROUP(73, WEST, btfm_slimbus, phase_flag, _, _, _, _, _, _, _),
+ PINGROUP(74, WEST, btfm_slimbus, ter_mi2s, phase_flag, _, _, _, _, _, _),
+ PINGROUP(75, WEST, ter_mi2s, phase_flag, qdss, _, _, _, _, _, _),
+ PINGROUP(76, WEST, ter_mi2s, phase_flag, qdss, _, _, _, _, _, _),
+ PINGROUP(77, WEST, ter_mi2s, phase_flag, qdss, _, _, _, _, _, _),
+ PINGROUP(78, WEST, ter_mi2s, gcc_gp1_b, _, _, _, _, _, _, _),
+ PINGROUP(79, WEST, sec_mi2s, _, qdss, _, _, _, _, _, _),
+ PINGROUP(80, WEST, sec_mi2s, _, qdss, _, _, _, _, _, _),
+ PINGROUP(81, WEST, sec_mi2s, blsp_spi12, blsp_uart9_b, blsp_uim9_b, gcc_gp2_b, _, _, _, _),
+ PINGROUP(82, WEST, sec_mi2s, blsp_spi12, blsp_uart9_b, blsp_uim9_b, gcc_gp3_b, _, _, _, _),
+ PINGROUP(83, WEST, sec_mi2s, blsp_spi12, blsp_uart9_b, blsp_i2c12, _, _, _, _, _),
+ PINGROUP(84, WEST, blsp_spi12, blsp_uart9_b, blsp_i2c12, _, _, _, _, _, _),
+ PINGROUP(85, EAST, blsp_spi5, blsp_uart2_b, blsp_uim2_b, _, _, _, _, _, _),
+ PINGROUP(86, EAST, blsp_spi5, blsp_uart2_b, blsp_uim2_b, _, _, _, _, _, _),
+ PINGROUP(87, EAST, blsp_spi5, blsp_uart2_b, blsp_i2c5, _, _, _, _, _, _),
+ PINGROUP(88, EAST, blsp_spi5, blsp_uart2_b, blsp_i2c5, _, _, _, _, _, _),
+ PINGROUP(89, EAST, tsif1_clk, phase_flag, _, _, _, _, _, _, _),
+ PINGROUP(90, EAST, tsif1_en, mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3, blsp1_spi, tgu_ch0, qdss_cti1_b, _),
+ PINGROUP(91, EAST, tsif1_data, sdc4_cmd, tgu_ch1, phase_flag, qdss_cti1_b, _, _, _, _),
+ PINGROUP(92, EAST, tsif2_error, sdc43, vfr_1, phase_flag, _, _, _, _, _),
+ PINGROUP(93, EAST, tsif2_clk, sdc4_clk, _, qdss, _, _, _, _, _),
+ PINGROUP(94, EAST, tsif2_en, sdc42, _, _, _, _, _, _, _),
+ PINGROUP(95, EAST, tsif2_data, sdc41, _, _, _, _, _, _, _),
+ PINGROUP(96, EAST, tsif2_sync, sdc40, phase_flag, _, _, _, _, _, _),
+ PINGROUP(97, WEST, _, mdp_vsync_b, ldo_en, _, _, _, _, _, _),
+ PINGROUP(98, WEST, _, mdp_vsync_b, ldo_update, _, _, _, _, _, _),
+ PINGROUP(99, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(100, WEST, _, _, blsp_uart8, _, _, _, _, _, _),
+ PINGROUP(101, WEST, _, blsp_uart8, _, _, _, _, _, _, _),
+ PINGROUP(102, WEST, _, blsp11_i2c, prng_rosc, _, _, _, _, _, _),
+ PINGROUP(103, WEST, _, blsp11_i2c, phase_flag, _, _, _, _, _, _),
+ PINGROUP(104, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(105, NORTH, uim2_data, _, _, _, _, _, _, _, _),
+ PINGROUP(106, NORTH, uim2_clk, _, _, _, _, _, _, _, _),
+ PINGROUP(107, NORTH, uim2_reset, _, _, _, _, _, _, _, _),
+ PINGROUP(108, NORTH, uim2_present, _, _, _, _, _, _, _, _),
+ PINGROUP(109, NORTH, uim1_data, _, _, _, _, _, _, _, _),
+ PINGROUP(110, NORTH, uim1_clk, _, _, _, _, _, _, _, _),
+ PINGROUP(111, NORTH, uim1_reset, _, _, _, _, _, _, _, _),
+ PINGROUP(112, NORTH, uim1_present, _, _, _, _, _, _, _, _),
+ PINGROUP(113, NORTH, uim_batt, _, _, _, _, _, _, _, _),
+ PINGROUP(114, WEST, _, _, phase_flag, _, _, _, _, _, _),
+ PINGROUP(115, WEST, _, nav_dr, phase_flag, _, _, _, _, _, _),
+ PINGROUP(116, WEST, phase_flag, _, _, _, _, _, _, _, _),
+ PINGROUP(117, EAST, phase_flag, qdss, atest_char, _, _, _, _, _, _),
+ PINGROUP(118, EAST, adsp_ext, phase_flag, qdss, atest_char, _, _, _, _, _),
+ PINGROUP(119, EAST, phase_flag, qdss, atest_char, _, _, _, _, _, _),
+ PINGROUP(120, EAST, phase_flag, qdss, atest_char, _, _, _, _, _, _),
+ PINGROUP(121, EAST, phase_flag, qdss, atest_char, _, _, _, _, _, _),
+ PINGROUP(122, EAST, phase_flag, qdss, _, _, _, _, _, _, _),
+ PINGROUP(123, EAST, phase_flag, qdss, _, _, _, _, _, _, _),
+ PINGROUP(124, EAST, phase_flag, qdss, _, _, _, _, _, _, _),
+ PINGROUP(125, EAST, phase_flag, _, _, _, _, _, _, _, _),
+ PINGROUP(126, EAST, phase_flag, _, _, _, _, _, _, _, _),
+ PINGROUP(127, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(128, WEST, modem_tsync, nav_pps, phase_flag, _, _, _, _, _, _),
+ PINGROUP(129, WEST, phase_flag, _, _, _, _, _, _, _, _),
+ PINGROUP(130, NORTH, qlink_request, phase_flag, _, _, _, _, _, _, _),
+ PINGROUP(131, NORTH, qlink_enable, phase_flag, _, _, _, _, _, _, _),
+ PINGROUP(132, WEST, _, phase_flag, _, _, _, _, _, _, _),
+ PINGROUP(133, WEST, phase_flag, _, _, _, _, _, _, _, _),
+ PINGROUP(134, WEST, phase_flag, _, _, _, _, _, _, _, _),
+ PINGROUP(135, WEST, _, pa_indicator, _, _, _, _, _, _, _),
+ PINGROUP(136, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(137, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(138, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(139, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(140, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(141, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(142, WEST, _, ssbi1, _, _, _, _, _, _, _),
+ PINGROUP(143, WEST, isense_dbg, _, _, _, _, _, _, _, _),
+ PINGROUP(144, WEST, mss_lte, _, _, _, _, _, _, _, _),
+ PINGROUP(145, WEST, mss_lte, _, _, _, _, _, _, _, _),
+ PINGROUP(146, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(147, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(148, WEST, _, _, _, _, _, _, _, _, _),
+ PINGROUP(149, WEST, _, _, _, _, _, _, _, _, _),
+ SDC_QDSD_PINGROUP(sdc2_clk, 0x999000, 14, 6),
+ SDC_QDSD_PINGROUP(sdc2_cmd, 0x999000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc2_data, 0x999000, 9, 0),
+ UFS_RESET(ufs_reset, 0x19d000),
+};
+
+static const struct msm_pinctrl_soc_data msm8998_pinctrl = {
+ .pins = msm8998_pins,
+ .npins = ARRAY_SIZE(msm8998_pins),
+ .functions = msm8998_functions,
+ .nfunctions = ARRAY_SIZE(msm8998_functions),
+ .groups = msm8998_groups,
+ .ngroups = ARRAY_SIZE(msm8998_groups),
+ .ngpios = 150,
+};
+
+static int msm8998_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &msm8998_pinctrl);
+}
+
+static const struct of_device_id msm8998_pinctrl_of_match[] = {
+ { .compatible = "qcom,msm8998-pinctrl", },
+ { },
+};
+
+static struct platform_driver msm8998_pinctrl_driver = {
+ .driver = {
+ .name = "msm8998-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = msm8998_pinctrl_of_match,
+ },
+ .probe = msm8998_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init msm8998_pinctrl_init(void)
+{
+ return platform_driver_register(&msm8998_pinctrl_driver);
+}
+arch_initcall(msm8998_pinctrl_init);
+
+static void __exit msm8998_pinctrl_exit(void)
+{
+ platform_driver_unregister(&msm8998_pinctrl_driver);
+}
+module_exit(msm8998_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI msm8998 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8998_pinctrl_of_match);
diff --git a/drivers/pinctrl/samsung/Kconfig b/drivers/pinctrl/samsung/Kconfig
index ecfb90059eeb..11b5eeb14c4a 100644
--- a/drivers/pinctrl/samsung/Kconfig
+++ b/drivers/pinctrl/samsung/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Samsung Pin control drivers
#
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm.c
index 071084d3ee9c..c32399faff57 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm.c
@@ -1,22 +1,17 @@
-/*
- * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- * http://www.linaro.org
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This file contains the Samsung Exynos specific information required by the
- * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+// http://www.samsung.com
+// Copyright (c) 2012 Linaro Ltd
+// http://www.linaro.org
+//
+// Author: Thomas Abraham <thomas.ab@samsung.com>
+//
+// This file contains the Samsung Exynos specific information required by the
+// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+// external gpio and wakeup interrupt support.
#include <linux/device.h>
#include <linux/of_address.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 08e9fdb58fd2..fc8f7833bec0 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1,22 +1,17 @@
-/*
- * Exynos ARMv8 specific support for Samsung pinctrl/gpiolib driver
- * with eint support.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- * http://www.linaro.org
- * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This file contains the Samsung Exynos specific information required by the
- * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Exynos ARMv8 specific support for Samsung pinctrl/gpiolib driver
+// with eint support.
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+// http://www.samsung.com
+// Copyright (c) 2012 Linaro Ltd
+// http://www.linaro.org
+// Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
+//
+// This file contains the Samsung Exynos specific information required by the
+// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+// external gpio and wakeup interrupt support.
#include <linux/slab.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index c8d0de7ea160..0a625a64ff5d 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -1,22 +1,17 @@
-/*
- * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- * http://www.linaro.org
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This file contains the Samsung Exynos specific information required by the
- * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+// http://www.samsung.com
+// Copyright (c) 2012 Linaro Ltd
+// http://www.linaro.org
+//
+// Author: Thomas Abraham <thomas.ab@samsung.com>
+//
+// This file contains the Samsung Exynos specific information required by the
+// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+// external gpio and wakeup interrupt support.
#include <linux/device.h>
#include <linux/interrupt.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 7639b926c5c1..abd43aa7eb0d 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Exynos specific definitions for Samsung pinctrl and gpiolib driver.
*
@@ -10,11 +11,6 @@
* pinctrl/gpiolib interface drivers.
*
* Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#ifndef __PINCTRL_SAMSUNG_EXYNOS_H
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index 32a3a9fd65c4..3d8d5e812839 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -1,16 +1,11 @@
-/*
- * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC.
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC.
+//
+// Author: Thomas Abraham <thomas.ab@samsung.com>
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+// http://www.samsung.com
#include <linux/init.h>
#include <linux/platform_device.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
index edf27264b603..10187cb0e9b9 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
@@ -1,17 +1,12 @@
-/*
- * S3C24XX specific support for Samsung pinctrl/gpiolib driver.
- *
- * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This file contains the SamsungS3C24XX specific information required by the
- * Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// S3C24XX specific support for Samsung pinctrl/gpiolib driver.
+//
+// Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
+//
+// This file contains the SamsungS3C24XX specific information required by the
+// Samsung pinctrl/gpiolib driver. It also includes the implementation of
+// external gpio and wakeup interrupt support.
#include <linux/init.h>
#include <linux/device.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
index e63663b32907..679628ac4b31 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
@@ -1,19 +1,14 @@
-/*
- * S3C64xx specific support for pinctrl-samsung driver.
- *
- * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
- *
- * Based on pinctrl-exynos.c, please see the file for original copyrights.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This file contains the Samsung S3C64xx specific information required by the
- * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
- * external gpio and wakeup interrupt support.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// S3C64xx specific support for pinctrl-samsung driver.
+//
+// Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+//
+// Based on pinctrl-exynos.c, please see the file for original copyrights.
+//
+// This file contains the Samsung S3C64xx specific information required by the
+// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+// external gpio and wakeup interrupt support.
#include <linux/init.h>
#include <linux/device.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index e04f7fe0a65d..da58e4554137 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1,24 +1,19 @@
-/*
- * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- * Copyright (c) 2012 Linaro Ltd
- * http://www.linaro.org
- *
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This driver implements the Samsung pinctrl driver. It supports setting up of
- * pinmux and pinconf configurations. The gpiolib interface is also included.
- * External interrupt (gpio and wakeup) support are not included in this driver
- * but provides extensions to which platform specific implementation of the gpio
- * and wakeup interrupts can be hooked to.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+// http://www.samsung.com
+// Copyright (c) 2012 Linaro Ltd
+// http://www.linaro.org
+//
+// Author: Thomas Abraham <thomas.ab@samsung.com>
+//
+// This driver implements the Samsung pinctrl driver. It supports setting up of
+// pinmux and pinconf configurations. The gpiolib interface is also included.
+// External interrupt (gpio and wakeup) support are not included in this driver
+// but provides extensions to which platform specific implementation of the gpio
+// and wakeup interrupts can be hooked to.
#include <linux/init.h>
#include <linux/platform_device.h>
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 9af07af6cad6..e204f609823b 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
*
@@ -7,11 +8,6 @@
* http://www.linaro.org
*
* Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#ifndef __PINCTRL_SAMSUNG_H
diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
index 5d5312eb7102..4ed3761418f9 100644
--- a/drivers/pinctrl/sh-pfc/Kconfig
+++ b/drivers/pinctrl/sh-pfc/Kconfig
@@ -89,6 +89,11 @@ config PINCTRL_PFC_R8A7796
depends on ARCH_R8A7796
select PINCTRL_SH_PFC
+config PINCTRL_PFC_R8A77970
+ def_bool y
+ depends on ARCH_R8A77970
+ select PINCTRL_SH_PFC
+
config PINCTRL_PFC_R8A77995
def_bool y
depends on ARCH_R8A77995
diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile
index a7903904b64e..22e758ce1fc2 100644
--- a/drivers/pinctrl/sh-pfc/Makefile
+++ b/drivers/pinctrl/sh-pfc/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7794) += pfc-r8a7794.o
obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795.o
obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795-es1.o
obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o
+obj-$(CONFIG_PINCTRL_PFC_R8A77970) += pfc-r8a77970.o
obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o
obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index cf4ae4bc9115..e9eb7a7c6fac 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -557,6 +557,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
.data = &r8a7796_pinmux_info,
},
#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77970
+ {
+ .compatible = "renesas,pfc-r8a77970",
+ .data = &r8a77970_pinmux_info,
+ },
+#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77995
{
.compatible = "renesas,pfc-r8a77995",
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 10bd35f8c894..5811784d88cb 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -4145,6 +4145,32 @@ static const unsigned int ssi9_ctrl_b_mux[] = {
SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
};
+/* - TPU -------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ RCAR_GP_PIN(6, 14),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPU_TO0_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ RCAR_GP_PIN(1, 17),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPU_TO1_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ RCAR_GP_PIN(1, 18),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPU_TO2_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPU_TO3_MARK,
+};
+
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
RCAR_GP_PIN(7, 23), /* PWEN */
@@ -4431,7 +4457,7 @@ static const unsigned int vin2_clk_mux[] = {
};
static const struct {
- struct sh_pfc_pin_group common[342];
+ struct sh_pfc_pin_group common[346];
struct sh_pfc_pin_group r8a779x[9];
} pinmux_groups = {
.common = {
@@ -4743,6 +4769,10 @@ static const struct {
SH_PFC_PIN_GROUP(ssi9_data_b),
SH_PFC_PIN_GROUP(ssi9_ctrl),
SH_PFC_PIN_GROUP(ssi9_ctrl_b),
+ SH_PFC_PIN_GROUP(tpu_to0),
+ SH_PFC_PIN_GROUP(tpu_to1),
+ SH_PFC_PIN_GROUP(tpu_to2),
+ SH_PFC_PIN_GROUP(tpu_to3),
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
VIN_DATA_PIN_GROUP(vin0_data, 24),
@@ -4826,6 +4856,10 @@ static const char * const can0_groups[] = {
"can0_data_d",
"can0_data_e",
"can0_data_f",
+ /*
+ * Retained for backwards compatibility, use can_clk_groups in new
+ * designs.
+ */
"can_clk",
"can_clk_b",
"can_clk_c",
@@ -4837,6 +4871,21 @@ static const char * const can1_groups[] = {
"can1_data_b",
"can1_data_c",
"can1_data_d",
+ /*
+ * Retained for backwards compatibility, use can_clk_groups in new
+ * designs.
+ */
+ "can_clk",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+};
+
+/*
+ * can_clk_groups allows for independent configuration, use can_clk function
+ * in new designs.
+ */
+static const char * const can_clk_groups[] = {
"can_clk",
"can_clk_b",
"can_clk_c",
@@ -5259,6 +5308,13 @@ static const char * const ssi_groups[] = {
"ssi9_ctrl_b",
};
+static const char * const tpu_groups[] = {
+ "tpu_to0",
+ "tpu_to1",
+ "tpu_to2",
+ "tpu_to3",
+};
+
static const char * const usb0_groups[] = {
"usb0",
};
@@ -5308,7 +5364,7 @@ static const char * const vin2_groups[] = {
};
static const struct {
- struct sh_pfc_function common[56];
+ struct sh_pfc_function common[58];
struct sh_pfc_function r8a779x[2];
} pinmux_functions = {
.common = {
@@ -5316,6 +5372,7 @@ static const struct {
SH_PFC_FUNCTION(avb),
SH_PFC_FUNCTION(can0),
SH_PFC_FUNCTION(can1),
+ SH_PFC_FUNCTION(can_clk),
SH_PFC_FUNCTION(du),
SH_PFC_FUNCTION(du0),
SH_PFC_FUNCTION(du1),
@@ -5363,6 +5420,7 @@ static const struct {
SH_PFC_FUNCTION(sdhi1),
SH_PFC_FUNCTION(sdhi2),
SH_PFC_FUNCTION(ssi),
+ SH_PFC_FUNCTION(tpu),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(vin0),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
index 333a3470e842..164002437594 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
@@ -1608,6 +1608,116 @@ static const unsigned int avb_gmii_mux[] = {
AVB_TX_EN_MARK, AVB_TX_ER_MARK, AVB_TX_CLK_MARK,
AVB_COL_MARK,
};
+
+/* - CAN -------------------------------------------------------------------- */
+static const unsigned int can0_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(6, 15), RCAR_GP_PIN(6, 14),
+};
+
+static const unsigned int can0_data_mux[] = {
+ CAN0_TX_MARK, CAN0_RX_MARK,
+};
+
+static const unsigned int can0_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15),
+};
+
+static const unsigned int can0_data_b_mux[] = {
+ CAN0_TX_B_MARK, CAN0_RX_B_MARK,
+};
+
+static const unsigned int can0_data_c_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 16),
+};
+
+static const unsigned int can0_data_c_mux[] = {
+ CAN0_TX_C_MARK, CAN0_RX_C_MARK,
+};
+
+static const unsigned int can0_data_d_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 11),
+};
+
+static const unsigned int can0_data_d_mux[] = {
+ CAN0_TX_D_MARK, CAN0_RX_D_MARK,
+};
+
+static const unsigned int can1_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(6, 25), RCAR_GP_PIN(6, 24),
+};
+
+static const unsigned int can1_data_mux[] = {
+ CAN1_TX_MARK, CAN1_RX_MARK,
+};
+
+static const unsigned int can1_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 1),
+};
+
+static const unsigned int can1_data_b_mux[] = {
+ CAN1_TX_B_MARK, CAN1_RX_B_MARK,
+};
+
+static const unsigned int can1_data_c_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 5),
+};
+
+static const unsigned int can1_data_c_mux[] = {
+ CAN1_TX_C_MARK, CAN1_RX_C_MARK,
+};
+
+static const unsigned int can1_data_d_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30),
+};
+
+static const unsigned int can1_data_d_mux[] = {
+ CAN1_TX_D_MARK, CAN1_RX_D_MARK,
+};
+
+static const unsigned int can_clk_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(3, 31),
+};
+
+static const unsigned int can_clk_mux[] = {
+ CAN_CLK_MARK,
+};
+
+static const unsigned int can_clk_b_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(1, 23),
+};
+
+static const unsigned int can_clk_b_mux[] = {
+ CAN_CLK_B_MARK,
+};
+
+static const unsigned int can_clk_c_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(1, 0),
+};
+
+static const unsigned int can_clk_c_mux[] = {
+ CAN_CLK_C_MARK,
+};
+
+static const unsigned int can_clk_d_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(5, 0),
+};
+
+static const unsigned int can_clk_d_mux[] = {
+ CAN_CLK_D_MARK,
+};
+
/* - DU --------------------------------------------------------------------- */
static const unsigned int du0_rgb666_pins[] = {
/* R[7:2], G[7:2], B[7:2] */
@@ -2118,6 +2228,35 @@ static const unsigned int i2c4_e_pins[] = {
static const unsigned int i2c4_e_mux[] = {
I2C4_SCL_E_MARK, I2C4_SDA_E_MARK,
};
+/* - I2C5 ------------------------------------------------------------------- */
+static const unsigned int i2c5_pins[] = {
+ /* SCL, SDA */
+ RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 15),
+};
+static const unsigned int i2c5_mux[] = {
+ I2C5_SCL_MARK, I2C5_SDA_MARK,
+};
+static const unsigned int i2c5_b_pins[] = {
+ /* SCL, SDA */
+ RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15),
+};
+static const unsigned int i2c5_b_mux[] = {
+ I2C5_SCL_B_MARK, I2C5_SDA_B_MARK,
+};
+static const unsigned int i2c5_c_pins[] = {
+ /* SCL, SDA */
+ RCAR_GP_PIN(4, 31), RCAR_GP_PIN(4, 30),
+};
+static const unsigned int i2c5_c_mux[] = {
+ I2C5_SCL_C_MARK, I2C5_SDA_C_MARK,
+};
+static const unsigned int i2c5_d_pins[] = {
+ /* SCL, SDA */
+ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14),
+};
+static const unsigned int i2c5_d_mux[] = {
+ I2C5_SCL_D_MARK, I2C5_SDA_D_MARK,
+};
/* - INTC ------------------------------------------------------------------- */
static const unsigned int intc_irq0_pins[] = {
/* IRQ0 */
@@ -2436,6 +2575,109 @@ static const unsigned int msiof2_tx_b_pins[] = {
static const unsigned int msiof2_tx_b_mux[] = {
MSIOF2_TXD_B_MARK,
};
+/* - PWM -------------------------------------------------------------------- */
+static const unsigned int pwm0_pins[] = {
+ RCAR_GP_PIN(1, 14),
+};
+static const unsigned int pwm0_mux[] = {
+ PWM0_MARK,
+};
+static const unsigned int pwm0_b_pins[] = {
+ RCAR_GP_PIN(5, 3),
+};
+static const unsigned int pwm0_b_mux[] = {
+ PWM0_B_MARK,
+};
+static const unsigned int pwm1_pins[] = {
+ RCAR_GP_PIN(4, 5),
+};
+static const unsigned int pwm1_mux[] = {
+ PWM1_MARK,
+};
+static const unsigned int pwm1_b_pins[] = {
+ RCAR_GP_PIN(5, 10),
+};
+static const unsigned int pwm1_b_mux[] = {
+ PWM1_B_MARK,
+};
+static const unsigned int pwm1_c_pins[] = {
+ RCAR_GP_PIN(1, 18),
+};
+static const unsigned int pwm1_c_mux[] = {
+ PWM1_C_MARK,
+};
+static const unsigned int pwm2_pins[] = {
+ RCAR_GP_PIN(4, 10),
+};
+static const unsigned int pwm2_mux[] = {
+ PWM2_MARK,
+};
+static const unsigned int pwm2_b_pins[] = {
+ RCAR_GP_PIN(5, 17),
+};
+static const unsigned int pwm2_b_mux[] = {
+ PWM2_B_MARK,
+};
+static const unsigned int pwm2_c_pins[] = {
+ RCAR_GP_PIN(0, 13),
+};
+static const unsigned int pwm2_c_mux[] = {
+ PWM2_C_MARK,
+};
+static const unsigned int pwm3_pins[] = {
+ RCAR_GP_PIN(4, 13),
+};
+static const unsigned int pwm3_mux[] = {
+ PWM3_MARK,
+};
+static const unsigned int pwm3_b_pins[] = {
+ RCAR_GP_PIN(0, 16),
+};
+static const unsigned int pwm3_b_mux[] = {
+ PWM3_B_MARK,
+};
+static const unsigned int pwm4_pins[] = {
+ RCAR_GP_PIN(1, 3),
+};
+static const unsigned int pwm4_mux[] = {
+ PWM4_MARK,
+};
+static const unsigned int pwm4_b_pins[] = {
+ RCAR_GP_PIN(0, 21),
+};
+static const unsigned int pwm4_b_mux[] = {
+ PWM4_B_MARK,
+};
+static const unsigned int pwm5_pins[] = {
+ RCAR_GP_PIN(3, 30),
+};
+static const unsigned int pwm5_mux[] = {
+ PWM5_MARK,
+};
+static const unsigned int pwm5_b_pins[] = {
+ RCAR_GP_PIN(4, 0),
+};
+static const unsigned int pwm5_b_mux[] = {
+ PWM5_B_MARK,
+};
+static const unsigned int pwm5_c_pins[] = {
+ RCAR_GP_PIN(0, 10),
+};
+static const unsigned int pwm5_c_mux[] = {
+ PWM5_C_MARK,
+};
+static const unsigned int pwm6_pins[] = {
+ RCAR_GP_PIN(4, 8),
+};
+static const unsigned int pwm6_mux[] = {
+ PWM6_MARK,
+};
+static const unsigned int pwm6_b_pins[] = {
+ RCAR_GP_PIN(0, 7),
+};
+static const unsigned int pwm6_b_mux[] = {
+ PWM6_B_MARK,
+};
/* - QSPI ------------------------------------------------------------------- */
static const unsigned int qspi_ctrl_pins[] = {
/* SPCLK, SSL */
@@ -3280,6 +3522,79 @@ static const unsigned int ssi9_ctrl_b_pins[] = {
static const unsigned int ssi9_ctrl_b_mux[] = {
SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
};
+/* - TPU -------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ RCAR_GP_PIN(3, 31),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPUTO0_MARK,
+};
+static const unsigned int tpu_to0_b_pins[] = {
+ RCAR_GP_PIN(3, 30),
+};
+static const unsigned int tpu_to0_b_mux[] = {
+ TPUTO0_B_MARK,
+};
+static const unsigned int tpu_to0_c_pins[] = {
+ RCAR_GP_PIN(1, 18),
+};
+static const unsigned int tpu_to0_c_mux[] = {
+ TPUTO0_C_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ RCAR_GP_PIN(4, 9),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPUTO1_MARK,
+};
+static const unsigned int tpu_to1_b_pins[] = {
+ RCAR_GP_PIN(4, 0),
+};
+static const unsigned int tpu_to1_b_mux[] = {
+ TPUTO1_B_MARK,
+};
+static const unsigned int tpu_to1_c_pins[] = {
+ RCAR_GP_PIN(4, 4),
+};
+static const unsigned int tpu_to1_c_mux[] = {
+ TPUTO1_C_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ RCAR_GP_PIN(1, 3),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPUTO2_MARK,
+};
+static const unsigned int tpu_to2_b_pins[] = {
+ RCAR_GP_PIN(1, 0),
+};
+static const unsigned int tpu_to2_b_mux[] = {
+ TPUTO2_B_MARK,
+};
+static const unsigned int tpu_to2_c_pins[] = {
+ RCAR_GP_PIN(0, 22),
+};
+static const unsigned int tpu_to2_c_mux[] = {
+ TPUTO2_C_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ RCAR_GP_PIN(1, 14),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPUTO3_MARK,
+};
+static const unsigned int tpu_to3_b_pins[] = {
+ RCAR_GP_PIN(1, 13),
+};
+static const unsigned int tpu_to3_b_mux[] = {
+ TPUTO3_B_MARK,
+};
+static const unsigned int tpu_to3_c_pins[] = {
+ RCAR_GP_PIN(0, 21),
+};
+static const unsigned int tpu_to3_c_mux[] = {
+ TPUTO3_C_MARK,
+};
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
RCAR_GP_PIN(5, 24), /* PWEN */
@@ -3459,6 +3774,18 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(avb_mdio),
SH_PFC_PIN_GROUP(avb_mii),
SH_PFC_PIN_GROUP(avb_gmii),
+ SH_PFC_PIN_GROUP(can0_data),
+ SH_PFC_PIN_GROUP(can0_data_b),
+ SH_PFC_PIN_GROUP(can0_data_c),
+ SH_PFC_PIN_GROUP(can0_data_d),
+ SH_PFC_PIN_GROUP(can1_data),
+ SH_PFC_PIN_GROUP(can1_data_b),
+ SH_PFC_PIN_GROUP(can1_data_c),
+ SH_PFC_PIN_GROUP(can1_data_d),
+ SH_PFC_PIN_GROUP(can_clk),
+ SH_PFC_PIN_GROUP(can_clk_b),
+ SH_PFC_PIN_GROUP(can_clk_c),
+ SH_PFC_PIN_GROUP(can_clk_d),
SH_PFC_PIN_GROUP(du0_rgb666),
SH_PFC_PIN_GROUP(du0_rgb888),
SH_PFC_PIN_GROUP(du0_clk0_out),
@@ -3523,6 +3850,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(i2c4_c),
SH_PFC_PIN_GROUP(i2c4_d),
SH_PFC_PIN_GROUP(i2c4_e),
+ SH_PFC_PIN_GROUP(i2c5),
+ SH_PFC_PIN_GROUP(i2c5_b),
+ SH_PFC_PIN_GROUP(i2c5_c),
+ SH_PFC_PIN_GROUP(i2c5_d),
SH_PFC_PIN_GROUP(intc_irq0),
SH_PFC_PIN_GROUP(intc_irq1),
SH_PFC_PIN_GROUP(intc_irq2),
@@ -3567,6 +3898,23 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(msiof2_ss2_b),
SH_PFC_PIN_GROUP(msiof2_rx_b),
SH_PFC_PIN_GROUP(msiof2_tx_b),
+ SH_PFC_PIN_GROUP(pwm0),
+ SH_PFC_PIN_GROUP(pwm0_b),
+ SH_PFC_PIN_GROUP(pwm1),
+ SH_PFC_PIN_GROUP(pwm1_b),
+ SH_PFC_PIN_GROUP(pwm1_c),
+ SH_PFC_PIN_GROUP(pwm2),
+ SH_PFC_PIN_GROUP(pwm2_b),
+ SH_PFC_PIN_GROUP(pwm2_c),
+ SH_PFC_PIN_GROUP(pwm3),
+ SH_PFC_PIN_GROUP(pwm3_b),
+ SH_PFC_PIN_GROUP(pwm4),
+ SH_PFC_PIN_GROUP(pwm4_b),
+ SH_PFC_PIN_GROUP(pwm5),
+ SH_PFC_PIN_GROUP(pwm5_b),
+ SH_PFC_PIN_GROUP(pwm5_c),
+ SH_PFC_PIN_GROUP(pwm6),
+ SH_PFC_PIN_GROUP(pwm6_b),
SH_PFC_PIN_GROUP(qspi_ctrl),
SH_PFC_PIN_GROUP(qspi_data2),
SH_PFC_PIN_GROUP(qspi_data4),
@@ -3684,6 +4032,18 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(ssi9_ctrl),
SH_PFC_PIN_GROUP(ssi9_data_b),
SH_PFC_PIN_GROUP(ssi9_ctrl_b),
+ SH_PFC_PIN_GROUP(tpu_to0),
+ SH_PFC_PIN_GROUP(tpu_to0_b),
+ SH_PFC_PIN_GROUP(tpu_to0_c),
+ SH_PFC_PIN_GROUP(tpu_to1),
+ SH_PFC_PIN_GROUP(tpu_to1_b),
+ SH_PFC_PIN_GROUP(tpu_to1_c),
+ SH_PFC_PIN_GROUP(tpu_to2),
+ SH_PFC_PIN_GROUP(tpu_to2_b),
+ SH_PFC_PIN_GROUP(tpu_to2_c),
+ SH_PFC_PIN_GROUP(tpu_to3),
+ SH_PFC_PIN_GROUP(tpu_to3_b),
+ SH_PFC_PIN_GROUP(tpu_to3_c),
SH_PFC_PIN_GROUP(usb0),
SH_PFC_PIN_GROUP(usb1),
VIN_DATA_PIN_GROUP(vin0_data, 24),
@@ -3731,6 +4091,47 @@ static const char * const avb_groups[] = {
"avb_gmii",
};
+static const char * const can0_groups[] = {
+ "can0_data",
+ "can0_data_b",
+ "can0_data_c",
+ "can0_data_d",
+ /*
+ * Retained for backwards compatibility, use can_clk_groups in new
+ * designs.
+ */
+ "can_clk",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+};
+
+static const char * const can1_groups[] = {
+ "can1_data",
+ "can1_data_b",
+ "can1_data_c",
+ "can1_data_d",
+ /*
+ * Retained for backwards compatibility, use can_clk_groups in new
+ * designs.
+ */
+ "can_clk",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+};
+
+/*
+ * can_clk_groups allows for independent configuration, use can_clk function
+ * in new designs.
+ */
+static const char * const can_clk_groups[] = {
+ "can_clk",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+};
+
static const char * const du0_groups[] = {
"du0_rgb666",
"du0_rgb888",
@@ -3828,6 +4229,13 @@ static const char * const i2c4_groups[] = {
"i2c4_e",
};
+static const char * const i2c5_groups[] = {
+ "i2c5",
+ "i2c5_b",
+ "i2c5_c",
+ "i2c5_d",
+};
+
static const char * const intc_groups[] = {
"intc_irq0",
"intc_irq1",
@@ -3887,6 +4295,44 @@ static const char * const msiof2_groups[] = {
"msiof2_tx_b",
};
+static const char * const pwm0_groups[] = {
+ "pwm0",
+ "pwm0_b",
+};
+
+static const char * const pwm1_groups[] = {
+ "pwm1",
+ "pwm1_b",
+ "pwm1_c",
+};
+
+static const char * const pwm2_groups[] = {
+ "pwm2",
+ "pwm2_b",
+ "pwm2_c",
+};
+
+static const char * const pwm3_groups[] = {
+ "pwm3",
+ "pwm3_b",
+};
+
+static const char * const pwm4_groups[] = {
+ "pwm4",
+ "pwm4_b",
+};
+
+static const char * const pwm5_groups[] = {
+ "pwm5",
+ "pwm5_b",
+ "pwm5_c",
+};
+
+static const char * const pwm6_groups[] = {
+ "pwm6",
+ "pwm6_b",
+};
+
static const char * const qspi_groups[] = {
"qspi_ctrl",
"qspi_data2",
@@ -4067,6 +4513,21 @@ static const char * const ssi_groups[] = {
"ssi9_ctrl_b",
};
+static const char * const tpu_groups[] = {
+ "tpu_to0",
+ "tpu_to0_b",
+ "tpu_to0_c",
+ "tpu_to1",
+ "tpu_to1_b",
+ "tpu_to1_c",
+ "tpu_to2",
+ "tpu_to2_b",
+ "tpu_to2_c",
+ "tpu_to3",
+ "tpu_to3_b",
+ "tpu_to3_c",
+};
+
static const char * const usb0_groups[] = {
"usb0",
};
@@ -4102,6 +4563,9 @@ static const char * const vin1_groups[] = {
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
SH_PFC_FUNCTION(avb),
+ SH_PFC_FUNCTION(can0),
+ SH_PFC_FUNCTION(can1),
+ SH_PFC_FUNCTION(can_clk),
SH_PFC_FUNCTION(du0),
SH_PFC_FUNCTION(du1),
SH_PFC_FUNCTION(eth),
@@ -4113,11 +4577,19 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(i2c2),
SH_PFC_FUNCTION(i2c3),
SH_PFC_FUNCTION(i2c4),
+ SH_PFC_FUNCTION(i2c5),
SH_PFC_FUNCTION(intc),
SH_PFC_FUNCTION(mmc),
SH_PFC_FUNCTION(msiof0),
SH_PFC_FUNCTION(msiof1),
SH_PFC_FUNCTION(msiof2),
+ 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(qspi),
SH_PFC_FUNCTION(scif0),
SH_PFC_FUNCTION(scif1),
@@ -4139,6 +4611,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(sdhi1),
SH_PFC_FUNCTION(sdhi2),
SH_PFC_FUNCTION(ssi),
+ SH_PFC_FUNCTION(tpu),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(vin0),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c
index 1d4d84f34d60..292e35d4d2f4 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c
@@ -1397,7 +1397,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP16_27_24, AUDIO_CLKOUT_B, SEL_ADG_1),
PINMUX_IPSR_MSEL(IP16_27_24, SSI_SCK2_B, SEL_SSI_1),
PINMUX_IPSR_MSEL(IP16_27_24, TS_SDEN1_D, SEL_TSIF1_3),
- PINMUX_IPSR_MSEL(IP16_27_24, STP_ISEN_1_D, SEL_SSP1_1_2),
+ PINMUX_IPSR_MSEL(IP16_27_24, STP_ISEN_1_D, SEL_SSP1_1_3),
PINMUX_IPSR_MSEL(IP16_27_24, STP_OPWM_0_E, SEL_SSP1_0_4),
PINMUX_IPSR_MSEL(IP16_27_24, RIF3_D0_B, SEL_DRIF3_1),
PINMUX_IPSR_MSEL(IP16_27_24, TCLK2_B, SEL_TIMER_TMU_1),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
index d1cec6d12e81..18aeee592fdc 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
@@ -20,7 +20,7 @@
#define CPU_ALL_PORT(fn, sfx) \
PORT_GP_CFG_16(0, fn, sfx, CFG_FLAGS), \
- PORT_GP_CFG_28(1, fn, sfx, CFG_FLAGS), \
+ PORT_GP_CFG_29(1, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_15(2, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_12(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE), \
PORT_GP_CFG_1(3, 12, fn, sfx, CFG_FLAGS), \
@@ -55,6 +55,7 @@
#define GPSR0_0 F_(D0, IP5_15_12)
/* GPSR1 */
+#define GPSR1_28 FM(CLKOUT)
#define GPSR1_27 F_(EX_WAIT0_A, IP5_11_8)
#define GPSR1_26 F_(WE1_N, IP5_7_4)
#define GPSR1_25 F_(WE0_N, IP5_3_0)
@@ -157,11 +158,11 @@
#define GPSR5_11 F_(RX2_A, IP13_7_4)
#define GPSR5_10 F_(TX2_A, IP13_3_0)
#define GPSR5_9 F_(SCK2, IP12_31_28)
-#define GPSR5_8 F_(RTS1_N_TANS, IP12_27_24)
+#define GPSR5_8 F_(RTS1_N, IP12_27_24)
#define GPSR5_7 F_(CTS1_N, IP12_23_20)
#define GPSR5_6 F_(TX1_A, IP12_19_16)
#define GPSR5_5 F_(RX1_A, IP12_15_12)
-#define GPSR5_4 F_(RTS0_N_TANS, IP12_11_8)
+#define GPSR5_4 F_(RTS0_N, IP12_11_8)
#define GPSR5_3 F_(CTS0_N, IP12_7_4)
#define GPSR5_2 F_(TX0, IP12_3_0)
#define GPSR5_1 F_(RX0, IP11_31_28)
@@ -214,16 +215,16 @@
#define IP0_11_8 FM(AVB_PHY_INT) F_(0, 0) FM(MSIOF2_SYNC_C) FM(RX4_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 IP0_15_12 FM(AVB_LINK) F_(0, 0) FM(MSIOF2_SCK_C) FM(TX4_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 IP0_19_16 FM(AVB_AVTP_MATCH_A) F_(0, 0) FM(MSIOF2_RXD_C) FM(CTS4_N_A) F_(0, 0) FM(FSCLKST2_N_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 IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_TANS_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 IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_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 IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) FM(MSIOF3_SS2_E) 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 IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) FM(MSIOF3_SS1_E) 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 IP1_3_0 FM(IRQ2) FM(QCPV_QDE) F_(0, 0) FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(VI4_DATA2_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SYNC_E) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) FM(A25) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SCK_E) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) FM(A24) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) FM(MSIOF3_RXD_E) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_15_12 FM(IRQ5) FM(QSTB_QHE) FM(A23) FM(DU_EXVSYNC_DU_VSYNC) FM(VI4_DATA5_B) FM(FSCLKST2_N_B) F_(0, 0) FM(MSIOF3_TXD_E) F_(0, 0) FM(PWM6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_19_16 FM(PWM0) FM(AVB_AVTP_PPS)FM(A22) F_(0, 0) FM(VI4_DATA6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IECLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_23_20 FM(PWM1_A) F_(0, 0) FM(A21) FM(HRX3_D) FM(VI4_DATA7_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IERX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_27_24 FM(PWM2_A) F_(0, 0) FM(A20) FM(HTX3_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IETX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) F_(0, 0) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SCK_E) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) F_(0, 0) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) FM(MSIOF3_RXD_E) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_15_12 FM(IRQ5) FM(QSTB_QHE) F_(0, 0) FM(DU_EXVSYNC_DU_VSYNC) FM(VI4_DATA5_B) FM(FSCLKST2_N_B) F_(0, 0) FM(MSIOF3_TXD_E) F_(0, 0) FM(PWM6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_19_16 FM(PWM0) FM(AVB_AVTP_PPS)F_(0, 0) F_(0, 0) FM(VI4_DATA6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IECLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_23_20 FM(PWM1_A) F_(0, 0) F_(0, 0) FM(HRX3_D) FM(VI4_DATA7_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IERX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_27_24 FM(PWM2_A) F_(0, 0) F_(0, 0) FM(HTX3_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IETX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_31_28 FM(A0) FM(LCDOUT16) FM(MSIOF3_SYNC_B) F_(0, 0) FM(VI4_DATA8) F_(0, 0) FM(DU_DB0) F_(0, 0) F_(0, 0) FM(PWM3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP2_3_0 FM(A1) FM(LCDOUT17) FM(MSIOF3_TXD_B) F_(0, 0) FM(VI4_DATA9) F_(0, 0) FM(DU_DB1) F_(0, 0) F_(0, 0) FM(PWM4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP2_7_4 FM(A2) FM(LCDOUT18) FM(MSIOF3_SCK_B) F_(0, 0) FM(VI4_DATA10) F_(0, 0) FM(DU_DB2) F_(0, 0) F_(0, 0) FM(PWM5_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -236,7 +237,7 @@
#define IP2_27_24 FM(A7) FM(LCDOUT23) FM(MSIOF2_SS2_A) FM(TX4_B) FM(VI4_DATA15) FM(VI5_DATA15) FM(DU_DB7) F_(0, 0) 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 IP2_31_28 FM(A8) FM(RX3_B) FM(MSIOF2_SYNC_A) FM(HRX4_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(SDA6_A) FM(AVB_AVTP_MATCH_B) FM(PWM1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP3_3_0 FM(A9) F_(0, 0) FM(MSIOF2_SCK_A) FM(CTS4_N_B) F_(0, 0) FM(VI5_VSYNC_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)
-#define IP3_7_4 FM(A10) F_(0, 0) FM(MSIOF2_RXD_A) FM(RTS4_N_TANS_B) F_(0, 0) FM(VI5_HSYNC_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)
+#define IP3_7_4 FM(A10) F_(0, 0) FM(MSIOF2_RXD_A) FM(RTS4_N_B) F_(0, 0) FM(VI5_HSYNC_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)
#define IP3_11_8 FM(A11) FM(TX3_B) FM(MSIOF2_TXD_A) FM(HTX4_B) FM(HSCK4) FM(VI5_FIELD) F_(0, 0) FM(SCL6_A) FM(AVB_AVTP_CAPTURE_B) FM(PWM2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP3_15_12 FM(A12) FM(LCDOUT12) FM(MSIOF3_SCK_C) F_(0, 0) FM(HRX4_A) FM(VI5_DATA8) FM(DU_DG4) F_(0, 0) 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 IP3_19_16 FM(A13) FM(LCDOUT13) FM(MSIOF3_SYNC_C) F_(0, 0) FM(HTX4_A) FM(VI5_DATA9) FM(DU_DG5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -252,7 +253,7 @@
#define IP4_27_24 FM(RD_N) F_(0, 0) FM(MSIOF3_SYNC_D) FM(RX3_A) FM(HRX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_TX_A) FM(CANFD0_TX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP4_31_28 FM(RD_WR_N) F_(0, 0) FM(MSIOF3_RXD_D) FM(TX3_A) FM(HTX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_RX_A) FM(CANFD0_RX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP5_3_0 FM(WE0_N) F_(0, 0) FM(MSIOF3_TXD_D) FM(CTS3_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) FM(SCL6_B) FM(CAN_CLK) F_(0, 0) FM(IECLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP5_7_4 FM(WE1_N) F_(0, 0) FM(MSIOF3_SS1_D) FM(RTS3_N_TANS) FM(HRTS3_N) F_(0, 0) F_(0, 0) FM(SDA6_B) FM(CAN1_RX) FM(CANFD1_RX) FM(IERX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_7_4 FM(WE1_N) F_(0, 0) FM(MSIOF3_SS1_D) FM(RTS3_N) FM(HRTS3_N) F_(0, 0) F_(0, 0) FM(SDA6_B) FM(CAN1_RX) FM(CANFD1_RX) FM(IERX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP5_11_8 FM(EX_WAIT0_A) FM(QCLK) F_(0, 0) F_(0, 0) FM(VI4_CLK) F_(0, 0) FM(DU_DOTCLKOUT0) F_(0, 0) 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 IP5_15_12 FM(D0) FM(MSIOF2_SS1_B)FM(MSIOF3_SCK_A) F_(0, 0) FM(VI4_DATA16) FM(VI5_DATA0) F_(0, 0) F_(0, 0) 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 IP5_19_16 FM(D1) FM(MSIOF2_SS2_B)FM(MSIOF3_SYNC_A) F_(0, 0) FM(VI4_DATA17) FM(VI5_DATA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -265,7 +266,7 @@
#define IP6_15_12 FM(D8) FM(LCDOUT0) FM(MSIOF2_SCK_D) FM(SCK4_C) FM(VI4_DATA0_A) F_(0, 0) FM(DU_DR0) F_(0, 0) 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 IP6_19_16 FM(D9) FM(LCDOUT1) FM(MSIOF2_SYNC_D) F_(0, 0) FM(VI4_DATA1_A) F_(0, 0) FM(DU_DR1) F_(0, 0) 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 IP6_23_20 FM(D10) FM(LCDOUT2) FM(MSIOF2_RXD_D) FM(HRX3_B) FM(VI4_DATA2_A) FM(CTS4_N_C) FM(DU_DR2) F_(0, 0) 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 IP6_27_24 FM(D11) FM(LCDOUT3) FM(MSIOF2_TXD_D) FM(HTX3_B) FM(VI4_DATA3_A) FM(RTS4_N_TANS_C)FM(DU_DR3) F_(0, 0) 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 IP6_27_24 FM(D11) FM(LCDOUT3) FM(MSIOF2_TXD_D) FM(HTX3_B) FM(VI4_DATA3_A) FM(RTS4_N_C) FM(DU_DR3) F_(0, 0) 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 IP6_31_28 FM(D12) FM(LCDOUT4) FM(MSIOF2_SS1_D) FM(RX4_C) FM(VI4_DATA4_A) F_(0, 0) FM(DU_DR4) F_(0, 0) 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 IP7_3_0 FM(D13) FM(LCDOUT5) FM(MSIOF2_SS2_D) FM(TX4_C) FM(VI4_DATA5_A) F_(0, 0) FM(DU_DR5) F_(0, 0) 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 IP7_7_4 FM(D14) FM(LCDOUT6) FM(MSIOF3_SS1_A) FM(HRX3_C) FM(VI4_DATA6_A) F_(0, 0) FM(DU_DR6) FM(SCL6_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -312,11 +313,11 @@
#define IP11_31_28 FM(RX0) FM(HRX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SCK0_C) FM(STP_ISCLK_0_C) FM(RIF0_D0_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)
#define IP12_3_0 FM(TX0) FM(HTX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SPSYNC0_C)FM(STP_ISSYNC_0_C) FM(RIF0_D1_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)
#define IP12_7_4 FM(CTS0_N) FM(HCTS1_N_B) FM(MSIOF1_SYNC_B) F_(0, 0) F_(0, 0) FM(TS_SPSYNC1_C)FM(STP_ISSYNC_1_C) FM(RIF1_SYNC_B) FM(AUDIO_CLKOUT_C) FM(ADICS_SAMP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP12_11_8 FM(RTS0_N_TANS) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) F_(0, 0) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_11_8 FM(RTS0_N) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) F_(0, 0) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP12_15_12 FM(RX1_A) FM(HRX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDAT0_C) FM(STP_ISD_0_C) FM(RIF1_CLK_C) 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 IP12_19_16 FM(TX1_A) FM(HTX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDEN0_C) FM(STP_ISEN_0_C) FM(RIF1_D0_C) 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 IP12_23_20 FM(CTS1_N) FM(HCTS1_N_A) FM(MSIOF1_RXD_B) F_(0, 0) F_(0, 0) FM(TS_SDEN1_C) FM(STP_ISEN_1_C) FM(RIF1_D0_B) F_(0, 0) FM(ADIDATA) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP12_27_24 FM(RTS1_N_TANS) FM(HRTS1_N_A) FM(MSIOF1_TXD_B) F_(0, 0) F_(0, 0) FM(TS_SDAT1_C) FM(STP_ISD_1_C) FM(RIF1_D1_B) F_(0, 0) FM(ADICHS0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_27_24 FM(RTS1_N) FM(HRTS1_N_A) FM(MSIOF1_TXD_B) F_(0, 0) F_(0, 0) FM(TS_SDAT1_C) FM(STP_ISD_1_C) FM(RIF1_D1_B) F_(0, 0) FM(ADICHS0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP12_31_28 FM(SCK2) FM(SCIF_CLK_B) FM(MSIOF1_SCK_B) F_(0, 0) F_(0, 0) FM(TS_SCK1_C) FM(STP_ISCLK_1_C) FM(RIF1_CLK_B) F_(0, 0) FM(ADICLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP13_3_0 FM(TX2_A) F_(0, 0) F_(0, 0) FM(SD2_CD_B) FM(SCL1_A) F_(0, 0) FM(FMCLK_A) FM(RIF1_D1_C) F_(0, 0) FM(FSO_CFE_0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP13_7_4 FM(RX2_A) F_(0, 0) F_(0, 0) FM(SD2_WP_B) FM(SDA1_A) F_(0, 0) FM(FMIN_A) FM(RIF1_SYNC_C) F_(0, 0) FM(FSO_CFE_1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -368,7 +369,7 @@
GPSR6_31 \
GPSR6_30 \
GPSR6_29 \
- GPSR6_28 \
+ GPSR1_28 GPSR6_28 \
GPSR1_27 GPSR6_27 \
GPSR1_26 GPSR6_26 \
GPSR1_25 GPSR5_25 GPSR6_25 \
@@ -548,7 +549,7 @@ MOD_SEL0_4_3 MOD_SEL1_4 \
FM(AVB_TX_CTL) FM(AVB_TXC) FM(AVB_TD0) FM(AVB_TD1) FM(AVB_TD2) FM(AVB_TD3) \
FM(AVB_RX_CTL) FM(AVB_RXC) FM(AVB_RD0) FM(AVB_RD1) FM(AVB_RD2) FM(AVB_RD3) \
FM(AVB_TXCREFCLK) FM(AVB_MDIO) \
- FM(CLKOUT) FM(PRESETOUT) \
+ FM(PRESETOUT) \
FM(DU_DOTCLKIN0) FM(DU_DOTCLKIN1) FM(DU_DOTCLKIN2) FM(DU_DOTCLKIN3) \
FM(TMS) FM(TDO) FM(ASEBRK) FM(MLB_REF) FM(TDI) FM(TCK) FM(TRST) FM(EXTALR)
@@ -587,6 +588,7 @@ static const u16 pinmux_data[] = {
PINMUX_SINGLE(AVS1),
PINMUX_SINGLE(AVS2),
+ PINMUX_SINGLE(CLKOUT),
PINMUX_SINGLE(HDMI0_CEC),
PINMUX_SINGLE(HDMI1_CEC),
PINMUX_SINGLE(I2C_SEL_0_1),
@@ -622,7 +624,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP0_23_20, AVB_AVTP_CAPTURE_A, SEL_ETHERAVB_0),
PINMUX_IPSR_MSEL(IP0_23_20, MSIOF2_TXD_C, SEL_MSIOF2_2),
- PINMUX_IPSR_MSEL(IP0_23_20, RTS4_N_TANS_A, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP0_23_20, RTS4_N_A, SEL_SCIF4_0),
PINMUX_IPSR_GPSR(IP0_27_24, IRQ0),
PINMUX_IPSR_GPSR(IP0_27_24, QPOLB),
@@ -650,7 +652,6 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_7_4, IRQ3),
PINMUX_IPSR_GPSR(IP1_7_4, QSTVB_QVE),
- PINMUX_IPSR_GPSR(IP1_7_4, A25),
PINMUX_IPSR_GPSR(IP1_7_4, DU_DOTCLKOUT1),
PINMUX_IPSR_MSEL(IP1_7_4, VI4_DATA3_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_7_4, PWM4_B, SEL_PWM4_1),
@@ -658,7 +659,6 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_11_8, IRQ4),
PINMUX_IPSR_GPSR(IP1_11_8, QSTH_QHS),
- PINMUX_IPSR_GPSR(IP1_11_8, A24),
PINMUX_IPSR_GPSR(IP1_11_8, DU_EXHSYNC_DU_HSYNC),
PINMUX_IPSR_MSEL(IP1_11_8, VI4_DATA4_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_11_8, PWM5_B, SEL_PWM5_1),
@@ -666,7 +666,6 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_15_12, IRQ5),
PINMUX_IPSR_GPSR(IP1_15_12, QSTB_QHE),
- PINMUX_IPSR_GPSR(IP1_15_12, A23),
PINMUX_IPSR_GPSR(IP1_15_12, DU_EXVSYNC_DU_VSYNC),
PINMUX_IPSR_MSEL(IP1_15_12, VI4_DATA5_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_15_12, PWM6_B, SEL_PWM6_1),
@@ -675,18 +674,15 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_19_16, PWM0),
PINMUX_IPSR_GPSR(IP1_19_16, AVB_AVTP_PPS),
- PINMUX_IPSR_GPSR(IP1_19_16, A22),
PINMUX_IPSR_MSEL(IP1_19_16, VI4_DATA6_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_19_16, IECLK_B, SEL_IEBUS_1),
PINMUX_IPSR_MSEL(IP1_23_20, PWM1_A, SEL_PWM1_0),
- PINMUX_IPSR_GPSR(IP1_23_20, A21),
PINMUX_IPSR_MSEL(IP1_23_20, HRX3_D, SEL_HSCIF3_3),
PINMUX_IPSR_MSEL(IP1_23_20, VI4_DATA7_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_23_20, IERX_B, SEL_IEBUS_1),
PINMUX_IPSR_MSEL(IP1_27_24, PWM2_A, SEL_PWM2_0),
- PINMUX_IPSR_GPSR(IP1_27_24, A20),
PINMUX_IPSR_MSEL(IP1_27_24, HTX3_D, SEL_HSCIF3_3),
PINMUX_IPSR_MSEL(IP1_27_24, IETX_B, SEL_IEBUS_1),
@@ -766,7 +762,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP3_7_4, A10),
PINMUX_IPSR_MSEL(IP3_7_4, MSIOF2_RXD_A, SEL_MSIOF2_0),
- PINMUX_IPSR_MSEL(IP3_7_4, RTS4_N_TANS_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP3_7_4, RTS4_N_B, SEL_SCIF4_1),
PINMUX_IPSR_GPSR(IP3_7_4, VI5_HSYNC_N),
PINMUX_IPSR_GPSR(IP3_11_8, A11),
@@ -869,7 +865,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP5_7_4, WE1_N),
PINMUX_IPSR_MSEL(IP5_7_4, MSIOF3_SS1_D, SEL_MSIOF3_3),
- PINMUX_IPSR_GPSR(IP5_7_4, RTS3_N_TANS),
+ PINMUX_IPSR_GPSR(IP5_7_4, RTS3_N),
PINMUX_IPSR_GPSR(IP5_7_4, HRTS3_N),
PINMUX_IPSR_MSEL(IP5_7_4, SDA6_B, SEL_I2C6_1),
PINMUX_IPSR_GPSR(IP5_7_4, CAN1_RX),
@@ -950,7 +946,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP6_27_24, MSIOF2_TXD_D, SEL_MSIOF2_3),
PINMUX_IPSR_MSEL(IP6_27_24, HTX3_B, SEL_HSCIF3_1),
PINMUX_IPSR_MSEL(IP6_27_24, VI4_DATA3_A, SEL_VIN4_0),
- PINMUX_IPSR_MSEL(IP6_27_24, RTS4_N_TANS_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP6_27_24, RTS4_N_C, SEL_SCIF4_2),
PINMUX_IPSR_GPSR(IP6_27_24, DU_DR3),
PINMUX_IPSR_GPSR(IP6_31_28, D12),
@@ -1159,7 +1155,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP12_7_4, AUDIO_CLKOUT_C),
PINMUX_IPSR_GPSR(IP12_7_4, ADICS_SAMP),
- PINMUX_IPSR_GPSR(IP12_11_8, RTS0_N_TANS),
+ PINMUX_IPSR_GPSR(IP12_11_8, RTS0_N),
PINMUX_IPSR_MSEL(IP12_11_8, HRTS1_N_B, SEL_HSCIF1_1),
PINMUX_IPSR_MSEL(IP12_11_8, MSIOF1_SS1_B, SEL_MSIOF1_1),
PINMUX_IPSR_MSEL(IP12_11_8, AUDIO_CLKA_B, SEL_ADG_A_1),
@@ -1188,7 +1184,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP12_23_20, RIF1_D0_B, SEL_DRIF1_1),
PINMUX_IPSR_GPSR(IP12_23_20, ADIDATA),
- PINMUX_IPSR_GPSR(IP12_27_24, RTS1_N_TANS),
+ PINMUX_IPSR_GPSR(IP12_27_24, RTS1_N),
PINMUX_IPSR_MSEL(IP12_27_24, HRTS1_N_A, SEL_HSCIF1_0),
PINMUX_IPSR_MSEL(IP12_27_24, MSIOF1_TXD_B, SEL_MSIOF1_1),
PINMUX_IPSR_MSEL(IP12_27_24, TS_SDAT1_C, SEL_TSIF1_2),
@@ -1781,6 +1777,61 @@ static const unsigned int avb_avtp_capture_b_mux[] = {
AVB_AVTP_CAPTURE_B_MARK,
};
+/* - CAN ------------------------------------------------------------------ */
+static const unsigned int can0_data_a_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24),
+};
+static const unsigned int can0_data_a_mux[] = {
+ CAN0_TX_A_MARK, CAN0_RX_A_MARK,
+};
+static const unsigned int can0_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int can0_data_b_mux[] = {
+ CAN0_TX_B_MARK, CAN0_RX_B_MARK,
+};
+static const unsigned int can1_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 26),
+};
+static const unsigned int can1_data_mux[] = {
+ CAN1_TX_MARK, CAN1_RX_MARK,
+};
+
+/* - CAN Clock -------------------------------------------------------------- */
+static const unsigned int can_clk_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int can_clk_mux[] = {
+ CAN_CLK_MARK,
+};
+
+/* - CAN FD --------------------------------------------------------------- */
+static const unsigned int canfd0_data_a_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24),
+};
+static const unsigned int canfd0_data_a_mux[] = {
+ CANFD0_TX_A_MARK, CANFD0_RX_A_MARK,
+};
+static const unsigned int canfd0_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int canfd0_data_b_mux[] = {
+ CANFD0_TX_B_MARK, CANFD0_RX_B_MARK,
+};
+static const unsigned int canfd1_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 26),
+};
+static const unsigned int canfd1_data_mux[] = {
+ CANFD1_TX_MARK, CANFD1_RX_MARK,
+};
+
/* - DRIF0 --------------------------------------------------------------- */
static const unsigned int drif0_ctrl_a_pins[] = {
/* CLK, SYNC */
@@ -3176,6 +3227,22 @@ static const unsigned int pwm6_b_mux[] = {
PWM6_B_MARK,
};
+/* - SATA --------------------------------------------------------------------*/
+static const unsigned int sata0_devslp_a_pins[] = {
+ /* DEVSLP */
+ RCAR_GP_PIN(6, 16),
+};
+static const unsigned int sata0_devslp_a_mux[] = {
+ SATA_DEVSLP_A_MARK,
+};
+static const unsigned int sata0_devslp_b_pins[] = {
+ /* DEVSLP */
+ RCAR_GP_PIN(4, 6),
+};
+static const unsigned int sata0_devslp_b_mux[] = {
+ SATA_DEVSLP_B_MARK,
+};
+
/* - SCIF0 ------------------------------------------------------------------ */
static const unsigned int scif0_data_pins[] = {
/* RX, TX */
@@ -3196,7 +3263,7 @@ static const unsigned int scif0_ctrl_pins[] = {
RCAR_GP_PIN(5, 4), RCAR_GP_PIN(5, 3),
};
static const unsigned int scif0_ctrl_mux[] = {
- RTS0_N_TANS_MARK, CTS0_N_MARK,
+ RTS0_N_MARK, CTS0_N_MARK,
};
/* - SCIF1 ------------------------------------------------------------------ */
static const unsigned int scif1_data_a_pins[] = {
@@ -3218,7 +3285,7 @@ static const unsigned int scif1_ctrl_pins[] = {
RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 7),
};
static const unsigned int scif1_ctrl_mux[] = {
- RTS1_N_TANS_MARK, CTS1_N_MARK,
+ RTS1_N_MARK, CTS1_N_MARK,
};
static const unsigned int scif1_data_b_pins[] = {
@@ -3270,7 +3337,7 @@ static const unsigned int scif3_ctrl_pins[] = {
RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25),
};
static const unsigned int scif3_ctrl_mux[] = {
- RTS3_N_TANS_MARK, CTS3_N_MARK,
+ RTS3_N_MARK, CTS3_N_MARK,
};
static const unsigned int scif3_data_b_pins[] = {
/* RX, TX */
@@ -3299,7 +3366,7 @@ static const unsigned int scif4_ctrl_a_pins[] = {
RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
};
static const unsigned int scif4_ctrl_a_mux[] = {
- RTS4_N_TANS_A_MARK, CTS4_N_A_MARK,
+ RTS4_N_A_MARK, CTS4_N_A_MARK,
};
static const unsigned int scif4_data_b_pins[] = {
/* RX, TX */
@@ -3320,7 +3387,7 @@ static const unsigned int scif4_ctrl_b_pins[] = {
RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 9),
};
static const unsigned int scif4_ctrl_b_mux[] = {
- RTS4_N_TANS_B_MARK, CTS4_N_B_MARK,
+ RTS4_N_B_MARK, CTS4_N_B_MARK,
};
static const unsigned int scif4_data_c_pins[] = {
/* RX, TX */
@@ -3341,7 +3408,7 @@ static const unsigned int scif4_ctrl_c_pins[] = {
RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10),
};
static const unsigned int scif4_ctrl_c_mux[] = {
- RTS4_N_TANS_C_MARK, CTS4_N_C_MARK,
+ RTS4_N_C_MARK, CTS4_N_C_MARK,
};
/* - SCIF5 ------------------------------------------------------------------ */
static const unsigned int scif5_data_a_pins[] = {
@@ -3843,6 +3910,13 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(avb_avtp_capture_a),
SH_PFC_PIN_GROUP(avb_avtp_match_b),
SH_PFC_PIN_GROUP(avb_avtp_capture_b),
+ SH_PFC_PIN_GROUP(can0_data_a),
+ SH_PFC_PIN_GROUP(can0_data_b),
+ SH_PFC_PIN_GROUP(can1_data),
+ SH_PFC_PIN_GROUP(can_clk),
+ SH_PFC_PIN_GROUP(canfd0_data_a),
+ SH_PFC_PIN_GROUP(canfd0_data_b),
+ SH_PFC_PIN_GROUP(canfd1_data),
SH_PFC_PIN_GROUP(drif0_ctrl_a),
SH_PFC_PIN_GROUP(drif0_data0_a),
SH_PFC_PIN_GROUP(drif0_data1_a),
@@ -4034,6 +4108,8 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(pwm5_b),
SH_PFC_PIN_GROUP(pwm6_a),
SH_PFC_PIN_GROUP(pwm6_b),
+ SH_PFC_PIN_GROUP(sata0_devslp_a),
+ SH_PFC_PIN_GROUP(sata0_devslp_b),
SH_PFC_PIN_GROUP(scif0_data),
SH_PFC_PIN_GROUP(scif0_clk),
SH_PFC_PIN_GROUP(scif0_ctrl),
@@ -4154,6 +4230,28 @@ static const char * const avb_groups[] = {
"avb_avtp_capture_b",
};
+static const char * const can0_groups[] = {
+ "can0_data_a",
+ "can0_data_b",
+};
+
+static const char * const can1_groups[] = {
+ "can1_data",
+};
+
+static const char * const can_clk_groups[] = {
+ "can_clk",
+};
+
+static const char * const canfd0_groups[] = {
+ "canfd0_data_a",
+ "canfd0_data_b",
+};
+
+static const char * const canfd1_groups[] = {
+ "canfd1_data",
+};
+
static const char * const drif0_groups[] = {
"drif0_ctrl_a",
"drif0_data0_a",
@@ -4420,6 +4518,11 @@ static const char * const pwm6_groups[] = {
"pwm6_b",
};
+static const char * const sata0_groups[] = {
+ "sata0_devslp_a",
+ "sata0_devslp_b",
+};
+
static const char * const scif0_groups[] = {
"scif0_data",
"scif0_clk",
@@ -4559,6 +4662,11 @@ static const char * const usb30_groups[] = {
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
SH_PFC_FUNCTION(avb),
+ SH_PFC_FUNCTION(can0),
+ SH_PFC_FUNCTION(can1),
+ SH_PFC_FUNCTION(can_clk),
+ SH_PFC_FUNCTION(canfd0),
+ SH_PFC_FUNCTION(canfd1),
SH_PFC_FUNCTION(drif0),
SH_PFC_FUNCTION(drif1),
SH_PFC_FUNCTION(drif2),
@@ -4584,6 +4692,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(pwm4),
SH_PFC_FUNCTION(pwm5),
SH_PFC_FUNCTION(pwm6),
+ SH_PFC_FUNCTION(sata0),
SH_PFC_FUNCTION(scif0),
SH_PFC_FUNCTION(scif1),
SH_PFC_FUNCTION(scif2),
@@ -4644,7 +4753,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
0, 0,
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,
@@ -5246,7 +5355,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(1, 19), 0, 3 }, /* A19 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL8", 0xe6060320) {
- { PIN_NUMBER('F', 1), 28, 3 }, /* CLKOUT */
+ { RCAR_GP_PIN(1, 28), 28, 3 }, /* CLKOUT */
{ RCAR_GP_PIN(1, 20), 24, 3 }, /* CS0 */
{ RCAR_GP_PIN(1, 21), 20, 3 }, /* CS1_A26 */
{ RCAR_GP_PIN(1, 22), 16, 3 }, /* BS */
@@ -5342,11 +5451,11 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 3), 0, 3 }, /* CTS0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL18", 0xe6060348) {
- { RCAR_GP_PIN(5, 4), 28, 3 }, /* RTS0_TANS */
+ { RCAR_GP_PIN(5, 4), 28, 3 }, /* RTS0 */
{ RCAR_GP_PIN(5, 5), 24, 3 }, /* RX1 */
{ RCAR_GP_PIN(5, 6), 20, 3 }, /* TX1 */
{ RCAR_GP_PIN(5, 7), 16, 3 }, /* CTS1 */
- { RCAR_GP_PIN(5, 8), 12, 3 }, /* RTS1_TANS */
+ { RCAR_GP_PIN(5, 8), 12, 3 }, /* RTS1 */
{ RCAR_GP_PIN(5, 9), 8, 3 }, /* SCK2 */
{ RCAR_GP_PIN(5, 10), 4, 3 }, /* TX2 */
{ RCAR_GP_PIN(5, 11), 0, 3 }, /* RX2 */
@@ -5507,7 +5616,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[31] = RCAR_GP_PIN(1, 19), /* A19 */
} },
{ PINMUX_BIAS_REG("PUEN2", 0xe6060408, "PUD2", 0xe6060448) {
- [ 0] = PIN_NUMBER('F', 1), /* CLKOUT */
+ [ 0] = RCAR_GP_PIN(1, 28), /* CLKOUT */
[ 1] = RCAR_GP_PIN(1, 20), /* CS0_N */
[ 2] = RCAR_GP_PIN(1, 21), /* CS1_N */
[ 3] = RCAR_GP_PIN(1, 22), /* BS_N */
@@ -5591,11 +5700,11 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[13] = RCAR_GP_PIN(5, 1), /* RX0 */
[14] = RCAR_GP_PIN(5, 2), /* TX0 */
[15] = RCAR_GP_PIN(5, 3), /* CTS0_N */
- [16] = RCAR_GP_PIN(5, 4), /* RTS0_N_TANS */
+ [16] = RCAR_GP_PIN(5, 4), /* RTS0_N */
[17] = RCAR_GP_PIN(5, 5), /* RX1_A */
[18] = RCAR_GP_PIN(5, 6), /* TX1_A */
[19] = RCAR_GP_PIN(5, 7), /* CTS1_N */
- [20] = RCAR_GP_PIN(5, 8), /* RTS1_N_TANS */
+ [20] = RCAR_GP_PIN(5, 8), /* RTS1_N */
[21] = RCAR_GP_PIN(5, 9), /* SCK2 */
[22] = RCAR_GP_PIN(5, 10), /* TX2_A */
[23] = RCAR_GP_PIN(5, 11), /* RX2_A */
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
index 73ed9c74c137..e5807d1ce0dc 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
@@ -163,11 +163,11 @@
#define GPSR5_11 F_(RX2_A, IP13_7_4)
#define GPSR5_10 F_(TX2_A, IP13_3_0)
#define GPSR5_9 F_(SCK2, IP12_31_28)
-#define GPSR5_8 F_(RTS1_N_TANS, IP12_27_24)
+#define GPSR5_8 F_(RTS1_N, IP12_27_24)
#define GPSR5_7 F_(CTS1_N, IP12_23_20)
#define GPSR5_6 F_(TX1_A, IP12_19_16)
#define GPSR5_5 F_(RX1_A, IP12_15_12)
-#define GPSR5_4 F_(RTS0_N_TANS, IP12_11_8)
+#define GPSR5_4 F_(RTS0_N, IP12_11_8)
#define GPSR5_3 F_(CTS0_N, IP12_7_4)
#define GPSR5_2 F_(TX0, IP12_3_0)
#define GPSR5_1 F_(RX0, IP11_31_28)
@@ -220,16 +220,16 @@
#define IP0_11_8 FM(AVB_PHY_INT) F_(0, 0) FM(MSIOF2_SYNC_C) FM(RX4_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 IP0_15_12 FM(AVB_LINK) F_(0, 0) FM(MSIOF2_SCK_C) FM(TX4_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 IP0_19_16 FM(AVB_AVTP_MATCH_A) F_(0, 0) FM(MSIOF2_RXD_C) FM(CTS4_N_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 IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_TANS_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 IP0_23_20 FM(AVB_AVTP_CAPTURE_A) F_(0, 0) FM(MSIOF2_TXD_C) FM(RTS4_N_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 IP0_27_24 FM(IRQ0) FM(QPOLB) F_(0, 0) FM(DU_CDE) FM(VI4_DATA0_B) FM(CAN0_TX_B) FM(CANFD0_TX_B) FM(MSIOF3_SS2_E) 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 IP0_31_28 FM(IRQ1) FM(QPOLA) F_(0, 0) FM(DU_DISP) FM(VI4_DATA1_B) FM(CAN0_RX_B) FM(CANFD0_RX_B) FM(MSIOF3_SS1_E) 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 IP1_3_0 FM(IRQ2) FM(QCPV_QDE) F_(0, 0) FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(VI4_DATA2_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SYNC_E) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) FM(A25) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SCK_E) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) FM(A24) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) FM(MSIOF3_RXD_E) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_15_12 FM(IRQ5) FM(QSTB_QHE) FM(A23) FM(DU_EXVSYNC_DU_VSYNC) FM(VI4_DATA5_B) F_(0, 0) F_(0, 0) FM(MSIOF3_TXD_E) F_(0, 0) FM(PWM6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_19_16 FM(PWM0) FM(AVB_AVTP_PPS)FM(A22) F_(0, 0) FM(VI4_DATA6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IECLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_23_20 FM(PWM1_A) F_(0, 0) FM(A21) FM(HRX3_D) FM(VI4_DATA7_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IERX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_27_24 FM(PWM2_A) F_(0, 0) FM(A20) FM(HTX3_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IETX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_7_4 FM(IRQ3) FM(QSTVB_QVE) F_(0, 0) FM(DU_DOTCLKOUT1) FM(VI4_DATA3_B) F_(0, 0) F_(0, 0) FM(MSIOF3_SCK_E) F_(0, 0) FM(PWM4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_11_8 FM(IRQ4) FM(QSTH_QHS) F_(0, 0) FM(DU_EXHSYNC_DU_HSYNC) FM(VI4_DATA4_B) F_(0, 0) F_(0, 0) FM(MSIOF3_RXD_E) F_(0, 0) FM(PWM5_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_15_12 FM(IRQ5) FM(QSTB_QHE) F_(0, 0) FM(DU_EXVSYNC_DU_VSYNC) FM(VI4_DATA5_B) F_(0, 0) F_(0, 0) FM(MSIOF3_TXD_E) F_(0, 0) FM(PWM6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_19_16 FM(PWM0) FM(AVB_AVTP_PPS)F_(0, 0) F_(0, 0) FM(VI4_DATA6_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IECLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_23_20 FM(PWM1_A) F_(0, 0) F_(0, 0) FM(HRX3_D) FM(VI4_DATA7_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IERX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_27_24 FM(PWM2_A) F_(0, 0) F_(0, 0) FM(HTX3_D) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(IETX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_31_28 FM(A0) FM(LCDOUT16) FM(MSIOF3_SYNC_B) F_(0, 0) FM(VI4_DATA8) F_(0, 0) FM(DU_DB0) F_(0, 0) F_(0, 0) FM(PWM3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP2_3_0 FM(A1) FM(LCDOUT17) FM(MSIOF3_TXD_B) F_(0, 0) FM(VI4_DATA9) F_(0, 0) FM(DU_DB1) F_(0, 0) F_(0, 0) FM(PWM4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP2_7_4 FM(A2) FM(LCDOUT18) FM(MSIOF3_SCK_B) F_(0, 0) FM(VI4_DATA10) F_(0, 0) FM(DU_DB2) F_(0, 0) F_(0, 0) FM(PWM5_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -240,7 +240,7 @@
#define IP2_27_24 FM(A7) FM(LCDOUT23) FM(MSIOF2_SS2_A) FM(TX4_B) FM(VI4_DATA15) FM(VI5_DATA15) FM(DU_DB7) F_(0, 0) 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 IP2_31_28 FM(A8) FM(RX3_B) FM(MSIOF2_SYNC_A) FM(HRX4_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(SDA6_A) FM(AVB_AVTP_MATCH_B) FM(PWM1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP3_3_0 FM(A9) F_(0, 0) FM(MSIOF2_SCK_A) FM(CTS4_N_B) F_(0, 0) FM(VI5_VSYNC_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)
-#define IP3_7_4 FM(A10) F_(0, 0) FM(MSIOF2_RXD_A) FM(RTS4_N_TANS_B) F_(0, 0) FM(VI5_HSYNC_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)
+#define IP3_7_4 FM(A10) F_(0, 0) FM(MSIOF2_RXD_A) FM(RTS4_N_B) F_(0, 0) FM(VI5_HSYNC_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)
#define IP3_11_8 FM(A11) FM(TX3_B) FM(MSIOF2_TXD_A) FM(HTX4_B) FM(HSCK4) FM(VI5_FIELD) F_(0, 0) FM(SCL6_A) FM(AVB_AVTP_CAPTURE_B) FM(PWM2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */
@@ -258,7 +258,7 @@
#define IP4_27_24 FM(RD_N) F_(0, 0) FM(MSIOF3_SYNC_D) FM(RX3_A) FM(HRX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_TX_A) FM(CANFD0_TX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP4_31_28 FM(RD_WR_N) F_(0, 0) FM(MSIOF3_RXD_D) FM(TX3_A) FM(HTX3_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(CAN0_RX_A) FM(CANFD0_RX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP5_3_0 FM(WE0_N) F_(0, 0) FM(MSIOF3_TXD_D) FM(CTS3_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) FM(SCL6_B) FM(CAN_CLK) F_(0, 0) FM(IECLK_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP5_7_4 FM(WE1_N) F_(0, 0) FM(MSIOF3_SS1_D) FM(RTS3_N_TANS) FM(HRTS3_N) F_(0, 0) F_(0, 0) FM(SDA6_B) FM(CAN1_RX) FM(CANFD1_RX) FM(IERX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP5_7_4 FM(WE1_N) F_(0, 0) FM(MSIOF3_SS1_D) FM(RTS3_N) FM(HRTS3_N) F_(0, 0) F_(0, 0) FM(SDA6_B) FM(CAN1_RX) FM(CANFD1_RX) FM(IERX_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP5_11_8 FM(EX_WAIT0_A) FM(QCLK) F_(0, 0) F_(0, 0) FM(VI4_CLK) F_(0, 0) FM(DU_DOTCLKOUT0) F_(0, 0) 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 IP5_15_12 FM(D0) FM(MSIOF2_SS1_B)FM(MSIOF3_SCK_A) F_(0, 0) FM(VI4_DATA16) FM(VI5_DATA0) F_(0, 0) F_(0, 0) 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 IP5_19_16 FM(D1) FM(MSIOF2_SS2_B)FM(MSIOF3_SYNC_A) F_(0, 0) FM(VI4_DATA17) FM(VI5_DATA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -271,7 +271,7 @@
#define IP6_15_12 FM(D8) FM(LCDOUT0) FM(MSIOF2_SCK_D) FM(SCK4_C) FM(VI4_DATA0_A) F_(0, 0) FM(DU_DR0) F_(0, 0) 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 IP6_19_16 FM(D9) FM(LCDOUT1) FM(MSIOF2_SYNC_D) F_(0, 0) FM(VI4_DATA1_A) F_(0, 0) FM(DU_DR1) F_(0, 0) 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 IP6_23_20 FM(D10) FM(LCDOUT2) FM(MSIOF2_RXD_D) FM(HRX3_B) FM(VI4_DATA2_A) FM(CTS4_N_C) FM(DU_DR2) F_(0, 0) 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 IP6_27_24 FM(D11) FM(LCDOUT3) FM(MSIOF2_TXD_D) FM(HTX3_B) FM(VI4_DATA3_A) FM(RTS4_N_TANS_C)FM(DU_DR3) F_(0, 0) 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 IP6_27_24 FM(D11) FM(LCDOUT3) FM(MSIOF2_TXD_D) FM(HTX3_B) FM(VI4_DATA3_A) FM(RTS4_N_C) FM(DU_DR3) F_(0, 0) 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 IP6_31_28 FM(D12) FM(LCDOUT4) FM(MSIOF2_SS1_D) FM(RX4_C) FM(VI4_DATA4_A) F_(0, 0) FM(DU_DR4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C - F */
@@ -318,11 +318,11 @@
#define IP11_31_28 FM(RX0) FM(HRX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SCK0_C) FM(STP_ISCLK_0_C) FM(RIF0_D0_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)
#define IP12_3_0 FM(TX0) FM(HTX1_B) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SPSYNC0_C)FM(STP_ISSYNC_0_C) FM(RIF0_D1_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)
#define IP12_7_4 FM(CTS0_N) FM(HCTS1_N_B) FM(MSIOF1_SYNC_B) F_(0, 0) F_(0, 0) FM(TS_SPSYNC1_C)FM(STP_ISSYNC_1_C) FM(RIF1_SYNC_B) FM(AUDIO_CLKOUT_C) FM(ADICS_SAMP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP12_11_8 FM(RTS0_N_TANS) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) F_(0, 0) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_11_8 FM(RTS0_N) FM(HRTS1_N_B) FM(MSIOF1_SS1_B) FM(AUDIO_CLKA_B) FM(SCL2_A) F_(0, 0) FM(STP_IVCXO27_1_C) FM(RIF0_SYNC_B) F_(0, 0) FM(ADICHS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP12_15_12 FM(RX1_A) FM(HRX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDAT0_C) FM(STP_ISD_0_C) FM(RIF1_CLK_C) 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 IP12_19_16 FM(TX1_A) FM(HTX1_A) F_(0, 0) F_(0, 0) F_(0, 0) FM(TS_SDEN0_C) FM(STP_ISEN_0_C) FM(RIF1_D0_C) 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 IP12_23_20 FM(CTS1_N) FM(HCTS1_N_A) FM(MSIOF1_RXD_B) F_(0, 0) F_(0, 0) FM(TS_SDEN1_C) FM(STP_ISEN_1_C) FM(RIF1_D0_B) F_(0, 0) FM(ADIDATA) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP12_27_24 FM(RTS1_N_TANS) FM(HRTS1_N_A) FM(MSIOF1_TXD_B) F_(0, 0) F_(0, 0) FM(TS_SDAT1_C) FM(STP_ISD_1_C) FM(RIF1_D1_B) F_(0, 0) FM(ADICHS0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP12_27_24 FM(RTS1_N) FM(HRTS1_N_A) FM(MSIOF1_TXD_B) F_(0, 0) F_(0, 0) FM(TS_SDAT1_C) FM(STP_ISD_1_C) FM(RIF1_D1_B) F_(0, 0) FM(ADICHS0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP12_31_28 FM(SCK2) FM(SCIF_CLK_B) FM(MSIOF1_SCK_B) F_(0, 0) F_(0, 0) FM(TS_SCK1_C) FM(STP_ISCLK_1_C) FM(RIF1_CLK_B) F_(0, 0) FM(ADICLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP13_3_0 FM(TX2_A) F_(0, 0) F_(0, 0) FM(SD2_CD_B) FM(SCL1_A) F_(0, 0) FM(FMCLK_A) FM(RIF1_D1_C) F_(0, 0) FM(FSO_CFE_0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP13_7_4 FM(RX2_A) F_(0, 0) F_(0, 0) FM(SD2_WP_B) FM(SDA1_A) F_(0, 0) FM(FMIN_A) FM(RIF1_SYNC_C) F_(0, 0) FM(FSO_CFE_1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -626,7 +626,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP0_23_20, AVB_AVTP_CAPTURE_A, SEL_ETHERAVB_0),
PINMUX_IPSR_MSEL(IP0_23_20, MSIOF2_TXD_C, SEL_MSIOF2_2),
- PINMUX_IPSR_MSEL(IP0_23_20, RTS4_N_TANS_A, SEL_SCIF4_0),
+ PINMUX_IPSR_MSEL(IP0_23_20, RTS4_N_A, SEL_SCIF4_0),
PINMUX_IPSR_GPSR(IP0_27_24, IRQ0),
PINMUX_IPSR_GPSR(IP0_27_24, QPOLB),
@@ -654,7 +654,6 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_7_4, IRQ3),
PINMUX_IPSR_GPSR(IP1_7_4, QSTVB_QVE),
- PINMUX_IPSR_GPSR(IP1_7_4, A25),
PINMUX_IPSR_GPSR(IP1_7_4, DU_DOTCLKOUT1),
PINMUX_IPSR_MSEL(IP1_7_4, VI4_DATA3_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_7_4, PWM4_B, SEL_PWM4_1),
@@ -662,7 +661,6 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_11_8, IRQ4),
PINMUX_IPSR_GPSR(IP1_11_8, QSTH_QHS),
- PINMUX_IPSR_GPSR(IP1_11_8, A24),
PINMUX_IPSR_GPSR(IP1_11_8, DU_EXHSYNC_DU_HSYNC),
PINMUX_IPSR_MSEL(IP1_11_8, VI4_DATA4_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_11_8, PWM5_B, SEL_PWM5_1),
@@ -670,7 +668,6 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_15_12, IRQ5),
PINMUX_IPSR_GPSR(IP1_15_12, QSTB_QHE),
- PINMUX_IPSR_GPSR(IP1_15_12, A23),
PINMUX_IPSR_GPSR(IP1_15_12, DU_EXVSYNC_DU_VSYNC),
PINMUX_IPSR_MSEL(IP1_15_12, VI4_DATA5_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_15_12, PWM6_B, SEL_PWM6_1),
@@ -678,18 +675,15 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP1_19_16, PWM0),
PINMUX_IPSR_GPSR(IP1_19_16, AVB_AVTP_PPS),
- PINMUX_IPSR_GPSR(IP1_19_16, A22),
PINMUX_IPSR_MSEL(IP1_19_16, VI4_DATA6_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_19_16, IECLK_B, SEL_IEBUS_1),
PINMUX_IPSR_MSEL(IP1_23_20, PWM1_A, SEL_PWM1_0),
- PINMUX_IPSR_GPSR(IP1_23_20, A21),
PINMUX_IPSR_MSEL(IP1_23_20, HRX3_D, SEL_HSCIF3_3),
PINMUX_IPSR_MSEL(IP1_23_20, VI4_DATA7_B, SEL_VIN4_1),
PINMUX_IPSR_MSEL(IP1_23_20, IERX_B, SEL_IEBUS_1),
PINMUX_IPSR_MSEL(IP1_27_24, PWM2_A, SEL_PWM2_0),
- PINMUX_IPSR_GPSR(IP1_27_24, A20),
PINMUX_IPSR_MSEL(IP1_27_24, HTX3_D, SEL_HSCIF3_3),
PINMUX_IPSR_MSEL(IP1_27_24, IETX_B, SEL_IEBUS_1),
@@ -769,7 +763,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP3_7_4, A10),
PINMUX_IPSR_MSEL(IP3_7_4, MSIOF2_RXD_A, SEL_MSIOF2_0),
- PINMUX_IPSR_MSEL(IP3_7_4, RTS4_N_TANS_B, SEL_SCIF4_1),
+ PINMUX_IPSR_MSEL(IP3_7_4, RTS4_N_B, SEL_SCIF4_1),
PINMUX_IPSR_GPSR(IP3_7_4, VI5_HSYNC_N),
PINMUX_IPSR_GPSR(IP3_11_8, A11),
@@ -872,7 +866,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP5_7_4, WE1_N),
PINMUX_IPSR_MSEL(IP5_7_4, MSIOF3_SS1_D, SEL_MSIOF3_3),
- PINMUX_IPSR_GPSR(IP5_7_4, RTS3_N_TANS),
+ PINMUX_IPSR_GPSR(IP5_7_4, RTS3_N),
PINMUX_IPSR_GPSR(IP5_7_4, HRTS3_N),
PINMUX_IPSR_MSEL(IP5_7_4, SDA6_B, SEL_I2C6_1),
PINMUX_IPSR_GPSR(IP5_7_4, CAN1_RX),
@@ -953,7 +947,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP6_27_24, MSIOF2_TXD_D, SEL_MSIOF2_3),
PINMUX_IPSR_MSEL(IP6_27_24, HTX3_B, SEL_HSCIF3_1),
PINMUX_IPSR_MSEL(IP6_27_24, VI4_DATA3_A, SEL_VIN4_0),
- PINMUX_IPSR_MSEL(IP6_27_24, RTS4_N_TANS_C, SEL_SCIF4_2),
+ PINMUX_IPSR_MSEL(IP6_27_24, RTS4_N_C, SEL_SCIF4_2),
PINMUX_IPSR_GPSR(IP6_27_24, DU_DR3),
PINMUX_IPSR_GPSR(IP6_31_28, D12),
@@ -1161,7 +1155,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP12_7_4, AUDIO_CLKOUT_C),
PINMUX_IPSR_GPSR(IP12_7_4, ADICS_SAMP),
- PINMUX_IPSR_GPSR(IP12_11_8, RTS0_N_TANS),
+ PINMUX_IPSR_GPSR(IP12_11_8, RTS0_N),
PINMUX_IPSR_MSEL(IP12_11_8, HRTS1_N_B, SEL_HSCIF1_1),
PINMUX_IPSR_MSEL(IP12_11_8, MSIOF1_SS1_B, SEL_MSIOF1_1),
PINMUX_IPSR_MSEL(IP12_11_8, AUDIO_CLKA_B, SEL_ADG_A_1),
@@ -1190,7 +1184,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP12_23_20, RIF1_D0_B, SEL_DRIF1_1),
PINMUX_IPSR_GPSR(IP12_23_20, ADIDATA),
- PINMUX_IPSR_GPSR(IP12_27_24, RTS1_N_TANS),
+ PINMUX_IPSR_GPSR(IP12_27_24, RTS1_N),
PINMUX_IPSR_MSEL(IP12_27_24, HRTS1_N_A, SEL_HSCIF1_0),
PINMUX_IPSR_MSEL(IP12_27_24, MSIOF1_TXD_B, SEL_MSIOF1_1),
PINMUX_IPSR_MSEL(IP12_27_24, TS_SDAT1_C, SEL_TSIF1_2),
@@ -3255,7 +3249,7 @@ static const unsigned int scif0_ctrl_pins[] = {
RCAR_GP_PIN(5, 4), RCAR_GP_PIN(5, 3),
};
static const unsigned int scif0_ctrl_mux[] = {
- RTS0_N_TANS_MARK, CTS0_N_MARK,
+ RTS0_N_MARK, CTS0_N_MARK,
};
/* - SCIF1 ------------------------------------------------------------------ */
static const unsigned int scif1_data_a_pins[] = {
@@ -3277,7 +3271,7 @@ static const unsigned int scif1_ctrl_pins[] = {
RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 7),
};
static const unsigned int scif1_ctrl_mux[] = {
- RTS1_N_TANS_MARK, CTS1_N_MARK,
+ RTS1_N_MARK, CTS1_N_MARK,
};
static const unsigned int scif1_data_b_pins[] = {
@@ -3329,7 +3323,7 @@ static const unsigned int scif3_ctrl_pins[] = {
RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25),
};
static const unsigned int scif3_ctrl_mux[] = {
- RTS3_N_TANS_MARK, CTS3_N_MARK,
+ RTS3_N_MARK, CTS3_N_MARK,
};
static const unsigned int scif3_data_b_pins[] = {
/* RX, TX */
@@ -3358,7 +3352,7 @@ static const unsigned int scif4_ctrl_a_pins[] = {
RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
};
static const unsigned int scif4_ctrl_a_mux[] = {
- RTS4_N_TANS_A_MARK, CTS4_N_A_MARK,
+ RTS4_N_A_MARK, CTS4_N_A_MARK,
};
static const unsigned int scif4_data_b_pins[] = {
/* RX, TX */
@@ -3379,7 +3373,7 @@ static const unsigned int scif4_ctrl_b_pins[] = {
RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 9),
};
static const unsigned int scif4_ctrl_b_mux[] = {
- RTS4_N_TANS_B_MARK, CTS4_N_B_MARK,
+ RTS4_N_B_MARK, CTS4_N_B_MARK,
};
static const unsigned int scif4_data_c_pins[] = {
/* RX, TX */
@@ -3400,7 +3394,7 @@ static const unsigned int scif4_ctrl_c_pins[] = {
RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10),
};
static const unsigned int scif4_ctrl_c_mux[] = {
- RTS4_N_TANS_C_MARK, CTS4_N_C_MARK,
+ RTS4_N_C_MARK, CTS4_N_C_MARK,
};
/* - SCIF5 ------------------------------------------------------------------ */
static const unsigned int scif5_data_a_pins[] = {
@@ -5406,11 +5400,11 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 3), 0, 3 }, /* CTS0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL18", 0xe6060348) {
- { RCAR_GP_PIN(5, 4), 28, 3 }, /* RTS0_TANS */
+ { RCAR_GP_PIN(5, 4), 28, 3 }, /* RTS0 */
{ RCAR_GP_PIN(5, 5), 24, 3 }, /* RX1 */
{ RCAR_GP_PIN(5, 6), 20, 3 }, /* TX1 */
{ RCAR_GP_PIN(5, 7), 16, 3 }, /* CTS1 */
- { RCAR_GP_PIN(5, 8), 12, 3 }, /* RTS1_TANS */
+ { RCAR_GP_PIN(5, 8), 12, 3 }, /* RTS1 */
{ RCAR_GP_PIN(5, 9), 8, 3 }, /* SCK2 */
{ RCAR_GP_PIN(5, 10), 4, 3 }, /* TX2 */
{ RCAR_GP_PIN(5, 11), 0, 3 }, /* RX2 */
@@ -5655,11 +5649,11 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[13] = RCAR_GP_PIN(5, 1), /* RX0 */
[14] = RCAR_GP_PIN(5, 2), /* TX0 */
[15] = RCAR_GP_PIN(5, 3), /* CTS0_N */
- [16] = RCAR_GP_PIN(5, 4), /* RTS0_N_TANS */
+ [16] = RCAR_GP_PIN(5, 4), /* RTS0_N */
[17] = RCAR_GP_PIN(5, 5), /* RX1_A */
[18] = RCAR_GP_PIN(5, 6), /* TX1_A */
[19] = RCAR_GP_PIN(5, 7), /* CTS1_N */
- [20] = RCAR_GP_PIN(5, 8), /* RTS1_N_TANS */
+ [20] = RCAR_GP_PIN(5, 8), /* RTS1_N */
[21] = RCAR_GP_PIN(5, 9), /* SCK2 */
[22] = RCAR_GP_PIN(5, 10), /* TX2_A */
[23] = RCAR_GP_PIN(5, 11), /* RX2_A */
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c
new file mode 100644
index 000000000000..794f12d74449
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c
@@ -0,0 +1,2329 @@
+/*
+ * R8A77970 processor support - PFC hardware block.
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ * Copyright (C) 2017 Cogent Embedded, Inc. <source@cogentembedded.com>
+ *
+ * This file is based on the drivers/pinctrl/sh-pfc/pfc-r8a7795.c
+ *
+ * R-Car Gen3 processor support - PFC hardware block.
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include "core.h"
+#include "sh_pfc.h"
+
+#define CPU_ALL_PORT(fn, sfx) \
+ PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PORT_GP_CFG_17(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PORT_GP_CFG_6(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PORT_GP_CFG_15(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH)
+/*
+ * F_() : just information
+ * FM() : macro for FN_xxx / xxx_MARK
+ */
+
+/* GPSR0 */
+#define GPSR0_21 F_(DU_EXODDF_DU_ODDF_DISP_CDE, IP2_23_20)
+#define GPSR0_20 F_(DU_EXVSYNC_DU_VSYNC, IP2_19_16)
+#define GPSR0_19 F_(DU_EXHSYNC_DU_HSYNC, IP2_15_12)
+#define GPSR0_18 F_(DU_DOTCLKOUT, IP2_11_8)
+#define GPSR0_17 F_(DU_DB7, IP2_7_4)
+#define GPSR0_16 F_(DU_DB6, IP2_3_0)
+#define GPSR0_15 F_(DU_DB5, IP1_31_28)
+#define GPSR0_14 F_(DU_DB4, IP1_27_24)
+#define GPSR0_13 F_(DU_DB3, IP1_23_20)
+#define GPSR0_12 F_(DU_DB2, IP1_19_16)
+#define GPSR0_11 F_(DU_DG7, IP1_15_12)
+#define GPSR0_10 F_(DU_DG6, IP1_11_8)
+#define GPSR0_9 F_(DU_DG5, IP1_7_4)
+#define GPSR0_8 F_(DU_DG4, IP1_3_0)
+#define GPSR0_7 F_(DU_DG3, IP0_31_28)
+#define GPSR0_6 F_(DU_DG2, IP0_27_24)
+#define GPSR0_5 F_(DU_DR7, IP0_23_20)
+#define GPSR0_4 F_(DU_DR6, IP0_19_16)
+#define GPSR0_3 F_(DU_DR5, IP0_15_12)
+#define GPSR0_2 F_(DU_DR4, IP0_11_8)
+#define GPSR0_1 F_(DU_DR3, IP0_7_4)
+#define GPSR0_0 F_(DU_DR2, IP0_3_0)
+
+/* GPSR1 */
+#define GPSR1_27 F_(DIGRF_CLKOUT, IP8_27_24)
+#define GPSR1_26 F_(DIGRF_CLKIN, IP8_23_20)
+#define GPSR1_25 F_(CANFD_CLK_A, IP8_19_16)
+#define GPSR1_24 F_(CANFD1_RX, IP8_15_12)
+#define GPSR1_23 F_(CANFD1_TX, IP8_11_8)
+#define GPSR1_22 F_(CANFD0_RX_A, IP8_7_4)
+#define GPSR1_21 F_(CANFD0_TX_A, IP8_3_0)
+#define GPSR1_20 F_(AVB0_AVTP_CAPTURE, IP7_31_28)
+#define GPSR1_19 FM(AVB0_AVTP_MATCH)
+#define GPSR1_18 FM(AVB0_LINK)
+#define GPSR1_17 FM(AVB0_PHY_INT)
+#define GPSR1_16 FM(AVB0_MAGIC)
+#define GPSR1_15 FM(AVB0_MDC)
+#define GPSR1_14 FM(AVB0_MDIO)
+#define GPSR1_13 FM(AVB0_TXCREFCLK)
+#define GPSR1_12 FM(AVB0_TD3)
+#define GPSR1_11 FM(AVB0_TD2)
+#define GPSR1_10 FM(AVB0_TD1)
+#define GPSR1_9 FM(AVB0_TD0)
+#define GPSR1_8 FM(AVB0_TXC)
+#define GPSR1_7 FM(AVB0_TX_CTL)
+#define GPSR1_6 FM(AVB0_RD3)
+#define GPSR1_5 FM(AVB0_RD2)
+#define GPSR1_4 FM(AVB0_RD1)
+#define GPSR1_3 FM(AVB0_RD0)
+#define GPSR1_2 FM(AVB0_RXC)
+#define GPSR1_1 FM(AVB0_RX_CTL)
+#define GPSR1_0 F_(IRQ0, IP2_27_24)
+
+/* GPSR2 */
+#define GPSR2_16 F_(VI0_FIELD, IP4_31_28)
+#define GPSR2_15 F_(VI0_DATA11, IP4_27_24)
+#define GPSR2_14 F_(VI0_DATA10, IP4_23_20)
+#define GPSR2_13 F_(VI0_DATA9, IP4_19_16)
+#define GPSR2_12 F_(VI0_DATA8, IP4_15_12)
+#define GPSR2_11 F_(VI0_DATA7, IP4_11_8)
+#define GPSR2_10 F_(VI0_DATA6, IP4_7_4)
+#define GPSR2_9 F_(VI0_DATA5, IP4_3_0)
+#define GPSR2_8 F_(VI0_DATA4, IP3_31_28)
+#define GPSR2_7 F_(VI0_DATA3, IP3_27_24)
+#define GPSR2_6 F_(VI0_DATA2, IP3_23_20)
+#define GPSR2_5 F_(VI0_DATA1, IP3_19_16)
+#define GPSR2_4 F_(VI0_DATA0, IP3_15_12)
+#define GPSR2_3 F_(VI0_VSYNC_N, IP3_11_8)
+#define GPSR2_2 F_(VI0_HSYNC_N, IP3_7_4)
+#define GPSR2_1 F_(VI0_CLKENB, IP3_3_0)
+#define GPSR2_0 F_(VI0_CLK, IP2_31_28)
+
+/* GPSR3 */
+#define GPSR3_16 F_(VI1_FIELD, IP7_3_0)
+#define GPSR3_15 F_(VI1_DATA11, IP6_31_28)
+#define GPSR3_14 F_(VI1_DATA10, IP6_27_24)
+#define GPSR3_13 F_(VI1_DATA9, IP6_23_20)
+#define GPSR3_12 F_(VI1_DATA8, IP6_19_16)
+#define GPSR3_11 F_(VI1_DATA7, IP6_15_12)
+#define GPSR3_10 F_(VI1_DATA6, IP6_11_8)
+#define GPSR3_9 F_(VI1_DATA5, IP6_7_4)
+#define GPSR3_8 F_(VI1_DATA4, IP6_3_0)
+#define GPSR3_7 F_(VI1_DATA3, IP5_31_28)
+#define GPSR3_6 F_(VI1_DATA2, IP5_27_24)
+#define GPSR3_5 F_(VI1_DATA1, IP5_23_20)
+#define GPSR3_4 F_(VI1_DATA0, IP5_19_16)
+#define GPSR3_3 F_(VI1_VSYNC_N, IP5_15_12)
+#define GPSR3_2 F_(VI1_HSYNC_N, IP5_11_8)
+#define GPSR3_1 F_(VI1_CLKENB, IP5_7_4)
+#define GPSR3_0 F_(VI1_CLK, IP5_3_0)
+
+/* GPSR4 */
+#define GPSR4_5 F_(SDA2, IP7_27_24)
+#define GPSR4_4 F_(SCL2, IP7_23_20)
+#define GPSR4_3 F_(SDA1, IP7_19_16)
+#define GPSR4_2 F_(SCL1, IP7_15_12)
+#define GPSR4_1 F_(SDA0, IP7_11_8)
+#define GPSR4_0 F_(SCL0, IP7_7_4)
+
+/* GPSR5 */
+#define GPSR5_14 FM(RPC_INT_N)
+#define GPSR5_13 FM(RPC_WP_N)
+#define GPSR5_12 FM(RPC_RESET_N)
+#define GPSR5_11 FM(QSPI1_SSL)
+#define GPSR5_10 FM(QSPI1_IO3)
+#define GPSR5_9 FM(QSPI1_IO2)
+#define GPSR5_8 FM(QSPI1_MISO_IO1)
+#define GPSR5_7 FM(QSPI1_MOSI_IO0)
+#define GPSR5_6 FM(QSPI1_SPCLK)
+#define GPSR5_5 FM(QSPI0_SSL)
+#define GPSR5_4 FM(QSPI0_IO3)
+#define GPSR5_3 FM(QSPI0_IO2)
+#define GPSR5_2 FM(QSPI0_MISO_IO1)
+#define GPSR5_1 FM(QSPI0_MOSI_IO0)
+#define GPSR5_0 FM(QSPI0_SPCLK)
+
+
+/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */
+#define IP0_3_0 FM(DU_DR2) FM(HSCK0) F_(0, 0) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_7_4 FM(DU_DR3) FM(HRTS0_N) F_(0, 0) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_11_8 FM(DU_DR4) FM(HCTS0_N) F_(0, 0) FM(A2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_15_12 FM(DU_DR5) FM(HTX0) F_(0, 0) FM(A3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_19_16 FM(DU_DR6) FM(MSIOF3_RXD) F_(0, 0) FM(A4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_23_20 FM(DU_DR7) FM(MSIOF3_TXD) F_(0, 0) FM(A5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_27_24 FM(DU_DG2) FM(MSIOF3_SS1) F_(0, 0) FM(A6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_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)
+#define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_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)
+#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_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)
+#define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP1_27_24 FM(DU_DB4) F_(0, 0) F_(0, 0) FM(A14) FM(FXR_CLKOUT2) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP1_31_28 FM(DU_DB5) F_(0, 0) F_(0, 0) FM(A15) FM(FXR_TXENA_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 IP2_3_0 FM(DU_DB6) F_(0, 0) F_(0, 0) FM(A16) 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)
+#define IP2_7_4 FM(DU_DB7) F_(0, 0) F_(0, 0) FM(A17) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP2_11_8 FM(DU_DOTCLKOUT) FM(SCIF_CLK_A) F_(0, 0) FM(A18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP2_15_12 FM(DU_EXHSYNC_DU_HSYNC) FM(HRX0) F_(0, 0) FM(A19) FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP2_19_16 FM(DU_EXVSYNC_DU_VSYNC) 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 IP2_23_20 FM(DU_EXODDF_DU_ODDF_DISP_CDE) 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 IP2_27_24 FM(IRQ0) 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) F_(0, 0)
+#define IP2_31_28 FM(VI0_CLK) FM(MSIOF2_SCK) FM(SCK3) F_(0, 0) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP3_3_0 FM(VI0_CLKENB) FM(MSIOF2_RXD) FM(RX3) FM(RD_WR_N) FM(HCTS3_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 IP3_7_4 FM(VI0_HSYNC_N) FM(MSIOF2_TXD) FM(TX3) F_(0, 0) FM(HRTS3_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 IP3_11_8 FM(VI0_VSYNC_N) FM(MSIOF2_SYNC) FM(CTS3_N) F_(0, 0) FM(HTX3) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP3_15_12 FM(VI0_DATA0) FM(MSIOF2_SS1) FM(RTS3_N_TANS) F_(0, 0) FM(HRX3) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP3_19_16 FM(VI0_DATA1) FM(MSIOF2_SS2) FM(SCK1) F_(0, 0) FM(SPEEDIN_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)
+#define IP3_23_20 FM(VI0_DATA2) FM(AVB0_AVTP_PPS) FM(SDA3_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 IP3_27_24 FM(VI0_DATA3) FM(HSCK1) FM(SCL3_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 IP3_31_28 FM(VI0_DATA4) FM(HRTS1_N) FM(RX1_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 IP4_3_0 FM(VI0_DATA5) FM(HCTS1_N) FM(TX1_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 IP4_7_4 FM(VI0_DATA6) FM(HTX1) 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 IP4_11_8 FM(VI0_DATA7) FM(HRX1) FM(RTS1_N_TANS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP4_15_12 FM(VI0_DATA8) FM(HSCK2) FM(PWM0_A) FM(A22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP4_19_16 FM(VI0_DATA9) FM(HCTS2_N) FM(PWM1_A) FM(A23) FM(FSO_CFE_0_N_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)
+#define IP4_23_20 FM(VI0_DATA10) FM(HRTS2_N) FM(PWM2_A) FM(A24) FM(FSO_CFE_1_N_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)
+#define IP4_27_24 FM(VI0_DATA11) FM(HTX2) FM(PWM3_A) FM(A25) FM(FSO_TOE_N_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)
+#define IP4_31_28 FM(VI0_FIELD) FM(HRX2) FM(PWM4_A) FM(CS1_N) FM(FSCLKST2_N_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)
+#define IP5_3_0 FM(VI1_CLK) FM(MSIOF1_RXD) F_(0, 0) FM(CS0_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)
+#define IP5_7_4 FM(VI1_CLKENB) FM(MSIOF1_TXD) F_(0, 0) FM(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)
+#define IP5_11_8 FM(VI1_HSYNC_N) FM(MSIOF1_SCK) F_(0, 0) FM(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)
+#define IP5_15_12 FM(VI1_VSYNC_N) FM(MSIOF1_SYNC) F_(0, 0) FM(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)
+#define IP5_19_16 FM(VI1_DATA0) FM(MSIOF1_SS1) F_(0, 0) FM(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)
+#define IP5_23_20 FM(VI1_DATA1) FM(MSIOF1_SS2) F_(0, 0) FM(D4) FM(MMC_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)
+#define IP5_27_24 FM(VI1_DATA2) FM(CANFD0_TX_B) F_(0, 0) FM(D5) FM(MMC_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)
+#define IP5_31_28 FM(VI1_DATA3) FM(CANFD0_RX_B) F_(0, 0) FM(D6) FM(MMC_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)
+#define IP6_3_0 FM(VI1_DATA4) FM(CANFD_CLK_B) F_(0, 0) FM(D7) FM(MMC_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)
+#define IP6_7_4 FM(VI1_DATA5) F_(0,0) FM(SCK4) FM(D8) FM(MMC_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)
+#define IP6_11_8 FM(VI1_DATA6) F_(0,0) FM(RX4) FM(D9) FM(MMC_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)
+#define IP6_15_12 FM(VI1_DATA7) F_(0,0) FM(TX4) FM(D10) 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)
+#define IP6_19_16 FM(VI1_DATA8) F_(0,0) FM(CTS4_N) FM(D11) 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)
+#define IP6_23_20 FM(VI1_DATA9) F_(0,0) FM(RTS4_N_TANS) FM(D12) FM(MMC_D6) FM(SCL3_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)
+#define IP6_27_24 FM(VI1_DATA10) F_(0,0) F_(0, 0) FM(D13) FM(MMC_D7) FM(SDA3_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)
+#define IP6_31_28 FM(VI1_DATA11) FM(SCL4) FM(IRQ4) FM(D14) FM(MMC_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)
+#define IP7_3_0 FM(VI1_FIELD) FM(SDA4) FM(IRQ5) FM(D15) FM(MMC_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)
+#define IP7_7_4 FM(SCL0) FM(DU_DR0) FM(TPU0TO0) FM(CLKOUT) F_(0, 0) 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)
+#define IP7_11_8 FM(SDA0) FM(DU_DR1) FM(TPU0TO1) FM(BS_N) FM(SCK0) FM(MSIOF0_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)
+#define IP7_15_12 FM(SCL1) FM(DU_DG0) FM(TPU0TO2) FM(RD_N) FM(CTS0_N) FM(MSIOF0_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)
+#define IP7_19_16 FM(SDA1) FM(DU_DG1) FM(TPU0TO3) FM(WE0_N) FM(RTS0_N_TANS) FM(MSIOF0_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)
+#define IP7_23_20 FM(SCL2) FM(DU_DB0) FM(TCLK1_A) FM(WE1_N) FM(RX0) FM(MSIOF0_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)
+#define IP7_27_24 FM(SDA2) FM(DU_DB1) FM(TCLK2_A) FM(EX_WAIT0) FM(TX0) FM(MSIOF0_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)
+#define IP7_31_28 FM(AVB0_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) FM(FSCLKST2_N_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)
+#define IP8_3_0 FM(CANFD0_TX_A) FM(FXR_TXDA) FM(PWM0_B) FM(DU_DISP) FM(FSCLKST2_N_C) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP8_7_4 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP8_11_8 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_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)
+#define IP8_15_12 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_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)
+#define IP8_19_16 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_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)
+#define IP8_23_20 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP8_27_24 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP8_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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_27 \
+ GPSR1_26 \
+ GPSR1_25 \
+ GPSR1_24 \
+ GPSR1_23 \
+ GPSR1_22 \
+GPSR0_21 GPSR1_21 \
+GPSR0_20 GPSR1_20 \
+GPSR0_19 GPSR1_19 \
+GPSR0_18 GPSR1_18 \
+GPSR0_17 GPSR1_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 GPSR5_14 \
+GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR5_13 \
+GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR5_12 \
+GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR5_11 \
+GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR5_10 \
+GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR5_9 \
+GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR5_8 \
+GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR5_7 \
+GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR5_6 \
+GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 \
+GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 \
+GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 \
+GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 \
+GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 \
+GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0
+
+#define PINMUX_IPSR \
+\
+FM(IP0_3_0) IP0_3_0 FM(IP1_3_0) IP1_3_0 FM(IP2_3_0) IP2_3_0 FM(IP3_3_0) IP3_3_0 \
+FM(IP0_7_4) IP0_7_4 FM(IP1_7_4) IP1_7_4 FM(IP2_7_4) IP2_7_4 FM(IP3_7_4) IP3_7_4 \
+FM(IP0_11_8) IP0_11_8 FM(IP1_11_8) IP1_11_8 FM(IP2_11_8) IP2_11_8 FM(IP3_11_8) IP3_11_8 \
+FM(IP0_15_12) IP0_15_12 FM(IP1_15_12) IP1_15_12 FM(IP2_15_12) IP2_15_12 FM(IP3_15_12) IP3_15_12 \
+FM(IP0_19_16) IP0_19_16 FM(IP1_19_16) IP1_19_16 FM(IP2_19_16) IP2_19_16 FM(IP3_19_16) IP3_19_16 \
+FM(IP0_23_20) IP0_23_20 FM(IP1_23_20) IP1_23_20 FM(IP2_23_20) IP2_23_20 FM(IP3_23_20) IP3_23_20 \
+FM(IP0_27_24) IP0_27_24 FM(IP1_27_24) IP1_27_24 FM(IP2_27_24) IP2_27_24 FM(IP3_27_24) IP3_27_24 \
+FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_31_28) IP3_31_28 \
+\
+FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \
+FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \
+FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \
+FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \
+FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \
+FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \
+FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \
+FM(IP4_31_28) IP4_31_28 FM(IP5_31_28) IP5_31_28 FM(IP6_31_28) IP6_31_28 FM(IP7_31_28) IP7_31_28 \
+\
+FM(IP8_3_0) IP8_3_0 \
+FM(IP8_7_4) IP8_7_4 \
+FM(IP8_11_8) IP8_11_8 \
+FM(IP8_15_12) IP8_15_12 \
+FM(IP8_19_16) IP8_19_16 \
+FM(IP8_23_20) IP8_23_20 \
+FM(IP8_27_24) IP8_27_24 \
+FM(IP8_31_28) IP8_31_28
+
+/* MOD_SEL0 */ /* 0 */ /* 1 */
+#define MOD_SEL0_11 FM(SEL_I2C3_0) FM(SEL_I2C3_1)
+#define MOD_SEL0_10 FM(SEL_HSCIF0_0) FM(SEL_HSCIF0_1)
+#define MOD_SEL0_9 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1)
+#define MOD_SEL0_8 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1)
+#define MOD_SEL0_7 FM(SEL_PWM4_0) FM(SEL_PWM4_1)
+#define MOD_SEL0_6 FM(SEL_PWM3_0) FM(SEL_PWM3_1)
+#define MOD_SEL0_5 FM(SEL_PWM2_0) FM(SEL_PWM2_1)
+#define MOD_SEL0_4 FM(SEL_PWM1_0) FM(SEL_PWM1_1)
+#define MOD_SEL0_3 FM(SEL_PWM0_0) FM(SEL_PWM0_1)
+#define MOD_SEL0_2 FM(SEL_RFSO_0) FM(SEL_RFSO_1)
+#define MOD_SEL0_1 FM(SEL_RSP_0) FM(SEL_RSP_1)
+#define MOD_SEL0_0 FM(SEL_TMU_0) FM(SEL_TMU_1)
+
+#define PINMUX_MOD_SELS \
+\
+MOD_SEL0_11 \
+MOD_SEL0_10 \
+MOD_SEL0_9 \
+MOD_SEL0_8 \
+MOD_SEL0_7 \
+MOD_SEL0_6 \
+MOD_SEL0_5 \
+MOD_SEL0_4 \
+MOD_SEL0_3 \
+MOD_SEL0_2 \
+MOD_SEL0_1 \
+MOD_SEL0_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(AVB0_RX_CTL),
+ PINMUX_SINGLE(AVB0_RXC),
+ PINMUX_SINGLE(AVB0_RD0),
+ PINMUX_SINGLE(AVB0_RD1),
+ PINMUX_SINGLE(AVB0_RD2),
+ PINMUX_SINGLE(AVB0_RD3),
+ PINMUX_SINGLE(AVB0_TX_CTL),
+ PINMUX_SINGLE(AVB0_TXC),
+ PINMUX_SINGLE(AVB0_TD0),
+ PINMUX_SINGLE(AVB0_TD1),
+ PINMUX_SINGLE(AVB0_TD2),
+ PINMUX_SINGLE(AVB0_TD3),
+ PINMUX_SINGLE(AVB0_TXCREFCLK),
+ PINMUX_SINGLE(AVB0_MDIO),
+ PINMUX_SINGLE(AVB0_MDC),
+ PINMUX_SINGLE(AVB0_MAGIC),
+ PINMUX_SINGLE(AVB0_PHY_INT),
+ PINMUX_SINGLE(AVB0_LINK),
+ PINMUX_SINGLE(AVB0_AVTP_MATCH),
+
+ PINMUX_SINGLE(QSPI0_SPCLK),
+ PINMUX_SINGLE(QSPI0_MOSI_IO0),
+ PINMUX_SINGLE(QSPI0_MISO_IO1),
+ PINMUX_SINGLE(QSPI0_IO2),
+ PINMUX_SINGLE(QSPI0_IO3),
+ PINMUX_SINGLE(QSPI0_SSL),
+ PINMUX_SINGLE(QSPI1_SPCLK),
+ PINMUX_SINGLE(QSPI1_MOSI_IO0),
+ PINMUX_SINGLE(QSPI1_MISO_IO1),
+ PINMUX_SINGLE(QSPI1_IO2),
+ PINMUX_SINGLE(QSPI1_IO3),
+ PINMUX_SINGLE(QSPI1_SSL),
+ PINMUX_SINGLE(RPC_RESET_N),
+ PINMUX_SINGLE(RPC_WP_N),
+ PINMUX_SINGLE(RPC_INT_N),
+
+ /* IPSR0 */
+ PINMUX_IPSR_GPSR(IP0_3_0, DU_DR2),
+ PINMUX_IPSR_GPSR(IP0_3_0, HSCK0),
+ PINMUX_IPSR_GPSR(IP0_3_0, A0),
+
+ PINMUX_IPSR_GPSR(IP0_7_4, DU_DR3),
+ PINMUX_IPSR_GPSR(IP0_7_4, HRTS0_N),
+ PINMUX_IPSR_GPSR(IP0_7_4, A1),
+
+ PINMUX_IPSR_GPSR(IP0_11_8, DU_DR4),
+ PINMUX_IPSR_GPSR(IP0_11_8, HCTS0_N),
+ PINMUX_IPSR_GPSR(IP0_11_8, A2),
+
+ PINMUX_IPSR_GPSR(IP0_15_12, DU_DR5),
+ PINMUX_IPSR_GPSR(IP0_15_12, HTX0),
+ PINMUX_IPSR_GPSR(IP0_15_12, A3),
+
+ PINMUX_IPSR_GPSR(IP0_19_16, DU_DR6),
+ PINMUX_IPSR_GPSR(IP0_19_16, MSIOF3_RXD),
+ PINMUX_IPSR_GPSR(IP0_19_16, A4),
+
+ PINMUX_IPSR_GPSR(IP0_23_20, DU_DR7),
+ PINMUX_IPSR_GPSR(IP0_23_20, MSIOF3_TXD),
+ PINMUX_IPSR_GPSR(IP0_23_20, A5),
+
+ PINMUX_IPSR_GPSR(IP0_27_24, DU_DG2),
+ PINMUX_IPSR_GPSR(IP0_27_24, MSIOF3_SS1),
+ PINMUX_IPSR_GPSR(IP0_27_24, A6),
+
+ PINMUX_IPSR_GPSR(IP0_31_28, DU_DG3),
+ PINMUX_IPSR_GPSR(IP0_31_28, MSIOF3_SS2),
+ PINMUX_IPSR_GPSR(IP0_31_28, A7),
+ PINMUX_IPSR_GPSR(IP0_31_28, PWMFSW0),
+
+ /* IPSR1 */
+ PINMUX_IPSR_GPSR(IP1_3_0, DU_DG4),
+ PINMUX_IPSR_GPSR(IP1_3_0, A8),
+ PINMUX_IPSR_MSEL(IP1_3_0, FSO_CFE_0_N_A, SEL_RFSO_0),
+
+ PINMUX_IPSR_GPSR(IP1_7_4, DU_DG5),
+ PINMUX_IPSR_GPSR(IP1_7_4, A9),
+ PINMUX_IPSR_MSEL(IP1_7_4, FSO_CFE_1_N_A, SEL_RFSO_0),
+
+ PINMUX_IPSR_GPSR(IP1_11_8, DU_DG6),
+ PINMUX_IPSR_GPSR(IP1_11_8, A10),
+ PINMUX_IPSR_MSEL(IP1_11_8, FSO_TOE_N_A, SEL_RFSO_0),
+
+ PINMUX_IPSR_GPSR(IP1_15_12, DU_DG7),
+ PINMUX_IPSR_GPSR(IP1_15_12, A11),
+ PINMUX_IPSR_GPSR(IP1_15_12, IRQ1),
+
+ PINMUX_IPSR_GPSR(IP1_19_16, DU_DB2),
+ PINMUX_IPSR_GPSR(IP1_19_16, A12),
+ PINMUX_IPSR_GPSR(IP1_19_16, IRQ2),
+
+ PINMUX_IPSR_GPSR(IP1_23_20, DU_DB3),
+ PINMUX_IPSR_GPSR(IP1_23_20, A13),
+ PINMUX_IPSR_GPSR(IP1_23_20, FXR_CLKOUT1),
+
+ PINMUX_IPSR_GPSR(IP1_27_24, DU_DB4),
+ PINMUX_IPSR_GPSR(IP1_27_24, A14),
+ PINMUX_IPSR_GPSR(IP1_27_24, FXR_CLKOUT2),
+
+ PINMUX_IPSR_GPSR(IP1_31_28, DU_DB5),
+ PINMUX_IPSR_GPSR(IP1_31_28, A15),
+ PINMUX_IPSR_GPSR(IP1_31_28, FXR_TXENA_N),
+
+ /* IPSR2 */
+ PINMUX_IPSR_GPSR(IP2_3_0, DU_DB6),
+ PINMUX_IPSR_GPSR(IP2_3_0, A16),
+ PINMUX_IPSR_GPSR(IP2_3_0, FXR_TXENB_N),
+
+ PINMUX_IPSR_GPSR(IP2_7_4, DU_DB7),
+ PINMUX_IPSR_GPSR(IP2_7_4, A17),
+
+ PINMUX_IPSR_GPSR(IP2_11_8, DU_DOTCLKOUT),
+ PINMUX_IPSR_MSEL(IP2_11_8, SCIF_CLK_A, SEL_HSCIF0_0),
+ PINMUX_IPSR_GPSR(IP2_11_8, A18),
+
+ PINMUX_IPSR_GPSR(IP2_15_12, DU_EXHSYNC_DU_HSYNC),
+ PINMUX_IPSR_GPSR(IP2_15_12, HRX0),
+ PINMUX_IPSR_GPSR(IP2_15_12, A19),
+ PINMUX_IPSR_GPSR(IP2_15_12, IRQ3),
+
+ PINMUX_IPSR_GPSR(IP2_19_16, DU_EXVSYNC_DU_VSYNC),
+ PINMUX_IPSR_GPSR(IP2_19_16, MSIOF3_SCK),
+
+ PINMUX_IPSR_GPSR(IP2_23_20, DU_EXODDF_DU_ODDF_DISP_CDE),
+ PINMUX_IPSR_GPSR(IP2_23_20, MSIOF3_SYNC),
+
+ PINMUX_IPSR_GPSR(IP2_27_24, IRQ0),
+ PINMUX_IPSR_GPSR(IP2_27_24, CC5_OSCOUT),
+
+ PINMUX_IPSR_GPSR(IP2_31_28, VI0_CLK),
+ PINMUX_IPSR_GPSR(IP2_31_28, MSIOF2_SCK),
+ PINMUX_IPSR_GPSR(IP2_31_28, SCK3),
+ PINMUX_IPSR_GPSR(IP2_31_28, HSCK3),
+
+ /* IPSR3 */
+ PINMUX_IPSR_GPSR(IP3_3_0, VI0_CLKENB),
+ PINMUX_IPSR_GPSR(IP3_3_0, MSIOF2_RXD),
+ PINMUX_IPSR_GPSR(IP3_3_0, RX3),
+ PINMUX_IPSR_GPSR(IP3_3_0, RD_WR_N),
+ PINMUX_IPSR_GPSR(IP3_3_0, HCTS3_N),
+
+ PINMUX_IPSR_GPSR(IP3_7_4, VI0_HSYNC_N),
+ PINMUX_IPSR_GPSR(IP3_7_4, MSIOF2_TXD),
+ PINMUX_IPSR_GPSR(IP3_7_4, TX3),
+ PINMUX_IPSR_GPSR(IP3_7_4, HRTS3_N),
+
+ PINMUX_IPSR_GPSR(IP3_11_8, VI0_VSYNC_N),
+ PINMUX_IPSR_GPSR(IP3_11_8, MSIOF2_SYNC),
+ PINMUX_IPSR_GPSR(IP3_11_8, CTS3_N),
+ PINMUX_IPSR_GPSR(IP3_11_8, HTX3),
+
+ PINMUX_IPSR_GPSR(IP3_15_12, VI0_DATA0),
+ PINMUX_IPSR_GPSR(IP3_15_12, MSIOF2_SS1),
+ PINMUX_IPSR_GPSR(IP3_15_12, RTS3_N_TANS),
+ PINMUX_IPSR_GPSR(IP3_15_12, HRX3),
+
+ PINMUX_IPSR_GPSR(IP3_19_16, VI0_DATA1),
+ PINMUX_IPSR_GPSR(IP3_19_16, MSIOF2_SS2),
+ PINMUX_IPSR_GPSR(IP3_19_16, SCK1),
+ PINMUX_IPSR_MSEL(IP3_19_16, SPEEDIN_A, SEL_RSP_0),
+
+ PINMUX_IPSR_GPSR(IP3_23_20, VI0_DATA2),
+ PINMUX_IPSR_GPSR(IP3_23_20, AVB0_AVTP_PPS),
+ PINMUX_IPSR_MSEL(IP3_23_20, SDA3_A, SEL_I2C3_0),
+
+ PINMUX_IPSR_GPSR(IP3_27_24, VI0_DATA3),
+ PINMUX_IPSR_GPSR(IP3_27_24, HSCK1),
+ PINMUX_IPSR_MSEL(IP3_27_24, SCL3_A, SEL_I2C3_0),
+
+ PINMUX_IPSR_GPSR(IP3_31_28, VI0_DATA4),
+ PINMUX_IPSR_GPSR(IP3_31_28, HRTS1_N),
+ PINMUX_IPSR_MSEL(IP3_31_28, RX1_A, SEL_SCIF1_0),
+
+ /* IPSR4 */
+ PINMUX_IPSR_GPSR(IP4_3_0, VI0_DATA5),
+ PINMUX_IPSR_GPSR(IP4_3_0, HCTS1_N),
+ PINMUX_IPSR_MSEL(IP4_3_0, TX1_A, SEL_SCIF1_0),
+
+ PINMUX_IPSR_GPSR(IP4_7_4, VI0_DATA6),
+ PINMUX_IPSR_GPSR(IP4_7_4, HTX1),
+ PINMUX_IPSR_GPSR(IP4_7_4, CTS1_N),
+
+ PINMUX_IPSR_GPSR(IP4_11_8, VI0_DATA7),
+ PINMUX_IPSR_GPSR(IP4_11_8, HRX1),
+ PINMUX_IPSR_GPSR(IP4_11_8, RTS1_N_TANS),
+
+ PINMUX_IPSR_GPSR(IP4_15_12, VI0_DATA8),
+ PINMUX_IPSR_GPSR(IP4_15_12, HSCK2),
+ PINMUX_IPSR_MSEL(IP4_15_12, PWM0_A, SEL_PWM0_0),
+
+ PINMUX_IPSR_GPSR(IP4_19_16, VI0_DATA9),
+ PINMUX_IPSR_GPSR(IP4_19_16, HCTS2_N),
+ PINMUX_IPSR_MSEL(IP4_19_16, PWM1_A, SEL_PWM1_0),
+ PINMUX_IPSR_MSEL(IP4_19_16, FSO_CFE_0_N_B, SEL_RFSO_1),
+
+ PINMUX_IPSR_GPSR(IP4_23_20, VI0_DATA10),
+ PINMUX_IPSR_GPSR(IP4_23_20, HRTS2_N),
+ PINMUX_IPSR_MSEL(IP4_23_20, PWM2_A, SEL_PWM2_0),
+ PINMUX_IPSR_MSEL(IP4_23_20, FSO_CFE_1_N_B, SEL_RFSO_1),
+
+ PINMUX_IPSR_GPSR(IP4_27_24, VI0_DATA11),
+ PINMUX_IPSR_GPSR(IP4_27_24, HTX2),
+ PINMUX_IPSR_MSEL(IP4_27_24, PWM3_A, SEL_PWM3_0),
+ PINMUX_IPSR_MSEL(IP4_27_24, FSO_TOE_N_B, SEL_RFSO_1),
+
+ PINMUX_IPSR_GPSR(IP4_31_28, VI0_FIELD),
+ PINMUX_IPSR_GPSR(IP4_31_28, HRX2),
+ PINMUX_IPSR_MSEL(IP4_31_28, PWM4_A, SEL_PWM4_0),
+ PINMUX_IPSR_GPSR(IP4_31_28, CS1_N),
+ PINMUX_IPSR_GPSR(IP4_31_28, FSCLKST2_N_A),
+
+ /* IPSR5 */
+ PINMUX_IPSR_GPSR(IP5_3_0, VI1_CLK),
+ PINMUX_IPSR_GPSR(IP5_3_0, MSIOF1_RXD),
+ PINMUX_IPSR_GPSR(IP5_3_0, CS0_N),
+
+ PINMUX_IPSR_GPSR(IP5_7_4, VI1_CLKENB),
+ PINMUX_IPSR_GPSR(IP5_7_4, MSIOF1_TXD),
+ PINMUX_IPSR_GPSR(IP5_7_4, D0),
+
+ PINMUX_IPSR_GPSR(IP5_11_8, VI1_HSYNC_N),
+ PINMUX_IPSR_GPSR(IP5_11_8, MSIOF1_SCK),
+ PINMUX_IPSR_GPSR(IP5_11_8, D1),
+
+ PINMUX_IPSR_GPSR(IP5_15_12, VI1_VSYNC_N),
+ PINMUX_IPSR_GPSR(IP5_15_12, MSIOF1_SYNC),
+ PINMUX_IPSR_GPSR(IP5_15_12, D2),
+
+ PINMUX_IPSR_GPSR(IP5_19_16, VI1_DATA0),
+ PINMUX_IPSR_GPSR(IP5_19_16, MSIOF1_SS1),
+ PINMUX_IPSR_GPSR(IP5_19_16, D3),
+
+ PINMUX_IPSR_GPSR(IP5_23_20, VI1_DATA1),
+ PINMUX_IPSR_GPSR(IP5_23_20, MSIOF1_SS2),
+ PINMUX_IPSR_GPSR(IP5_23_20, D4),
+ PINMUX_IPSR_GPSR(IP5_23_20, MMC_CMD),
+
+ PINMUX_IPSR_GPSR(IP5_27_24, VI1_DATA2),
+ PINMUX_IPSR_MSEL(IP5_27_24, CANFD0_TX_B, SEL_CANFD0_1),
+ PINMUX_IPSR_GPSR(IP5_27_24, D5),
+ PINMUX_IPSR_GPSR(IP5_27_24, MMC_D0),
+
+ PINMUX_IPSR_GPSR(IP5_31_28, VI1_DATA3),
+ PINMUX_IPSR_MSEL(IP5_31_28, CANFD0_RX_B, SEL_CANFD0_1),
+ PINMUX_IPSR_GPSR(IP5_31_28, D6),
+ PINMUX_IPSR_GPSR(IP5_31_28, MMC_D1),
+
+ /* IPSR6 */
+ PINMUX_IPSR_GPSR(IP6_3_0, VI1_DATA4),
+ PINMUX_IPSR_MSEL(IP6_3_0, CANFD_CLK_B, SEL_CANFD0_1),
+ PINMUX_IPSR_GPSR(IP6_3_0, D7),
+ PINMUX_IPSR_GPSR(IP6_3_0, MMC_D2),
+
+ PINMUX_IPSR_GPSR(IP6_7_4, VI1_DATA5),
+ PINMUX_IPSR_GPSR(IP6_7_4, SCK4),
+ PINMUX_IPSR_GPSR(IP6_7_4, D8),
+ PINMUX_IPSR_GPSR(IP6_7_4, MMC_D3),
+
+ PINMUX_IPSR_GPSR(IP6_11_8, VI1_DATA6),
+ PINMUX_IPSR_GPSR(IP6_11_8, RX4),
+ PINMUX_IPSR_GPSR(IP6_11_8, D9),
+ PINMUX_IPSR_GPSR(IP6_11_8, MMC_CLK),
+
+ PINMUX_IPSR_GPSR(IP6_15_12, VI1_DATA7),
+ PINMUX_IPSR_GPSR(IP6_15_12, TX4),
+ PINMUX_IPSR_GPSR(IP6_15_12, D10),
+ PINMUX_IPSR_GPSR(IP6_15_12, MMC_D4),
+
+ PINMUX_IPSR_GPSR(IP6_19_16, VI1_DATA8),
+ PINMUX_IPSR_GPSR(IP6_19_16, CTS4_N),
+ PINMUX_IPSR_GPSR(IP6_19_16, D11),
+ PINMUX_IPSR_GPSR(IP6_19_16, MMC_D5),
+
+ PINMUX_IPSR_GPSR(IP6_23_20, VI1_DATA9),
+ PINMUX_IPSR_GPSR(IP6_23_20, RTS4_N_TANS),
+ PINMUX_IPSR_GPSR(IP6_23_20, D12),
+ PINMUX_IPSR_GPSR(IP6_23_20, MMC_D6),
+ PINMUX_IPSR_MSEL(IP6_23_20, SCL3_B, SEL_I2C3_1),
+
+ PINMUX_IPSR_GPSR(IP6_27_24, VI1_DATA10),
+ PINMUX_IPSR_GPSR(IP6_27_24, D13),
+ PINMUX_IPSR_GPSR(IP6_27_24, MMC_D7),
+ PINMUX_IPSR_MSEL(IP6_27_24, SDA3_B, SEL_I2C3_1),
+
+ PINMUX_IPSR_GPSR(IP6_31_28, VI1_DATA11),
+ PINMUX_IPSR_GPSR(IP6_31_28, SCL4),
+ PINMUX_IPSR_GPSR(IP6_31_28, IRQ4),
+ PINMUX_IPSR_GPSR(IP6_31_28, D14),
+ PINMUX_IPSR_GPSR(IP6_31_28, MMC_WP),
+
+ /* IPSR7 */
+ PINMUX_IPSR_GPSR(IP7_3_0, VI1_FIELD),
+ PINMUX_IPSR_GPSR(IP7_3_0, SDA4),
+ PINMUX_IPSR_GPSR(IP7_3_0, IRQ5),
+ PINMUX_IPSR_GPSR(IP7_3_0, D15),
+ PINMUX_IPSR_GPSR(IP7_3_0, MMC_CD),
+
+ PINMUX_IPSR_GPSR(IP7_7_4, SCL0),
+ PINMUX_IPSR_GPSR(IP7_7_4, DU_DR0),
+ PINMUX_IPSR_GPSR(IP7_7_4, TPU0TO0),
+ PINMUX_IPSR_GPSR(IP7_7_4, CLKOUT),
+ PINMUX_IPSR_GPSR(IP7_7_4, MSIOF0_RXD),
+
+ PINMUX_IPSR_GPSR(IP7_11_8, SDA0),
+ PINMUX_IPSR_GPSR(IP7_11_8, DU_DR1),
+ PINMUX_IPSR_GPSR(IP7_11_8, TPU0TO1),
+ PINMUX_IPSR_GPSR(IP7_11_8, BS_N),
+ PINMUX_IPSR_GPSR(IP7_11_8, SCK0),
+ PINMUX_IPSR_GPSR(IP7_11_8, MSIOF0_TXD),
+
+ PINMUX_IPSR_GPSR(IP7_15_12, SCL1),
+ PINMUX_IPSR_GPSR(IP7_15_12, DU_DG0),
+ PINMUX_IPSR_GPSR(IP7_15_12, TPU0TO2),
+ PINMUX_IPSR_GPSR(IP7_15_12, RD_N),
+ PINMUX_IPSR_GPSR(IP7_15_12, CTS0_N),
+ PINMUX_IPSR_GPSR(IP7_15_12, MSIOF0_SCK),
+
+ PINMUX_IPSR_GPSR(IP7_19_16, SDA1),
+ PINMUX_IPSR_GPSR(IP7_19_16, DU_DG1),
+ PINMUX_IPSR_GPSR(IP7_19_16, TPU0TO3),
+ PINMUX_IPSR_GPSR(IP7_19_16, WE0_N),
+ PINMUX_IPSR_GPSR(IP7_19_16, RTS0_N_TANS),
+ PINMUX_IPSR_GPSR(IP7_19_16, MSIOF0_SYNC),
+
+ PINMUX_IPSR_GPSR(IP7_23_20, SCL2),
+ PINMUX_IPSR_GPSR(IP7_23_20, DU_DB0),
+ PINMUX_IPSR_MSEL(IP7_23_20, TCLK1_A, SEL_TMU_0),
+ PINMUX_IPSR_GPSR(IP7_23_20, WE1_N),
+ PINMUX_IPSR_GPSR(IP7_23_20, RX0),
+ PINMUX_IPSR_GPSR(IP7_23_20, MSIOF0_SS1),
+
+ PINMUX_IPSR_GPSR(IP7_27_24, SDA2),
+ PINMUX_IPSR_GPSR(IP7_27_24, DU_DB1),
+ PINMUX_IPSR_MSEL(IP7_27_24, TCLK2_A, SEL_TMU_0),
+ PINMUX_IPSR_GPSR(IP7_27_24, EX_WAIT0),
+ PINMUX_IPSR_GPSR(IP7_27_24, TX0),
+ PINMUX_IPSR_GPSR(IP7_27_24, MSIOF0_SS2),
+
+ PINMUX_IPSR_GPSR(IP7_31_28, AVB0_AVTP_CAPTURE),
+ PINMUX_IPSR_GPSR(IP7_31_28, FSCLKST2_N_B),
+
+ /* IPSR8 */
+ PINMUX_IPSR_MSEL(IP8_3_0, CANFD0_TX_A, SEL_CANFD0_0),
+ PINMUX_IPSR_GPSR(IP8_3_0, FXR_TXDA),
+ PINMUX_IPSR_MSEL(IP8_3_0, PWM0_B, SEL_PWM0_1),
+ PINMUX_IPSR_GPSR(IP8_3_0, DU_DISP),
+ PINMUX_IPSR_GPSR(IP8_3_0, FSCLKST2_N_C),
+
+ PINMUX_IPSR_MSEL(IP8_7_4, CANFD0_RX_A, SEL_CANFD0_0),
+ PINMUX_IPSR_GPSR(IP8_7_4, RXDA_EXTFXR),
+ PINMUX_IPSR_MSEL(IP8_7_4, PWM1_B, SEL_PWM1_1),
+ PINMUX_IPSR_GPSR(IP8_7_4, DU_CDE),
+
+ PINMUX_IPSR_GPSR(IP8_11_8, CANFD1_TX),
+ PINMUX_IPSR_GPSR(IP8_11_8, FXR_TXDB),
+ PINMUX_IPSR_MSEL(IP8_11_8, PWM2_B, SEL_PWM2_1),
+ PINMUX_IPSR_MSEL(IP8_11_8, TCLK1_B, SEL_TMU_1),
+ PINMUX_IPSR_MSEL(IP8_11_8, TX1_B, SEL_SCIF1_1),
+
+ PINMUX_IPSR_GPSR(IP8_15_12, CANFD1_RX),
+ PINMUX_IPSR_GPSR(IP8_15_12, RXDB_EXTFXR),
+ PINMUX_IPSR_MSEL(IP8_15_12, PWM3_B, SEL_PWM3_1),
+ PINMUX_IPSR_MSEL(IP8_15_12, TCLK2_B, SEL_TMU_1),
+ PINMUX_IPSR_MSEL(IP8_15_12, RX1_B, SEL_SCIF1_1),
+
+ PINMUX_IPSR_MSEL(IP8_19_16, CANFD_CLK_A, SEL_CANFD0_0),
+ PINMUX_IPSR_GPSR(IP8_19_16, CLK_EXTFXR),
+ PINMUX_IPSR_MSEL(IP8_19_16, PWM4_B, SEL_PWM4_1),
+ PINMUX_IPSR_MSEL(IP8_19_16, SPEEDIN_B, SEL_RSP_1),
+ PINMUX_IPSR_MSEL(IP8_19_16, SCIF_CLK_B, SEL_HSCIF0_1),
+
+ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKIN),
+ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKEN_IN),
+
+ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKOUT),
+ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKEN_OUT),
+};
+
+static const struct sh_pfc_pin pinmux_pins[] = {
+ PINMUX_GPIO_GP_ALL(),
+};
+
+/* - CANFD Clock ------------------------------------------------------------ */
+static const unsigned int canfd_clk_a_pins[] = {
+ /* CANFD_CLK */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int canfd_clk_a_mux[] = {
+ CANFD_CLK_A_MARK,
+};
+static const unsigned int canfd_clk_b_pins[] = {
+ /* CANFD_CLK */
+ RCAR_GP_PIN(3, 8),
+};
+static const unsigned int canfd_clk_b_mux[] = {
+ CANFD_CLK_B_MARK,
+};
+
+/* - CANFD0 ----------------------------------------------------------------- */
+static const unsigned int canfd0_data_a_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 21), RCAR_GP_PIN(1, 22),
+};
+static const unsigned int canfd0_data_a_mux[] = {
+ CANFD0_TX_A_MARK, CANFD0_RX_A_MARK,
+};
+static const unsigned int canfd0_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+};
+static const unsigned int canfd0_data_b_mux[] = {
+ CANFD0_TX_B_MARK, CANFD0_RX_B_MARK,
+};
+
+/* - CANFD1 ----------------------------------------------------------------- */
+static const unsigned int canfd1_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24),
+};
+static const unsigned int canfd1_data_mux[] = {
+ CANFD1_TX_MARK, CANFD1_RX_MARK,
+};
+
+/* - DU --------------------------------------------------------------------- */
+static const unsigned int du_rgb666_pins[] = {
+ /* R[7:2], G[7:2], B[7:2] */
+ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 3),
+ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 0),
+ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 9),
+ RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 6),
+ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), RCAR_GP_PIN(0, 15),
+ RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 12),
+};
+static const unsigned int du_rgb666_mux[] = {
+ DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK,
+ DU_DR4_MARK, DU_DR3_MARK, DU_DR2_MARK,
+ DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK,
+ DU_DG4_MARK, DU_DG3_MARK, DU_DG2_MARK,
+ DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK,
+ DU_DB4_MARK, DU_DB3_MARK, DU_DB2_MARK,
+};
+static const unsigned int du_clk_out_pins[] = {
+ /* DOTCLKOUT */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int du_clk_out_mux[] = {
+ DU_DOTCLKOUT_MARK,
+};
+static const unsigned int du_sync_pins[] = {
+ /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */
+ RCAR_GP_PIN(0, 20), RCAR_GP_PIN(0, 19),
+};
+static const unsigned int du_sync_mux[] = {
+ DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK
+};
+static const unsigned int du_oddf_pins[] = {
+ /* EXODDF/ODDF/DISP/CDE */
+ RCAR_GP_PIN(0, 21),
+};
+static const unsigned int du_oddf_mux[] = {
+ DU_EXODDF_DU_ODDF_DISP_CDE_MARK,
+};
+static const unsigned int du_cde_pins[] = {
+ /* CDE */
+ RCAR_GP_PIN(1, 22),
+};
+static const unsigned int du_cde_mux[] = {
+ DU_CDE_MARK,
+};
+static const unsigned int du_disp_pins[] = {
+ /* DISP */
+ RCAR_GP_PIN(1, 21),
+};
+static const unsigned int du_disp_mux[] = {
+ DU_DISP_MARK,
+};
+
+/* - HSCIF0 ----------------------------------------------------------------- */
+static const unsigned int hscif0_data_pins[] = {
+ /* HRX, HTX */
+ RCAR_GP_PIN(0, 19), RCAR_GP_PIN(0, 3),
+};
+static const unsigned int hscif0_data_mux[] = {
+ HRX0_MARK, HTX0_MARK,
+};
+static const unsigned int hscif0_clk_pins[] = {
+ /* HSCK */
+ RCAR_GP_PIN(0, 0),
+};
+static const unsigned int hscif0_clk_mux[] = {
+ HSCK0_MARK,
+};
+static const unsigned int hscif0_ctrl_pins[] = {
+ /* HRTS#, HCTS# */
+ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2),
+};
+static const unsigned int hscif0_ctrl_mux[] = {
+ HRTS0_N_MARK, HCTS0_N_MARK,
+};
+
+/* - HSCIF1 ----------------------------------------------------------------- */
+static const unsigned int hscif1_data_pins[] = {
+ /* HRX, HTX */
+ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10),
+};
+static const unsigned int hscif1_data_mux[] = {
+ HRX1_MARK, HTX1_MARK,
+};
+static const unsigned int hscif1_clk_pins[] = {
+ /* HSCK */
+ RCAR_GP_PIN(2, 7),
+};
+static const unsigned int hscif1_clk_mux[] = {
+ HSCK1_MARK,
+};
+static const unsigned int hscif1_ctrl_pins[] = {
+ /* HRTS#, HCTS# */
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+};
+static const unsigned int hscif1_ctrl_mux[] = {
+ HRTS1_N_MARK, HCTS1_N_MARK,
+};
+
+/* - HSCIF2 ----------------------------------------------------------------- */
+static const unsigned int hscif2_data_pins[] = {
+ /* HRX, HTX */
+ RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 15),
+};
+static const unsigned int hscif2_data_mux[] = {
+ HRX2_MARK, HTX2_MARK,
+};
+static const unsigned int hscif2_clk_pins[] = {
+ /* HSCK */
+ RCAR_GP_PIN(2, 12),
+};
+static const unsigned int hscif2_clk_mux[] = {
+ HSCK2_MARK,
+};
+static const unsigned int hscif2_ctrl_pins[] = {
+ /* HRTS#, HCTS# */
+ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
+};
+static const unsigned int hscif2_ctrl_mux[] = {
+ HRTS2_N_MARK, HCTS2_N_MARK,
+};
+
+/* - HSCIF3 ----------------------------------------------------------------- */
+static const unsigned int hscif3_data_pins[] = {
+ /* HRX, HTX */
+ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3),
+};
+static const unsigned int hscif3_data_mux[] = {
+ HRX3_MARK, HTX3_MARK,
+};
+static const unsigned int hscif3_clk_pins[] = {
+ /* HSCK */
+ RCAR_GP_PIN(2, 0),
+};
+static const unsigned int hscif3_clk_mux[] = {
+ HSCK3_MARK,
+};
+static const unsigned int hscif3_ctrl_pins[] = {
+ /* HRTS#, HCTS# */
+ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int hscif3_ctrl_mux[] = {
+ HRTS3_N_MARK, HCTS3_N_MARK,
+};
+
+/* - I2C0 ------------------------------------------------------------------- */
+static const unsigned int i2c0_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0),
+};
+static const unsigned int i2c0_mux[] = {
+ SDA0_MARK, SCL0_MARK,
+};
+
+/* - I2C1 ------------------------------------------------------------------- */
+static const unsigned int i2c1_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2),
+};
+static const unsigned int i2c1_mux[] = {
+ SDA1_MARK, SCL1_MARK,
+};
+
+/* - I2C2 ------------------------------------------------------------------- */
+static const unsigned int i2c2_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(4, 5), RCAR_GP_PIN(4, 4),
+};
+static const unsigned int i2c2_mux[] = {
+ SDA2_MARK, SCL2_MARK,
+};
+
+/* - I2C3 ------------------------------------------------------------------- */
+static const unsigned int i2c3_a_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
+};
+static const unsigned int i2c3_a_mux[] = {
+ SDA3_A_MARK, SCL3_A_MARK,
+};
+static const unsigned int i2c3_b_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 13),
+};
+static const unsigned int i2c3_b_mux[] = {
+ SDA3_B_MARK, SCL3_B_MARK,
+};
+
+/* - I2C4 ------------------------------------------------------------------- */
+static const unsigned int i2c4_pins[] = {
+ /* SDA, SCL */
+ RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15),
+};
+static const unsigned int i2c4_mux[] = {
+ SDA4_MARK, SCL4_MARK,
+};
+
+/* - INTC-EX ---------------------------------------------------------------- */
+static const unsigned int intc_ex_irq0_pins[] = {
+ /* IRQ0 */
+ RCAR_GP_PIN(1, 0),
+};
+static const unsigned int intc_ex_irq0_mux[] = {
+ IRQ0_MARK,
+};
+static const unsigned int intc_ex_irq1_pins[] = {
+ /* IRQ1 */
+ RCAR_GP_PIN(0, 11),
+};
+static const unsigned int intc_ex_irq1_mux[] = {
+ IRQ1_MARK,
+};
+static const unsigned int intc_ex_irq2_pins[] = {
+ /* IRQ2 */
+ RCAR_GP_PIN(0, 12),
+};
+static const unsigned int intc_ex_irq2_mux[] = {
+ IRQ2_MARK,
+};
+static const unsigned int intc_ex_irq3_pins[] = {
+ /* IRQ3 */
+ RCAR_GP_PIN(0, 19),
+};
+static const unsigned int intc_ex_irq3_mux[] = {
+ IRQ3_MARK,
+};
+static const unsigned int intc_ex_irq4_pins[] = {
+ /* IRQ4 */
+ RCAR_GP_PIN(3, 15),
+};
+static const unsigned int intc_ex_irq4_mux[] = {
+ IRQ4_MARK,
+};
+static const unsigned int intc_ex_irq5_pins[] = {
+ /* IRQ5 */
+ RCAR_GP_PIN(3, 16),
+};
+static const unsigned int intc_ex_irq5_mux[] = {
+ IRQ5_MARK,
+};
+
+/* - MMC -------------------------------------------------------------------- */
+static const unsigned int mmc_data1_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(3, 6),
+};
+static const unsigned int mmc_data1_mux[] = {
+ MMC_D0_MARK,
+};
+static const unsigned int mmc_data4_pins[] = {
+ /* D[0:3] */
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+};
+static const unsigned int mmc_data4_mux[] = {
+ MMC_D0_MARK, MMC_D1_MARK,
+ MMC_D2_MARK, MMC_D3_MARK,
+};
+static const unsigned int mmc_data8_pins[] = {
+ /* D[0:7] */
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+ RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 12),
+ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14),
+};
+static const unsigned int mmc_data8_mux[] = {
+ MMC_D0_MARK, MMC_D1_MARK,
+ MMC_D2_MARK, MMC_D3_MARK,
+ MMC_D4_MARK, MMC_D5_MARK,
+ MMC_D6_MARK, MMC_D7_MARK,
+};
+static const unsigned int mmc_ctrl_pins[] = {
+ /* CLK, CMD */
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 5),
+};
+static const unsigned int mmc_ctrl_mux[] = {
+ MMC_CLK_MARK, MMC_CMD_MARK,
+};
+static const unsigned int mmc_cd_pins[] = {
+ /* CD */
+ RCAR_GP_PIN(3, 16),
+};
+static const unsigned int mmc_cd_mux[] = {
+ MMC_CD_MARK,
+};
+static const unsigned int mmc_wp_pins[] = {
+ /* WP */
+ RCAR_GP_PIN(3, 15),
+};
+static const unsigned int mmc_wp_mux[] = {
+ MMC_WP_MARK,
+};
+
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(4, 2),
+};
+static const unsigned int msiof0_clk_mux[] = {
+ MSIOF0_SCK_MARK,
+};
+static const unsigned int msiof0_sync_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(4, 3),
+};
+static const unsigned int msiof0_sync_mux[] = {
+ MSIOF0_SYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(4, 4),
+};
+static const unsigned int msiof0_ss1_mux[] = {
+ MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(4, 5),
+};
+static const unsigned int msiof0_ss2_mux[] = {
+ MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_txd_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(4, 1),
+};
+static const unsigned int msiof0_txd_mux[] = {
+ MSIOF0_TXD_MARK,
+};
+static const unsigned int msiof0_rxd_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(4, 0),
+};
+static const unsigned int msiof0_rxd_mux[] = {
+ MSIOF0_RXD_MARK,
+};
+
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(3, 2),
+};
+static const unsigned int msiof1_clk_mux[] = {
+ MSIOF1_SCK_MARK,
+};
+static const unsigned int msiof1_sync_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(3, 3),
+};
+static const unsigned int msiof1_sync_mux[] = {
+ MSIOF1_SYNC_MARK,
+};
+static const unsigned int msiof1_ss1_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(3, 4),
+};
+static const unsigned int msiof1_ss1_mux[] = {
+ MSIOF1_SS1_MARK,
+};
+static const unsigned int msiof1_ss2_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(3, 5),
+};
+static const unsigned int msiof1_ss2_mux[] = {
+ MSIOF1_SS2_MARK,
+};
+static const unsigned int msiof1_txd_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(3, 1),
+};
+static const unsigned int msiof1_txd_mux[] = {
+ MSIOF1_TXD_MARK,
+};
+static const unsigned int msiof1_rxd_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(3, 0),
+};
+static const unsigned int msiof1_rxd_mux[] = {
+ MSIOF1_RXD_MARK,
+};
+
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(2, 0),
+};
+static const unsigned int msiof2_clk_mux[] = {
+ MSIOF2_SCK_MARK,
+};
+static const unsigned int msiof2_sync_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(2, 3),
+};
+static const unsigned int msiof2_sync_mux[] = {
+ MSIOF2_SYNC_MARK,
+};
+static const unsigned int msiof2_ss1_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(2, 4),
+};
+static const unsigned int msiof2_ss1_mux[] = {
+ MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss2_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(2, 5),
+};
+static const unsigned int msiof2_ss2_mux[] = {
+ MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_txd_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(2, 2),
+};
+static const unsigned int msiof2_txd_mux[] = {
+ MSIOF2_TXD_MARK,
+};
+static const unsigned int msiof2_rxd_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(2, 1),
+};
+static const unsigned int msiof2_rxd_mux[] = {
+ MSIOF2_RXD_MARK,
+};
+
+/* - MSIOF3 ----------------------------------------------------------------- */
+static const unsigned int msiof3_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(0, 20),
+};
+static const unsigned int msiof3_clk_mux[] = {
+ MSIOF3_SCK_MARK,
+};
+static const unsigned int msiof3_sync_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(0, 21),
+};
+static const unsigned int msiof3_sync_mux[] = {
+ MSIOF3_SYNC_MARK,
+};
+static const unsigned int msiof3_ss1_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(0, 6),
+};
+static const unsigned int msiof3_ss1_mux[] = {
+ MSIOF3_SS1_MARK,
+};
+static const unsigned int msiof3_ss2_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(0, 7),
+};
+static const unsigned int msiof3_ss2_mux[] = {
+ MSIOF3_SS2_MARK,
+};
+static const unsigned int msiof3_txd_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(0, 5),
+};
+static const unsigned int msiof3_txd_mux[] = {
+ MSIOF3_TXD_MARK,
+};
+static const unsigned int msiof3_rxd_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(0, 4),
+};
+static const unsigned int msiof3_rxd_mux[] = {
+ MSIOF3_RXD_MARK,
+};
+
+/* - PWM0 ------------------------------------------------------------------- */
+static const unsigned int pwm0_a_pins[] = {
+ RCAR_GP_PIN(2, 12),
+};
+static const unsigned int pwm0_a_mux[] = {
+ PWM0_A_MARK,
+};
+static const unsigned int pwm0_b_pins[] = {
+ RCAR_GP_PIN(1, 21),
+};
+static const unsigned int pwm0_b_mux[] = {
+ PWM0_B_MARK,
+};
+
+/* - PWM1 ------------------------------------------------------------------- */
+static const unsigned int pwm1_a_pins[] = {
+ RCAR_GP_PIN(2, 13),
+};
+static const unsigned int pwm1_a_mux[] = {
+ PWM1_A_MARK,
+};
+static const unsigned int pwm1_b_pins[] = {
+ RCAR_GP_PIN(1, 22),
+};
+static const unsigned int pwm1_b_mux[] = {
+ PWM1_B_MARK,
+};
+
+/* - PWM2 ------------------------------------------------------------------- */
+static const unsigned int pwm2_a_pins[] = {
+ RCAR_GP_PIN(2, 14),
+};
+static const unsigned int pwm2_a_mux[] = {
+ PWM2_A_MARK,
+};
+static const unsigned int pwm2_b_pins[] = {
+ RCAR_GP_PIN(1, 23),
+};
+static const unsigned int pwm2_b_mux[] = {
+ PWM2_B_MARK,
+};
+
+/* - PWM3 ------------------------------------------------------------------- */
+static const unsigned int pwm3_a_pins[] = {
+ RCAR_GP_PIN(2, 15),
+};
+static const unsigned int pwm3_a_mux[] = {
+ PWM3_A_MARK,
+};
+static const unsigned int pwm3_b_pins[] = {
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int pwm3_b_mux[] = {
+ PWM3_B_MARK,
+};
+
+/* - PWM4 ------------------------------------------------------------------- */
+static const unsigned int pwm4_a_pins[] = {
+ RCAR_GP_PIN(2, 16),
+};
+static const unsigned int pwm4_a_mux[] = {
+ PWM4_A_MARK,
+};
+static const unsigned int pwm4_b_pins[] = {
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int pwm4_b_mux[] = {
+ PWM4_B_MARK,
+};
+
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_a_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(0, 18),
+};
+static const unsigned int scif_clk_a_mux[] = {
+ SCIF_CLK_A_MARK,
+};
+static const unsigned int scif_clk_b_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int scif_clk_b_mux[] = {
+ SCIF_CLK_B_MARK,
+};
+
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5),
+};
+static const unsigned int scif0_data_mux[] = {
+ RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(4, 1),
+};
+static const unsigned int scif0_clk_mux[] = {
+ SCK0_MARK,
+};
+static const unsigned int scif0_ctrl_pins[] = {
+ /* RTS#, CTS# */
+ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2),
+};
+static const unsigned int scif0_ctrl_mux[] = {
+ RTS0_N_TANS_MARK, CTS0_N_MARK,
+};
+
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+};
+static const unsigned int scif1_data_a_mux[] = {
+ RX1_A_MARK, TX1_A_MARK,
+};
+static const unsigned int scif1_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(2, 5),
+};
+static const unsigned int scif1_clk_mux[] = {
+ SCK1_MARK,
+};
+static const unsigned int scif1_ctrl_pins[] = {
+ /* RTS#, CTS# */
+ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10),
+};
+static const unsigned int scif1_ctrl_mux[] = {
+ RTS1_N_TANS_MARK, CTS1_N_MARK,
+};
+static const unsigned int scif1_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 23),
+};
+static const unsigned int scif1_data_b_mux[] = {
+ RX1_B_MARK, TX1_B_MARK,
+};
+
+/* - SCIF3 ------------------------------------------------------------------ */
+static const unsigned int scif3_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2),
+};
+static const unsigned int scif3_data_mux[] = {
+ RX3_MARK, TX3_MARK,
+};
+static const unsigned int scif3_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(2, 0),
+};
+static const unsigned int scif3_clk_mux[] = {
+ SCK3_MARK,
+};
+static const unsigned int scif3_ctrl_pins[] = {
+ /* RTS#, CTS# */
+ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3),
+};
+static const unsigned int scif3_ctrl_mux[] = {
+ RTS3_N_TANS_MARK, CTS3_N_MARK,
+};
+
+/* - SCIF4 ------------------------------------------------------------------ */
+static const unsigned int scif4_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
+};
+static const unsigned int scif4_data_mux[] = {
+ RX4_MARK, TX4_MARK,
+};
+static const unsigned int scif4_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(3, 9),
+};
+static const unsigned int scif4_clk_mux[] = {
+ SCK4_MARK,
+};
+static const unsigned int scif4_ctrl_pins[] = {
+ /* RTS#, CTS# */
+ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12),
+};
+static const unsigned int scif4_ctrl_mux[] = {
+ RTS4_N_TANS_MARK, CTS4_N_MARK,
+};
+
+/* - TMU -------------------------------------------------------------------- */
+static const unsigned int tmu_tclk1_a_pins[] = {
+ /* TCLK1 */
+ RCAR_GP_PIN(4, 4),
+};
+static const unsigned int tmu_tclk1_a_mux[] = {
+ TCLK1_A_MARK,
+};
+static const unsigned int tmu_tclk1_b_pins[] = {
+ /* TCLK1 */
+ RCAR_GP_PIN(1, 23),
+};
+static const unsigned int tmu_tclk1_b_mux[] = {
+ TCLK1_B_MARK,
+};
+static const unsigned int tmu_tclk2_a_pins[] = {
+ /* TCLK2 */
+ RCAR_GP_PIN(4, 5),
+};
+static const unsigned int tmu_tclk2_a_mux[] = {
+ TCLK2_A_MARK,
+};
+static const unsigned int tmu_tclk2_b_pins[] = {
+ /* TCLK2 */
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int tmu_tclk2_b_mux[] = {
+ TCLK2_B_MARK,
+};
+
+/* - VIN0 ------------------------------------------------------------------- */
+static const unsigned int vin0_data8_pins[] = {
+ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
+ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
+};
+static const unsigned int vin0_data8_mux[] = {
+ VI0_DATA0_MARK, VI0_DATA1_MARK,
+ VI0_DATA2_MARK, VI0_DATA3_MARK,
+ VI0_DATA4_MARK, VI0_DATA5_MARK,
+ VI0_DATA6_MARK, VI0_DATA7_MARK,
+};
+static const unsigned int vin0_data10_pins[] = {
+ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
+ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
+ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13),
+};
+static const unsigned int vin0_data10_mux[] = {
+ VI0_DATA0_MARK, VI0_DATA1_MARK,
+ VI0_DATA2_MARK, VI0_DATA3_MARK,
+ VI0_DATA4_MARK, VI0_DATA5_MARK,
+ VI0_DATA6_MARK, VI0_DATA7_MARK,
+ VI0_DATA8_MARK, VI0_DATA9_MARK,
+};
+static const unsigned int vin0_data12_pins[] = {
+ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
+ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
+ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13),
+ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15),
+};
+static const unsigned int vin0_data12_mux[] = {
+ VI0_DATA0_MARK, VI0_DATA1_MARK,
+ VI0_DATA2_MARK, VI0_DATA3_MARK,
+ VI0_DATA4_MARK, VI0_DATA5_MARK,
+ VI0_DATA6_MARK, VI0_DATA7_MARK,
+ VI0_DATA8_MARK, VI0_DATA9_MARK,
+ VI0_DATA10_MARK, VI0_DATA11_MARK,
+};
+static const unsigned int vin0_sync_pins[] = {
+ /* HSYNC#, VSYNC# */
+ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3),
+};
+static const unsigned int vin0_sync_mux[] = {
+ VI0_HSYNC_N_MARK, VI0_VSYNC_N_MARK,
+};
+static const unsigned int vin0_field_pins[] = {
+ /* FIELD */
+ RCAR_GP_PIN(2, 16),
+};
+static const unsigned int vin0_field_mux[] = {
+ VI0_FIELD_MARK,
+};
+static const unsigned int vin0_clkenb_pins[] = {
+ /* CLKENB */
+ RCAR_GP_PIN(2, 1),
+};
+static const unsigned int vin0_clkenb_mux[] = {
+ VI0_CLKENB_MARK,
+};
+static const unsigned int vin0_clk_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(2, 0),
+};
+static const unsigned int vin0_clk_mux[] = {
+ VI0_CLK_MARK,
+};
+
+/* - VIN1 ------------------------------------------------------------------- */
+static const unsigned int vin1_data8_pins[] = {
+ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
+};
+static const unsigned int vin1_data8_mux[] = {
+ VI1_DATA0_MARK, VI1_DATA1_MARK,
+ VI1_DATA2_MARK, VI1_DATA3_MARK,
+ VI1_DATA4_MARK, VI1_DATA5_MARK,
+ VI1_DATA6_MARK, VI1_DATA7_MARK,
+};
+static const unsigned int vin1_data10_pins[] = {
+ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
+ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13),
+};
+static const unsigned int vin1_data10_mux[] = {
+ VI1_DATA0_MARK, VI1_DATA1_MARK,
+ VI1_DATA2_MARK, VI1_DATA3_MARK,
+ VI1_DATA4_MARK, VI1_DATA5_MARK,
+ VI1_DATA6_MARK, VI1_DATA7_MARK,
+ VI1_DATA8_MARK, VI1_DATA9_MARK,
+};
+static const unsigned int vin1_data12_pins[] = {
+ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
+ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13),
+ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15),
+};
+static const unsigned int vin1_data12_mux[] = {
+ VI1_DATA0_MARK, VI1_DATA1_MARK,
+ VI1_DATA2_MARK, VI1_DATA3_MARK,
+ VI1_DATA4_MARK, VI1_DATA5_MARK,
+ VI1_DATA6_MARK, VI1_DATA7_MARK,
+ VI1_DATA8_MARK, VI1_DATA9_MARK,
+ VI1_DATA10_MARK, VI1_DATA11_MARK,
+};
+static const unsigned int vin1_sync_pins[] = {
+ /* HSYNC#, VSYNC# */
+ RCAR_GP_PIN(3, 2), RCAR_GP_PIN(3, 3),
+};
+static const unsigned int vin1_sync_mux[] = {
+ VI1_HSYNC_N_MARK, VI1_VSYNC_N_MARK,
+};
+static const unsigned int vin1_field_pins[] = {
+ RCAR_GP_PIN(3, 16),
+};
+static const unsigned int vin1_field_mux[] = {
+ /* FIELD */
+ VI1_FIELD_MARK,
+};
+static const unsigned int vin1_clkenb_pins[] = {
+ RCAR_GP_PIN(3, 1),
+};
+static const unsigned int vin1_clkenb_mux[] = {
+ /* CLKENB */
+ VI1_CLKENB_MARK,
+};
+static const unsigned int vin1_clk_pins[] = {
+ RCAR_GP_PIN(3, 0),
+};
+static const unsigned int vin1_clk_mux[] = {
+ /* CLK */
+ VI1_CLK_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(canfd_clk_a),
+ SH_PFC_PIN_GROUP(canfd_clk_b),
+ SH_PFC_PIN_GROUP(canfd0_data_a),
+ SH_PFC_PIN_GROUP(canfd0_data_b),
+ SH_PFC_PIN_GROUP(canfd1_data),
+ SH_PFC_PIN_GROUP(du_rgb666),
+ SH_PFC_PIN_GROUP(du_clk_out),
+ SH_PFC_PIN_GROUP(du_sync),
+ SH_PFC_PIN_GROUP(du_oddf),
+ SH_PFC_PIN_GROUP(du_cde),
+ SH_PFC_PIN_GROUP(du_disp),
+ 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_a),
+ SH_PFC_PIN_GROUP(i2c3_b),
+ SH_PFC_PIN_GROUP(i2c4),
+ 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),
+ SH_PFC_PIN_GROUP(mmc_data1),
+ SH_PFC_PIN_GROUP(mmc_data4),
+ SH_PFC_PIN_GROUP(mmc_data8),
+ SH_PFC_PIN_GROUP(mmc_ctrl),
+ SH_PFC_PIN_GROUP(mmc_cd),
+ SH_PFC_PIN_GROUP(mmc_wp),
+ 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(pwm0_a),
+ SH_PFC_PIN_GROUP(pwm0_b),
+ SH_PFC_PIN_GROUP(pwm1_a),
+ SH_PFC_PIN_GROUP(pwm1_b),
+ SH_PFC_PIN_GROUP(pwm2_a),
+ SH_PFC_PIN_GROUP(pwm2_b),
+ SH_PFC_PIN_GROUP(pwm3_a),
+ SH_PFC_PIN_GROUP(pwm3_b),
+ SH_PFC_PIN_GROUP(pwm4_a),
+ SH_PFC_PIN_GROUP(pwm4_b),
+ SH_PFC_PIN_GROUP(scif_clk_a),
+ SH_PFC_PIN_GROUP(scif_clk_b),
+ SH_PFC_PIN_GROUP(scif0_data),
+ SH_PFC_PIN_GROUP(scif0_clk),
+ SH_PFC_PIN_GROUP(scif0_ctrl),
+ SH_PFC_PIN_GROUP(scif1_data_a),
+ SH_PFC_PIN_GROUP(scif1_clk),
+ SH_PFC_PIN_GROUP(scif1_ctrl),
+ SH_PFC_PIN_GROUP(scif1_data_b),
+ 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(tmu_tclk1_a),
+ SH_PFC_PIN_GROUP(tmu_tclk1_b),
+ SH_PFC_PIN_GROUP(tmu_tclk2_a),
+ SH_PFC_PIN_GROUP(tmu_tclk2_b),
+ SH_PFC_PIN_GROUP(vin0_data8),
+ SH_PFC_PIN_GROUP(vin0_data10),
+ SH_PFC_PIN_GROUP(vin0_data12),
+ SH_PFC_PIN_GROUP(vin0_sync),
+ SH_PFC_PIN_GROUP(vin0_field),
+ SH_PFC_PIN_GROUP(vin0_clkenb),
+ SH_PFC_PIN_GROUP(vin0_clk),
+ SH_PFC_PIN_GROUP(vin1_data8),
+ SH_PFC_PIN_GROUP(vin1_data10),
+ SH_PFC_PIN_GROUP(vin1_data12),
+ SH_PFC_PIN_GROUP(vin1_sync),
+ SH_PFC_PIN_GROUP(vin1_field),
+ SH_PFC_PIN_GROUP(vin1_clkenb),
+ SH_PFC_PIN_GROUP(vin1_clk),
+};
+
+static const char * const canfd_clk_groups[] = {
+ "canfd_clk_a",
+ "canfd_clk_b",
+};
+
+static const char * const canfd0_groups[] = {
+ "canfd0_data_a",
+ "canfd0_data_b",
+};
+
+static const char * const canfd1_groups[] = {
+ "canfd1_data",
+};
+
+static const char * const du_groups[] = {
+ "du_rgb666",
+ "du_clk_out",
+ "du_sync",
+ "du_oddf",
+ "du_cde",
+ "du_disp",
+};
+
+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_a",
+ "i2c3_b",
+};
+
+static const char * const i2c4_groups[] = {
+ "i2c4",
+};
+
+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",
+};
+
+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 pwm0_groups[] = {
+ "pwm0_a",
+ "pwm0_b",
+};
+
+static const char * const pwm1_groups[] = {
+ "pwm1_a",
+ "pwm1_b",
+};
+
+static const char * const pwm2_groups[] = {
+ "pwm2_a",
+ "pwm2_b",
+};
+
+static const char * const pwm3_groups[] = {
+ "pwm3_a",
+ "pwm3_b",
+};
+
+static const char * const pwm4_groups[] = {
+ "pwm4_a",
+ "pwm4_b",
+};
+
+static const char * const scif_clk_groups[] = {
+ "scif_clk_a",
+ "scif_clk_b",
+};
+
+static const char * const scif0_groups[] = {
+ "scif0_data",
+ "scif0_clk",
+ "scif0_ctrl",
+};
+
+static const char * const scif1_groups[] = {
+ "scif1_data_a",
+ "scif1_clk",
+ "scif1_ctrl",
+ "scif1_data_b",
+};
+
+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 tmu_groups[] = {
+ "tmu_tclk1_a",
+ "tmu_tclk1_b",
+ "tmu_tclk2_a",
+ "tmu_tclk2_b",
+};
+
+static const char * const vin0_groups[] = {
+ "vin0_data8",
+ "vin0_data10",
+ "vin0_data12",
+ "vin0_sync",
+ "vin0_field",
+ "vin0_clkenb",
+ "vin0_clk",
+};
+
+static const char * const vin1_groups[] = {
+ "vin1_data8",
+ "vin1_data10",
+ "vin1_data12",
+ "vin1_sync",
+ "vin1_field",
+ "vin1_clkenb",
+ "vin1_clk",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(canfd_clk),
+ SH_PFC_FUNCTION(canfd0),
+ SH_PFC_FUNCTION(canfd1),
+ SH_PFC_FUNCTION(du),
+ 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(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(pwm0),
+ SH_PFC_FUNCTION(pwm1),
+ SH_PFC_FUNCTION(pwm2),
+ SH_PFC_FUNCTION(pwm3),
+ SH_PFC_FUNCTION(pwm4),
+ SH_PFC_FUNCTION(scif_clk),
+ SH_PFC_FUNCTION(scif0),
+ SH_PFC_FUNCTION(scif1),
+ SH_PFC_FUNCTION(scif3),
+ SH_PFC_FUNCTION(scif4),
+ SH_PFC_FUNCTION(tmu),
+ SH_PFC_FUNCTION(vin0),
+ SH_PFC_FUNCTION(vin1),
+};
+
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
+#define F_(x, y) FN_##y
+#define FM(x) FN_##x
+ { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_0_21_FN, GPSR0_21,
+ 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("GPSR1", 0xe6060104, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 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("GPSR2", 0xe6060108, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 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", 0xe606010c, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 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", 0xe6060110, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 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("GPSR5", 0xe6060114, 32, 1) {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 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, }
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG("IPSR0", 0xe6060200, 32, 4) {
+ IP0_31_28
+ IP0_27_24
+ IP0_23_20
+ IP0_19_16
+ IP0_15_12
+ IP0_11_8
+ IP0_7_4
+ IP0_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR1", 0xe6060204, 32, 4) {
+ IP1_31_28
+ IP1_27_24
+ IP1_23_20
+ IP1_19_16
+ IP1_15_12
+ IP1_11_8
+ IP1_7_4
+ IP1_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR2", 0xe6060208, 32, 4) {
+ IP2_31_28
+ IP2_27_24
+ IP2_23_20
+ IP2_19_16
+ IP2_15_12
+ IP2_11_8
+ IP2_7_4
+ IP2_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR3", 0xe606020c, 32, 4) {
+ IP3_31_28
+ IP3_27_24
+ IP3_23_20
+ IP3_19_16
+ IP3_15_12
+ IP3_11_8
+ IP3_7_4
+ IP3_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR4", 0xe6060210, 32, 4) {
+ IP4_31_28
+ IP4_27_24
+ IP4_23_20
+ IP4_19_16
+ IP4_15_12
+ IP4_11_8
+ IP4_7_4
+ IP4_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR5", 0xe6060214, 32, 4) {
+ IP5_31_28
+ IP5_27_24
+ IP5_23_20
+ IP5_19_16
+ IP5_15_12
+ IP5_11_8
+ IP5_7_4
+ IP5_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR6", 0xe6060218, 32, 4) {
+ IP6_31_28
+ IP6_27_24
+ IP6_23_20
+ IP6_19_16
+ IP6_15_12
+ IP6_11_8
+ IP6_7_4
+ IP6_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4) {
+ IP7_31_28
+ IP7_27_24
+ IP7_23_20
+ IP7_19_16
+ IP7_15_12
+ IP7_11_8
+ IP7_7_4
+ IP7_3_0 }
+ },
+ { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4) {
+ IP8_31_28
+ IP8_27_24
+ IP8_23_20
+ IP8_19_16
+ IP8_15_12
+ IP8_11_8
+ IP8_7_4
+ IP8_3_0 }
+ },
+#undef F_
+#undef FM
+
+#define F_(x, y) x,
+#define FM(x) FN_##x,
+ { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32,
+ 4, 4, 4, 4,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) {
+ /* RESERVED 31, 30, 29, 28 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 27, 26, 25, 24 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 23, 22, 21, 20 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 19, 18, 17, 16 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* RESERVED 15, 14, 13, 12 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ MOD_SEL0_11
+ MOD_SEL0_10
+ MOD_SEL0_9
+ MOD_SEL0_8
+ MOD_SEL0_7
+ MOD_SEL0_6
+ MOD_SEL0_5
+ MOD_SEL0_4
+ MOD_SEL0_3
+ MOD_SEL0_2
+ MOD_SEL0_1
+ MOD_SEL0_0 }
+ },
+ { },
+};
+
+static int r8a77970_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin,
+ u32 *pocctrl)
+{
+ int bit = pin & 0x1f;
+
+ *pocctrl = 0xe6060380;
+ if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21))
+ return bit;
+ if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9))
+ return bit + 22;
+
+ *pocctrl += 4;
+ if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16))
+ return bit - 10;
+ if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16))
+ return bit + 7;
+
+ return -EINVAL;
+}
+
+static const struct sh_pfc_soc_operations pinmux_ops = {
+ .pin_to_pocctrl = r8a77970_pin_to_pocctrl,
+};
+
+const struct sh_pfc_soc_info r8a77970_pinmux_info = {
+ .name = "r8a77970_pfc",
+ .ops = &pinmux_ops,
+ .unlock_reg = 0xe6060000, /* PMMR */
+
+ .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,
+
+ .pinmux_data = pinmux_data,
+ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
+};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77995.c b/drivers/pinctrl/sh-pfc/pfc-r8a77995.c
index 89b7541ab1ed..a4927b78a17b 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77995.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77995.c
@@ -518,6 +518,8 @@ static const u16 pinmux_data[] = {
PINMUX_SINGLE(QSPI0_MISO_IO1),
PINMUX_SINGLE(QSPI0_MOSI_IO0),
PINMUX_SINGLE(QSPI0_SPCLK),
+ PINMUX_SINGLE(SCL0),
+ PINMUX_SINGLE(SDA0),
/* IPSR0 */
PINMUX_IPSR_MSEL(IP0_3_0, IRQ0_A, SEL_IRQ_0_0),
@@ -1057,6 +1059,61 @@ static const unsigned int avb0_avtp_capture_b_mux[] = {
AVB0_AVTP_CAPTURE_B_MARK,
};
+/* - CAN ------------------------------------------------------------------ */
+static const unsigned int can0_data_a_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 31),
+};
+static const unsigned int can0_data_a_mux[] = {
+ CAN0_TX_A_MARK, CAN0_RX_A_MARK,
+};
+static const unsigned int can0_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 22), RCAR_GP_PIN(4, 5),
+};
+static const unsigned int can0_data_b_mux[] = {
+ CAN0_TX_B_MARK, CAN0_RX_B_MARK,
+};
+static const unsigned int can1_data_a_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 30), RCAR_GP_PIN(4, 29),
+};
+static const unsigned int can1_data_a_mux[] = {
+ CAN1_TX_A_MARK, CAN1_RX_A_MARK,
+};
+static const unsigned int can1_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 6),
+};
+static const unsigned int can1_data_b_mux[] = {
+ CAN1_TX_B_MARK, CAN1_RX_B_MARK,
+};
+
+/* - CAN Clock -------------------------------------------------------------- */
+static const unsigned int can_clk_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(5, 2),
+};
+static const unsigned int can_clk_mux[] = {
+ CAN_CLK_MARK,
+};
+
+/* - CAN FD ----------------------------------------------------------------- */
+static const unsigned int canfd0_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 31),
+};
+static const unsigned int canfd0_data_mux[] = {
+ CANFD0_TX_MARK, CANFD0_RX_MARK,
+};
+static const unsigned int canfd1_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 30), RCAR_GP_PIN(4, 29),
+};
+static const unsigned int canfd1_data_mux[] = {
+ CANFD1_TX_MARK, CANFD1_RX_MARK,
+};
+
/* - I2C -------------------------------------------------------------------- */
static const unsigned int i2c0_pins[] = {
/* SCL, SDA */
@@ -1504,6 +1561,13 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(avb0_avtp_pps_b),
SH_PFC_PIN_GROUP(avb0_avtp_match_b),
SH_PFC_PIN_GROUP(avb0_avtp_capture_b),
+ SH_PFC_PIN_GROUP(can0_data_a),
+ SH_PFC_PIN_GROUP(can0_data_b),
+ SH_PFC_PIN_GROUP(can1_data_a),
+ SH_PFC_PIN_GROUP(can1_data_b),
+ SH_PFC_PIN_GROUP(can_clk),
+ SH_PFC_PIN_GROUP(canfd0_data),
+ SH_PFC_PIN_GROUP(canfd1_data),
SH_PFC_PIN_GROUP(i2c0),
SH_PFC_PIN_GROUP(i2c1),
SH_PFC_PIN_GROUP(i2c2_a),
@@ -1581,6 +1645,25 @@ static const char * const avb0_groups[] = {
"avb0_avtp_capture_b",
};
+static const char * const can0_groups[] = {
+ "can0_data_a",
+ "can0_data_b",
+};
+static const char * const can1_groups[] = {
+ "can1_data_a",
+ "can1_data_b",
+};
+static const char * const can_clk_groups[] = {
+ "can_clk",
+};
+
+static const char * const canfd0_groups[] = {
+ "canfd0_data",
+};
+static const char * const canfd1_groups[] = {
+ "canfd1_data",
+};
+
static const char * const i2c0_groups[] = {
"i2c0",
};
@@ -1691,6 +1774,11 @@ static const char * const usb0_groups[] = {
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
SH_PFC_FUNCTION(avb0),
+ SH_PFC_FUNCTION(can0),
+ SH_PFC_FUNCTION(can1),
+ SH_PFC_FUNCTION(can_clk),
+ SH_PFC_FUNCTION(canfd0),
+ SH_PFC_FUNCTION(canfd1),
SH_PFC_FUNCTION(i2c0),
SH_PFC_FUNCTION(i2c1),
SH_PFC_FUNCTION(i2c2),
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 213108a058fe..5747ab0472df 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -283,6 +283,7 @@ extern const struct sh_pfc_soc_info r8a7794_pinmux_info;
extern const struct sh_pfc_soc_info r8a7795_pinmux_info;
extern const struct sh_pfc_soc_info r8a7795es1_pinmux_info;
extern const struct sh_pfc_soc_info r8a7796_pinmux_info;
+extern const struct sh_pfc_soc_info r8a77970_pinmux_info;
extern const struct sh_pfc_soc_info r8a77995_pinmux_info;
extern const struct sh_pfc_soc_info sh7203_pinmux_info;
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
@@ -389,10 +390,14 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
PORT_GP_CFG_1(bank, 3, fn, sfx, cfg)
#define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0)
-#define PORT_GP_CFG_8(bank, fn, sfx, cfg) \
+#define PORT_GP_CFG_6(bank, fn, sfx, cfg) \
PORT_GP_CFG_4(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 5, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 5, fn, sfx, cfg)
+#define PORT_GP_6(bank, fn, sfx) PORT_GP_CFG_6(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_8(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_6(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 6, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 7, fn, sfx, cfg)
#define PORT_GP_8(bank, fn, sfx) PORT_GP_CFG_8(bank, fn, sfx, 0)
@@ -450,9 +455,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
PORT_GP_CFG_1(bank, 20, fn, sfx, cfg)
#define PORT_GP_21(bank, fn, sfx) PORT_GP_CFG_21(bank, fn, sfx, 0)
-#define PORT_GP_CFG_23(bank, fn, sfx, cfg) \
+#define PORT_GP_CFG_22(bank, fn, sfx, cfg) \
PORT_GP_CFG_21(bank, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 21, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 21, fn, sfx, cfg)
+#define PORT_GP_22(bank, fn, sfx) PORT_GP_CFG_22(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_23(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_22(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 22, fn, sfx, cfg)
#define PORT_GP_23(bank, fn, sfx) PORT_GP_CFG_23(bank, fn, sfx, 0)
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index 6a0ed8ab33b9..d2123e396b29 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -519,10 +519,8 @@ static int plgpio_probe(struct platform_device *pdev)
int ret, irq;
plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
- if (!plgpio) {
- dev_err(&pdev->dev, "memory allocation fail\n");
+ if (!plgpio)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
plgpio->base = devm_ioremap_resource(&pdev->dev, res);
@@ -544,10 +542,8 @@ static int plgpio_probe(struct platform_device *pdev)
sizeof(*plgpio->csave_regs) *
DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
GFP_KERNEL);
- if (!plgpio->csave_regs) {
- dev_err(&pdev->dev, "csave registers memory allocation fail\n");
+ if (!plgpio->csave_regs)
return -ENOMEM;
- }
#endif
platform_set_drvdata(pdev, plgpio);
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 4db52ba38d8d..efe79d3f7659 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -361,10 +361,8 @@ int spear_pinctrl_probe(struct platform_device *pdev,
return -ENODEV;
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
- if (!pmx) {
- dev_err(&pdev->dev, "Can't alloc spear_pmx\n");
+ if (!pmx)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pmx->vbase = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c
index 63529911445c..ba1c2ca406e4 100644
--- a/drivers/pinctrl/sprd/pinctrl-sprd.c
+++ b/drivers/pinctrl/sprd/pinctrl-sprd.c
@@ -818,7 +818,7 @@ static void sprd_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
grp = &info->groups[selector];
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
for (i = 0; i < grp->npins; i++, config++) {
unsigned int pin_id = grp->pins[i];
diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig
index 7e1fe39a56a5..1c4e00b2eb65 100644
--- a/drivers/pinctrl/stm32/Kconfig
+++ b/drivers/pinctrl/stm32/Kconfig
@@ -27,9 +27,21 @@ config PINCTRL_STM32F746
default MACH_STM32F746
select PINCTRL_STM32
+config PINCTRL_STM32F769
+ bool "STMicroelectronics STM32F769 pin control" if COMPILE_TEST && !MACH_STM32F769
+ depends on OF
+ default MACH_STM32F769
+ select PINCTRL_STM32
+
config PINCTRL_STM32H743
bool "STMicroelectronics STM32H743 pin control" if COMPILE_TEST && !MACH_STM32H743
depends on OF
default MACH_STM32H743
select PINCTRL_STM32
+
+config PINCTRL_STM32MP157
+ bool "STMicroelectronics STM32MP157 pin control" if COMPILE_TEST && !MACH_STM32MP157
+ depends on OF
+ default MACH_STM32MP157
+ select PINCTRL_STM32
endif
diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile
index d13ca3573486..f7c56d4b941c 100644
--- a/drivers/pinctrl/stm32/Makefile
+++ b/drivers/pinctrl/stm32/Makefile
@@ -6,4 +6,6 @@ obj-$(CONFIG_PINCTRL_STM32) += pinctrl-stm32.o
obj-$(CONFIG_PINCTRL_STM32F429) += pinctrl-stm32f429.o
obj-$(CONFIG_PINCTRL_STM32F469) += pinctrl-stm32f469.o
obj-$(CONFIG_PINCTRL_STM32F746) += pinctrl-stm32f746.o
+obj-$(CONFIG_PINCTRL_STM32F769) += pinctrl-stm32f769.o
obj-$(CONFIG_PINCTRL_STM32H743) += pinctrl-stm32h743.o
+obj-$(CONFIG_PINCTRL_STM32MP157) += pinctrl-stm32mp157.o
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index e62ab087bfd8..617df163067f 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Maxime Coquelin 2015
+ * Copyright (C) STMicroelectronics 2017
* Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
- * License terms: GNU General Public License (GPL), version 2
*
* Heavily based on Mediatek's pinctrl driver
*/
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h
index 8702a9992ce5..473a6238a27b 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.h
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Maxime Coquelin 2015
+ * Copyright (C) STMicroelectronics 2017
* Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
- * License terms: GNU General Public License (GPL), version 2
*/
#ifndef __PINCTRL_STM32_H
#define __PINCTRL_STM32_H
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f429.c b/drivers/pinctrl/stm32/pinctrl-stm32f429.c
index 4bbade25acc6..663a97113c51 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32f429.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32f429.c
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Maxime Coquelin 2015
+ * Copyright (C) STMicroelectronics 2017
* Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
- * License terms: GNU General Public License (GPL), version 2
*/
#include <linux/init.h>
#include <linux/of.h>
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f469.c b/drivers/pinctrl/stm32/pinctrl-stm32f469.c
index 86c8cebfa9b9..ed5397f6d7f2 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32f469.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32f469.c
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) Alexandre Torgue 2016
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
- * License terms: GNU General Public License (GPL), version 2
+ * Copyright (C) STMicroelectronics 2017
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
#include <linux/init.h>
#include <linux/of.h>
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f746.c b/drivers/pinctrl/stm32/pinctrl-stm32f746.c
index a2fae7357c36..d832aab7ebe1 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32f746.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32f746.c
@@ -1,7 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Maxime Coquelin 2015
+ * Copyright (C) STMicroelectronics 2017
* Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
- * License terms: GNU General Public License (GPL), version 2
*/
#include <linux/init.h>
#include <linux/of.h>
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f769.c b/drivers/pinctrl/stm32/pinctrl-stm32f769.c
new file mode 100644
index 000000000000..f81c51c5aedf
--- /dev/null
+++ b/drivers/pinctrl/stm32/pinctrl-stm32f769.c
@@ -0,0 +1,1827 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2017
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-stm32.h"
+
+static const struct stm32_desc_pin stm32f769_pins[] = {
+ STM32_PIN(
+ PINCTRL_PIN(0, "PA0"),
+ STM32_FUNCTION(0, "GPIOA0"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(3, "TIM5_CH1"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(8, "USART2_CTS"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(12, "ETH_MII_CRS"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(1, "PA1"),
+ STM32_FUNCTION(0, "GPIOA1"),
+ STM32_FUNCTION(2, "TIM2_CH2"),
+ STM32_FUNCTION(3, "TIM5_CH2"),
+ STM32_FUNCTION(8, "USART2_RTS"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(12, "ETH_MII_RX_CLK ETH_RMII_REF_CLK"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(2, "PA2"),
+ STM32_FUNCTION(0, "GPIOA2"),
+ STM32_FUNCTION(2, "TIM2_CH3"),
+ STM32_FUNCTION(3, "TIM5_CH3"),
+ STM32_FUNCTION(4, "TIM9_CH1"),
+ STM32_FUNCTION(8, "USART2_TX"),
+ STM32_FUNCTION(9, "SAI2_SCK_B"),
+ STM32_FUNCTION(12, "ETH_MDIO"),
+ STM32_FUNCTION(13, "MDIOS_MDIO"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(3, "PA3"),
+ STM32_FUNCTION(0, "GPIOA3"),
+ STM32_FUNCTION(2, "TIM2_CH4"),
+ STM32_FUNCTION(3, "TIM5_CH4"),
+ STM32_FUNCTION(4, "TIM9_CH2"),
+ STM32_FUNCTION(8, "USART2_RX"),
+ STM32_FUNCTION(10, "LCD_B2"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D0"),
+ STM32_FUNCTION(12, "ETH_MII_COL"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(4, "PA4"),
+ STM32_FUNCTION(0, "GPIOA4"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(8, "USART2_CK"),
+ STM32_FUNCTION(9, "SPI6_NSS"),
+ STM32_FUNCTION(13, "OTG_HS_SOF"),
+ STM32_FUNCTION(14, "DCMI_HSYNC"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(5, "PA5"),
+ STM32_FUNCTION(0, "GPIOA5"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(9, "SPI6_SCK"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_CK"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(6, "PA6"),
+ STM32_FUNCTION(0, "GPIOA6"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(6, "SPI1_MISO"),
+ STM32_FUNCTION(9, "SPI6_MISO"),
+ STM32_FUNCTION(10, "TIM13_CH1"),
+ STM32_FUNCTION(13, "MDIOS_MDC"),
+ STM32_FUNCTION(14, "DCMI_PIXCLK"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(7, "PA7"),
+ STM32_FUNCTION(0, "GPIOA7"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SD"),
+ STM32_FUNCTION(9, "SPI6_MOSI"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(12, "ETH_MII_RX_DV ETH_RMII_CRS_DV"),
+ STM32_FUNCTION(13, "FMC_SDNWE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(8, "PA8"),
+ STM32_FUNCTION(0, "GPIOA8"),
+ STM32_FUNCTION(1, "MCO1"),
+ STM32_FUNCTION(2, "TIM1_CH1"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(5, "I2C3_SCL"),
+ STM32_FUNCTION(8, "USART1_CK"),
+ STM32_FUNCTION(11, "OTG_FS_SOF"),
+ STM32_FUNCTION(12, "CAN3_RX"),
+ STM32_FUNCTION(13, "UART7_RX"),
+ STM32_FUNCTION(14, "LCD_B3"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(9, "PA9"),
+ STM32_FUNCTION(0, "GPIOA9"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(5, "I2C3_SMBA"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(14, "DCMI_D0"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(10, "PA10"),
+ STM32_FUNCTION(0, "GPIOA10"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(10, "LCD_B4"),
+ STM32_FUNCTION(11, "OTG_FS_ID"),
+ STM32_FUNCTION(13, "MDIOS_MDIO"),
+ STM32_FUNCTION(14, "DCMI_D1"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(11, "PA11"),
+ STM32_FUNCTION(0, "GPIOA11"),
+ STM32_FUNCTION(2, "TIM1_CH4"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "UART4_RX"),
+ STM32_FUNCTION(8, "USART1_CTS"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(11, "OTG_FS_DM"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(12, "PA12"),
+ STM32_FUNCTION(0, "GPIOA12"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "UART4_TX"),
+ STM32_FUNCTION(8, "USART1_RTS"),
+ STM32_FUNCTION(9, "SAI2_FS_B"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(11, "OTG_FS_DP"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(13, "PA13"),
+ STM32_FUNCTION(0, "GPIOA13"),
+ STM32_FUNCTION(1, "JTMS SWDIO"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(14, "PA14"),
+ STM32_FUNCTION(0, "GPIOA14"),
+ STM32_FUNCTION(1, "JTCK SWCLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(15, "PA15"),
+ STM32_FUNCTION(0, "GPIOA15"),
+ STM32_FUNCTION(1, "JTDI"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(5, "HDMI_CEC"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(8, "SPI6_NSS"),
+ STM32_FUNCTION(9, "UART4_RTS"),
+ STM32_FUNCTION(12, "CAN3_TX"),
+ STM32_FUNCTION(13, "UART7_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(16, "PB0"),
+ STM32_FUNCTION(0, "GPIOB0"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(3, "TIM3_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(7, "DFSDM_CKOUT"),
+ STM32_FUNCTION(9, "UART4_CTS"),
+ STM32_FUNCTION(10, "LCD_R3"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D1"),
+ STM32_FUNCTION(12, "ETH_MII_RXD2"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(17, "PB1"),
+ STM32_FUNCTION(0, "GPIOB1"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(3, "TIM3_CH4"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(7, "DFSDM_DATIN1"),
+ STM32_FUNCTION(10, "LCD_R6"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D2"),
+ STM32_FUNCTION(12, "ETH_MII_RXD3"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(18, "PB2"),
+ STM32_FUNCTION(0, "GPIOB2"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(8, "SPI3_MOSI I2S3_SD"),
+ STM32_FUNCTION(10, "QUADSPI_CLK"),
+ STM32_FUNCTION(11, "DFSDM_CKIN1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(19, "PB3"),
+ STM32_FUNCTION(0, "GPIOB3"),
+ STM32_FUNCTION(1, "JTDO TRACESWO"),
+ STM32_FUNCTION(2, "TIM2_CH2"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(9, "SPI6_SCK"),
+ STM32_FUNCTION(11, "SDMMC2_D2"),
+ STM32_FUNCTION(12, "CAN3_RX"),
+ STM32_FUNCTION(13, "UART7_RX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(20, "PB4"),
+ STM32_FUNCTION(0, "GPIOB4"),
+ STM32_FUNCTION(1, "NJTRST"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(6, "SPI1_MISO"),
+ STM32_FUNCTION(7, "SPI3_MISO"),
+ STM32_FUNCTION(8, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(9, "SPI6_MISO"),
+ STM32_FUNCTION(11, "SDMMC2_D3"),
+ STM32_FUNCTION(12, "CAN3_TX"),
+ STM32_FUNCTION(13, "UART7_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(21, "PB5"),
+ STM32_FUNCTION(0, "GPIOB5"),
+ STM32_FUNCTION(2, "UART5_RX"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(5, "I2C1_SMBA"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SD"),
+ STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"),
+ STM32_FUNCTION(9, "SPI6_MOSI"),
+ STM32_FUNCTION(10, "CAN2_RX"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D7"),
+ STM32_FUNCTION(12, "ETH_PPS_OUT"),
+ STM32_FUNCTION(13, "FMC_SDCKE1"),
+ STM32_FUNCTION(14, "DCMI_D10"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(22, "PB6"),
+ STM32_FUNCTION(0, "GPIOB6"),
+ STM32_FUNCTION(2, "UART5_TX"),
+ STM32_FUNCTION(3, "TIM4_CH1"),
+ STM32_FUNCTION(4, "HDMI_CEC"),
+ STM32_FUNCTION(5, "I2C1_SCL"),
+ STM32_FUNCTION(7, "DFSDM_DATIN5"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(10, "CAN2_TX"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(12, "I2C4_SCL"),
+ STM32_FUNCTION(13, "FMC_SDNE1"),
+ STM32_FUNCTION(14, "DCMI_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(23, "PB7"),
+ STM32_FUNCTION(0, "GPIOB7"),
+ STM32_FUNCTION(3, "TIM4_CH2"),
+ STM32_FUNCTION(5, "I2C1_SDA"),
+ STM32_FUNCTION(7, "DFSDM_CKIN5"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(12, "I2C4_SDA"),
+ STM32_FUNCTION(13, "FMC_NL"),
+ STM32_FUNCTION(14, "DCMI_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(24, "PB8"),
+ STM32_FUNCTION(0, "GPIOB8"),
+ STM32_FUNCTION(2, "I2C4_SCL"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(4, "TIM10_CH1"),
+ STM32_FUNCTION(5, "I2C1_SCL"),
+ STM32_FUNCTION(7, "DFSDM_CKIN7"),
+ STM32_FUNCTION(8, "UART5_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(11, "SDMMC2_D4"),
+ STM32_FUNCTION(12, "ETH_MII_TXD3"),
+ STM32_FUNCTION(13, "SDMMC1_D4"),
+ STM32_FUNCTION(14, "DCMI_D6"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(25, "PB9"),
+ STM32_FUNCTION(0, "GPIOB9"),
+ STM32_FUNCTION(2, "I2C4_SDA"),
+ STM32_FUNCTION(3, "TIM4_CH4"),
+ STM32_FUNCTION(4, "TIM11_CH1"),
+ STM32_FUNCTION(5, "I2C1_SDA"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "DFSDM_DATIN7"),
+ STM32_FUNCTION(8, "UART5_TX"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(11, "SDMMC2_D5"),
+ STM32_FUNCTION(12, "I2C4_SMBA"),
+ STM32_FUNCTION(13, "SDMMC1_D5"),
+ STM32_FUNCTION(14, "DCMI_D7"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(26, "PB10"),
+ STM32_FUNCTION(0, "GPIOB10"),
+ STM32_FUNCTION(2, "TIM2_CH3"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "DFSDM_DATIN7"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D3"),
+ STM32_FUNCTION(12, "ETH_MII_RX_ER"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(27, "PB11"),
+ STM32_FUNCTION(0, "GPIOB11"),
+ STM32_FUNCTION(2, "TIM2_CH4"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(7, "DFSDM_CKIN7"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D4"),
+ STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"),
+ STM32_FUNCTION(14, "DSI_TE"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(28, "PB12"),
+ STM32_FUNCTION(0, "GPIOB12"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "DFSDM_DATIN1"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(9, "UART5_RX"),
+ STM32_FUNCTION(10, "CAN2_RX"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D5"),
+ STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"),
+ STM32_FUNCTION(13, "OTG_HS_ID"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(29, "PB13"),
+ STM32_FUNCTION(0, "GPIOB13"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "DFSDM_CKIN1"),
+ STM32_FUNCTION(8, "USART3_CTS"),
+ STM32_FUNCTION(9, "UART5_TX"),
+ STM32_FUNCTION(10, "CAN2_TX"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_D6"),
+ STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(30, "PB14"),
+ STM32_FUNCTION(0, "GPIOB14"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(5, "USART1_TX"),
+ STM32_FUNCTION(6, "SPI2_MISO"),
+ STM32_FUNCTION(7, "DFSDM_DATIN2"),
+ STM32_FUNCTION(8, "USART3_RTS"),
+ STM32_FUNCTION(9, "UART4_RTS"),
+ STM32_FUNCTION(10, "TIM12_CH1"),
+ STM32_FUNCTION(11, "SDMMC2_D0"),
+ STM32_FUNCTION(13, "OTG_HS_DM"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(31, "PB15"),
+ STM32_FUNCTION(0, "GPIOB15"),
+ STM32_FUNCTION(1, "RTC_REFIN"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(5, "USART1_RX"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+ STM32_FUNCTION(7, "DFSDM_CKIN2"),
+ STM32_FUNCTION(9, "UART4_CTS"),
+ STM32_FUNCTION(10, "TIM12_CH2"),
+ STM32_FUNCTION(11, "SDMMC2_D1"),
+ STM32_FUNCTION(13, "OTG_HS_DP"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(32, "PC0"),
+ STM32_FUNCTION(0, "GPIOC0"),
+ STM32_FUNCTION(4, "DFSDM_CKIN0"),
+ STM32_FUNCTION(7, "DFSDM_DATIN4"),
+ STM32_FUNCTION(9, "SAI2_FS_B"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_STP"),
+ STM32_FUNCTION(13, "FMC_SDNWE"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(33, "PC1"),
+ STM32_FUNCTION(0, "GPIOC1"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(4, "DFSDM_DATIN0"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(11, "DFSDM_CKIN4"),
+ STM32_FUNCTION(12, "ETH_MDC"),
+ STM32_FUNCTION(13, "MDIOS_MDC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(34, "PC2"),
+ STM32_FUNCTION(0, "GPIOC2"),
+ STM32_FUNCTION(4, "DFSDM_CKIN1"),
+ STM32_FUNCTION(6, "SPI2_MISO"),
+ STM32_FUNCTION(7, "DFSDM_CKOUT"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"),
+ STM32_FUNCTION(12, "ETH_MII_TXD2"),
+ STM32_FUNCTION(13, "FMC_SDNE0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(35, "PC3"),
+ STM32_FUNCTION(0, "GPIOC3"),
+ STM32_FUNCTION(4, "DFSDM_DATIN1"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"),
+ STM32_FUNCTION(12, "ETH_MII_TX_CLK"),
+ STM32_FUNCTION(13, "FMC_SDCKE0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(36, "PC4"),
+ STM32_FUNCTION(0, "GPIOC4"),
+ STM32_FUNCTION(4, "DFSDM_CKIN2"),
+ STM32_FUNCTION(6, "I2S1_MCK"),
+ STM32_FUNCTION(9, "SPDIF_RX2"),
+ STM32_FUNCTION(12, "ETH_MII_RXD0 ETH_RMII_RXD0"),
+ STM32_FUNCTION(13, "FMC_SDNE0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(37, "PC5"),
+ STM32_FUNCTION(0, "GPIOC5"),
+ STM32_FUNCTION(4, "DFSDM_DATIN2"),
+ STM32_FUNCTION(9, "SPDIF_RX3"),
+ STM32_FUNCTION(12, "ETH_MII_RXD1 ETH_RMII_RXD1"),
+ STM32_FUNCTION(13, "FMC_SDCKE0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(38, "PC6"),
+ STM32_FUNCTION(0, "GPIOC6"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(6, "I2S2_MCK"),
+ STM32_FUNCTION(8, "DFSDM_CKIN3"),
+ STM32_FUNCTION(9, "USART6_TX"),
+ STM32_FUNCTION(10, "FMC_NWAIT"),
+ STM32_FUNCTION(11, "SDMMC2_D6"),
+ STM32_FUNCTION(13, "SDMMC1_D6"),
+ STM32_FUNCTION(14, "DCMI_D0"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(39, "PC7"),
+ STM32_FUNCTION(0, "GPIOC7"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(7, "I2S3_MCK"),
+ STM32_FUNCTION(8, "DFSDM_DATIN3"),
+ STM32_FUNCTION(9, "USART6_RX"),
+ STM32_FUNCTION(10, "FMC_NE1"),
+ STM32_FUNCTION(11, "SDMMC2_D7"),
+ STM32_FUNCTION(13, "SDMMC1_D7"),
+ STM32_FUNCTION(14, "DCMI_D1"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(40, "PC8"),
+ STM32_FUNCTION(0, "GPIOC8"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(3, "TIM3_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(8, "UART5_RTS"),
+ STM32_FUNCTION(9, "USART6_CK"),
+ STM32_FUNCTION(10, "FMC_NE2 FMC_NCE"),
+ STM32_FUNCTION(13, "SDMMC1_D0"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(41, "PC9"),
+ STM32_FUNCTION(0, "GPIOC9"),
+ STM32_FUNCTION(1, "MCO2"),
+ STM32_FUNCTION(3, "TIM3_CH4"),
+ STM32_FUNCTION(4, "TIM8_CH4"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(8, "UART5_CTS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(11, "LCD_G3"),
+ STM32_FUNCTION(13, "SDMMC1_D1"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(42, "PC10"),
+ STM32_FUNCTION(0, "GPIOC10"),
+ STM32_FUNCTION(4, "DFSDM_CKIN5"),
+ STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(13, "SDMMC1_D2"),
+ STM32_FUNCTION(14, "DCMI_D8"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(43, "PC11"),
+ STM32_FUNCTION(0, "GPIOC11"),
+ STM32_FUNCTION(4, "DFSDM_DATIN5"),
+ STM32_FUNCTION(7, "SPI3_MISO"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_NCS"),
+ STM32_FUNCTION(13, "SDMMC1_D3"),
+ STM32_FUNCTION(14, "DCMI_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(44, "PC12"),
+ STM32_FUNCTION(0, "GPIOC12"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(9, "UART5_TX"),
+ STM32_FUNCTION(13, "SDMMC1_CK"),
+ STM32_FUNCTION(14, "DCMI_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(45, "PC13"),
+ STM32_FUNCTION(0, "GPIOC13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(46, "PC14"),
+ STM32_FUNCTION(0, "GPIOC14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(47, "PC15"),
+ STM32_FUNCTION(0, "GPIOC15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(48, "PD0"),
+ STM32_FUNCTION(0, "GPIOD0"),
+ STM32_FUNCTION(4, "DFSDM_CKIN6"),
+ STM32_FUNCTION(7, "DFSDM_DATIN7"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(13, "FMC_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(49, "PD1"),
+ STM32_FUNCTION(0, "GPIOD1"),
+ STM32_FUNCTION(4, "DFSDM_DATIN6"),
+ STM32_FUNCTION(7, "DFSDM_CKIN7"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(13, "FMC_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(50, "PD2"),
+ STM32_FUNCTION(0, "GPIOD2"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(3, "TIM3_ETR"),
+ STM32_FUNCTION(9, "UART5_RX"),
+ STM32_FUNCTION(13, "SDMMC1_CMD"),
+ STM32_FUNCTION(14, "DCMI_D11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(51, "PD3"),
+ STM32_FUNCTION(0, "GPIOD3"),
+ STM32_FUNCTION(4, "DFSDM_CKOUT"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "DFSDM_DATIN0"),
+ STM32_FUNCTION(8, "USART2_CTS"),
+ STM32_FUNCTION(13, "FMC_CLK"),
+ STM32_FUNCTION(14, "DCMI_D5"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(52, "PD4"),
+ STM32_FUNCTION(0, "GPIOD4"),
+ STM32_FUNCTION(7, "DFSDM_CKIN0"),
+ STM32_FUNCTION(8, "USART2_RTS"),
+ STM32_FUNCTION(13, "FMC_NOE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(53, "PD5"),
+ STM32_FUNCTION(0, "GPIOD5"),
+ STM32_FUNCTION(8, "USART2_TX"),
+ STM32_FUNCTION(13, "FMC_NWE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(54, "PD6"),
+ STM32_FUNCTION(0, "GPIOD6"),
+ STM32_FUNCTION(4, "DFSDM_CKIN4"),
+ STM32_FUNCTION(6, "SPI3_MOSI I2S3_SD"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(8, "USART2_RX"),
+ STM32_FUNCTION(11, "DFSDM_DATIN1"),
+ STM32_FUNCTION(12, "SDMMC2_CK"),
+ STM32_FUNCTION(13, "FMC_NWAIT"),
+ STM32_FUNCTION(14, "DCMI_D10"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(55, "PD7"),
+ STM32_FUNCTION(0, "GPIOD7"),
+ STM32_FUNCTION(4, "DFSDM_DATIN4"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SD"),
+ STM32_FUNCTION(7, "DFSDM_CKIN1"),
+ STM32_FUNCTION(8, "USART2_CK"),
+ STM32_FUNCTION(9, "SPDIF_RX0"),
+ STM32_FUNCTION(12, "SDMMC2_CMD"),
+ STM32_FUNCTION(13, "FMC_NE1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(56, "PD8"),
+ STM32_FUNCTION(0, "GPIOD8"),
+ STM32_FUNCTION(4, "DFSDM_CKIN3"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(9, "SPDIF_RX1"),
+ STM32_FUNCTION(13, "FMC_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(57, "PD9"),
+ STM32_FUNCTION(0, "GPIOD9"),
+ STM32_FUNCTION(4, "DFSDM_DATIN3"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(13, "FMC_D14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(58, "PD10"),
+ STM32_FUNCTION(0, "GPIOD10"),
+ STM32_FUNCTION(4, "DFSDM_CKOUT"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(13, "FMC_D15"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(59, "PD11"),
+ STM32_FUNCTION(0, "GPIOD11"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(8, "USART3_CTS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(11, "SAI2_SD_A"),
+ STM32_FUNCTION(13, "FMC_A16 FMC_CLE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(60, "PD12"),
+ STM32_FUNCTION(0, "GPIOD12"),
+ STM32_FUNCTION(3, "TIM4_CH1"),
+ STM32_FUNCTION(4, "LPTIM1_IN1"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(8, "USART3_RTS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(11, "SAI2_FS_A"),
+ STM32_FUNCTION(13, "FMC_A17 FMC_ALE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(61, "PD13"),
+ STM32_FUNCTION(0, "GPIOD13"),
+ STM32_FUNCTION(3, "TIM4_CH2"),
+ STM32_FUNCTION(4, "LPTIM1_OUT"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(11, "SAI2_SCK_A"),
+ STM32_FUNCTION(13, "FMC_A18"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(62, "PD14"),
+ STM32_FUNCTION(0, "GPIOD14"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(9, "UART8_CTS"),
+ STM32_FUNCTION(13, "FMC_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(63, "PD15"),
+ STM32_FUNCTION(0, "GPIOD15"),
+ STM32_FUNCTION(3, "TIM4_CH4"),
+ STM32_FUNCTION(9, "UART8_RTS"),
+ STM32_FUNCTION(13, "FMC_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(64, "PE0"),
+ STM32_FUNCTION(0, "GPIOE0"),
+ STM32_FUNCTION(3, "TIM4_ETR"),
+ STM32_FUNCTION(4, "LPTIM1_ETR"),
+ STM32_FUNCTION(9, "UART8_RX"),
+ STM32_FUNCTION(11, "SAI2_MCLK_A"),
+ STM32_FUNCTION(13, "FMC_NBL0"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(65, "PE1"),
+ STM32_FUNCTION(0, "GPIOE1"),
+ STM32_FUNCTION(4, "LPTIM1_IN2"),
+ STM32_FUNCTION(9, "UART8_TX"),
+ STM32_FUNCTION(13, "FMC_NBL1"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(66, "PE2"),
+ STM32_FUNCTION(0, "GPIOE2"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(6, "SPI4_SCK"),
+ STM32_FUNCTION(7, "SAI1_MCLK_A"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2"),
+ STM32_FUNCTION(12, "ETH_MII_TXD3"),
+ STM32_FUNCTION(13, "FMC_A23"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(67, "PE3"),
+ STM32_FUNCTION(0, "GPIOE3"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(7, "SAI1_SD_B"),
+ STM32_FUNCTION(13, "FMC_A19"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(68, "PE4"),
+ STM32_FUNCTION(0, "GPIOE4"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(6, "SPI4_NSS"),
+ STM32_FUNCTION(7, "SAI1_FS_A"),
+ STM32_FUNCTION(11, "DFSDM_DATIN3"),
+ STM32_FUNCTION(13, "FMC_A20"),
+ STM32_FUNCTION(14, "DCMI_D4"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(69, "PE5"),
+ STM32_FUNCTION(0, "GPIOE5"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(4, "TIM9_CH1"),
+ STM32_FUNCTION(6, "SPI4_MISO"),
+ STM32_FUNCTION(7, "SAI1_SCK_A"),
+ STM32_FUNCTION(11, "DFSDM_CKIN3"),
+ STM32_FUNCTION(13, "FMC_A21"),
+ STM32_FUNCTION(14, "DCMI_D6"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(70, "PE6"),
+ STM32_FUNCTION(0, "GPIOE6"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(2, "TIM1_BKIN2"),
+ STM32_FUNCTION(4, "TIM9_CH2"),
+ STM32_FUNCTION(6, "SPI4_MOSI"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(13, "FMC_A22"),
+ STM32_FUNCTION(14, "DCMI_D7"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(71, "PE7"),
+ STM32_FUNCTION(0, "GPIOE7"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(7, "DFSDM_DATIN2"),
+ STM32_FUNCTION(9, "UART7_RX"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO0"),
+ STM32_FUNCTION(13, "FMC_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(72, "PE8"),
+ STM32_FUNCTION(0, "GPIOE8"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(7, "DFSDM_CKIN2"),
+ STM32_FUNCTION(9, "UART7_TX"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO1"),
+ STM32_FUNCTION(13, "FMC_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(73, "PE9"),
+ STM32_FUNCTION(0, "GPIOE9"),
+ STM32_FUNCTION(2, "TIM1_CH1"),
+ STM32_FUNCTION(7, "DFSDM_CKOUT"),
+ STM32_FUNCTION(9, "UART7_RTS"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO2"),
+ STM32_FUNCTION(13, "FMC_D6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(74, "PE10"),
+ STM32_FUNCTION(0, "GPIOE10"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(7, "DFSDM_DATIN4"),
+ STM32_FUNCTION(9, "UART7_CTS"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO3"),
+ STM32_FUNCTION(13, "FMC_D7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(75, "PE11"),
+ STM32_FUNCTION(0, "GPIOE11"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(6, "SPI4_NSS"),
+ STM32_FUNCTION(7, "DFSDM_CKIN4"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(13, "FMC_D8"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(76, "PE12"),
+ STM32_FUNCTION(0, "GPIOE12"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(6, "SPI4_SCK"),
+ STM32_FUNCTION(7, "DFSDM_DATIN5"),
+ STM32_FUNCTION(11, "SAI2_SCK_B"),
+ STM32_FUNCTION(13, "FMC_D9"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(77, "PE13"),
+ STM32_FUNCTION(0, "GPIOE13"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(6, "SPI4_MISO"),
+ STM32_FUNCTION(7, "DFSDM_CKIN5"),
+ STM32_FUNCTION(11, "SAI2_FS_B"),
+ STM32_FUNCTION(13, "FMC_D10"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(78, "PE14"),
+ STM32_FUNCTION(0, "GPIOE14"),
+ STM32_FUNCTION(2, "TIM1_CH4"),
+ STM32_FUNCTION(6, "SPI4_MOSI"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(13, "FMC_D11"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(79, "PE15"),
+ STM32_FUNCTION(0, "GPIOE15"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(13, "FMC_D12"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(80, "PF0"),
+ STM32_FUNCTION(0, "GPIOF0"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(13, "FMC_A0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(81, "PF1"),
+ STM32_FUNCTION(0, "GPIOF1"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(13, "FMC_A1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(82, "PF2"),
+ STM32_FUNCTION(0, "GPIOF2"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(13, "FMC_A2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(83, "PF3"),
+ STM32_FUNCTION(0, "GPIOF3"),
+ STM32_FUNCTION(13, "FMC_A3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(84, "PF4"),
+ STM32_FUNCTION(0, "GPIOF4"),
+ STM32_FUNCTION(13, "FMC_A4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(85, "PF5"),
+ STM32_FUNCTION(0, "GPIOF5"),
+ STM32_FUNCTION(13, "FMC_A5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(86, "PF6"),
+ STM32_FUNCTION(0, "GPIOF6"),
+ STM32_FUNCTION(4, "TIM10_CH1"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(7, "SAI1_SD_B"),
+ STM32_FUNCTION(9, "UART7_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(87, "PF7"),
+ STM32_FUNCTION(0, "GPIOF7"),
+ STM32_FUNCTION(4, "TIM11_CH1"),
+ STM32_FUNCTION(6, "SPI5_SCK"),
+ STM32_FUNCTION(7, "SAI1_MCLK_B"),
+ STM32_FUNCTION(9, "UART7_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(88, "PF8"),
+ STM32_FUNCTION(0, "GPIOF8"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(7, "SAI1_SCK_B"),
+ STM32_FUNCTION(9, "UART7_RTS"),
+ STM32_FUNCTION(10, "TIM13_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(89, "PF9"),
+ STM32_FUNCTION(0, "GPIOF9"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(7, "SAI1_FS_B"),
+ STM32_FUNCTION(9, "UART7_CTS"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(90, "PF10"),
+ STM32_FUNCTION(0, "GPIOF10"),
+ STM32_FUNCTION(10, "QUADSPI_CLK"),
+ STM32_FUNCTION(14, "DCMI_D11"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(91, "PF11"),
+ STM32_FUNCTION(0, "GPIOF11"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(13, "FMC_SDNRAS"),
+ STM32_FUNCTION(14, "DCMI_D12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(92, "PF12"),
+ STM32_FUNCTION(0, "GPIOF12"),
+ STM32_FUNCTION(13, "FMC_A6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(93, "PF13"),
+ STM32_FUNCTION(0, "GPIOF13"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(7, "DFSDM_DATIN6"),
+ STM32_FUNCTION(13, "FMC_A7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(94, "PF14"),
+ STM32_FUNCTION(0, "GPIOF14"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(7, "DFSDM_CKIN6"),
+ STM32_FUNCTION(13, "FMC_A8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(95, "PF15"),
+ STM32_FUNCTION(0, "GPIOF15"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(13, "FMC_A9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(96, "PG0"),
+ STM32_FUNCTION(0, "GPIOG0"),
+ STM32_FUNCTION(13, "FMC_A10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(97, "PG1"),
+ STM32_FUNCTION(0, "GPIOG1"),
+ STM32_FUNCTION(13, "FMC_A11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(98, "PG2"),
+ STM32_FUNCTION(0, "GPIOG2"),
+ STM32_FUNCTION(13, "FMC_A12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(99, "PG3"),
+ STM32_FUNCTION(0, "GPIOG3"),
+ STM32_FUNCTION(13, "FMC_A13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(100, "PG4"),
+ STM32_FUNCTION(0, "GPIOG4"),
+ STM32_FUNCTION(13, "FMC_A14 FMC_BA0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(101, "PG5"),
+ STM32_FUNCTION(0, "GPIOG5"),
+ STM32_FUNCTION(13, "FMC_A15 FMC_BA1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(102, "PG6"),
+ STM32_FUNCTION(0, "GPIOG6"),
+ STM32_FUNCTION(13, "FMC_NE3"),
+ STM32_FUNCTION(14, "DCMI_D12"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(103, "PG7"),
+ STM32_FUNCTION(0, "GPIOG7"),
+ STM32_FUNCTION(7, "SAI1_MCLK_A"),
+ STM32_FUNCTION(9, "USART6_CK"),
+ STM32_FUNCTION(13, "FMC_INT"),
+ STM32_FUNCTION(14, "DCMI_D13"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(104, "PG8"),
+ STM32_FUNCTION(0, "GPIOG8"),
+ STM32_FUNCTION(6, "SPI6_NSS"),
+ STM32_FUNCTION(8, "SPDIF_RX2"),
+ STM32_FUNCTION(9, "USART6_RTS"),
+ STM32_FUNCTION(12, "ETH_PPS_OUT"),
+ STM32_FUNCTION(13, "FMC_SDCLK"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(105, "PG9"),
+ STM32_FUNCTION(0, "GPIOG9"),
+ STM32_FUNCTION(6, "SPI1_MISO"),
+ STM32_FUNCTION(8, "SPDIF_RX3"),
+ STM32_FUNCTION(9, "USART6_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO2"),
+ STM32_FUNCTION(11, "SAI2_FS_B"),
+ STM32_FUNCTION(12, "SDMMC2_D0"),
+ STM32_FUNCTION(13, "FMC_NE2 FMC_NCE"),
+ STM32_FUNCTION(14, "DCMI_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(106, "PG10"),
+ STM32_FUNCTION(0, "GPIOG10"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(10, "LCD_G3"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(12, "SDMMC2_D1"),
+ STM32_FUNCTION(13, "FMC_NE3"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(107, "PG11"),
+ STM32_FUNCTION(0, "GPIOG11"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(8, "SPDIF_RX0"),
+ STM32_FUNCTION(11, "SDMMC2_D2"),
+ STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(108, "PG12"),
+ STM32_FUNCTION(0, "GPIOG12"),
+ STM32_FUNCTION(4, "LPTIM1_IN1"),
+ STM32_FUNCTION(6, "SPI6_MISO"),
+ STM32_FUNCTION(8, "SPDIF_RX1"),
+ STM32_FUNCTION(9, "USART6_RTS"),
+ STM32_FUNCTION(10, "LCD_B4"),
+ STM32_FUNCTION(12, "SDMMC2_D3"),
+ STM32_FUNCTION(13, "FMC_NE4"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(109, "PG13"),
+ STM32_FUNCTION(0, "GPIOG13"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(4, "LPTIM1_OUT"),
+ STM32_FUNCTION(6, "SPI6_SCK"),
+ STM32_FUNCTION(9, "USART6_CTS"),
+ STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"),
+ STM32_FUNCTION(13, "FMC_A24"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(110, "PG14"),
+ STM32_FUNCTION(0, "GPIOG14"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(4, "LPTIM1_ETR"),
+ STM32_FUNCTION(6, "SPI6_MOSI"),
+ STM32_FUNCTION(9, "USART6_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO3"),
+ STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"),
+ STM32_FUNCTION(13, "FMC_A25"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(111, "PG15"),
+ STM32_FUNCTION(0, "GPIOG15"),
+ STM32_FUNCTION(9, "USART6_CTS"),
+ STM32_FUNCTION(13, "FMC_SDNCAS"),
+ STM32_FUNCTION(14, "DCMI_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(112, "PH0"),
+ STM32_FUNCTION(0, "GPIOH0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(113, "PH1"),
+ STM32_FUNCTION(0, "GPIOH1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(114, "PH2"),
+ STM32_FUNCTION(0, "GPIOH2"),
+ STM32_FUNCTION(4, "LPTIM1_IN2"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO0"),
+ STM32_FUNCTION(11, "SAI2_SCK_B"),
+ STM32_FUNCTION(12, "ETH_MII_CRS"),
+ STM32_FUNCTION(13, "FMC_SDCKE0"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(115, "PH3"),
+ STM32_FUNCTION(0, "GPIOH3"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO1"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(12, "ETH_MII_COL"),
+ STM32_FUNCTION(13, "FMC_SDNE0"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(116, "PH4"),
+ STM32_FUNCTION(0, "GPIOH4"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(10, "LCD_G5"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(117, "PH5"),
+ STM32_FUNCTION(0, "GPIOH5"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(13, "FMC_SDNWE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(118, "PH6"),
+ STM32_FUNCTION(0, "GPIOH6"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(6, "SPI5_SCK"),
+ STM32_FUNCTION(10, "TIM12_CH1"),
+ STM32_FUNCTION(12, "ETH_MII_RXD2"),
+ STM32_FUNCTION(13, "FMC_SDNE1"),
+ STM32_FUNCTION(14, "DCMI_D8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(119, "PH7"),
+ STM32_FUNCTION(0, "GPIOH7"),
+ STM32_FUNCTION(5, "I2C3_SCL"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(12, "ETH_MII_RXD3"),
+ STM32_FUNCTION(13, "FMC_SDCKE1"),
+ STM32_FUNCTION(14, "DCMI_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(120, "PH8"),
+ STM32_FUNCTION(0, "GPIOH8"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(13, "FMC_D16"),
+ STM32_FUNCTION(14, "DCMI_HSYNC"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(121, "PH9"),
+ STM32_FUNCTION(0, "GPIOH9"),
+ STM32_FUNCTION(5, "I2C3_SMBA"),
+ STM32_FUNCTION(10, "TIM12_CH2"),
+ STM32_FUNCTION(13, "FMC_D17"),
+ STM32_FUNCTION(14, "DCMI_D0"),
+ STM32_FUNCTION(15, "LCD_R3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(122, "PH10"),
+ STM32_FUNCTION(0, "GPIOH10"),
+ STM32_FUNCTION(3, "TIM5_CH1"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(13, "FMC_D18"),
+ STM32_FUNCTION(14, "DCMI_D1"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(123, "PH11"),
+ STM32_FUNCTION(0, "GPIOH11"),
+ STM32_FUNCTION(3, "TIM5_CH2"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(13, "FMC_D19"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(124, "PH12"),
+ STM32_FUNCTION(0, "GPIOH12"),
+ STM32_FUNCTION(3, "TIM5_CH3"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(13, "FMC_D20"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(125, "PH13"),
+ STM32_FUNCTION(0, "GPIOH13"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(13, "FMC_D21"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(126, "PH14"),
+ STM32_FUNCTION(0, "GPIOH14"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(13, "FMC_D22"),
+ STM32_FUNCTION(14, "DCMI_D4"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(127, "PH15"),
+ STM32_FUNCTION(0, "GPIOH15"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(13, "FMC_D23"),
+ STM32_FUNCTION(14, "DCMI_D11"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(128, "PI0"),
+ STM32_FUNCTION(0, "GPIOI0"),
+ STM32_FUNCTION(3, "TIM5_CH4"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(13, "FMC_D24"),
+ STM32_FUNCTION(14, "DCMI_D13"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(129, "PI1"),
+ STM32_FUNCTION(0, "GPIOI1"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(13, "FMC_D25"),
+ STM32_FUNCTION(14, "DCMI_D8"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(130, "PI2"),
+ STM32_FUNCTION(0, "GPIOI2"),
+ STM32_FUNCTION(4, "TIM8_CH4"),
+ STM32_FUNCTION(6, "SPI2_MISO"),
+ STM32_FUNCTION(13, "FMC_D26"),
+ STM32_FUNCTION(14, "DCMI_D9"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(131, "PI3"),
+ STM32_FUNCTION(0, "GPIOI3"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+ STM32_FUNCTION(13, "FMC_D27"),
+ STM32_FUNCTION(14, "DCMI_D10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(132, "PI4"),
+ STM32_FUNCTION(0, "GPIOI4"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(11, "SAI2_MCLK_A"),
+ STM32_FUNCTION(13, "FMC_NBL2"),
+ STM32_FUNCTION(14, "DCMI_D5"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(133, "PI5"),
+ STM32_FUNCTION(0, "GPIOI5"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(11, "SAI2_SCK_A"),
+ STM32_FUNCTION(13, "FMC_NBL3"),
+ STM32_FUNCTION(14, "DCMI_VSYNC"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(134, "PI6"),
+ STM32_FUNCTION(0, "GPIOI6"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(11, "SAI2_SD_A"),
+ STM32_FUNCTION(13, "FMC_D28"),
+ STM32_FUNCTION(14, "DCMI_D6"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(135, "PI7"),
+ STM32_FUNCTION(0, "GPIOI7"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(11, "SAI2_FS_A"),
+ STM32_FUNCTION(13, "FMC_D29"),
+ STM32_FUNCTION(14, "DCMI_D7"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(136, "PI8"),
+ STM32_FUNCTION(0, "GPIOI8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(137, "PI9"),
+ STM32_FUNCTION(0, "GPIOI9"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(13, "FMC_D30"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(138, "PI10"),
+ STM32_FUNCTION(0, "GPIOI10"),
+ STM32_FUNCTION(12, "ETH_MII_RX_ER"),
+ STM32_FUNCTION(13, "FMC_D31"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(139, "PI11"),
+ STM32_FUNCTION(0, "GPIOI11"),
+ STM32_FUNCTION(10, "LCD_G6"),
+ STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(140, "PI12"),
+ STM32_FUNCTION(0, "GPIOI12"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(141, "PI13"),
+ STM32_FUNCTION(0, "GPIOI13"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(142, "PI14"),
+ STM32_FUNCTION(0, "GPIOI14"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(143, "PI15"),
+ STM32_FUNCTION(0, "GPIOI15"),
+ STM32_FUNCTION(10, "LCD_G2"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(144, "PJ0"),
+ STM32_FUNCTION(0, "GPIOJ0"),
+ STM32_FUNCTION(10, "LCD_R7"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(145, "PJ1"),
+ STM32_FUNCTION(0, "GPIOJ1"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(146, "PJ2"),
+ STM32_FUNCTION(0, "GPIOJ2"),
+ STM32_FUNCTION(14, "DSI_TE"),
+ STM32_FUNCTION(15, "LCD_R3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(147, "PJ3"),
+ STM32_FUNCTION(0, "GPIOJ3"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(148, "PJ4"),
+ STM32_FUNCTION(0, "GPIOJ4"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(149, "PJ5"),
+ STM32_FUNCTION(0, "GPIOJ5"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(150, "PJ6"),
+ STM32_FUNCTION(0, "GPIOJ6"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(151, "PJ7"),
+ STM32_FUNCTION(0, "GPIOJ7"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(152, "PJ8"),
+ STM32_FUNCTION(0, "GPIOJ8"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(153, "PJ9"),
+ STM32_FUNCTION(0, "GPIOJ9"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(154, "PJ10"),
+ STM32_FUNCTION(0, "GPIOJ10"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(155, "PJ11"),
+ STM32_FUNCTION(0, "GPIOJ11"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(156, "PJ12"),
+ STM32_FUNCTION(0, "GPIOJ12"),
+ STM32_FUNCTION(10, "LCD_G3"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(157, "PJ13"),
+ STM32_FUNCTION(0, "GPIOJ13"),
+ STM32_FUNCTION(10, "LCD_G4"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(158, "PJ14"),
+ STM32_FUNCTION(0, "GPIOJ14"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(159, "PJ15"),
+ STM32_FUNCTION(0, "GPIOJ15"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(160, "PK0"),
+ STM32_FUNCTION(0, "GPIOK0"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(161, "PK1"),
+ STM32_FUNCTION(0, "GPIOK1"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(162, "PK2"),
+ STM32_FUNCTION(0, "GPIOK2"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(163, "PK3"),
+ STM32_FUNCTION(0, "GPIOK3"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(164, "PK4"),
+ STM32_FUNCTION(0, "GPIOK4"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(165, "PK5"),
+ STM32_FUNCTION(0, "GPIOK5"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(166, "PK6"),
+ STM32_FUNCTION(0, "GPIOK6"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(167, "PK7"),
+ STM32_FUNCTION(0, "GPIOK7"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+};
+
+static struct stm32_pinctrl_match_data stm32f769_match_data = {
+ .pins = stm32f769_pins,
+ .npins = ARRAY_SIZE(stm32f769_pins),
+};
+
+static const struct of_device_id stm32f769_pctrl_match[] = {
+ {
+ .compatible = "st,stm32f769-pinctrl",
+ .data = &stm32f769_match_data,
+ },
+ { }
+};
+
+static struct platform_driver stm32f769_pinctrl_driver = {
+ .probe = stm32_pctl_probe,
+ .driver = {
+ .name = "stm32f769-pinctrl",
+ .of_match_table = stm32f769_pctrl_match,
+ },
+};
+
+static int __init stm32f769_pinctrl_init(void)
+{
+ return platform_driver_register(&stm32f769_pinctrl_driver);
+}
+arch_initcall(stm32f769_pinctrl_init);
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32h743.c b/drivers/pinctrl/stm32/pinctrl-stm32h743.c
index e34b2b9217ce..ffe7b5271506 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32h743.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32h743.c
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) Alexandre Torgue 2017
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
- * License terms: GNU General Public License (GPL), version 2
+ * Copyright (C) STMicroelectronics 2017
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
#include <linux/init.h>
#include <linux/of.h>
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c
new file mode 100644
index 000000000000..7c7d6284b23c
--- /dev/null
+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c
@@ -0,0 +1,2188 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-stm32.h"
+
+static const struct stm32_desc_pin stm32mp157_pins[] = {
+ STM32_PIN(
+ PINCTRL_PIN(0, "PA0"),
+ STM32_FUNCTION(0, "GPIOA0"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(3, "TIM5_CH1"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(5, "TIM15_BKIN"),
+ STM32_FUNCTION(8, "USART2_CTS_NSS USART_BOOT2_CTS_NSS"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "SDMMC2_CMD"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(12, "ETH_GMII_CRS ETH_MII_CRS"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(1, "PA1"),
+ STM32_FUNCTION(0, "GPIOA1"),
+ STM32_FUNCTION(1, "ETH_CLK"),
+ STM32_FUNCTION(2, "TIM2_CH2"),
+ STM32_FUNCTION(3, "TIM5_CH2"),
+ STM32_FUNCTION(4, "LPTIM3_OUT"),
+ STM32_FUNCTION(5, "TIM15_CH1N"),
+ STM32_FUNCTION(8, "USART2_RTS USART_BOOT2_RTS"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3 QUADSPI_BOOTBK1_IO3"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(12, "ETH_GMII_RX_CLK ETH_MII_RX_CLK ETH_RGMII_RX_CLK ETH_RMII_REF_CLK"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(2, "PA2"),
+ STM32_FUNCTION(0, "GPIOA2"),
+ STM32_FUNCTION(2, "TIM2_CH3"),
+ STM32_FUNCTION(3, "TIM5_CH3"),
+ STM32_FUNCTION(4, "LPTIM4_OUT"),
+ STM32_FUNCTION(5, "TIM15_CH1"),
+ STM32_FUNCTION(8, "USART2_TX USART_BOOT2_TX"),
+ STM32_FUNCTION(9, "SAI2_SCK_B"),
+ STM32_FUNCTION(11, "SDMMC2_D0DIR SDMMC_BOOT2_D0DIR"),
+ STM32_FUNCTION(12, "ETH_MDIO"),
+ STM32_FUNCTION(13, "MDIOS_MDIO"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(3, "PA3"),
+ STM32_FUNCTION(0, "GPIOA3"),
+ STM32_FUNCTION(2, "TIM2_CH4"),
+ STM32_FUNCTION(3, "TIM5_CH4"),
+ STM32_FUNCTION(4, "LPTIM5_OUT"),
+ STM32_FUNCTION(5, "TIM15_CH2"),
+ STM32_FUNCTION(8, "USART2_RX USART_BOOT2_RX"),
+ STM32_FUNCTION(10, "LCD_B2"),
+ STM32_FUNCTION(12, "ETH_GMII_COL ETH_MII_COL"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(4, "PA4"),
+ STM32_FUNCTION(0, "GPIOA4"),
+ STM32_FUNCTION(1, "HDP0"),
+ STM32_FUNCTION(3, "TIM5_ETR"),
+ STM32_FUNCTION(5, "SAI4_D2"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(8, "USART2_CK USART_BOOT2_CK"),
+ STM32_FUNCTION(9, "SPI6_NSS"),
+ STM32_FUNCTION(13, "SAI4_FS_A"),
+ STM32_FUNCTION(14, "DCMI_HSYNC"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(5, "PA5"),
+ STM32_FUNCTION(0, "GPIOA5"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(5, "SAI4_CK1"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(9, "SPI6_SCK"),
+ STM32_FUNCTION(13, "SAI4_MCLK_A"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(6, "PA6"),
+ STM32_FUNCTION(0, "GPIOA6"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(5, "SAI4_CK2"),
+ STM32_FUNCTION(6, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(9, "SPI6_MISO"),
+ STM32_FUNCTION(10, "TIM13_CH1"),
+ STM32_FUNCTION(12, "MDIOS_MDC"),
+ STM32_FUNCTION(13, "SAI4_SCK_A"),
+ STM32_FUNCTION(14, "DCMI_PIXCLK"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(7, "PA7"),
+ STM32_FUNCTION(0, "GPIOA7"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(5, "SAI4_D1"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(9, "SPI6_MOSI"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_CLK"),
+ STM32_FUNCTION(12, "ETH_GMII_RX_DV ETH_MII_RX_DV ETH_RGMII_RX_CTL ETH_RMII_CRS_DV"),
+ STM32_FUNCTION(13, "SAI4_SD_A"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(8, "PA8"),
+ STM32_FUNCTION(0, "GPIOA8"),
+ STM32_FUNCTION(1, "MCO1"),
+ STM32_FUNCTION(2, "TIM1_CH1"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(5, "I2C3_SCL"),
+ STM32_FUNCTION(6, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(8, "USART1_CK"),
+ STM32_FUNCTION(9, "SDMMC2_CKIN SDMMC_BOOT2_CKIN"),
+ STM32_FUNCTION(10, "SDMMC2_D4 SDMMC_BOOT2_D4"),
+ STM32_FUNCTION(11, "USBO_SOF"),
+ STM32_FUNCTION(13, "SAI4_SD_B"),
+ STM32_FUNCTION(14, "UART7_RX"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(9, "PA9"),
+ STM32_FUNCTION(0, "GPIOA9"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(5, "I2C3_SMBA"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(9, "SDMMC2_CDIR SDMMC_BOOT2_CDIR"),
+ STM32_FUNCTION(10, "CAN1_RXFD"),
+ STM32_FUNCTION(11, "SDMMC2_D5 SDMMC_BOOT2_D5"),
+ STM32_FUNCTION(14, "DCMI_D0"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(10, "PA10"),
+ STM32_FUNCTION(0, "GPIOA10"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(6, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(10, "CAN1_TXFD"),
+ STM32_FUNCTION(12, "MDIOS_MDIO"),
+ STM32_FUNCTION(13, "SAI4_FS_B"),
+ STM32_FUNCTION(14, "DCMI_D1"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(11, "PA11"),
+ STM32_FUNCTION(0, "GPIOA11"),
+ STM32_FUNCTION(2, "TIM1_CH4"),
+ STM32_FUNCTION(3, "I2C6_SCL"),
+ STM32_FUNCTION(5, "I2C5_SCL"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "UART4_RX"),
+ STM32_FUNCTION(8, "USART1_CTS_NSS"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(12, "PA12"),
+ STM32_FUNCTION(0, "GPIOA12"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(3, "I2C6_SDA"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "UART4_TX"),
+ STM32_FUNCTION(8, "USART1_RTS"),
+ STM32_FUNCTION(9, "SAI2_FS_B"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(13, "PA13"),
+ STM32_FUNCTION(0, "GPIOA13"),
+ STM32_FUNCTION(1, "DBTRGO"),
+ STM32_FUNCTION(2, "DBTRGI"),
+ STM32_FUNCTION(3, "MCO1"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(14, "PA14"),
+ STM32_FUNCTION(0, "GPIOA14"),
+ STM32_FUNCTION(1, "DBTRGO"),
+ STM32_FUNCTION(2, "DBTRGI"),
+ STM32_FUNCTION(3, "MCO2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(15, "PA15"),
+ STM32_FUNCTION(0, "GPIOA15"),
+ STM32_FUNCTION(1, "DBTRGI"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(3, "SAI4_D2"),
+ STM32_FUNCTION(4, "SDMMC1_CDIR"),
+ STM32_FUNCTION(5, "HDMI_CEC"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(8, "SPI6_NSS"),
+ STM32_FUNCTION(9, "UART4_RTS UART_BOOT4_RTS"),
+ STM32_FUNCTION(10, "SDMMC2_D5 SDMMC_BOOT2_D5"),
+ STM32_FUNCTION(11, "SDMMC2_CDIR SDMMC_BOOT2_CDIR"),
+ STM32_FUNCTION(12, "SDMMC1_D5 SDMMC_BOOT1_D5"),
+ STM32_FUNCTION(13, "SAI4_FS_A"),
+ STM32_FUNCTION(14, "UART7_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(16, "PB0"),
+ STM32_FUNCTION(0, "GPIOB0"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(3, "TIM3_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(7, "DFSDM_CKOUT"),
+ STM32_FUNCTION(9, "UART4_CTS UART_BOOT4_CTS"),
+ STM32_FUNCTION(10, "LCD_R3"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD2 ETH_MII_RXD2 ETH_RGMII_RXD2"),
+ STM32_FUNCTION(13, "MDIOS_MDIO"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(17, "PB1"),
+ STM32_FUNCTION(0, "GPIOB1"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(3, "TIM3_CH4"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(7, "DFSDM_DATA1"),
+ STM32_FUNCTION(10, "LCD_R6"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD3 ETH_MII_RXD3 ETH_RGMII_RXD3"),
+ STM32_FUNCTION(13, "MDIOS_MDC"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(18, "PB2"),
+ STM32_FUNCTION(0, "GPIOB2"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(2, "RTC_OUT2"),
+ STM32_FUNCTION(3, "SAI1_D1"),
+ STM32_FUNCTION(4, "DFSDM_CK1"),
+ STM32_FUNCTION(5, "USART1_RX"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(8, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(9, "UART4_RX UART_BOOT4_RX"),
+ STM32_FUNCTION(10, "QUADSPI_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(19, "PB3"),
+ STM32_FUNCTION(0, "GPIOB3"),
+ STM32_FUNCTION(1, "TRACED9"),
+ STM32_FUNCTION(2, "TIM2_CH2"),
+ STM32_FUNCTION(5, "SAI4_CK1"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(9, "SPI6_SCK"),
+ STM32_FUNCTION(10, "SDMMC2_D2 SDMMC_BOOT2_D2"),
+ STM32_FUNCTION(13, "SAI4_MCLK_A"),
+ STM32_FUNCTION(14, "UART7_RX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(20, "PB4"),
+ STM32_FUNCTION(0, "GPIOB4"),
+ STM32_FUNCTION(1, "TRACED8"),
+ STM32_FUNCTION(2, "TIM16_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(5, "SAI4_CK2"),
+ STM32_FUNCTION(6, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(7, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(8, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(9, "SPI6_MISO"),
+ STM32_FUNCTION(10, "SDMMC2_D3 SDMMC_BOOT2_D3"),
+ STM32_FUNCTION(13, "SAI4_SCK_A"),
+ STM32_FUNCTION(14, "UART7_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(21, "PB5"),
+ STM32_FUNCTION(0, "GPIOB5"),
+ STM32_FUNCTION(1, "ETH_CLK"),
+ STM32_FUNCTION(2, "TIM17_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "SAI4_D1"),
+ STM32_FUNCTION(5, "I2C1_SMBA"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(7, "I2C4_SMBA"),
+ STM32_FUNCTION(8, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(9, "SPI6_MOSI"),
+ STM32_FUNCTION(10, "CAN2_RX"),
+ STM32_FUNCTION(11, "SAI4_SD_A"),
+ STM32_FUNCTION(12, "ETH_PPS_OUT"),
+ STM32_FUNCTION(13, "UART5_RX UART_BOOT5_RX"),
+ STM32_FUNCTION(14, "DCMI_D10"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(22, "PB6"),
+ STM32_FUNCTION(0, "GPIOB6"),
+ STM32_FUNCTION(2, "TIM16_CH1N"),
+ STM32_FUNCTION(3, "TIM4_CH1"),
+ STM32_FUNCTION(5, "I2C1_SCL"),
+ STM32_FUNCTION(6, "HDMI_CEC"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(10, "CAN2_TX"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_NCS QUADSPI_BOOTBK1_NCS"),
+ STM32_FUNCTION(12, "DFSDM_DATA5"),
+ STM32_FUNCTION(13, "UART5_TX"),
+ STM32_FUNCTION(14, "DCMI_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(23, "PB7"),
+ STM32_FUNCTION(0, "GPIOB7"),
+ STM32_FUNCTION(2, "TIM17_CH1N"),
+ STM32_FUNCTION(3, "TIM4_CH2"),
+ STM32_FUNCTION(5, "I2C1_SDA"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(10, "CAN2_TXFD"),
+ STM32_FUNCTION(11, "SDMMC2_D1 SDMMC_BOOT2_D1"),
+ STM32_FUNCTION(12, "DFSDM_CK5"),
+ STM32_FUNCTION(13, "FMC_NL"),
+ STM32_FUNCTION(14, "DCMI_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(24, "PB8"),
+ STM32_FUNCTION(0, "GPIOB8"),
+ STM32_FUNCTION(1, "HDP6"),
+ STM32_FUNCTION(2, "TIM16_CH1"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(4, "DFSDM_CK7"),
+ STM32_FUNCTION(5, "I2C1_SCL"),
+ STM32_FUNCTION(6, "SDMMC1_CKIN SDMMC_BOOT1_CKIN"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(8, "SDMMC2_CKIN SDMMC_BOOT2_CKIN"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(11, "SDMMC2_D4 SDMMC_BOOT2_D4"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD3 ETH_MII_TXD3 ETH_RGMII_TXD3"),
+ STM32_FUNCTION(13, "SDMMC1_D4 SDMMC_BOOT1_D4"),
+ STM32_FUNCTION(14, "DCMI_D6"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(25, "PB9"),
+ STM32_FUNCTION(0, "GPIOB9"),
+ STM32_FUNCTION(1, "HDP7"),
+ STM32_FUNCTION(2, "TIM17_CH1"),
+ STM32_FUNCTION(3, "TIM4_CH4"),
+ STM32_FUNCTION(4, "DFSDM_DATA7"),
+ STM32_FUNCTION(5, "I2C1_SDA"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(8, "SDMMC2_CDIR SDMMC_BOOT2_CDIR"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(11, "SDMMC2_D5 SDMMC_BOOT2_D5"),
+ STM32_FUNCTION(12, "SDMMC1_CDIR SDMMC_BOOT1_CDIR"),
+ STM32_FUNCTION(13, "SDMMC1_D5 SDMMC_BOOT1_D5"),
+ STM32_FUNCTION(14, "DCMI_D7"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(26, "PB10"),
+ STM32_FUNCTION(0, "GPIOB10"),
+ STM32_FUNCTION(2, "TIM2_CH3"),
+ STM32_FUNCTION(4, "LPTIM2_IN1"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "DFSDM_DATA7"),
+ STM32_FUNCTION(8, "USART3_TX USART_BOOT3_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(12, "ETH_GMII_RX_ER ETH_MII_RX_ER"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(27, "PB11"),
+ STM32_FUNCTION(0, "GPIOB11"),
+ STM32_FUNCTION(2, "TIM2_CH4"),
+ STM32_FUNCTION(4, "LPTIM2_ETR"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(7, "DFSDM_CK7"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(12, "ETH_GMII_TX_EN ETH_MII_TX_EN ETH_RGMII_TX_CTL ETH_RMII_TX_EN"),
+ STM32_FUNCTION(14, "DSI_TE"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(28, "PB12"),
+ STM32_FUNCTION(0, "GPIOB12"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(3, "I2C6_SMBA"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "DFSDM_DATA1"),
+ STM32_FUNCTION(8, "USART3_CK USART_BOOT3_CK"),
+ STM32_FUNCTION(9, "USART3_RX USART_BOOT3_RX"),
+ STM32_FUNCTION(10, "CAN2_RX"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD0 ETH_MII_TXD0 ETH_RGMII_TXD0 ETH_RMII_TXD0"),
+ STM32_FUNCTION(15, "UART5_RX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(29, "PB13"),
+ STM32_FUNCTION(0, "GPIOB13"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(4, "DFSDM_CKOUT"),
+ STM32_FUNCTION(5, "LPTIM2_OUT"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "DFSDM_CK1"),
+ STM32_FUNCTION(8, "USART3_CTS_NSS USART_BOOT3_CTS_NSS"),
+ STM32_FUNCTION(10, "CAN2_TX"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD1 ETH_MII_TXD1 ETH_RGMII_TXD1 ETH_RMII_TXD1"),
+ STM32_FUNCTION(15, "UART5_TX UART_BOOT5_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(30, "PB14"),
+ STM32_FUNCTION(0, "GPIOB14"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(3, "TIM12_CH1"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(5, "USART1_TX"),
+ STM32_FUNCTION(6, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(7, "DFSDM_DATA2"),
+ STM32_FUNCTION(8, "USART3_RTS USART_BOOT3_RTS"),
+ STM32_FUNCTION(10, "SDMMC2_D0 SDMMC_BOOT2_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(31, "PB15"),
+ STM32_FUNCTION(0, "GPIOB15"),
+ STM32_FUNCTION(1, "RTC_REFIN"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(3, "TIM12_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(5, "USART1_RX"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(7, "DFSDM_CK2"),
+ STM32_FUNCTION(10, "SDMMC2_D1 SDMMC_BOOT2_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(32, "PC0"),
+ STM32_FUNCTION(0, "GPIOC0"),
+ STM32_FUNCTION(4, "DFSDM_CK0"),
+ STM32_FUNCTION(5, "LPTIM2_IN2"),
+ STM32_FUNCTION(7, "DFSDM_DATA4"),
+ STM32_FUNCTION(9, "SAI2_FS_B"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_NCS QUADSPI_BOOTBK2_NCS"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(33, "PC1"),
+ STM32_FUNCTION(0, "GPIOC1"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(3, "SAI1_D1"),
+ STM32_FUNCTION(4, "DFSDM_DATA0"),
+ STM32_FUNCTION(5, "DFSDM_CK4"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(10, "SDMMC2_CK"),
+ STM32_FUNCTION(12, "ETH_MDC"),
+ STM32_FUNCTION(13, "MDIOS_MDC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(34, "PC2"),
+ STM32_FUNCTION(0, "GPIOC2"),
+ STM32_FUNCTION(4, "DFSDM_CK1"),
+ STM32_FUNCTION(6, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(7, "DFSDM_CKOUT"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD2 ETH_MII_TXD2 ETH_RGMII_TXD2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(35, "PC3"),
+ STM32_FUNCTION(0, "GPIOC3"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(4, "DFSDM_DATA1"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(12, "ETH_GMII_TX_CLK ETH_MII_TX_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(36, "PC4"),
+ STM32_FUNCTION(0, "GPIOC4"),
+ STM32_FUNCTION(4, "DFSDM_CK2"),
+ STM32_FUNCTION(6, "I2S1_MCK"),
+ STM32_FUNCTION(10, "SPDIF_IN2"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD0 ETH_MII_RXD0 ETH_RGMII_RXD0 ETH_RMII_RXD0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(37, "PC5"),
+ STM32_FUNCTION(0, "GPIOC5"),
+ STM32_FUNCTION(3, "SAI1_D3"),
+ STM32_FUNCTION(4, "DFSDM_DATA2"),
+ STM32_FUNCTION(5, "SAI4_D4"),
+ STM32_FUNCTION(7, "SAI1_D4"),
+ STM32_FUNCTION(10, "SPDIF_IN3"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD1 ETH_MII_RXD1 ETH_RGMII_RXD1 ETH_RMII_RXD1"),
+ STM32_FUNCTION(13, "SAI4_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(38, "PC6"),
+ STM32_FUNCTION(0, "GPIOC6"),
+ STM32_FUNCTION(1, "HDP1"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(5, "DFSDM_CK3"),
+ STM32_FUNCTION(6, "I2S2_MCK"),
+ STM32_FUNCTION(8, "USART6_TX USART_BOOT6_TX"),
+ STM32_FUNCTION(9, "SDMMC1_D0DIR SDMMC_BOOT1_D0DIR"),
+ STM32_FUNCTION(10, "SDMMC2_D0DIR SDMMC_BOOT2_D0DIR"),
+ STM32_FUNCTION(11, "SDMMC2_D6 SDMMC_BOOT2_D6"),
+ STM32_FUNCTION(12, "DSI_TE"),
+ STM32_FUNCTION(13, "SDMMC1_D6 SDMMC_BOOT1_D6"),
+ STM32_FUNCTION(14, "DCMI_D0"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(39, "PC7"),
+ STM32_FUNCTION(0, "GPIOC7"),
+ STM32_FUNCTION(1, "HDP4"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(5, "DFSDM_DATA3"),
+ STM32_FUNCTION(7, "I2S3_MCK"),
+ STM32_FUNCTION(8, "USART6_RX USART_BOOT6_RX"),
+ STM32_FUNCTION(9, "SDMMC1_D123DIR SDMMC_BOOT1_D123DIR"),
+ STM32_FUNCTION(10, "SDMMC2_D123DIR SDMMC_BOOT2_D123DIR"),
+ STM32_FUNCTION(11, "SDMMC2_D7 SDMMC_BOOT2_D7"),
+ STM32_FUNCTION(13, "SDMMC1_D7 SDMMC_BOOT1_D7"),
+ STM32_FUNCTION(14, "DCMI_D1"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(40, "PC8"),
+ STM32_FUNCTION(0, "GPIOC8"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(3, "TIM3_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(7, "UART4_TX"),
+ STM32_FUNCTION(8, "USART6_CK USART_BOOT6_CK"),
+ STM32_FUNCTION(9, "UART5_RTS UART_BOOT5_RTS"),
+ STM32_FUNCTION(13, "SDMMC1_D0 SDMMC_BOOT1_D0"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(41, "PC9"),
+ STM32_FUNCTION(0, "GPIOC9"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(3, "TIM3_CH4"),
+ STM32_FUNCTION(4, "TIM8_CH4"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(9, "UART5_CTS UART_BOOT5_CTS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(13, "SDMMC1_D1 SDMMC_BOOT1_D1"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(42, "PC10"),
+ STM32_FUNCTION(0, "GPIOC10"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(4, "DFSDM_CK5"),
+ STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(11, "SAI4_MCLK_B"),
+ STM32_FUNCTION(13, "SDMMC1_D2 SDMMC_BOOT1_D2"),
+ STM32_FUNCTION(14, "DCMI_D8"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(43, "PC11"),
+ STM32_FUNCTION(0, "GPIOC11"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(4, "DFSDM_DATA5"),
+ STM32_FUNCTION(7, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_NCS QUADSPI_BOOTBK2_NCS"),
+ STM32_FUNCTION(11, "SAI4_SCK_B"),
+ STM32_FUNCTION(13, "SDMMC1_D3 SDMMC_BOOT1_D3"),
+ STM32_FUNCTION(14, "DCMI_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(44, "PC12"),
+ STM32_FUNCTION(0, "GPIOC12"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(2, "MCO2"),
+ STM32_FUNCTION(3, "SAI4_D3"),
+ STM32_FUNCTION(7, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(8, "USART3_CK USART_BOOT3_CK"),
+ STM32_FUNCTION(9, "UART5_TX"),
+ STM32_FUNCTION(11, "SAI4_SD_B"),
+ STM32_FUNCTION(13, "SDMMC1_CK SDMMC_BOOT1_CK"),
+ STM32_FUNCTION(14, "DCMI_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(45, "PC13"),
+ STM32_FUNCTION(0, "GPIOC13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(46, "PC14"),
+ STM32_FUNCTION(0, "GPIOC14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(47, "PC15"),
+ STM32_FUNCTION(0, "GPIOC15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(48, "PD0"),
+ STM32_FUNCTION(0, "GPIOD0"),
+ STM32_FUNCTION(3, "I2C6_SDA"),
+ STM32_FUNCTION(4, "DFSDM_CK6"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(7, "SAI3_SCK_A"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(11, "SDMMC3_CMD"),
+ STM32_FUNCTION(12, "DFSDM_DATA7"),
+ STM32_FUNCTION(13, "FMC_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(49, "PD1"),
+ STM32_FUNCTION(0, "GPIOD1"),
+ STM32_FUNCTION(3, "I2C6_SCL"),
+ STM32_FUNCTION(4, "DFSDM_DATA6"),
+ STM32_FUNCTION(5, "I2C5_SCL"),
+ STM32_FUNCTION(7, "SAI3_SD_A"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(11, "SDMMC3_D0"),
+ STM32_FUNCTION(12, "DFSDM_CK7"),
+ STM32_FUNCTION(13, "FMC_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(50, "PD2"),
+ STM32_FUNCTION(0, "GPIOD2"),
+ STM32_FUNCTION(3, "TIM3_ETR"),
+ STM32_FUNCTION(5, "I2C5_SMBA"),
+ STM32_FUNCTION(7, "UART4_RX"),
+ STM32_FUNCTION(9, "UART5_RX"),
+ STM32_FUNCTION(13, "SDMMC1_CMD SDMMC_BOOT1_CMD"),
+ STM32_FUNCTION(14, "DCMI_D11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(51, "PD3"),
+ STM32_FUNCTION(0, "GPIOD3"),
+ STM32_FUNCTION(1, "HDP5"),
+ STM32_FUNCTION(4, "DFSDM_CKOUT"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "DFSDM_DATA0"),
+ STM32_FUNCTION(8, "USART2_CTS_NSS USART_BOOT2_CTS_NSS"),
+ STM32_FUNCTION(9, "SDMMC1_D123DIR SDMMC_BOOT1_D123DIR"),
+ STM32_FUNCTION(10, "SDMMC2_D7 SDMMC_BOOT2_D7"),
+ STM32_FUNCTION(11, "SDMMC2_D123DIR SDMMC_BOOT2_D123DIR"),
+ STM32_FUNCTION(12, "SDMMC1_D7 SDMMC_BOOT1_D7"),
+ STM32_FUNCTION(13, "FMC_CLK"),
+ STM32_FUNCTION(14, "DCMI_D5"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(52, "PD4"),
+ STM32_FUNCTION(0, "GPIOD4"),
+ STM32_FUNCTION(7, "SAI3_FS_A"),
+ STM32_FUNCTION(8, "USART2_RTS USART_BOOT2_RTS"),
+ STM32_FUNCTION(10, "CAN1_RXFD"),
+ STM32_FUNCTION(11, "SDMMC3_D1"),
+ STM32_FUNCTION(12, "DFSDM_CK0"),
+ STM32_FUNCTION(13, "FMC_NOE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(53, "PD5"),
+ STM32_FUNCTION(0, "GPIOD5"),
+ STM32_FUNCTION(8, "USART2_TX"),
+ STM32_FUNCTION(10, "CAN1_TXFD"),
+ STM32_FUNCTION(11, "SDMMC3_D2"),
+ STM32_FUNCTION(13, "FMC_NWE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(54, "PD6"),
+ STM32_FUNCTION(0, "GPIOD6"),
+ STM32_FUNCTION(2, "TIM16_CH1N"),
+ STM32_FUNCTION(3, "SAI1_D1"),
+ STM32_FUNCTION(4, "DFSDM_CK4"),
+ STM32_FUNCTION(5, "DFSDM_DATA1"),
+ STM32_FUNCTION(6, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(8, "USART2_RX"),
+ STM32_FUNCTION(10, "CAN2_RXFD"),
+ STM32_FUNCTION(11, "FMC_INT"),
+ STM32_FUNCTION(13, "FMC_NWAIT"),
+ STM32_FUNCTION(14, "DCMI_D10"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(55, "PD7"),
+ STM32_FUNCTION(0, "GPIOD7"),
+ STM32_FUNCTION(1, "TRACED6"),
+ STM32_FUNCTION(4, "DFSDM_DATA4"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(7, "DFSDM_CK1"),
+ STM32_FUNCTION(8, "USART2_CK USART_BOOT2_CK"),
+ STM32_FUNCTION(10, "SPDIF_IN0"),
+ STM32_FUNCTION(11, "SDMMC3_D3"),
+ STM32_FUNCTION(13, "FMC_NE1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(56, "PD8"),
+ STM32_FUNCTION(0, "GPIOD8"),
+ STM32_FUNCTION(4, "DFSDM_CK3"),
+ STM32_FUNCTION(7, "SAI3_SCK_B"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(10, "SPDIF_IN1"),
+ STM32_FUNCTION(13, "FMC_D13"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(57, "PD9"),
+ STM32_FUNCTION(0, "GPIOD9"),
+ STM32_FUNCTION(4, "DFSDM_DATA3"),
+ STM32_FUNCTION(7, "SAI3_SD_B"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(10, "CAN2_RXFD"),
+ STM32_FUNCTION(13, "FMC_D14"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(58, "PD10"),
+ STM32_FUNCTION(0, "GPIOD10"),
+ STM32_FUNCTION(1, "RTC_REFIN"),
+ STM32_FUNCTION(2, "TIM16_BKIN"),
+ STM32_FUNCTION(4, "DFSDM_CKOUT"),
+ STM32_FUNCTION(5, "I2C5_SMBA"),
+ STM32_FUNCTION(6, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(7, "SAI3_FS_B"),
+ STM32_FUNCTION(8, "USART3_CK USART_BOOT3_CK"),
+ STM32_FUNCTION(10, "CAN2_TXFD"),
+ STM32_FUNCTION(13, "FMC_D15"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(59, "PD11"),
+ STM32_FUNCTION(0, "GPIOD11"),
+ STM32_FUNCTION(4, "LPTIM2_IN2"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(6, "I2C1_SMBA"),
+ STM32_FUNCTION(8, "USART3_CTS_NSS USART_BOOT3_CTS_NSS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(11, "SAI2_SD_A"),
+ STM32_FUNCTION(13, "FMC_A16 FMC_CLE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(60, "PD12"),
+ STM32_FUNCTION(0, "GPIOD12"),
+ STM32_FUNCTION(2, "LPTIM1_IN1"),
+ STM32_FUNCTION(3, "TIM4_CH1"),
+ STM32_FUNCTION(4, "LPTIM2_IN1"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(6, "I2C1_SCL"),
+ STM32_FUNCTION(8, "USART3_RTS USART_BOOT3_RTS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(11, "SAI2_FS_A"),
+ STM32_FUNCTION(13, "FMC_A17 FMC_ALE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(61, "PD13"),
+ STM32_FUNCTION(0, "GPIOD13"),
+ STM32_FUNCTION(2, "LPTIM1_OUT"),
+ STM32_FUNCTION(3, "TIM4_CH2"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(6, "I2C1_SDA"),
+ STM32_FUNCTION(7, "I2S3_MCK"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3 QUADSPI_BOOTBK1_IO3"),
+ STM32_FUNCTION(11, "SAI2_SCK_A"),
+ STM32_FUNCTION(13, "FMC_A18"),
+ STM32_FUNCTION(14, "DSI_TE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(62, "PD14"),
+ STM32_FUNCTION(0, "GPIOD14"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(7, "SAI3_MCLK_B"),
+ STM32_FUNCTION(9, "UART8_CTS UART_BOOT8_CTS"),
+ STM32_FUNCTION(13, "FMC_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(63, "PD15"),
+ STM32_FUNCTION(0, "GPIOD15"),
+ STM32_FUNCTION(3, "TIM4_CH4"),
+ STM32_FUNCTION(7, "SAI3_MCLK_A"),
+ STM32_FUNCTION(9, "UART8_CTS UART_BOOT8_CTS"),
+ STM32_FUNCTION(13, "FMC_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(64, "PE0"),
+ STM32_FUNCTION(0, "GPIOE0"),
+ STM32_FUNCTION(2, "LPTIM1_ETR"),
+ STM32_FUNCTION(3, "TIM4_ETR"),
+ STM32_FUNCTION(5, "LPTIM2_ETR"),
+ STM32_FUNCTION(6, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(7, "SAI4_MCLK_B"),
+ STM32_FUNCTION(9, "UART8_RX UART_BOOT8_RX"),
+ STM32_FUNCTION(10, "CAN1_RXFD"),
+ STM32_FUNCTION(11, "SAI2_MCLK_A"),
+ STM32_FUNCTION(13, "FMC_NBL0"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(65, "PE1"),
+ STM32_FUNCTION(0, "GPIOE1"),
+ STM32_FUNCTION(2, "LPTIM1_IN2"),
+ STM32_FUNCTION(6, "I2S2_MCK"),
+ STM32_FUNCTION(7, "SAI3_SD_B"),
+ STM32_FUNCTION(9, "UART8_TX UART_BOOT8_TX"),
+ STM32_FUNCTION(10, "CAN1_TXFD"),
+ STM32_FUNCTION(13, "FMC_NBL1"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(66, "PE2"),
+ STM32_FUNCTION(0, "GPIOE2"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(3, "SAI1_CK1"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(6, "SPI4_SCK"),
+ STM32_FUNCTION(7, "SAI1_MCLK_A"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2 QUADSPI_BOOTBK1_IO2"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD3 ETH_MII_TXD3 ETH_RGMII_TXD3"),
+ STM32_FUNCTION(13, "FMC_A23"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(67, "PE3"),
+ STM32_FUNCTION(0, "GPIOE3"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(5, "TIM15_BKIN"),
+ STM32_FUNCTION(7, "SAI1_SD_B"),
+ STM32_FUNCTION(10, "SDMMC2_CK SDMMC_BOOT2_CK"),
+ STM32_FUNCTION(13, "FMC_A19"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(68, "PE4"),
+ STM32_FUNCTION(0, "GPIOE4"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(3, "SAI1_D2"),
+ STM32_FUNCTION(4, "DFSDM_DATA3"),
+ STM32_FUNCTION(5, "TIM15_CH1N"),
+ STM32_FUNCTION(6, "SPI4_NSS"),
+ STM32_FUNCTION(7, "SAI1_FS_A"),
+ STM32_FUNCTION(8, "SDMMC2_CKIN SDMMC_BOOT2_CKIN"),
+ STM32_FUNCTION(9, "SDMMC1_CKIN SDMMC_BOOT1_CKIN"),
+ STM32_FUNCTION(10, "SDMMC2_D4 SDMMC_BOOT2_D4"),
+ STM32_FUNCTION(12, "SDMMC1_D4 SDMMC_BOOT1_D4"),
+ STM32_FUNCTION(13, "FMC_A20"),
+ STM32_FUNCTION(14, "DCMI_D4"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(69, "PE5"),
+ STM32_FUNCTION(0, "GPIOE5"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(3, "SAI1_CK2"),
+ STM32_FUNCTION(4, "DFSDM_CK3"),
+ STM32_FUNCTION(5, "TIM15_CH1"),
+ STM32_FUNCTION(6, "SPI4_MISO"),
+ STM32_FUNCTION(7, "SAI1_SCK_A"),
+ STM32_FUNCTION(8, "SDMMC2_D0DIR SDMMC_BOOT2_D0DIR"),
+ STM32_FUNCTION(9, "SDMMC1_D0DIR SDMMC_BOOT1_D0DIR"),
+ STM32_FUNCTION(10, "SDMMC2_D6 SDMMC_BOOT2_D6"),
+ STM32_FUNCTION(12, "SDMMC1_D6 SDMMC_BOOT1_D6"),
+ STM32_FUNCTION(13, "FMC_A21"),
+ STM32_FUNCTION(14, "DCMI_D6"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(70, "PE6"),
+ STM32_FUNCTION(0, "GPIOE6"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(2, "TIM1_BKIN2"),
+ STM32_FUNCTION(3, "SAI1_D1"),
+ STM32_FUNCTION(5, "TIM15_CH2"),
+ STM32_FUNCTION(6, "SPI4_MOSI"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(8, "SDMMC2_D0"),
+ STM32_FUNCTION(9, "SDMMC1_D2 SDMMC_BOOT1_D2"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(13, "FMC_A22"),
+ STM32_FUNCTION(14, "DCMI_D7"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(71, "PE7"),
+ STM32_FUNCTION(0, "GPIOE7"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(3, "TIM3_ETR"),
+ STM32_FUNCTION(4, "DFSDM_DATA2"),
+ STM32_FUNCTION(8, "UART7_RX"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO0 QUADSPI_BOOTBK2_IO0"),
+ STM32_FUNCTION(13, "FMC_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(72, "PE8"),
+ STM32_FUNCTION(0, "GPIOE8"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(4, "DFSDM_CK2"),
+ STM32_FUNCTION(8, "UART7_TX"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO1 QUADSPI_BOOTBK2_IO1"),
+ STM32_FUNCTION(13, "FMC_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(73, "PE9"),
+ STM32_FUNCTION(0, "GPIOE9"),
+ STM32_FUNCTION(2, "TIM1_CH1"),
+ STM32_FUNCTION(4, "DFSDM_CKOUT"),
+ STM32_FUNCTION(8, "UART7_RTS UART_BOOT7_RTS"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO2 QUADSPI_BOOTBK2_IO2"),
+ STM32_FUNCTION(13, "FMC_D6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(74, "PE10"),
+ STM32_FUNCTION(0, "GPIOE10"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(4, "DFSDM_DATA4"),
+ STM32_FUNCTION(8, "UART7_CTS UART_BOOT7_CTS"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO3 QUADSPI_BOOTBK2_IO3"),
+ STM32_FUNCTION(13, "FMC_D7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(75, "PE11"),
+ STM32_FUNCTION(0, "GPIOE11"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(4, "DFSDM_CK4"),
+ STM32_FUNCTION(6, "SPI4_NSS"),
+ STM32_FUNCTION(8, "USART6_CK USART_BOOT6_CK"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(13, "FMC_D8"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(76, "PE12"),
+ STM32_FUNCTION(0, "GPIOE12"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(4, "DFSDM_DATA5"),
+ STM32_FUNCTION(6, "SPI4_SCK"),
+ STM32_FUNCTION(9, "SDMMC1_D0DIR SDMMC_BOOT1_D0DIR"),
+ STM32_FUNCTION(11, "SAI2_SCK_B"),
+ STM32_FUNCTION(13, "FMC_D9"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(77, "PE13"),
+ STM32_FUNCTION(0, "GPIOE13"),
+ STM32_FUNCTION(1, "HDP2"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(4, "DFSDM_CK5"),
+ STM32_FUNCTION(6, "SPI4_MISO"),
+ STM32_FUNCTION(11, "SAI2_FS_B"),
+ STM32_FUNCTION(13, "FMC_D10"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(78, "PE14"),
+ STM32_FUNCTION(0, "GPIOE14"),
+ STM32_FUNCTION(2, "TIM1_CH4"),
+ STM32_FUNCTION(6, "SPI4_MOSI"),
+ STM32_FUNCTION(9, "UART8_RTS UART_BOOT8_RTS"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(12, "SDMMC1_D123DIR SDMMC_BOOT1_D123DIR"),
+ STM32_FUNCTION(13, "FMC_D11"),
+ STM32_FUNCTION(14, "LCD_G0"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(79, "PE15"),
+ STM32_FUNCTION(0, "GPIOE15"),
+ STM32_FUNCTION(1, "HDP3"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(5, "TIM15_BKIN"),
+ STM32_FUNCTION(8, "USART2_CTS_NSS USART_BOOT2_CTS_NSS"),
+ STM32_FUNCTION(9, "UART8_CTS UART_BOOT8_CTS"),
+ STM32_FUNCTION(13, "FMC_D12"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(80, "PF0"),
+ STM32_FUNCTION(0, "GPIOF0"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(10, "SDMMC3_D0"),
+ STM32_FUNCTION(11, "SDMMC3_CKIN"),
+ STM32_FUNCTION(13, "FMC_A0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(81, "PF1"),
+ STM32_FUNCTION(0, "GPIOF1"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(10, "SDMMC3_CMD"),
+ STM32_FUNCTION(11, "SDMMC3_CDIR"),
+ STM32_FUNCTION(13, "FMC_A1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(82, "PF2"),
+ STM32_FUNCTION(0, "GPIOF2"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(10, "SDMMC2_D0DIR SDMMC_BOOT2_D0DIR"),
+ STM32_FUNCTION(11, "SDMMC3_D0DIR"),
+ STM32_FUNCTION(12, "SDMMC1_D0DIR SDMMC_BOOT1_D0DIR"),
+ STM32_FUNCTION(13, "FMC_A2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(83, "PF3"),
+ STM32_FUNCTION(0, "GPIOF3"),
+ STM32_FUNCTION(12, "ETH_GMII_TX_ER ETH_MII_TX_ER"),
+ STM32_FUNCTION(13, "FMC_A3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(84, "PF4"),
+ STM32_FUNCTION(0, "GPIOF4"),
+ STM32_FUNCTION(8, "USART2_RX"),
+ STM32_FUNCTION(10, "SDMMC3_D1"),
+ STM32_FUNCTION(11, "SDMMC3_D123DIR"),
+ STM32_FUNCTION(13, "FMC_A4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(85, "PF5"),
+ STM32_FUNCTION(0, "GPIOF5"),
+ STM32_FUNCTION(8, "USART2_TX"),
+ STM32_FUNCTION(10, "SDMMC3_D2"),
+ STM32_FUNCTION(13, "FMC_A5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(86, "PF6"),
+ STM32_FUNCTION(0, "GPIOF6"),
+ STM32_FUNCTION(2, "TIM16_CH1"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(7, "SAI1_SD_B"),
+ STM32_FUNCTION(8, "UART7_RX UART_BOOT7_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3 QUADSPI_BOOTBK1_IO3"),
+ STM32_FUNCTION(13, "SAI4_SCK_B"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(87, "PF7"),
+ STM32_FUNCTION(0, "GPIOF7"),
+ STM32_FUNCTION(2, "TIM17_CH1"),
+ STM32_FUNCTION(6, "SPI5_SCK"),
+ STM32_FUNCTION(7, "SAI1_MCLK_B"),
+ STM32_FUNCTION(8, "UART7_TX UART_BOOT7_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2 QUADSPI_BOOTBK1_IO2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(88, "PF8"),
+ STM32_FUNCTION(0, "GPIOF8"),
+ STM32_FUNCTION(1, "TRACED12"),
+ STM32_FUNCTION(2, "TIM16_CH1N"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(7, "SAI1_SCK_B"),
+ STM32_FUNCTION(8, "UART7_RTS UART_BOOT7_RTS"),
+ STM32_FUNCTION(10, "TIM13_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_IO0 QUADSPI_BOOTBK1_IO0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(89, "PF9"),
+ STM32_FUNCTION(0, "GPIOF9"),
+ STM32_FUNCTION(1, "TRACED13"),
+ STM32_FUNCTION(2, "TIM17_CH1N"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(7, "SAI1_FS_B"),
+ STM32_FUNCTION(8, "UART7_CTS UART_BOOT7_CTS"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_IO1 QUADSPI_BOOTBK1_IO1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(90, "PF10"),
+ STM32_FUNCTION(0, "GPIOF10"),
+ STM32_FUNCTION(2, "TIM16_BKIN"),
+ STM32_FUNCTION(3, "SAI1_D3"),
+ STM32_FUNCTION(4, "SAI4_D4"),
+ STM32_FUNCTION(7, "SAI1_D4"),
+ STM32_FUNCTION(10, "QUADSPI_CLK QUADSPI_BOOTCLK"),
+ STM32_FUNCTION(13, "SAI4_D3"),
+ STM32_FUNCTION(14, "DCMI_D11"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(91, "PF11"),
+ STM32_FUNCTION(0, "GPIOF11"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(14, "DCMI_D12"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(92, "PF12"),
+ STM32_FUNCTION(0, "GPIOF12"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD4"),
+ STM32_FUNCTION(13, "FMC_A6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(93, "PF13"),
+ STM32_FUNCTION(0, "GPIOF13"),
+ STM32_FUNCTION(1, "TRACED5"),
+ STM32_FUNCTION(4, "DFSDM_DATA6"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(6, "I2C1_SMBA"),
+ STM32_FUNCTION(7, "DFSDM_DATA3"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD5"),
+ STM32_FUNCTION(13, "FMC_A7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(94, "PF14"),
+ STM32_FUNCTION(0, "GPIOF14"),
+ STM32_FUNCTION(1, "TRACED6"),
+ STM32_FUNCTION(4, "DFSDM_CK6"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(6, "I2C1_SCL"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD6"),
+ STM32_FUNCTION(13, "FMC_A8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(95, "PF15"),
+ STM32_FUNCTION(0, "GPIOF15"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(6, "I2C1_SDA"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD7"),
+ STM32_FUNCTION(13, "FMC_A9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(96, "PG0"),
+ STM32_FUNCTION(0, "GPIOG0"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(4, "DFSDM_DATA0"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD4"),
+ STM32_FUNCTION(13, "FMC_A10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(97, "PG1"),
+ STM32_FUNCTION(0, "GPIOG1"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD5"),
+ STM32_FUNCTION(13, "FMC_A11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(98, "PG2"),
+ STM32_FUNCTION(0, "GPIOG2"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(2, "MCO2"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD6"),
+ STM32_FUNCTION(13, "FMC_A12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(99, "PG3"),
+ STM32_FUNCTION(0, "GPIOG3"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(5, "DFSDM_CK1"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD7"),
+ STM32_FUNCTION(13, "FMC_A13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(100, "PG4"),
+ STM32_FUNCTION(0, "GPIOG4"),
+ STM32_FUNCTION(2, "TIM1_BKIN2"),
+ STM32_FUNCTION(12, "ETH_GMII_GTX_CLK ETH_RGMII_GTX_CLK"),
+ STM32_FUNCTION(13, "FMC_A14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(101, "PG5"),
+ STM32_FUNCTION(0, "GPIOG5"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(12, "ETH_GMII_CLK125 ETH_RGMII_CLK125"),
+ STM32_FUNCTION(13, "FMC_A15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(102, "PG6"),
+ STM32_FUNCTION(0, "GPIOG6"),
+ STM32_FUNCTION(1, "TRACED14"),
+ STM32_FUNCTION(2, "TIM17_BKIN"),
+ STM32_FUNCTION(11, "SDMMC2_CMD SDMMC_BOOT2_CMD"),
+ STM32_FUNCTION(14, "DCMI_D12"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(103, "PG7"),
+ STM32_FUNCTION(0, "GPIOG7"),
+ STM32_FUNCTION(1, "TRACED5"),
+ STM32_FUNCTION(7, "SAI1_MCLK_A"),
+ STM32_FUNCTION(8, "USART6_CK USART_BOOT6_CK"),
+ STM32_FUNCTION(9, "UART8_RTS UART_BOOT8_RTS"),
+ STM32_FUNCTION(10, "QUADSPI_CLK"),
+ STM32_FUNCTION(12, "QUADSPI_BK2_IO3 QUADSPI_BOOTBK2_IO3"),
+ STM32_FUNCTION(13, "FMC_INT"),
+ STM32_FUNCTION(14, "DCMI_D13"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(104, "PG8"),
+ STM32_FUNCTION(0, "GPIOG8"),
+ STM32_FUNCTION(1, "TRACED15"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(3, "ETH_CLK"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(6, "SPI6_NSS"),
+ STM32_FUNCTION(7, "SAI4_D2"),
+ STM32_FUNCTION(8, "USART6_RTS USART_BOOT6_RTS"),
+ STM32_FUNCTION(9, "USART3_RTS"),
+ STM32_FUNCTION(10, "SPDIF_IN2"),
+ STM32_FUNCTION(11, "SAI4_FS_A"),
+ STM32_FUNCTION(12, "ETH_PPS_OUT"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(105, "PG9"),
+ STM32_FUNCTION(0, "GPIOG9"),
+ STM32_FUNCTION(1, "DBTRGO"),
+ STM32_FUNCTION(8, "USART6_RX"),
+ STM32_FUNCTION(9, "SPDIF_IN3"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO2 QUADSPI_BOOTBK2_IO2"),
+ STM32_FUNCTION(11, "SAI2_FS_B"),
+ STM32_FUNCTION(13, "FMC_NE2 FMC_NCE"),
+ STM32_FUNCTION(14, "DCMI_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(106, "PG10"),
+ STM32_FUNCTION(0, "GPIOG10"),
+ STM32_FUNCTION(1, "TRACED10"),
+ STM32_FUNCTION(9, "UART8_CTS UART_BOOT8_CTS"),
+ STM32_FUNCTION(10, "LCD_G3"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(12, "QUADSPI_BK2_IO2 QUADSPI_BOOTBK2_IO2"),
+ STM32_FUNCTION(13, "FMC_NE3"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(107, "PG11"),
+ STM32_FUNCTION(0, "GPIOG11"),
+ STM32_FUNCTION(1, "TRACED11"),
+ STM32_FUNCTION(5, "USART1_TX"),
+ STM32_FUNCTION(7, "UART4_TX UART_BOOT4_TX"),
+ STM32_FUNCTION(9, "SPDIF_IN0"),
+ STM32_FUNCTION(12, "ETH_GMII_TX_EN ETH_MII_TX_EN ETH_RGMII_TX_CTL ETH_RMII_TX_EN"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(108, "PG12"),
+ STM32_FUNCTION(0, "GPIOG12"),
+ STM32_FUNCTION(2, "LPTIM1_IN1"),
+ STM32_FUNCTION(6, "SPI6_MISO"),
+ STM32_FUNCTION(7, "SAI4_CK2"),
+ STM32_FUNCTION(8, "USART6_RTS USART_BOOT6_RTS"),
+ STM32_FUNCTION(9, "SPDIF_IN1"),
+ STM32_FUNCTION(10, "LCD_B4"),
+ STM32_FUNCTION(11, "SAI4_SCK_A"),
+ STM32_FUNCTION(12, "ETH_PHY_INTN"),
+ STM32_FUNCTION(13, "FMC_NE4"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(109, "PG13"),
+ STM32_FUNCTION(0, "GPIOG13"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(2, "LPTIM1_OUT"),
+ STM32_FUNCTION(3, "SAI1_CK2"),
+ STM32_FUNCTION(5, "SAI4_CK1"),
+ STM32_FUNCTION(6, "SPI6_SCK"),
+ STM32_FUNCTION(7, "SAI1_SCK_A"),
+ STM32_FUNCTION(8, "USART6_CTS_NSS USART_BOOT6_CTS_NSS"),
+ STM32_FUNCTION(11, "SAI4_MCLK_A"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD0 ETH_MII_TXD0 ETH_RGMII_TXD0 ETH_RMII_TXD0"),
+ STM32_FUNCTION(13, "FMC_A24"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(110, "PG14"),
+ STM32_FUNCTION(0, "GPIOG14"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(2, "LPTIM1_ETR"),
+ STM32_FUNCTION(6, "SPI6_MOSI"),
+ STM32_FUNCTION(7, "SAI4_D1"),
+ STM32_FUNCTION(8, "USART6_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO3 QUADSPI_BOOTBK2_IO3"),
+ STM32_FUNCTION(11, "SAI4_SD_A"),
+ STM32_FUNCTION(12, "ETH_GMII_TXD1 ETH_MII_TXD1 ETH_RGMII_TXD1 ETH_RMII_TXD1"),
+ STM32_FUNCTION(13, "FMC_A25"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(111, "PG15"),
+ STM32_FUNCTION(0, "GPIOG15"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(3, "SAI1_D2"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(7, "SAI1_FS_A"),
+ STM32_FUNCTION(8, "USART6_CTS_NSS USART_BOOT6_CTS_NSS"),
+ STM32_FUNCTION(11, "SDMMC3_CK"),
+ STM32_FUNCTION(14, "DCMI_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(112, "PH0"),
+ STM32_FUNCTION(0, "GPIOH0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(113, "PH1"),
+ STM32_FUNCTION(0, "GPIOH1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(114, "PH2"),
+ STM32_FUNCTION(0, "GPIOH2"),
+ STM32_FUNCTION(2, "LPTIM1_IN2"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO0 QUADSPI_BOOTBK2_IO0"),
+ STM32_FUNCTION(11, "SAI2_SCK_B"),
+ STM32_FUNCTION(12, "ETH_GMII_CRS ETH_MII_CRS"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(115, "PH3"),
+ STM32_FUNCTION(0, "GPIOH3"),
+ STM32_FUNCTION(4, "DFSDM_CK4"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO1 QUADSPI_BOOTBK2_IO1"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(12, "ETH_GMII_COL ETH_MII_COL"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(116, "PH4"),
+ STM32_FUNCTION(0, "GPIOH4"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(10, "LCD_G5"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(117, "PH5"),
+ STM32_FUNCTION(0, "GPIOH5"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(13, "SAI4_SD_B"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(118, "PH6"),
+ STM32_FUNCTION(0, "GPIOH6"),
+ STM32_FUNCTION(3, "TIM12_CH1"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(6, "SPI5_SCK"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD2 ETH_MII_RXD2 ETH_RGMII_RXD2"),
+ STM32_FUNCTION(13, "MDIOS_MDIO"),
+ STM32_FUNCTION(14, "DCMI_D8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(119, "PH7"),
+ STM32_FUNCTION(0, "GPIOH7"),
+ STM32_FUNCTION(5, "I2C3_SCL"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(12, "ETH_GMII_RXD3 ETH_MII_RXD3 ETH_RGMII_RXD3"),
+ STM32_FUNCTION(13, "MDIOS_MDC"),
+ STM32_FUNCTION(14, "DCMI_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(120, "PH8"),
+ STM32_FUNCTION(0, "GPIOH8"),
+ STM32_FUNCTION(3, "TIM5_ETR"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(14, "DCMI_HSYNC"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(121, "PH9"),
+ STM32_FUNCTION(0, "GPIOH9"),
+ STM32_FUNCTION(3, "TIM12_CH2"),
+ STM32_FUNCTION(5, "I2C3_SMBA"),
+ STM32_FUNCTION(14, "DCMI_D0"),
+ STM32_FUNCTION(15, "LCD_R3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(122, "PH10"),
+ STM32_FUNCTION(0, "GPIOH10"),
+ STM32_FUNCTION(3, "TIM5_CH1"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(6, "I2C1_SMBA"),
+ STM32_FUNCTION(14, "DCMI_D1"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(123, "PH11"),
+ STM32_FUNCTION(0, "GPIOH11"),
+ STM32_FUNCTION(3, "TIM5_CH2"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(6, "I2C1_SCL"),
+ STM32_FUNCTION(14, "DCMI_D2"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(124, "PH12"),
+ STM32_FUNCTION(0, "GPIOH12"),
+ STM32_FUNCTION(1, "HDP2"),
+ STM32_FUNCTION(3, "TIM5_CH3"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(6, "I2C1_SDA"),
+ STM32_FUNCTION(14, "DCMI_D3"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(125, "PH13"),
+ STM32_FUNCTION(0, "GPIOH13"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "CAN1_TX"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(126, "PH14"),
+ STM32_FUNCTION(0, "GPIOH14"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(14, "DCMI_D4"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(127, "PH15"),
+ STM32_FUNCTION(0, "GPIOH15"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(10, "CAN1_TXFD"),
+ STM32_FUNCTION(14, "DCMI_D11"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(128, "PI0"),
+ STM32_FUNCTION(0, "GPIOI0"),
+ STM32_FUNCTION(3, "TIM5_CH4"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(10, "CAN1_RXFD"),
+ STM32_FUNCTION(14, "DCMI_D13"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(129, "PI1"),
+ STM32_FUNCTION(0, "GPIOI1"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(14, "DCMI_D8"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(130, "PI2"),
+ STM32_FUNCTION(0, "GPIOI2"),
+ STM32_FUNCTION(4, "TIM8_CH4"),
+ STM32_FUNCTION(6, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(14, "DCMI_D9"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(131, "PI3"),
+ STM32_FUNCTION(0, "GPIOI3"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(6, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(14, "DCMI_D10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(132, "PI4"),
+ STM32_FUNCTION(0, "GPIOI4"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(11, "SAI2_MCLK_A"),
+ STM32_FUNCTION(14, "DCMI_D5"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(133, "PI5"),
+ STM32_FUNCTION(0, "GPIOI5"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(11, "SAI2_SCK_A"),
+ STM32_FUNCTION(14, "DCMI_VSYNC"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(134, "PI6"),
+ STM32_FUNCTION(0, "GPIOI6"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(11, "SAI2_SD_A"),
+ STM32_FUNCTION(14, "DCMI_D6"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(135, "PI7"),
+ STM32_FUNCTION(0, "GPIOI7"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(11, "SAI2_FS_A"),
+ STM32_FUNCTION(14, "DCMI_D7"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(136, "PI8"),
+ STM32_FUNCTION(0, "GPIOI8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(137, "PI9"),
+ STM32_FUNCTION(0, "GPIOI9"),
+ STM32_FUNCTION(1, "HDP1"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "CAN1_RX"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(138, "PI10"),
+ STM32_FUNCTION(0, "GPIOI10"),
+ STM32_FUNCTION(1, "HDP0"),
+ STM32_FUNCTION(9, "USART3_CTS_NSS USART_BOOT3_CTS_NSS"),
+ STM32_FUNCTION(10, "CAN1_RXFD"),
+ STM32_FUNCTION(12, "ETH_GMII_RX_ER ETH_MII_RX_ER"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(139, "PI11"),
+ STM32_FUNCTION(0, "GPIOI11"),
+ STM32_FUNCTION(1, "MCO1"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(10, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(140, "PI12"),
+ STM32_FUNCTION(0, "GPIOI12"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(3, "HDP0"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(141, "PI13"),
+ STM32_FUNCTION(0, "GPIOI13"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(3, "HDP1"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(142, "PI14"),
+ STM32_FUNCTION(0, "GPIOI14"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(143, "PI15"),
+ STM32_FUNCTION(0, "GPIOI15"),
+ STM32_FUNCTION(10, "LCD_G2"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(144, "PJ0"),
+ STM32_FUNCTION(0, "GPIOJ0"),
+ STM32_FUNCTION(1, "TRACED8"),
+ STM32_FUNCTION(10, "LCD_R7"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(145, "PJ1"),
+ STM32_FUNCTION(0, "GPIOJ1"),
+ STM32_FUNCTION(1, "TRACED9"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(146, "PJ2"),
+ STM32_FUNCTION(0, "GPIOJ2"),
+ STM32_FUNCTION(1, "TRACED10"),
+ STM32_FUNCTION(14, "DSI_TE"),
+ STM32_FUNCTION(15, "LCD_R3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(147, "PJ3"),
+ STM32_FUNCTION(0, "GPIOJ3"),
+ STM32_FUNCTION(1, "TRACED11"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(148, "PJ4"),
+ STM32_FUNCTION(0, "GPIOJ4"),
+ STM32_FUNCTION(1, "TRACED12"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(149, "PJ5"),
+ STM32_FUNCTION(0, "GPIOJ5"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(3, "HDP2"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(150, "PJ6"),
+ STM32_FUNCTION(0, "GPIOJ6"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(3, "HDP3"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(151, "PJ7"),
+ STM32_FUNCTION(0, "GPIOJ7"),
+ STM32_FUNCTION(1, "TRACED13"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(152, "PJ8"),
+ STM32_FUNCTION(0, "GPIOJ8"),
+ STM32_FUNCTION(1, "TRACED14"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(9, "UART8_TX"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(153, "PJ9"),
+ STM32_FUNCTION(0, "GPIOJ9"),
+ STM32_FUNCTION(1, "TRACED15"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(9, "UART8_RX"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(154, "PJ10"),
+ STM32_FUNCTION(0, "GPIOJ10"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(155, "PJ11"),
+ STM32_FUNCTION(0, "GPIOJ11"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(156, "PJ12"),
+ STM32_FUNCTION(0, "GPIOJ12"),
+ STM32_FUNCTION(10, "LCD_G3"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(157, "PJ13"),
+ STM32_FUNCTION(0, "GPIOJ13"),
+ STM32_FUNCTION(10, "LCD_G4"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(158, "PJ14"),
+ STM32_FUNCTION(0, "GPIOJ14"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(159, "PJ15"),
+ STM32_FUNCTION(0, "GPIOJ15"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(160, "PK0"),
+ STM32_FUNCTION(0, "GPIOK0"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(6, "SPI5_SCK"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(161, "PK1"),
+ STM32_FUNCTION(0, "GPIOK1"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(2, "TIM1_CH1"),
+ STM32_FUNCTION(3, "HDP4"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(162, "PK2"),
+ STM32_FUNCTION(0, "GPIOK2"),
+ STM32_FUNCTION(1, "TRACED5"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(3, "HDP5"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(163, "PK3"),
+ STM32_FUNCTION(0, "GPIOK3"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(164, "PK4"),
+ STM32_FUNCTION(0, "GPIOK4"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(165, "PK5"),
+ STM32_FUNCTION(0, "GPIOK5"),
+ STM32_FUNCTION(1, "TRACED6"),
+ STM32_FUNCTION(3, "HDP6"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(166, "PK6"),
+ STM32_FUNCTION(0, "GPIOK6"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(3, "HDP7"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(167, "PK7"),
+ STM32_FUNCTION(0, "GPIOK7"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+};
+
+static const struct stm32_desc_pin stm32mp157_z_pins[] = {
+ STM32_PIN(
+ PINCTRL_PIN(400, "PZ0"),
+ STM32_FUNCTION(0, "GPIOZ0"),
+ STM32_FUNCTION(3, "I2C6_SCL"),
+ STM32_FUNCTION(4, "I2C2_SCL"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(8, "USART1_CK"),
+ STM32_FUNCTION(9, "SPI6_SCK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(401, "PZ1"),
+ STM32_FUNCTION(0, "GPIOZ1"),
+ STM32_FUNCTION(3, "I2C6_SDA"),
+ STM32_FUNCTION(4, "I2C2_SDA"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(6, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(9, "SPI6_MISO"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(402, "PZ2"),
+ STM32_FUNCTION(0, "GPIOZ2"),
+ STM32_FUNCTION(3, "I2C6_SCL"),
+ STM32_FUNCTION(4, "I2C2_SCL"),
+ STM32_FUNCTION(5, "I2C5_SMBA"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(7, "I2C4_SMBA"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(9, "SPI6_MOSI"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(403, "PZ3"),
+ STM32_FUNCTION(0, "GPIOZ3"),
+ STM32_FUNCTION(3, "I2C6_SDA"),
+ STM32_FUNCTION(4, "I2C2_SDA"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(8, "USART1_CTS_NSS"),
+ STM32_FUNCTION(9, "SPI6_NSS"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(404, "PZ4"),
+ STM32_FUNCTION(0, "GPIOZ4"),
+ STM32_FUNCTION(3, "I2C6_SCL"),
+ STM32_FUNCTION(4, "I2C2_SCL"),
+ STM32_FUNCTION(5, "I2C5_SCL"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(405, "PZ5"),
+ STM32_FUNCTION(0, "GPIOZ5"),
+ STM32_FUNCTION(3, "I2C6_SDA"),
+ STM32_FUNCTION(4, "I2C2_SDA"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(8, "USART1_RTS"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(406, "PZ6"),
+ STM32_FUNCTION(0, "GPIOZ6"),
+ STM32_FUNCTION(3, "I2C6_SCL"),
+ STM32_FUNCTION(4, "I2C2_SCL"),
+ STM32_FUNCTION(5, "USART1_CK"),
+ STM32_FUNCTION(6, "I2S1_MCK"),
+ STM32_FUNCTION(7, "I2C4_SMBA"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(407, "PZ7"),
+ STM32_FUNCTION(0, "GPIOZ7"),
+ STM32_FUNCTION(3, "I2C6_SDA"),
+ STM32_FUNCTION(4, "I2C2_SDA"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+};
+
+static struct stm32_pinctrl_match_data stm32mp157_match_data = {
+ .pins = stm32mp157_pins,
+ .npins = ARRAY_SIZE(stm32mp157_pins),
+};
+
+static struct stm32_pinctrl_match_data stm32mp157_z_match_data = {
+ .pins = stm32mp157_z_pins,
+ .npins = ARRAY_SIZE(stm32mp157_z_pins),
+};
+
+static const struct of_device_id stm32mp157_pctrl_match[] = {
+ {
+ .compatible = "st,stm32mp157-pinctrl",
+ .data = &stm32mp157_match_data,
+ },
+ {
+ .compatible = "st,stm32mp157-z-pinctrl",
+ .data = &stm32mp157_z_match_data,
+ },
+ { }
+};
+
+static struct platform_driver stm32mp157_pinctrl_driver = {
+ .probe = stm32_pctl_probe,
+ .driver = {
+ .name = "stm32mp157-pinctrl",
+ .of_match_table = stm32mp157_pctrl_match,
+ },
+};
+
+static int __init stm32mp157_pinctrl_init(void)
+{
+ return platform_driver_register(&stm32mp157_pinctrl_driver);
+}
+arch_initcall(stm32mp157_pinctrl_init);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
index 295e48fc94bc..0c7c361ebac5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
@@ -1167,7 +1167,7 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = {
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "pwm"), /* PWM1 */
- SUNXI_FUNCTION_VARIANT(0x3, "i2c3", /* SDA */
+ SUNXI_FUNCTION_VARIANT(0x3, "i2c4", /* SDA */
PINCTRL_SUN7I_A20 |
PINCTRL_SUN8I_R40)),
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 4b6cb25bc796..341312d66512 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -12,6 +12,7 @@
#include <linux/io.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/gpio/driver.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
@@ -83,7 +84,9 @@ sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
struct sunxi_desc_function *func = pin->functions;
while (func->name) {
- if (!strcmp(func->name, func_name))
+ if (!strcmp(func->name, func_name) &&
+ (!func->variant ||
+ func->variant & pctl->variant))
return func;
func++;
@@ -1185,7 +1188,7 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
int i, ret;
/* Deal with old DTs that didn't have the oscillators */
- if (of_count_phandle_with_args(node, "clocks", "#clock-cells") != 3)
+ if (of_clk_get_parent_count(node) != 3)
return 0;
/* If we don't have any setup, bail out */
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index 51716819129d..72c718e66ebb 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -666,10 +666,9 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
int fn, gn, gfn;
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
- if (!pmx) {
- dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
+ if (!pmx)
return -ENOMEM;
- }
+
pmx->dev = &pdev->dev;
pmx->soc = soc_data;
@@ -722,10 +721,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs),
GFP_KERNEL);
- if (!pmx->regs) {
- dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+ if (!pmx->regs)
return -ENOMEM;
- }
for (i = 0; i < pmx->nbanks; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 26fda5c53e65..ec0f77afeaa4 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -146,6 +146,71 @@ static const struct pinctrl_ops uniphier_pctlops = {
.dt_free_map = pinctrl_utils_free_map,
};
+static const unsigned int uniphier_conf_drv_strengths_1bit[] = {4, 8};
+static const unsigned int uniphier_conf_drv_strengths_2bit[] = {8, 12, 16, 20};
+static const unsigned int uniphier_conf_drv_strengths_3bit[] = {4, 5, 7, 9, 11,
+ 12, 14, 16};
+static const unsigned int uniphier_conf_drv_strengths_fixed4[] = {4};
+static const unsigned int uniphier_conf_drv_strengths_fixed5[] = {5};
+static const unsigned int uniphier_conf_drv_strengths_fixed8[] = {8};
+
+static int uniphier_conf_get_drvctrl_data(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned int *reg,
+ unsigned int *shift,
+ unsigned int *mask,
+ const unsigned int **strengths)
+{
+ const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+ enum uniphier_pin_drv_type type =
+ uniphier_pin_get_drv_type(desc->drv_data);
+ unsigned int base = 0;
+ unsigned int stride = 0;
+ unsigned int width = 0;
+ unsigned int drvctrl;
+
+ switch (type) {
+ case UNIPHIER_PIN_DRV_1BIT:
+ *strengths = uniphier_conf_drv_strengths_1bit;
+ base = UNIPHIER_PINCTRL_DRVCTRL_BASE;
+ stride = 1;
+ width = 1;
+ break;
+ case UNIPHIER_PIN_DRV_2BIT:
+ *strengths = uniphier_conf_drv_strengths_2bit;
+ base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
+ stride = 2;
+ width = 2;
+ break;
+ case UNIPHIER_PIN_DRV_3BIT:
+ *strengths = uniphier_conf_drv_strengths_3bit;
+ base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
+ stride = 4;
+ width = 3;
+ break;
+ case UNIPHIER_PIN_DRV_FIXED4:
+ *strengths = uniphier_conf_drv_strengths_fixed4;
+ break;
+ case UNIPHIER_PIN_DRV_FIXED5:
+ *strengths = uniphier_conf_drv_strengths_fixed5;
+ break;
+ case UNIPHIER_PIN_DRV_FIXED8:
+ *strengths = uniphier_conf_drv_strengths_fixed8;
+ break;
+ default:
+ /* drive strength control is not supported for this pin */
+ return -EINVAL;
+ }
+
+ drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
+ drvctrl *= stride;
+
+ *reg = base + drvctrl / 32 * 4;
+ *shift = drvctrl % 32;
+ *mask = (1U << width) - 1;
+
+ return 0;
+}
+
static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
unsigned int pin,
enum pin_config_param param)
@@ -201,59 +266,24 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
unsigned int pin, u32 *strength)
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
- const struct pin_desc *desc = pin_desc_get(pctldev, pin);
- enum uniphier_pin_drv_type type =
- uniphier_pin_get_drv_type(desc->drv_data);
- static const unsigned int strength_1bit[] = {4, 8};
- static const unsigned int strength_2bit[] = {8, 12, 16, 20};
- static const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12,
- 14, 16};
- const unsigned int *supported_strength;
- unsigned int drvctrl, reg, shift, mask, width, val;
+ unsigned int reg, shift, mask, val;
+ const unsigned int *strengths;
int ret;
- switch (type) {
- case UNIPHIER_PIN_DRV_1BIT:
- supported_strength = strength_1bit;
- reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
- width = 1;
- break;
- case UNIPHIER_PIN_DRV_2BIT:
- supported_strength = strength_2bit;
- reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
- width = 2;
- break;
- case UNIPHIER_PIN_DRV_3BIT:
- supported_strength = strength_3bit;
- reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
- width = 4;
- break;
- case UNIPHIER_PIN_DRV_FIXED4:
- *strength = 4;
- return 0;
- case UNIPHIER_PIN_DRV_FIXED5:
- *strength = 5;
- return 0;
- case UNIPHIER_PIN_DRV_FIXED8:
- *strength = 8;
- return 0;
- default:
- /* drive strength control is not supported for this pin */
- return -EINVAL;
- }
-
- drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
- drvctrl *= width;
-
- reg += drvctrl / 32 * 4;
- shift = drvctrl % 32;
- mask = (1U << width) - 1;
-
- ret = regmap_read(priv->regmap, reg, &val);
+ ret = uniphier_conf_get_drvctrl_data(pctldev, pin, &reg, &shift,
+ &mask, &strengths);
if (ret)
return ret;
- *strength = supported_strength[(val >> shift) & mask];
+ if (mask) {
+ ret = regmap_read(priv->regmap, reg, &val);
+ if (ret)
+ return ret;
+ } else {
+ val = 0;
+ }
+
+ *strength = strengths[(val >> shift) & mask];
return 0;
}
@@ -398,40 +428,20 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
{
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
const struct pin_desc *desc = pin_desc_get(pctldev, pin);
- enum uniphier_pin_drv_type type =
- uniphier_pin_get_drv_type(desc->drv_data);
- static const unsigned int strength_1bit[] = {4, 8, -1};
- static const unsigned int strength_2bit[] = {8, 12, 16, 20, -1};
- static const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14,
- 16, -1};
- const unsigned int *supported_strength;
- unsigned int drvctrl, reg, shift, mask, width, val;
+ unsigned int reg, shift, mask, val;
+ const unsigned int *strengths;
+ int ret;
- switch (type) {
- case UNIPHIER_PIN_DRV_1BIT:
- supported_strength = strength_1bit;
- reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
- width = 1;
- break;
- case UNIPHIER_PIN_DRV_2BIT:
- supported_strength = strength_2bit;
- reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
- width = 2;
- break;
- case UNIPHIER_PIN_DRV_3BIT:
- supported_strength = strength_3bit;
- reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
- width = 4;
- break;
- default:
- dev_err(pctldev->dev,
- "cannot change drive strength for pin %s\n",
+ ret = uniphier_conf_get_drvctrl_data(pctldev, pin, &reg, &shift,
+ &mask, &strengths);
+ if (ret) {
+ dev_err(pctldev->dev, "cannot set drive strength for pin %s\n",
desc->name);
- return -EINVAL;
+ return ret;
}
- for (val = 0; supported_strength[val] > 0; val++) {
- if (supported_strength[val] > strength)
+ for (val = 0; val <= mask; val++) {
+ if (strengths[val] > strength)
break;
}
@@ -442,14 +452,10 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
return -EINVAL;
}
- val--;
-
- drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
- drvctrl *= width;
+ if (!mask)
+ return 0;
- reg += drvctrl / 32 * 4;
- shift = drvctrl % 32;
- mask = (1U << width) - 1;
+ val--;
return regmap_update_bits(priv->regmap, reg,
mask << shift, val << shift);
diff --git a/drivers/pinctrl/vt8500/pinctrl-vt8500.c b/drivers/pinctrl/vt8500/pinctrl-vt8500.c
index 767f340d6b11..9086a3758eee 100644
--- a/drivers/pinctrl/vt8500/pinctrl-vt8500.c
+++ b/drivers/pinctrl/vt8500/pinctrl-vt8500.c
@@ -458,10 +458,8 @@ static int vt8500_pinctrl_probe(struct platform_device *pdev)
struct wmt_pinctrl_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&pdev->dev, "failed to allocate data\n");
+ if (!data)
return -ENOMEM;
- }
data->banks = vt8500_banks;
data->nbanks = ARRAY_SIZE(vt8500_banks);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8505.c b/drivers/pinctrl/vt8500/pinctrl-wm8505.c
index a56fdbd87e42..e1aae1d4b0b1 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8505.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8505.c
@@ -489,10 +489,8 @@ static int wm8505_pinctrl_probe(struct platform_device *pdev)
struct wmt_pinctrl_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&pdev->dev, "failed to allocate data\n");
+ if (!data)
return -ENOMEM;
- }
data->banks = wm8505_banks;
data->nbanks = ARRAY_SIZE(wm8505_banks);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8650.c b/drivers/pinctrl/vt8500/pinctrl-wm8650.c
index 270dd491f5a1..4678227d4001 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8650.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8650.c
@@ -327,10 +327,8 @@ static int wm8650_pinctrl_probe(struct platform_device *pdev)
struct wmt_pinctrl_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&pdev->dev, "failed to allocate data\n");
+ if (!data)
return -ENOMEM;
- }
data->banks = wm8650_banks;
data->nbanks = ARRAY_SIZE(wm8650_banks);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8750.c b/drivers/pinctrl/vt8500/pinctrl-wm8750.c
index 74f7b3a18f3a..c46d6946c8f5 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8750.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8750.c
@@ -366,10 +366,8 @@ static int wm8750_pinctrl_probe(struct platform_device *pdev)
struct wmt_pinctrl_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&pdev->dev, "failed to allocate data\n");
+ if (!data)
return -ENOMEM;
- }
data->banks = wm8750_banks;
data->nbanks = ARRAY_SIZE(wm8750_banks);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8850.c b/drivers/pinctrl/vt8500/pinctrl-wm8850.c
index 45792aa7a06e..e2e85316a65e 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wm8850.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wm8850.c
@@ -345,10 +345,8 @@ static int wm8850_pinctrl_probe(struct platform_device *pdev)
struct wmt_pinctrl_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&pdev->dev, "failed to allocate data\n");
+ if (!data)
return -ENOMEM;
- }
data->banks = wm8850_banks;
data->nbanks = ARRAY_SIZE(wm8850_banks);
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 437fc35beb7b..e293606b0334 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -44,7 +44,6 @@ static struct ps3av {
struct mutex mutex;
struct work_struct work;
struct completion done;
- struct workqueue_struct *wq;
int open_count;
struct ps3_system_bus_device *dev;
@@ -485,7 +484,7 @@ static int ps3av_set_videomode(void)
ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
/* wake up ps3avd to do the actual video mode setting */
- queue_work(ps3av->wq, &ps3av->work);
+ schedule_work(&ps3av->work);
return 0;
}
@@ -956,11 +955,6 @@ static int ps3av_probe(struct ps3_system_bus_device *dev)
INIT_WORK(&ps3av->work, ps3avd);
init_completion(&ps3av->done);
complete(&ps3av->done);
- ps3av->wq = create_singlethread_workqueue("ps3avd");
- if (!ps3av->wq) {
- res = -ENOMEM;
- goto fail;
- }
switch (ps3_os_area_get_av_multi_out()) {
case PS3_PARAM_AV_MULTI_OUT_NTSC:
@@ -1018,8 +1012,7 @@ static int ps3av_remove(struct ps3_system_bus_device *dev)
dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
if (ps3av) {
ps3av_cmd_fin();
- if (ps3av->wq)
- destroy_workqueue(ps3av->wq);
+ flush_work(&ps3av->work);
kfree(ps3av);
ps3av = NULL;
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b59a31b079a5..8ab5f0a5d323 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1255,6 +1255,16 @@ config RTC_DRV_ZYNQMP
If you say yes here you get support for the RTC controller found on
Xilinx Zynq Ultrascale+ MPSoC.
+config RTC_DRV_CROS_EC
+ tristate "Chrome OS EC RTC driver"
+ depends on MFD_CROS_EC
+ help
+ If you say yes here you will get support for the
+ Chrome OS Embedded Controller's RTC.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-cros-ec.
+
comment "on-CPU RTC drivers"
config RTC_DRV_ASM9260
@@ -1392,13 +1402,6 @@ config RTC_DRV_PL031
To compile this driver as a module, choose M here: the
module will be called rtc-pl031.
-config RTC_DRV_AT32AP700X
- tristate "AT32AP700X series RTC"
- depends on PLATFORM_AT32AP || COMPILE_TEST
- help
- Driver for the internal RTC (Realtime Clock) on Atmel AVR32
- AT32AP700x family processors.
-
config RTC_DRV_AT91RM9200
tristate "AT91RM9200 or some AT91SAM9 RTC"
depends on ARCH_AT91 || COMPILE_TEST
@@ -1689,6 +1692,16 @@ config RTC_DRV_MXC
This driver can also be built as a module, if so, the module
will be called "rtc-mxc".
+config RTC_DRV_MXC_V2
+ tristate "Freescale MXC Real Time Clock for i.MX53"
+ depends on ARCH_MXC
+ help
+ If you say yes here you get support for the Freescale MXC
+ SRTC module in i.MX53 processor.
+
+ This driver can also be built as a module, if so, the module
+ will be called "rtc-mxc_v2".
+
config RTC_DRV_SNVS
tristate "Freescale SNVS RTC support"
select REGMAP_MMIO
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index f2f50c11dc38..4fbf87e45a7c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -33,7 +33,6 @@ obj-$(CONFIG_RTC_DRV_AC100) += rtc-ac100.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
-obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
@@ -44,6 +43,7 @@ obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o
+obj-$(CONFIG_RTC_DRV_CROS_EC) += rtc-cros-ec.o
obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o
obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o
obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o
@@ -106,6 +106,7 @@ obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o
+obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o
obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index 0282ccc6181c..8ff9dc3fe5bf 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -569,6 +569,12 @@ static int ac100_rtc_probe(struct platform_device *pdev)
return chip->irq;
}
+ chip->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(chip->rtc))
+ return PTR_ERR(chip->rtc);
+
+ chip->rtc->ops = &ac100_rtc_ops;
+
ret = devm_request_threaded_irq(&pdev->dev, chip->irq, NULL,
ac100_rtc_irq,
IRQF_SHARED | IRQF_ONESHOT,
@@ -588,17 +594,16 @@ static int ac100_rtc_probe(struct platform_device *pdev)
/* clear counter alarm pending interrupts */
regmap_write(chip->regmap, AC100_ALM_INT_STA, AC100_ALM_INT_ENABLE);
- chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-ac100",
- &ac100_rtc_ops, THIS_MODULE);
- if (IS_ERR(chip->rtc)) {
- dev_err(&pdev->dev, "unable to register device\n");
- return PTR_ERR(chip->rtc);
- }
-
ret = ac100_rtc_register_clks(chip);
if (ret)
return ret;
+ ret = rtc_register_device(chip->rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to register device\n");
+ return ret;
+ }
+
dev_info(&pdev->dev, "RTC enabled\n");
return 0;
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
deleted file mode 100644
index de8bf56a41e7..000000000000
--- a/drivers/rtc/rtc-at32ap700x.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * An RTC driver for the AVR32 AT32AP700x processor series.
- *
- * Copyright (C) 2007 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/rtc.h>
-#include <linux/io.h>
-
-/*
- * This is a bare-bones RTC. It runs during most system sleep states, but has
- * no battery backup and gets reset during system restart. It must be
- * initialized from an external clock (network, I2C, etc) before it can be of
- * much use.
- *
- * The alarm functionality is limited by the hardware, not supporting
- * periodic interrupts.
- */
-
-#define RTC_CTRL 0x00
-#define RTC_CTRL_EN 0
-#define RTC_CTRL_PCLR 1
-#define RTC_CTRL_TOPEN 2
-#define RTC_CTRL_PSEL 8
-
-#define RTC_VAL 0x04
-
-#define RTC_TOP 0x08
-
-#define RTC_IER 0x10
-#define RTC_IER_TOPI 0
-
-#define RTC_IDR 0x14
-#define RTC_IDR_TOPI 0
-
-#define RTC_IMR 0x18
-#define RTC_IMR_TOPI 0
-
-#define RTC_ISR 0x1c
-#define RTC_ISR_TOPI 0
-
-#define RTC_ICR 0x20
-#define RTC_ICR_TOPI 0
-
-#define RTC_BIT(name) (1 << RTC_##name)
-#define RTC_BF(name, value) ((value) << RTC_##name)
-
-#define rtc_readl(dev, reg) \
- __raw_readl((dev)->regs + RTC_##reg)
-#define rtc_writel(dev, reg, value) \
- __raw_writel((value), (dev)->regs + RTC_##reg)
-
-struct rtc_at32ap700x {
- struct rtc_device *rtc;
- void __iomem *regs;
- unsigned long alarm_time;
- unsigned long irq;
- /* Protect against concurrent register access. */
- spinlock_t lock;
-};
-
-static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
-{
- struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
- unsigned long now;
-
- now = rtc_readl(rtc, VAL);
- rtc_time_to_tm(now, tm);
-
- return 0;
-}
-
-static int at32_rtc_settime(struct device *dev, struct rtc_time *tm)
-{
- struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
- unsigned long now;
- int ret;
-
- ret = rtc_tm_to_time(tm, &now);
- if (ret == 0)
- rtc_writel(rtc, VAL, now);
-
- return ret;
-}
-
-static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
- struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
-
- spin_lock_irq(&rtc->lock);
- rtc_time_to_tm(rtc->alarm_time, &alrm->time);
- alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
- alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0;
- spin_unlock_irq(&rtc->lock);
-
- return 0;
-}
-
-static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
- struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
- unsigned long rtc_unix_time;
- unsigned long alarm_unix_time;
- int ret;
-
- rtc_unix_time = rtc_readl(rtc, VAL);
-
- ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
- if (ret)
- return ret;
-
- if (alarm_unix_time < rtc_unix_time)
- return -EINVAL;
-
- spin_lock_irq(&rtc->lock);
- rtc->alarm_time = alarm_unix_time;
- rtc_writel(rtc, TOP, rtc->alarm_time);
- if (alrm->enabled)
- rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
- | RTC_BIT(CTRL_TOPEN));
- else
- rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
- & ~RTC_BIT(CTRL_TOPEN));
- spin_unlock_irq(&rtc->lock);
-
- return ret;
-}
-
-static int at32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
-{
- struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
- int ret = 0;
-
- spin_lock_irq(&rtc->lock);
-
- if (enabled) {
- if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
- ret = -EINVAL;
- goto out;
- }
- rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
- | RTC_BIT(CTRL_TOPEN));
- rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
- rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
- } else {
- rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
- & ~RTC_BIT(CTRL_TOPEN));
- rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
- rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
- }
-out:
- spin_unlock_irq(&rtc->lock);
-
- return ret;
-}
-
-static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
-{
- struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
- unsigned long isr = rtc_readl(rtc, ISR);
- unsigned long events = 0;
- int ret = IRQ_NONE;
-
- spin_lock(&rtc->lock);
-
- if (isr & RTC_BIT(ISR_TOPI)) {
- rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
- rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
- rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
- & ~RTC_BIT(CTRL_TOPEN));
- rtc_writel(rtc, VAL, rtc->alarm_time);
- events = RTC_AF | RTC_IRQF;
- rtc_update_irq(rtc->rtc, 1, events);
- ret = IRQ_HANDLED;
- }
-
- spin_unlock(&rtc->lock);
-
- return ret;
-}
-
-static const struct rtc_class_ops at32_rtc_ops = {
- .read_time = at32_rtc_readtime,
- .set_time = at32_rtc_settime,
- .read_alarm = at32_rtc_readalarm,
- .set_alarm = at32_rtc_setalarm,
- .alarm_irq_enable = at32_rtc_alarm_irq_enable,
-};
-
-static int __init at32_rtc_probe(struct platform_device *pdev)
-{
- struct resource *regs;
- struct rtc_at32ap700x *rtc;
- int irq;
- int ret;
-
- rtc = devm_kzalloc(&pdev->dev, sizeof(struct rtc_at32ap700x),
- GFP_KERNEL);
- if (!rtc)
- return -ENOMEM;
-
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!regs) {
- dev_dbg(&pdev->dev, "no mmio resource defined\n");
- return -ENXIO;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_dbg(&pdev->dev, "could not get irq\n");
- return -ENXIO;
- }
-
- rtc->irq = irq;
- rtc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
- if (!rtc->regs) {
- dev_dbg(&pdev->dev, "could not map I/O memory\n");
- return -ENOMEM;
- }
- spin_lock_init(&rtc->lock);
-
- /*
- * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
- *
- * Do not reset VAL register, as it can hold an old time
- * from last JTAG reset.
- */
- if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
- rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
- rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
- rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
- | RTC_BIT(CTRL_EN));
- }
-
- ret = devm_request_irq(&pdev->dev, irq, at32_rtc_interrupt, IRQF_SHARED,
- "rtc", rtc);
- if (ret) {
- dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
- return ret;
- }
-
- platform_set_drvdata(pdev, rtc);
-
- rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &at32_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc->rtc)) {
- dev_dbg(&pdev->dev, "could not register rtc device\n");
- return PTR_ERR(rtc->rtc);
- }
-
- device_init_wakeup(&pdev->dev, 1);
-
- dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
- (unsigned long)rtc->regs, rtc->irq);
-
- return 0;
-}
-
-static int __exit at32_rtc_remove(struct platform_device *pdev)
-{
- device_init_wakeup(&pdev->dev, 0);
-
- return 0;
-}
-
-MODULE_ALIAS("platform:at32ap700x_rtc");
-
-static struct platform_driver at32_rtc_driver = {
- .remove = __exit_p(at32_rtc_remove),
- .driver = {
- .name = "at32ap700x_rtc",
- },
-};
-
-module_platform_driver_probe(at32_rtc_driver, at32_rtc_probe);
-
-MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
-MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
-MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index 796ac792a381..6cee61201c30 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -253,7 +253,7 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, timer->irq, brcmstb_waketmr_irq, 0,
"brcmstb-waketimer", timer);
if (ret < 0)
- return ret;
+ goto err_clk;
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
register_reboot_notifier(&timer->reboot_notifier);
@@ -262,12 +262,21 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
&brcmstb_waketmr_ops, THIS_MODULE);
if (IS_ERR(timer->rtc)) {
dev_err(dev, "unable to register device\n");
- unregister_reboot_notifier(&timer->reboot_notifier);
- return PTR_ERR(timer->rtc);
+ ret = PTR_ERR(timer->rtc);
+ goto err_notifier;
}
dev_info(dev, "registered, with irq %d\n", timer->irq);
+ return 0;
+
+err_notifier:
+ unregister_reboot_notifier(&timer->reboot_notifier);
+
+err_clk:
+ if (timer->clk)
+ clk_disable_unprepare(timer->clk);
+
return ret;
}
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
new file mode 100644
index 000000000000..f0ea6899c731
--- /dev/null
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -0,0 +1,413 @@
+/*
+ * RTC driver for Chrome OS Embedded Controller
+ *
+ * Copyright (c) 2017, Google, Inc
+ *
+ * Author: Stephen Barber <smbarber@chromium.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+#define DRV_NAME "cros-ec-rtc"
+
+/**
+ * struct cros_ec_rtc - Driver data for EC RTC
+ *
+ * @cros_ec: Pointer to EC device
+ * @rtc: Pointer to RTC device
+ * @notifier: Notifier info for responding to EC events
+ * @saved_alarm: Alarm to restore when interrupts are reenabled
+ */
+struct cros_ec_rtc {
+ struct cros_ec_device *cros_ec;
+ struct rtc_device *rtc;
+ struct notifier_block notifier;
+ u32 saved_alarm;
+};
+
+static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command,
+ u32 *response)
+{
+ int ret;
+ struct {
+ struct cros_ec_command msg;
+ struct ec_response_rtc data;
+ } __packed msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg.command = command;
+ msg.msg.insize = sizeof(msg.data);
+
+ ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+ if (ret < 0) {
+ dev_err(cros_ec->dev,
+ "error getting %s from EC: %d\n",
+ command == EC_CMD_RTC_GET_VALUE ? "time" : "alarm",
+ ret);
+ return ret;
+ }
+
+ *response = msg.data.time;
+
+ return 0;
+}
+
+static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command,
+ u32 param)
+{
+ int ret = 0;
+ struct {
+ struct cros_ec_command msg;
+ struct ec_response_rtc data;
+ } __packed msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg.command = command;
+ msg.msg.outsize = sizeof(msg.data);
+ msg.data.time = param;
+
+ ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+ if (ret < 0) {
+ dev_err(cros_ec->dev, "error setting %s on EC: %d\n",
+ command == EC_CMD_RTC_SET_VALUE ? "time" : "alarm",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Read the current time from the EC. */
+static int cros_ec_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
+ struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
+ int ret;
+ u32 time;
+
+ ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &time);
+ if (ret) {
+ dev_err(dev, "error getting time: %d\n", ret);
+ return ret;
+ }
+
+ rtc_time64_to_tm(time, tm);
+
+ return 0;
+}
+
+/* Set the current EC time. */
+static int cros_ec_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
+ struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
+ int ret;
+ time64_t time;
+
+ time = rtc_tm_to_time64(tm);
+ if (time < 0 || time > U32_MAX)
+ return -EINVAL;
+
+ ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_VALUE, (u32)time);
+ if (ret < 0) {
+ dev_err(dev, "error setting time: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Read alarm time from RTC. */
+static int cros_ec_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
+ struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
+ int ret;
+ u32 current_time, alarm_offset;
+
+ /*
+ * The EC host command for getting the alarm is relative (i.e. 5
+ * seconds from now) whereas rtc_wkalrm is absolute. Get the current
+ * RTC time first so we can calculate the relative time.
+ */
+ ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
+ if (ret < 0) {
+ dev_err(dev, "error getting time: %d\n", ret);
+ return ret;
+ }
+
+ ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM, &alarm_offset);
+ if (ret < 0) {
+ dev_err(dev, "error getting alarm: %d\n", ret);
+ return ret;
+ }
+
+ rtc_time64_to_tm(current_time + alarm_offset, &alrm->time);
+
+ return 0;
+}
+
+/* Set the EC's RTC alarm. */
+static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
+ struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
+ int ret;
+ time64_t alarm_time;
+ u32 current_time, alarm_offset;
+
+ /*
+ * The EC host command for setting the alarm is relative
+ * (i.e. 5 seconds from now) whereas rtc_wkalrm is absolute.
+ * Get the current RTC time first so we can calculate the
+ * relative time.
+ */
+ ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
+ if (ret < 0) {
+ dev_err(dev, "error getting time: %d\n", ret);
+ return ret;
+ }
+
+ alarm_time = rtc_tm_to_time64(&alrm->time);
+
+ if (alarm_time < 0 || alarm_time > U32_MAX)
+ return -EINVAL;
+
+ if (!alrm->enabled) {
+ /*
+ * If the alarm is being disabled, send an alarm
+ * clear command.
+ */
+ alarm_offset = EC_RTC_ALARM_CLEAR;
+ cros_ec_rtc->saved_alarm = (u32)alarm_time;
+ } else {
+ /* Don't set an alarm in the past. */
+ if ((u32)alarm_time < current_time)
+ alarm_offset = EC_RTC_ALARM_CLEAR;
+ else
+ alarm_offset = (u32)alarm_time - current_time;
+ }
+
+ ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset);
+ if (ret < 0) {
+ dev_err(dev, "error setting alarm: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cros_ec_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
+ struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
+ int ret;
+ u32 current_time, alarm_offset, alarm_value;
+
+ ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
+ if (ret < 0) {
+ dev_err(dev, "error getting time: %d\n", ret);
+ return ret;
+ }
+
+ if (enabled) {
+ /* Restore saved alarm if it's still in the future. */
+ if (cros_ec_rtc->saved_alarm < current_time)
+ alarm_offset = EC_RTC_ALARM_CLEAR;
+ else
+ alarm_offset = cros_ec_rtc->saved_alarm - current_time;
+
+ ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
+ alarm_offset);
+ if (ret < 0) {
+ dev_err(dev, "error restoring alarm: %d\n", ret);
+ return ret;
+ }
+ } else {
+ /* Disable alarm, saving the old alarm value. */
+ ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM,
+ &alarm_offset);
+ if (ret < 0) {
+ dev_err(dev, "error saving alarm: %d\n", ret);
+ return ret;
+ }
+
+ alarm_value = current_time + alarm_offset;
+
+ /*
+ * If the current EC alarm is already past, we don't want
+ * to set an alarm when we go through the alarm irq enable
+ * path.
+ */
+ if (alarm_value < current_time)
+ cros_ec_rtc->saved_alarm = EC_RTC_ALARM_CLEAR;
+ else
+ cros_ec_rtc->saved_alarm = alarm_value;
+
+ alarm_offset = EC_RTC_ALARM_CLEAR;
+ ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
+ alarm_offset);
+ if (ret < 0) {
+ dev_err(dev, "error disabling alarm: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int cros_ec_rtc_event(struct notifier_block *nb,
+ unsigned long queued_during_suspend,
+ void *_notify)
+{
+ struct cros_ec_rtc *cros_ec_rtc;
+ struct rtc_device *rtc;
+ struct cros_ec_device *cros_ec;
+ u32 host_event;
+
+ cros_ec_rtc = container_of(nb, struct cros_ec_rtc, notifier);
+ rtc = cros_ec_rtc->rtc;
+ cros_ec = cros_ec_rtc->cros_ec;
+
+ host_event = cros_ec_get_host_event(cros_ec);
+ if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) {
+ rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
+ return NOTIFY_OK;
+ } else {
+ return NOTIFY_DONE;
+ }
+}
+
+static const struct rtc_class_ops cros_ec_rtc_ops = {
+ .read_time = cros_ec_rtc_read_time,
+ .set_time = cros_ec_rtc_set_time,
+ .read_alarm = cros_ec_rtc_read_alarm,
+ .set_alarm = cros_ec_rtc_set_alarm,
+ .alarm_irq_enable = cros_ec_rtc_alarm_irq_enable,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_rtc_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(cros_ec_rtc->cros_ec->irq);
+
+ return 0;
+}
+
+static int cros_ec_rtc_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(cros_ec_rtc->cros_ec->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_ec_rtc_pm_ops, cros_ec_rtc_suspend,
+ cros_ec_rtc_resume);
+
+static int cros_ec_rtc_probe(struct platform_device *pdev)
+{
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
+ struct cros_ec_device *cros_ec = ec_dev->ec_dev;
+ struct cros_ec_rtc *cros_ec_rtc;
+ struct rtc_time tm;
+ int ret;
+
+ cros_ec_rtc = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_rtc),
+ GFP_KERNEL);
+ if (!cros_ec_rtc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cros_ec_rtc);
+ cros_ec_rtc->cros_ec = cros_ec;
+
+ /* Get initial time */
+ ret = cros_ec_rtc_read_time(&pdev->dev, &tm);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to read RTC time\n");
+ return ret;
+ }
+
+ ret = device_init_wakeup(&pdev->dev, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize wakeup\n");
+ return ret;
+ }
+
+ cros_ec_rtc->rtc = devm_rtc_device_register(&pdev->dev, DRV_NAME,
+ &cros_ec_rtc_ops,
+ THIS_MODULE);
+ if (IS_ERR(cros_ec_rtc->rtc)) {
+ ret = PTR_ERR(cros_ec_rtc->rtc);
+ dev_err(&pdev->dev, "failed to register rtc device\n");
+ return ret;
+ }
+
+ /* Get RTC events from the EC. */
+ cros_ec_rtc->notifier.notifier_call = cros_ec_rtc_event;
+ ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
+ &cros_ec_rtc->notifier);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register notifier\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cros_ec_rtc_remove(struct platform_device *pdev)
+{
+ struct cros_ec_rtc *cros_ec_rtc = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = blocking_notifier_chain_unregister(
+ &cros_ec_rtc->cros_ec->event_notifier,
+ &cros_ec_rtc->notifier);
+ if (ret) {
+ dev_err(dev, "failed to unregister notifier\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver cros_ec_rtc_driver = {
+ .probe = cros_ec_rtc_probe,
+ .remove = cros_ec_rtc_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .pm = &cros_ec_rtc_pm_ops,
+ },
+};
+
+module_platform_driver(cros_ec_rtc_driver);
+
+MODULE_DESCRIPTION("RTC driver for Chrome OS ECs");
+MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c
new file mode 100644
index 000000000000..784221dfc9c7
--- /dev/null
+++ b/drivers/rtc/rtc-mxc_v2.c
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Real Time Clock (RTC) Driver for i.MX53
+ * Copyright (c) 2004-2011 Freescale Semiconductor, Inc.
+ * Copyright (c) 2017 Beckhoff Automation GmbH & Co. KG
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+#define SRTC_LPPDR_INIT 0x41736166 /* init for glitch detect */
+
+#define SRTC_LPCR_EN_LP BIT(3) /* lp enable */
+#define SRTC_LPCR_WAE BIT(4) /* lp wakeup alarm enable */
+#define SRTC_LPCR_ALP BIT(7) /* lp alarm flag */
+#define SRTC_LPCR_NSA BIT(11) /* lp non secure access */
+#define SRTC_LPCR_NVE BIT(14) /* lp non valid state exit bit */
+#define SRTC_LPCR_IE BIT(15) /* lp init state exit bit */
+
+#define SRTC_LPSR_ALP BIT(3) /* lp alarm flag */
+#define SRTC_LPSR_NVES BIT(14) /* lp non-valid state exit status */
+#define SRTC_LPSR_IES BIT(15) /* lp init state exit status */
+
+#define SRTC_LPSCMR 0x00 /* LP Secure Counter MSB Reg */
+#define SRTC_LPSCLR 0x04 /* LP Secure Counter LSB Reg */
+#define SRTC_LPSAR 0x08 /* LP Secure Alarm Reg */
+#define SRTC_LPCR 0x10 /* LP Control Reg */
+#define SRTC_LPSR 0x14 /* LP Status Reg */
+#define SRTC_LPPDR 0x18 /* LP Power Supply Glitch Detector Reg */
+
+/* max. number of retries to read registers, 120 was max during test */
+#define REG_READ_TIMEOUT 2000
+
+struct mxc_rtc_data {
+ struct rtc_device *rtc;
+ void __iomem *ioaddr;
+ struct clk *clk;
+ spinlock_t lock; /* protects register access */
+ int irq;
+};
+
+/*
+ * This function does write synchronization for writes to the lp srtc block.
+ * To take care of the asynchronous CKIL clock, all writes from the IP domain
+ * will be synchronized to the CKIL domain.
+ * The caller should hold the pdata->lock
+ */
+static void mxc_rtc_sync_lp_locked(struct device *dev, void __iomem *ioaddr)
+{
+ unsigned int i;
+
+ /* Wait for 3 CKIL cycles */
+ for (i = 0; i < 3; i++) {
+ const u32 count = readl(ioaddr + SRTC_LPSCLR);
+ unsigned int timeout = REG_READ_TIMEOUT;
+
+ while ((readl(ioaddr + SRTC_LPSCLR)) == count) {
+ if (!--timeout) {
+ dev_err_once(dev, "SRTC_LPSCLR stuck! Check your hw.\n");
+ return;
+ }
+ }
+ }
+}
+
+/* This function is the RTC interrupt service routine. */
+static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
+{
+ struct device *dev = dev_id;
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ unsigned long flags;
+ u32 lp_status;
+ u32 lp_cr;
+
+ spin_lock_irqsave(&pdata->lock, flags);
+ if (clk_enable(pdata->clk)) {
+ spin_unlock_irqrestore(&pdata->lock, flags);
+ return IRQ_NONE;
+ }
+
+ lp_status = readl(ioaddr + SRTC_LPSR);
+ lp_cr = readl(ioaddr + SRTC_LPCR);
+
+ /* update irq data & counter */
+ if (lp_status & SRTC_LPSR_ALP) {
+ if (lp_cr & SRTC_LPCR_ALP)
+ rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF);
+
+ /* disable further lp alarm interrupts */
+ lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+ }
+
+ /* Update interrupt enables */
+ writel(lp_cr, ioaddr + SRTC_LPCR);
+
+ /* clear interrupt status */
+ writel(lp_status, ioaddr + SRTC_LPSR);
+
+ mxc_rtc_sync_lp_locked(dev, ioaddr);
+ clk_disable(pdata->clk);
+ spin_unlock_irqrestore(&pdata->lock, flags);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Enable clk and aquire spinlock
+ * @return 0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_lock(struct mxc_rtc_data *const pdata)
+{
+ int ret;
+
+ spin_lock_irq(&pdata->lock);
+ ret = clk_enable(pdata->clk);
+ if (ret) {
+ spin_unlock_irq(&pdata->lock);
+ return ret;
+ }
+ return 0;
+}
+
+static int mxc_rtc_unlock(struct mxc_rtc_data *const pdata)
+{
+ clk_disable(pdata->clk);
+ spin_unlock_irq(&pdata->lock);
+ return 0;
+}
+
+/*
+ * This function reads the current RTC time into tm in Gregorian date.
+ *
+ * @param tm contains the RTC time value upon return
+ *
+ * @return 0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+ const int clk_failed = clk_enable(pdata->clk);
+
+ if (!clk_failed) {
+ const time64_t now = readl(pdata->ioaddr + SRTC_LPSCMR);
+
+ rtc_time64_to_tm(now, tm);
+ clk_disable(pdata->clk);
+ return 0;
+ }
+ return clk_failed;
+}
+
+/*
+ * This function sets the internal RTC time based on tm in Gregorian date.
+ *
+ * @param tm the time value to be set in the RTC
+ *
+ * @return 0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+ time64_t time = rtc_tm_to_time64(tm);
+ int ret;
+
+ if (time > U32_MAX) {
+ dev_err(dev, "RTC exceeded by %llus\n", time - U32_MAX);
+ return -EINVAL;
+ }
+
+ ret = mxc_rtc_lock(pdata);
+ if (ret)
+ return ret;
+
+ writel(time, pdata->ioaddr + SRTC_LPSCMR);
+ mxc_rtc_sync_lp_locked(dev, pdata->ioaddr);
+ return mxc_rtc_unlock(pdata);
+}
+
+/*
+ * This function reads the current alarm value into the passed in \b alrm
+ * argument. It updates the \b alrm's pending field value based on the whether
+ * an alarm interrupt occurs or not.
+ *
+ * @param alrm contains the RTC alarm value upon return
+ *
+ * @return 0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ int ret;
+
+ ret = mxc_rtc_lock(pdata);
+ if (ret)
+ return ret;
+
+ rtc_time_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time);
+ alrm->pending = !!(readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_ALP);
+ return mxc_rtc_unlock(pdata);
+}
+
+/*
+ * Enable/Disable alarm interrupt
+ * The caller should hold the pdata->lock
+ */
+static void mxc_rtc_alarm_irq_enable_locked(struct mxc_rtc_data *pdata,
+ unsigned int enable)
+{
+ u32 lp_cr = readl(pdata->ioaddr + SRTC_LPCR);
+
+ if (enable)
+ lp_cr |= (SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+ else
+ lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+
+ writel(lp_cr, pdata->ioaddr + SRTC_LPCR);
+}
+
+static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+ int ret = mxc_rtc_lock(pdata);
+
+ if (ret)
+ return ret;
+
+ mxc_rtc_alarm_irq_enable_locked(pdata, enable);
+ return mxc_rtc_unlock(pdata);
+}
+
+/*
+ * This function sets the RTC alarm based on passed in alrm.
+ *
+ * @param alrm the alarm value to be set in the RTC
+ *
+ * @return 0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ const time64_t time = rtc_tm_to_time64(&alrm->time);
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+ int ret = mxc_rtc_lock(pdata);
+
+ if (ret)
+ return ret;
+
+ if (time > U32_MAX) {
+ dev_err(dev, "Hopefully I am out of service by then :-(\n");
+ return -EINVAL;
+ }
+
+ writel((u32)time, pdata->ioaddr + SRTC_LPSAR);
+
+ /* clear alarm interrupt status bit */
+ writel(SRTC_LPSR_ALP, pdata->ioaddr + SRTC_LPSR);
+ mxc_rtc_sync_lp_locked(dev, pdata->ioaddr);
+
+ mxc_rtc_alarm_irq_enable_locked(pdata, alrm->enabled);
+ mxc_rtc_sync_lp_locked(dev, pdata->ioaddr);
+ mxc_rtc_unlock(pdata);
+ return ret;
+}
+
+static const struct rtc_class_ops mxc_rtc_ops = {
+ .read_time = mxc_rtc_read_time,
+ .set_time = mxc_rtc_set_time,
+ .read_alarm = mxc_rtc_read_alarm,
+ .set_alarm = mxc_rtc_set_alarm,
+ .alarm_irq_enable = mxc_rtc_alarm_irq_enable,
+};
+
+static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag)
+{
+ unsigned int timeout = REG_READ_TIMEOUT;
+
+ while (!(readl(ioaddr) & flag)) {
+ if (!--timeout)
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int mxc_rtc_probe(struct platform_device *pdev)
+{
+ struct mxc_rtc_data *pdata;
+ struct resource *res;
+ void __iomem *ioaddr;
+ int ret = 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pdata->ioaddr))
+ return PTR_ERR(pdata->ioaddr);
+
+ ioaddr = pdata->ioaddr;
+
+ pdata->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pdata->clk)) {
+ dev_err(&pdev->dev, "unable to get rtc clock!\n");
+ return PTR_ERR(pdata->clk);
+ }
+
+ spin_lock_init(&pdata->lock);
+ pdata->irq = platform_get_irq(pdev, 0);
+ if (pdata->irq < 0)
+ return pdata->irq;
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ ret = clk_prepare_enable(pdata->clk);
+ if (ret)
+ return ret;
+ /* initialize glitch detect */
+ writel(SRTC_LPPDR_INIT, ioaddr + SRTC_LPPDR);
+
+ /* clear lp interrupt status */
+ writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);
+
+ /* move out of init state */
+ writel((SRTC_LPCR_IE | SRTC_LPCR_NSA), ioaddr + SRTC_LPCR);
+ ret = mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_IES);
+ if (ret) {
+ dev_err(&pdev->dev, "Timeout waiting for SRTC_LPSR_IES\n");
+ clk_disable_unprepare(pdata->clk);
+ return ret;
+ }
+
+ /* move out of non-valid state */
+ writel((SRTC_LPCR_IE | SRTC_LPCR_NVE | SRTC_LPCR_NSA |
+ SRTC_LPCR_EN_LP), ioaddr + SRTC_LPCR);
+ ret = mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_NVES);
+ if (ret) {
+ dev_err(&pdev->dev, "Timeout waiting for SRTC_LPSR_NVES\n");
+ clk_disable_unprepare(pdata->clk);
+ return ret;
+ }
+
+ clk_disable(pdata->clk);
+ platform_set_drvdata(pdev, pdata);
+ ret =
+ devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, 0,
+ pdev->name, &pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "interrupt not available.\n");
+ clk_unprepare(pdata->clk);
+ return ret;
+ }
+
+ pdata->rtc =
+ devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops,
+ THIS_MODULE);
+ if (IS_ERR(pdata->rtc)) {
+ clk_unprepare(pdata->clk);
+ return PTR_ERR(pdata->rtc);
+ }
+
+ return 0;
+}
+
+static int mxc_rtc_remove(struct platform_device *pdev)
+{
+ struct mxc_rtc_data *pdata = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(pdata->clk);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mxc_rtc_suspend(struct device *dev)
+{
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(pdata->irq);
+
+ return 0;
+}
+
+static int mxc_rtc_resume(struct device *dev)
+{
+ struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(pdata->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume);
+
+static const struct of_device_id mxc_ids[] = {
+ { .compatible = "fsl,imx53-rtc", },
+ {}
+};
+
+static struct platform_driver mxc_rtc_driver = {
+ .driver = {
+ .name = "mxc_rtc_v2",
+ .of_match_table = mxc_ids,
+ .pm = &mxc_rtc_pm_ops,
+ },
+ .probe = mxc_rtc_probe,
+ .remove = mxc_rtc_remove,
+};
+
+module_platform_driver(mxc_rtc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Real Time Clock (RTC) Driver for i.MX53");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 1d666ac9ef70..09ef802d6e54 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -753,8 +753,10 @@ static int omap_rtc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(rtc->base))
+ if (IS_ERR(rtc->base)) {
+ clk_disable_unprepare(rtc->clk);
return PTR_ERR(rtc->base);
+ }
platform_set_drvdata(pdev, rtc);
@@ -887,6 +889,7 @@ static int omap_rtc_probe(struct platform_device *pdev)
return 0;
err:
+ clk_disable_unprepare(rtc->clk);
device_init_wakeup(&pdev->dev, false);
rtc->type->lock(rtc);
pm_runtime_put_sync(&pdev->dev);
diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c
index e2a946c0e667..304e891e35fc 100644
--- a/drivers/rtc/rtc-opal.c
+++ b/drivers/rtc/rtc-opal.c
@@ -58,6 +58,7 @@ static void tm_to_opal(struct rtc_time *tm, u32 *y_m_d, u64 *h_m_s_ms)
static int opal_get_rtc_time(struct device *dev, struct rtc_time *tm)
{
long rc = OPAL_BUSY;
+ int retries = 10;
u32 y_m_d;
u64 h_m_s_ms;
__be32 __y_m_d;
@@ -67,8 +68,11 @@ static int opal_get_rtc_time(struct device *dev, struct rtc_time *tm)
rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms);
if (rc == OPAL_BUSY_EVENT)
opal_poll_events(NULL);
- else
+ else if (retries-- && (rc == OPAL_HARDWARE
+ || rc == OPAL_INTERNAL_ERROR))
msleep(10);
+ else if (rc != OPAL_BUSY && rc != OPAL_BUSY_EVENT)
+ break;
}
if (rc != OPAL_SUCCESS)
@@ -84,6 +88,7 @@ static int opal_get_rtc_time(struct device *dev, struct rtc_time *tm)
static int opal_set_rtc_time(struct device *dev, struct rtc_time *tm)
{
long rc = OPAL_BUSY;
+ int retries = 10;
u32 y_m_d = 0;
u64 h_m_s_ms = 0;
@@ -92,8 +97,11 @@ static int opal_set_rtc_time(struct device *dev, struct rtc_time *tm)
rc = opal_rtc_write(y_m_d, h_m_s_ms);
if (rc == OPAL_BUSY_EVENT)
opal_poll_events(NULL);
- else
+ else if (retries-- && (rc == OPAL_HARDWARE
+ || rc == OPAL_INTERNAL_ERROR))
msleep(10);
+ else if (rc != OPAL_BUSY && rc != OPAL_BUSY_EVENT)
+ break;
}
return rc == OPAL_SUCCESS ? 0 : -EIO;
diff --git a/drivers/rtc/rtc-r7301.c b/drivers/rtc/rtc-r7301.c
index 28d540885f3d..500e8c8a2605 100644
--- a/drivers/rtc/rtc-r7301.c
+++ b/drivers/rtc/rtc-r7301.c
@@ -95,7 +95,7 @@ static int rtc7301_wait_while_busy(struct rtc7301_priv *priv)
if (!(val & RTC7301_CONTROL_BUSY))
return 0;
- usleep_range(200, 300);
+ udelay(300);
}
return -ETIMEDOUT;
@@ -235,7 +235,7 @@ static int rtc7301_set_time(struct device *dev, struct rtc_time *tm)
spin_lock_irqsave(&priv->lock, flags);
rtc7301_stop(priv);
- usleep_range(200, 300);
+ udelay(300);
rtc7301_select_bank(priv, 0);
rtc7301_write_time(priv, tm, false);
rtc7301_start(priv);
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index 83d2bcca6a8f..b6c5eb97051c 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -164,17 +164,11 @@ static int r9701_probe(struct spi_device *spi)
return 0;
}
-static int r9701_remove(struct spi_device *spi)
-{
- return 0;
-}
-
static struct spi_driver r9701_driver = {
.driver = {
.name = "rtc-r9701",
},
.probe = r9701_probe,
- .remove = r9701_remove,
};
module_spi_driver(r9701_driver);
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 3a5c3d7d0c77..f25dabe8fd02 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -1,6 +1,6 @@
/*
- * Copyright (C) Amelie Delaunay 2016
- * Author: Amelie Delaunay <amelie.delaunay@st.com>
+ * Copyright (C) STMicroelectronics SA 2017
+ * Author: Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
* License terms: GNU General Public License (GPL), version 2
*/
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 3d2216ccd860..5bc28eed1adf 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -201,8 +201,10 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
clk_data = kzalloc(sizeof(*clk_data) + (sizeof(*clk_data->hws) * 2),
GFP_KERNEL);
- if (!clk_data)
+ if (!clk_data) {
+ kfree(rtc);
return;
+ }
spin_lock_init(&rtc->lock);
diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c
index c3765d29fd3f..b784002ef0bd 100644
--- a/drivers/scsi/scsi_debugfs.c
+++ b/drivers/scsi/scsi_debugfs.c
@@ -4,15 +4,49 @@
#include <scsi/scsi_dbg.h>
#include "scsi_debugfs.h"
+#define SCSI_CMD_FLAG_NAME(name) [ilog2(SCMD_##name)] = #name
+static const char *const scsi_cmd_flags[] = {
+ SCSI_CMD_FLAG_NAME(TAGGED),
+ SCSI_CMD_FLAG_NAME(UNCHECKED_ISA_DMA),
+ SCSI_CMD_FLAG_NAME(INITIALIZED),
+};
+#undef SCSI_CMD_FLAG_NAME
+
+static int scsi_flags_show(struct seq_file *m, const unsigned long flags,
+ const char *const *flag_name, int flag_name_count)
+{
+ bool sep = false;
+ int i;
+
+ for (i = 0; i < sizeof(flags) * BITS_PER_BYTE; i++) {
+ if (!(flags & BIT(i)))
+ continue;
+ if (sep)
+ seq_puts(m, "|");
+ sep = true;
+ if (i < flag_name_count && flag_name[i])
+ seq_puts(m, flag_name[i]);
+ else
+ seq_printf(m, "%d", i);
+ }
+ return 0;
+}
+
void scsi_show_rq(struct seq_file *m, struct request *rq)
{
struct scsi_cmnd *cmd = container_of(scsi_req(rq), typeof(*cmd), req);
- int msecs = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc);
+ int alloc_ms = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc);
+ int timeout_ms = jiffies_to_msecs(rq->timeout);
const u8 *const cdb = READ_ONCE(cmd->cmnd);
char buf[80] = "(?)";
if (cdb)
__scsi_format_command(buf, sizeof(buf), cdb, cmd->cmd_len);
- seq_printf(m, ", .cmd=%s, .retries=%d, allocated %d.%03d s ago", buf,
- cmd->retries, msecs / 1000, msecs % 1000);
+ seq_printf(m, ", .cmd=%s, .retries=%d, .result = %#x, .flags=", buf,
+ cmd->retries, cmd->result);
+ scsi_flags_show(m, cmd->flags, scsi_cmd_flags,
+ ARRAY_SIZE(scsi_cmd_flags));
+ seq_printf(m, ", .timeout=%d.%03d, allocated %d.%03d s ago",
+ timeout_ms / 1000, timeout_ms % 1000,
+ alloc_ms / 1000, alloc_ms % 1000);
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9bdf9200cacb..a86df9ca7d1c 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -79,14 +79,15 @@ int scsi_init_sense_cache(struct Scsi_Host *shost)
if (shost->unchecked_isa_dma) {
scsi_sense_isadma_cache =
kmem_cache_create("scsi_sense_cache(DMA)",
- SCSI_SENSE_BUFFERSIZE, 0,
- SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA, NULL);
+ SCSI_SENSE_BUFFERSIZE, 0,
+ SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA, NULL);
if (!scsi_sense_isadma_cache)
ret = -ENOMEM;
} else {
scsi_sense_cache =
- kmem_cache_create("scsi_sense_cache",
- SCSI_SENSE_BUFFERSIZE, 0, SLAB_HWCACHE_ALIGN, NULL);
+ kmem_cache_create_usercopy("scsi_sense_cache",
+ SCSI_SENSE_BUFFERSIZE, 0, SLAB_HWCACHE_ALIGN,
+ 0, SCSI_SENSE_BUFFERSIZE, NULL);
if (!scsi_sense_cache)
ret = -ENOMEM;
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ce756d575aff..bff21e636ddd 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -851,16 +851,13 @@ static int sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 sector = blk_rq_pos(rq) >> (ilog2(sdp->sector_size) - 9);
u32 nr_sectors = blk_rq_sectors(rq) >> (ilog2(sdp->sector_size) - 9);
- int ret;
if (!(rq->cmd_flags & REQ_NOUNMAP)) {
switch (sdkp->zeroing_mode) {
case SD_ZERO_WS16_UNMAP:
- ret = sd_setup_write_same16_cmnd(cmd, true);
- goto out;
+ return sd_setup_write_same16_cmnd(cmd, true);
case SD_ZERO_WS10_UNMAP:
- ret = sd_setup_write_same10_cmnd(cmd, true);
- goto out;
+ return sd_setup_write_same10_cmnd(cmd, true);
}
}
@@ -868,15 +865,9 @@ static int sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
return BLKPREP_INVALID;
if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff)
- ret = sd_setup_write_same16_cmnd(cmd, false);
- else
- ret = sd_setup_write_same10_cmnd(cmd, false);
-
-out:
- if (sd_is_zoned(sdkp) && ret == BLKPREP_OK)
- return sd_zbc_write_lock_zone(cmd);
+ return sd_setup_write_same16_cmnd(cmd, false);
- return ret;
+ return sd_setup_write_same10_cmnd(cmd, false);
}
static void sd_config_write_same(struct scsi_disk *sdkp)
@@ -964,12 +955,6 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
- if (sd_is_zoned(sdkp)) {
- ret = sd_zbc_write_lock_zone(cmd);
- if (ret != BLKPREP_OK)
- return ret;
- }
-
sector >>= ilog2(sdp->sector_size) - 9;
nr_sectors >>= ilog2(sdp->sector_size) - 9;
@@ -1004,9 +989,6 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
ret = scsi_init_io(cmd);
rq->__data_len = nr_bytes;
- if (sd_is_zoned(sdkp) && ret != BLKPREP_OK)
- sd_zbc_write_unlock_zone(cmd);
-
return ret;
}
@@ -1036,19 +1018,12 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
sector_t threshold;
unsigned int this_count = blk_rq_sectors(rq);
unsigned int dif, dix;
- bool zoned_write = sd_is_zoned(sdkp) && rq_data_dir(rq) == WRITE;
int ret;
unsigned char protect;
- if (zoned_write) {
- ret = sd_zbc_write_lock_zone(SCpnt);
- if (ret != BLKPREP_OK)
- return ret;
- }
-
ret = scsi_init_io(SCpnt);
if (ret != BLKPREP_OK)
- goto out;
+ return ret;
WARN_ON_ONCE(SCpnt != rq->special);
/* from here on until we're complete, any goto out
@@ -1267,9 +1242,6 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
*/
ret = BLKPREP_OK;
out:
- if (zoned_write && ret != BLKPREP_OK)
- sd_zbc_write_unlock_zone(SCpnt);
-
return ret;
}
@@ -1314,9 +1286,6 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
struct request *rq = SCpnt->request;
u8 *cmnd;
- if (SCpnt->flags & SCMD_ZONE_WRITE_LOCK)
- sd_zbc_write_unlock_zone(SCpnt);
-
if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
__free_page(rq->special_vec.bv_page);
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 320de758323e..0d663b5e45bb 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -77,7 +77,6 @@ struct scsi_disk {
unsigned int nr_zones;
unsigned int zone_blocks;
unsigned int zone_shift;
- unsigned long *zones_wlock;
unsigned int zones_optimal_open;
unsigned int zones_optimal_nonseq;
unsigned int zones_max_open;
@@ -283,8 +282,6 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp)
extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
extern void sd_zbc_remove(struct scsi_disk *sdkp);
extern void sd_zbc_print_zones(struct scsi_disk *sdkp);
-extern int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd);
-extern void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd);
extern int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd);
extern int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd);
extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
@@ -302,14 +299,6 @@ static inline void sd_zbc_remove(struct scsi_disk *sdkp) {}
static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {}
-static inline int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd)
-{
- /* Let the drive fail requests */
- return BLKPREP_OK;
-}
-
-static inline void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd) {}
-
static inline int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd)
{
return BLKPREP_INVALID;
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 27793b9f54c0..6c348a211ebb 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -230,17 +230,6 @@ static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp)
}
/**
- * sd_zbc_zone_no - Get the number of the zone conataining a sector.
- * @sdkp: The target disk
- * @sector: 512B sector address contained in the zone
- */
-static inline unsigned int sd_zbc_zone_no(struct scsi_disk *sdkp,
- sector_t sector)
-{
- return sectors_to_logical(sdkp->device, sector) >> sdkp->zone_shift;
-}
-
-/**
* sd_zbc_setup_reset_cmnd - Prepare a RESET WRITE POINTER scsi command.
* @cmd: the command to setup
*
@@ -279,78 +268,6 @@ int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd)
}
/**
- * sd_zbc_write_lock_zone - Write lock a sequential zone.
- * @cmd: write command
- *
- * Called from sd_init_cmd() for write requests (standard write, write same or
- * write zeroes operations). If the request target zone is not already locked,
- * the zone is locked and BLKPREP_OK returned, allowing the request to proceed
- * through dispatch in scsi_request_fn(). Otherwise, BLKPREP_DEFER is returned,
- * forcing the request to wait for the zone to be unlocked, that is, for the
- * previously issued write request targeting the same zone to complete.
- *
- * This is called from blk_peek_request() context with the queue lock held and
- * before the request is removed from the scheduler. As a result, multiple
- * contexts executing concurrently scsi_request_fn() cannot result in write
- * sequence reordering as only a single write request per zone is allowed to
- * proceed.
- */
-int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd)
-{
- struct request *rq = cmd->request;
- struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
- sector_t sector = blk_rq_pos(rq);
- sector_t zone_sectors = sd_zbc_zone_sectors(sdkp);
- unsigned int zno = sd_zbc_zone_no(sdkp, sector);
-
- /*
- * Note: Checks of the alignment of the write command on
- * logical blocks is done in sd.c
- */
-
- /* Do not allow zone boundaries crossing on host-managed drives */
- if (blk_queue_zoned_model(sdkp->disk->queue) == BLK_ZONED_HM &&
- (sector & (zone_sectors - 1)) + blk_rq_sectors(rq) > zone_sectors)
- return BLKPREP_KILL;
-
- /*
- * Do not issue more than one write at a time per
- * zone. This solves write ordering problems due to
- * the unlocking of the request queue in the dispatch
- * path in the non scsi-mq case.
- */
- if (sdkp->zones_wlock &&
- test_and_set_bit(zno, sdkp->zones_wlock))
- return BLKPREP_DEFER;
-
- WARN_ON_ONCE(cmd->flags & SCMD_ZONE_WRITE_LOCK);
- cmd->flags |= SCMD_ZONE_WRITE_LOCK;
-
- return BLKPREP_OK;
-}
-
-/**
- * sd_zbc_write_unlock_zone - Write unlock a sequential zone.
- * @cmd: write command
- *
- * Called from sd_uninit_cmd(). Unlocking the request target zone will allow
- * dispatching the next write request for the zone.
- */
-void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd)
-{
- struct request *rq = cmd->request;
- struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
-
- if (sdkp->zones_wlock && cmd->flags & SCMD_ZONE_WRITE_LOCK) {
- unsigned int zno = sd_zbc_zone_no(sdkp, blk_rq_pos(rq));
- WARN_ON_ONCE(!test_bit(zno, sdkp->zones_wlock));
- cmd->flags &= ~SCMD_ZONE_WRITE_LOCK;
- clear_bit_unlock(zno, sdkp->zones_wlock);
- smp_mb__after_atomic();
- }
-}
-
-/**
* sd_zbc_complete - ZBC command post processing.
* @cmd: Completed command
* @good_bytes: Command reply bytes
@@ -586,8 +503,123 @@ out:
return 0;
}
+/**
+ * sd_zbc_alloc_zone_bitmap - Allocate a zone bitmap (one bit per zone).
+ * @sdkp: The disk of the bitmap
+ */
+static inline unsigned long *sd_zbc_alloc_zone_bitmap(struct scsi_disk *sdkp)
+{
+ struct request_queue *q = sdkp->disk->queue;
+
+ return kzalloc_node(BITS_TO_LONGS(sdkp->nr_zones)
+ * sizeof(unsigned long),
+ GFP_KERNEL, q->node);
+}
+
+/**
+ * sd_zbc_get_seq_zones - Parse report zones reply to identify sequential zones
+ * @sdkp: disk used
+ * @buf: report reply buffer
+ * @seq_zone_bitamp: bitmap of sequential zones to set
+ *
+ * Parse reported zone descriptors in @buf to identify sequential zones and
+ * set the reported zone bit in @seq_zones_bitmap accordingly.
+ * Since read-only and offline zones cannot be written, do not
+ * mark them as sequential in the bitmap.
+ * Return the LBA after the last zone reported.
+ */
+static sector_t sd_zbc_get_seq_zones(struct scsi_disk *sdkp, unsigned char *buf,
+ unsigned int buflen,
+ unsigned long *seq_zones_bitmap)
+{
+ sector_t lba, next_lba = sdkp->capacity;
+ unsigned int buf_len, list_length;
+ unsigned char *rec;
+ u8 type, cond;
+
+ list_length = get_unaligned_be32(&buf[0]) + 64;
+ buf_len = min(list_length, buflen);
+ rec = buf + 64;
+
+ while (rec < buf + buf_len) {
+ type = rec[0] & 0x0f;
+ cond = (rec[1] >> 4) & 0xf;
+ lba = get_unaligned_be64(&rec[16]);
+ if (type != ZBC_ZONE_TYPE_CONV &&
+ cond != ZBC_ZONE_COND_READONLY &&
+ cond != ZBC_ZONE_COND_OFFLINE)
+ set_bit(lba >> sdkp->zone_shift, seq_zones_bitmap);
+ next_lba = lba + get_unaligned_be64(&rec[8]);
+ rec += 64;
+ }
+
+ return next_lba;
+}
+
+/**
+ * sd_zbc_setup_seq_zones_bitmap - Initialize the disk seq zone bitmap.
+ * @sdkp: target disk
+ *
+ * Allocate a zone bitmap and initialize it by identifying sequential zones.
+ */
+static int sd_zbc_setup_seq_zones_bitmap(struct scsi_disk *sdkp)
+{
+ struct request_queue *q = sdkp->disk->queue;
+ unsigned long *seq_zones_bitmap;
+ sector_t lba = 0;
+ unsigned char *buf;
+ int ret = -ENOMEM;
+
+ seq_zones_bitmap = sd_zbc_alloc_zone_bitmap(sdkp);
+ if (!seq_zones_bitmap)
+ return -ENOMEM;
+
+ buf = kmalloc(SD_ZBC_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ goto out;
+
+ while (lba < sdkp->capacity) {
+ ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, lba);
+ if (ret)
+ goto out;
+ lba = sd_zbc_get_seq_zones(sdkp, buf, SD_ZBC_BUF_SIZE,
+ seq_zones_bitmap);
+ }
+
+ if (lba != sdkp->capacity) {
+ /* Something went wrong */
+ ret = -EIO;
+ }
+
+out:
+ kfree(buf);
+ if (ret) {
+ kfree(seq_zones_bitmap);
+ return ret;
+ }
+
+ q->seq_zones_bitmap = seq_zones_bitmap;
+
+ return 0;
+}
+
+static void sd_zbc_cleanup(struct scsi_disk *sdkp)
+{
+ struct request_queue *q = sdkp->disk->queue;
+
+ kfree(q->seq_zones_bitmap);
+ q->seq_zones_bitmap = NULL;
+
+ kfree(q->seq_zones_wlock);
+ q->seq_zones_wlock = NULL;
+
+ q->nr_zones = 0;
+}
+
static int sd_zbc_setup(struct scsi_disk *sdkp)
{
+ struct request_queue *q = sdkp->disk->queue;
+ int ret;
/* READ16/WRITE16 is mandatory for ZBC disks */
sdkp->device->use_16_for_rw = 1;
@@ -599,15 +631,36 @@ static int sd_zbc_setup(struct scsi_disk *sdkp)
sdkp->nr_zones =
round_up(sdkp->capacity, sdkp->zone_blocks) >> sdkp->zone_shift;
- if (!sdkp->zones_wlock) {
- sdkp->zones_wlock = kcalloc(BITS_TO_LONGS(sdkp->nr_zones),
- sizeof(unsigned long),
- GFP_KERNEL);
- if (!sdkp->zones_wlock)
- return -ENOMEM;
+ /*
+ * Initialize the device request queue information if the number
+ * of zones changed.
+ */
+ if (sdkp->nr_zones != q->nr_zones) {
+
+ sd_zbc_cleanup(sdkp);
+
+ q->nr_zones = sdkp->nr_zones;
+ if (sdkp->nr_zones) {
+ q->seq_zones_wlock = sd_zbc_alloc_zone_bitmap(sdkp);
+ if (!q->seq_zones_wlock) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = sd_zbc_setup_seq_zones_bitmap(sdkp);
+ if (ret) {
+ sd_zbc_cleanup(sdkp);
+ goto err;
+ }
+ }
+
}
return 0;
+
+err:
+ sd_zbc_cleanup(sdkp);
+ return ret;
}
int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
@@ -661,14 +714,14 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
err:
sdkp->capacity = 0;
+ sd_zbc_cleanup(sdkp);
return ret;
}
void sd_zbc_remove(struct scsi_disk *sdkp)
{
- kfree(sdkp->zones_wlock);
- sdkp->zones_wlock = NULL;
+ sd_zbc_cleanup(sdkp);
}
void sd_zbc_print_zones(struct scsi_disk *sdkp)