summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpi_lpss.c4
-rw-r--r--drivers/acpi/utils.c11
-rw-r--r--drivers/amba/tegra-ahb.c4
-rw-r--r--drivers/base/arch_topology.c5
-rw-r--r--drivers/base/bus.c6
-rw-r--r--drivers/base/cacheinfo.c3
-rw-r--r--drivers/base/core.c6
-rw-r--r--drivers/base/dd.c55
-rw-r--r--drivers/base/devcon.c2
-rw-r--r--drivers/base/driver.c4
-rw-r--r--drivers/base/firmware_loader/Kconfig18
-rw-r--r--drivers/base/firmware_loader/fallback.c65
-rw-r--r--drivers/base/firmware_loader/firmware.h16
-rw-r--r--drivers/base/firmware_loader/main.c224
-rw-r--r--drivers/base/node.c5
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/char/ipmi/Kconfig9
-rw-r--r--drivers/char/ipmi/Makefile1
-rw-r--r--drivers/char/ipmi/ipmb_dev_int.c364
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c8
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c4
-rw-r--r--drivers/char/ipmi/ipmi_si_platform.c9
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c5
-rw-r--r--drivers/clk/renesas/r8a77470-cpg-mssr.c2
-rw-r--r--drivers/dma/mxs-dma.c25
-rw-r--r--drivers/firmware/arm_scmi/common.h2
-rw-r--r--drivers/firmware/efi/dev-path-parser.c4
-rw-r--r--drivers/firmware/ti_sci.h2
-rw-r--r--drivers/fpga/of-fpga-region.c7
-rw-r--r--drivers/gpio/gpio-cs5535.c2
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/i915/.gitignore1
-rw-r--r--drivers/gpu/drm/i915/Makefile.header-test12
-rw-r--r--drivers/gpu/drm/i915/i915_mm.c3
-rw-r--r--drivers/gpu/drm/tegra/dc.c4
-rw-r--r--drivers/hid/hid-quirks.c22
-rw-r--r--drivers/hv/vmbus_drv.c1
-rw-r--r--drivers/hwtracing/coresight/coresight-cpu-debug.c15
-rw-r--r--drivers/hwtracing/coresight/coresight-platform.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h2
-rw-r--r--drivers/hwtracing/coresight/coresight.c6
-rw-r--r--drivers/hwtracing/intel_th/core.c5
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2-pci.c2
-rw-r--r--drivers/i2c/i2c-core-acpi.c4
-rw-r--r--drivers/i2c/i2c-core-of.c4
-rw-r--r--drivers/iio/inkern.c2
-rw-r--r--drivers/infiniband/core/uverbs_ioctl.c2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v1.c2
-rw-r--r--drivers/input/joydev.c24
-rw-r--r--drivers/input/joystick/iforce/Kconfig8
-rw-r--r--drivers/input/joystick/iforce/Makefile7
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c18
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c178
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c215
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c161
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c192
-rw-r--r--drivers/input/joystick/iforce/iforce.h55
-rw-r--r--drivers/input/keyboard/gpio_keys.c6
-rw-r--r--drivers/input/keyboard/gpio_keys_polled.c10
-rw-r--r--drivers/input/keyboard/imx_keypad.c4
-rw-r--r--drivers/input/keyboard/tca8418_keypad.c3
-rw-r--r--drivers/input/misc/da9063_onkey.c11
-rw-r--r--drivers/input/misc/max77650-onkey.c1
-rw-r--r--drivers/input/mouse/elan_i2c_core.c122
-rw-r--r--drivers/input/mouse/elantech.c322
-rw-r--r--drivers/input/mouse/elantech.h8
-rw-r--r--drivers/input/mouse/synaptics.c1
-rw-r--r--drivers/input/rmi4/rmi_f12.c6
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c23
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c18
-rw-r--r--drivers/input/touchscreen/eeti_ts.c71
-rw-r--r--drivers/input/touchscreen/imx6ul_tsc.c8
-rw-r--r--drivers/input/touchscreen/iqs5xx.c2
-rw-r--r--drivers/iommu/arm-smmu-v3.c2
-rw-r--r--drivers/iommu/arm-smmu.c2
-rw-r--r--drivers/iommu/dma-iommu.c14
-rw-r--r--drivers/macintosh/smu.c4
-rw-r--r--drivers/mailbox/bcm-flexrm-mailbox.c28
-rw-r--r--drivers/mailbox/bcm-pdc-mailbox.c8
-rw-r--r--drivers/md/dm-bufio.c4
-rw-r--r--drivers/md/dm-crypt.c101
-rw-r--r--drivers/md/dm-integrity.c7
-rw-r--r--drivers/md/dm-log-writes.c4
-rw-r--r--drivers/md/dm-rq.c2
-rw-r--r--drivers/md/dm-snap.c186
-rw-r--r--drivers/md/dm-thin-metadata.c7
-rw-r--r--drivers/mfd/altera-sysmgr.c4
-rw-r--r--drivers/mfd/syscon.c21
-rw-r--r--drivers/misc/cxl/cxl.h15
-rw-r--r--drivers/misc/cxl/debugfs.c36
-rw-r--r--drivers/misc/genwqe/card_base.c5
-rw-r--r--drivers/misc/genwqe/card_base.h2
-rw-r--r--drivers/misc/genwqe/card_debugfs.c165
-rw-r--r--drivers/misc/genwqe/card_dev.c6
-rw-r--r--drivers/misc/lkdtm/core.c20
-rw-r--r--drivers/misc/lkdtm/heap.c72
-rw-r--r--drivers/misc/lkdtm/lkdtm.h5
-rw-r--r--drivers/misc/mei/debugfs.c47
-rw-r--r--drivers/misc/mei/main.c8
-rw-r--r--drivers/misc/mei/mei_dev.h7
-rw-r--r--drivers/misc/mic/card/mic_debugfs.c18
-rw-r--r--drivers/misc/mic/cosm/cosm_debugfs.c4
-rw-r--r--drivers/misc/mic/host/mic_debugfs.c4
-rw-r--r--drivers/misc/mic/scif/scif_debugfs.c5
-rw-r--r--drivers/misc/mic/vop/vop_debugfs.c4
-rw-r--r--drivers/misc/ocxl/config.c181
-rw-r--r--drivers/misc/ocxl/pci.c2
-rw-r--r--drivers/misc/ti-st/st_kim.c4
-rw-r--r--drivers/misc/vmw_balloon.c20
-rw-r--r--drivers/mtd/Kconfig2
-rw-r--r--drivers/mtd/Makefile1
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c143
-rw-r--r--drivers/mtd/hyperbus/Kconfig23
-rw-r--r--drivers/mtd/hyperbus/Makefile4
-rw-r--r--drivers/mtd/hyperbus/hbmc-am654.c147
-rw-r--r--drivers/mtd/hyperbus/hyperbus-core.c153
-rw-r--r--drivers/mtd/mtdconcat.c37
-rw-r--r--drivers/mtd/mtdcore.c3
-rw-r--r--drivers/mtd/nand/onenand/onenand_base.c5
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmnand.c263
-rw-r--r--drivers/mtd/nand/raw/fsmc_nand.c19
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/Makefile1
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c934
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c1709
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h64
-rw-r--r--drivers/mtd/nand/raw/mtk_ecc.c4
-rw-r--r--drivers/mtd/nand/raw/mtk_ecc.h2
-rw-r--r--drivers/mtd/nand/raw/mtk_nand.c88
-rw-r--r--drivers/mtd/nand/raw/nand_base.c80
-rw-r--r--drivers/mtd/nand/raw/nand_bch.c3
-rw-r--r--drivers/mtd/nand/raw/nand_macronix.c45
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c21
-rw-r--r--drivers/mtd/nand/spi/Makefile2
-rw-r--r--drivers/mtd/nand/spi/core.c5
-rw-r--r--drivers/mtd/nand/spi/gigadevice.c79
-rw-r--r--drivers/mtd/nand/spi/paragon.c147
-rw-r--r--drivers/mtd/parsers/afs.c3
-rw-r--r--drivers/mtd/spi-nor/Kconfig7
-rw-r--r--drivers/mtd/spi-nor/Makefile1
-rw-r--r--drivers/mtd/spi-nor/cadence-quadspi.c21
-rw-r--r--drivers/mtd/spi-nor/intel-spi-pci.c1
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c37
-rw-r--r--drivers/mtd/spi-nor/stm32-quadspi.c707
-rw-r--r--drivers/net/dsa/qca8k.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c19
-rw-r--r--drivers/net/ethernet/hisilicon/hip04_eth.c7
-rw-r--r--drivers/net/ethernet/hisilicon/hisi_femac.c7
-rw-r--r--drivers/net/ethernet/hisilicon/hix5hd2_gmac.c7
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns_mdio.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c2
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.h2
-rw-r--r--drivers/net/ethernet/mediatek/mtk_sgmii.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c34
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c23
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/offload.c28
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/descs.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c4
-rw-r--r--drivers/net/ethernet/ti/cpsw-phy-sel.c4
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c26
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c2
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c4
-rw-r--r--drivers/net/phy/phy_device.c6
-rw-r--r--drivers/net/ppp/ppp_mppe.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h2
-rw-r--r--drivers/nvmem/core.c2
-rw-r--r--drivers/of/of_mdio.c2
-rw-r--r--drivers/of/platform.c2
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pci/search.c4
-rw-r--r--drivers/pinctrl/aspeed/Makefile2
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c94
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c127
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.c246
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.h542
-rw-r--r--drivers/pinctrl/aspeed/pinmux-aspeed.c96
-rw-r--r--drivers/pinctrl/aspeed/pinmux-aspeed.h735
-rw-r--r--drivers/pinctrl/bcm/Kconfig6
-rw-r--r--drivers/pinctrl/bcm/pinctrl-ns2-mux.c2
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs47l35.c6
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs47l85.c6
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs47l90.c6
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera-core.c6
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera.h6
-rw-r--r--drivers/pinctrl/core.c44
-rw-r--r--drivers/pinctrl/devicetree.c7
-rw-r--r--drivers/pinctrl/freescale/Kconfig7
-rw-r--r--drivers/pinctrl/freescale/Makefile1
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx8mn.c348
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c322
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8183.c1
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-paris.c19
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-paris.h2
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson-g12a.c36
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.c350
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.h18
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-kirkwood.c576
-rw-r--r--drivers/pinctrl/pinconf-generic.c2
-rw-r--r--drivers/pinctrl/pinctrl-bm1880.c733
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c1
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c1
-rw-r--r--drivers/pinctrl/pinctrl-tb10x.c12
-rw-r--r--drivers/pinctrl/qcom/Kconfig11
-rw-r--r--drivers/pinctrl/qcom/Makefile1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c43
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.h1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm845.c46
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8150.c1548
-rw-r--r--drivers/pinctrl/sh-pfc/core.c60
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-emev2.c70
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a73a4.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7740.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77470.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7778.c125
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7779.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7790.c36
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7791.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7792.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7794.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c434
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795.c414
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7796.c414
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77965.c410
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77970.c26
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77980.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77990.c181
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a77995.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh73a0.c21
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7734.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c3
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h90
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.c184
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.h2
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32mp157.c5
-rw-r--r--drivers/pinctrl/tegra/Kconfig4
-rw-r--r--drivers/pinctrl/tegra/Makefile1
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.c26
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.h12
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra114.c6
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra124.c6
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra194.c170
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra20.c6
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra210.c62
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra30.c4
-rw-r--r--drivers/s390/block/dasd.c233
-rw-r--r--drivers/s390/block/dasd_devmap.c70
-rw-r--r--drivers/s390/block/dasd_diag.c22
-rw-r--r--drivers/s390/block/dasd_eckd.c966
-rw-r--r--drivers/s390/block/dasd_eckd.h175
-rw-r--r--drivers/s390/block/dasd_eer.c1
-rw-r--r--drivers/s390/block/dasd_fba.c45
-rw-r--r--drivers/s390/block/dasd_fba.h5
-rw-r--r--drivers/s390/block/dasd_int.h33
-rw-r--r--drivers/s390/block/dasd_ioctl.c56
-rw-r--r--drivers/s390/char/sclp_early.c1
-rw-r--r--drivers/s390/cio/ccwgroup.c6
-rw-r--r--drivers/s390/cio/chsc_sch.c2
-rw-r--r--drivers/s390/cio/css.c4
-rw-r--r--drivers/s390/cio/device.c10
-rw-r--r--drivers/s390/cio/scm.c4
-rw-r--r--drivers/s390/crypto/ap_bus.c9
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
-rw-r--r--drivers/scsi/scsi_proc.c2
-rw-r--r--drivers/spi/spi.c4
-rw-r--r--drivers/staging/most/core.c9
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c2
-rw-r--r--drivers/thermal/broadcom/bcm2835_thermal.c2
-rw-r--r--drivers/thermal/intel/intel_powerclamp.c12
-rw-r--r--drivers/thermal/intel/x86_pkg_temp_thermal.c25
-rw-r--r--drivers/thermal/tegra/soctherm.c14
-rw-r--r--drivers/thunderbolt/switch.c4
-rw-r--r--drivers/tty/hvc/hvc_vio.c16
-rw-r--r--drivers/tty/serial/sunhv.c2
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/core/buffer.c17
-rw-r--r--drivers/usb/core/devio.c4
-rw-r--r--drivers/usb/core/hcd.c51
-rw-r--r--drivers/usb/core/usb.c4
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/fotg210-hcd.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c25
-rw-r--r--drivers/usb/host/ohci-mem.c37
-rw-r--r--drivers/usb/host/ohci-sm501.c50
-rw-r--r--drivers/usb/host/ohci-tmio.c15
-rw-r--r--drivers/usb/host/ohci.h2
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/phy/phy-am335x-control.c4
-rw-r--r--drivers/usb/phy/phy-isp1301.c4
-rw-r--r--drivers/video/fbdev/au1100fb.c24
-rw-r--r--drivers/video/fbdev/au1100fb.h1
-rw-r--r--drivers/visorbus/visorbus_main.c4
-rw-r--r--drivers/watchdog/bcm_kona_wdt.c14
-rw-r--r--drivers/watchdog/mei_wdt.c30
-rw-r--r--drivers/xen/gntdev.c6
-rw-r--r--drivers/xen/privcmd.c6
-rw-r--r--drivers/xen/xlate_mmu.c3
306 files changed, 12326 insertions, 7007 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 398451839178..d696f165a50e 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -508,10 +508,10 @@ struct hid_uid {
const char *uid;
};
-static int match_hid_uid(struct device *dev, void *data)
+static int match_hid_uid(struct device *dev, const void *data)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
- struct hid_uid *id = data;
+ const struct hid_uid *id = data;
if (!adev)
return 0;
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 7def63ab00c0..e3974a8f8fd4 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -725,17 +725,15 @@ bool acpi_dev_found(const char *hid)
EXPORT_SYMBOL(acpi_dev_found);
struct acpi_dev_match_info {
- const char *dev_name;
- struct acpi_device *adev;
struct acpi_device_id hid[2];
const char *uid;
s64 hrv;
};
-static int acpi_dev_match_cb(struct device *dev, void *data)
+static int acpi_dev_match_cb(struct device *dev, const void *data)
{
struct acpi_device *adev = to_acpi_device(dev);
- struct acpi_dev_match_info *match = data;
+ const struct acpi_dev_match_info *match = data;
unsigned long long hrv;
acpi_status status;
@@ -746,9 +744,6 @@ static int acpi_dev_match_cb(struct device *dev, void *data)
strcmp(adev->pnp.unique_id, match->uid)))
return 0;
- match->dev_name = acpi_dev_name(adev);
- match->adev = adev;
-
if (match->hrv == -1)
return 1;
@@ -818,7 +813,7 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
match.hrv = hrv;
dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
- return dev ? match.adev : NULL;
+ return dev ? to_acpi_device(dev) : NULL;
}
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
index 3eaa459ae057..aa64eece77a6 100644
--- a/drivers/amba/tegra-ahb.c
+++ b/drivers/amba/tegra-ahb.c
@@ -134,10 +134,10 @@ static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
}
#ifdef CONFIG_TEGRA_IOMMU_SMMU
-static int tegra_ahb_match_by_smmu(struct device *dev, void *data)
+static int tegra_ahb_match_by_smmu(struct device *dev, const void *data)
{
struct tegra_ahb *ahb = dev_get_drvdata(dev);
- struct device_node *dn = data;
+ const struct device_node *dn = data;
return (ahb->dev->of_node == dn) ? 1 : 0;
}
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 9b09e31ae82f..63c1e76739f1 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -137,7 +137,6 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
sizeof(*raw_capacity),
GFP_KERNEL);
if (!raw_capacity) {
- pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
cap_parsing_failed = true;
return false;
}
@@ -217,10 +216,8 @@ static int __init register_cpufreq_notifier(void)
if (!acpi_disabled || !raw_capacity)
return -EINVAL;
- if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) {
- pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n");
+ if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL))
return -ENOMEM;
- }
cpumask_copy(cpus_to_visit, cpu_possible_mask);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 0a58e969f8b7..df3cac739813 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -323,8 +323,8 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev);
* return to the caller and not iterate over any more devices.
*/
struct device *bus_find_device(struct bus_type *bus,
- struct device *start, void *data,
- int (*match)(struct device *dev, void *data))
+ struct device *start, const void *data,
+ int (*match)(struct device *dev, const void *data))
{
struct klist_iter i;
struct device *dev;
@@ -342,7 +342,7 @@ struct device *bus_find_device(struct bus_type *bus,
}
EXPORT_SYMBOL_GPL(bus_find_device);
-static int match_name(struct device *dev, void *data)
+static int match_name(struct device *dev, const void *data)
{
const char *name = data;
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 8827c60f51e2..8d553c92cd32 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -660,7 +660,8 @@ static int cacheinfo_cpu_pre_down(unsigned int cpu)
static int __init cacheinfo_sysfs_init(void)
{
- return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "base/cacheinfo:online",
+ return cpuhp_setup_state(CPUHP_AP_BASE_CACHEINFO_ONLINE,
+ "base/cacheinfo:online",
cacheinfo_cpu_online, cacheinfo_cpu_pre_down);
}
device_initcall(cacheinfo_sysfs_init);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b4c64528f13c..da84a73f2ba6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -3356,3 +3356,9 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
dev->of_node_reused = true;
}
EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
+
+int device_match_of_node(struct device *dev, const void *np)
+{
+ return dev->of_node == np;
+}
+EXPORT_SYMBOL_GPL(device_match_of_node);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 0df9b4461766..994a90747420 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -235,6 +235,19 @@ static int __init deferred_probe_timeout_setup(char *str)
}
__setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
+static int __driver_deferred_probe_check_state(struct device *dev)
+{
+ if (!initcalls_done)
+ return -EPROBE_DEFER;
+
+ if (!deferred_probe_timeout) {
+ dev_WARN(dev, "deferred probe timeout, ignoring dependency");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
/**
* driver_deferred_probe_check_state() - Check deferred probe state
* @dev: device to check
@@ -248,14 +261,40 @@ __setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
*/
int driver_deferred_probe_check_state(struct device *dev)
{
- if (initcalls_done) {
- if (!deferred_probe_timeout) {
- dev_WARN(dev, "deferred probe timeout, ignoring dependency");
- return -ETIMEDOUT;
- }
- dev_warn(dev, "ignoring dependency for device, assuming no driver");
- return -ENODEV;
- }
+ int ret;
+
+ ret = __driver_deferred_probe_check_state(dev);
+ if (ret < 0)
+ return ret;
+
+ dev_warn(dev, "ignoring dependency for device, assuming no driver");
+
+ return -ENODEV;
+}
+
+/**
+ * driver_deferred_probe_check_state_continue() - check deferred probe state
+ * @dev: device to check
+ *
+ * Returns -ETIMEDOUT if deferred probe debug timeout has expired, or
+ * -EPROBE_DEFER otherwise.
+ *
+ * Drivers or subsystems can opt-in to calling this function instead of
+ * directly returning -EPROBE_DEFER.
+ *
+ * This is similar to driver_deferred_probe_check_state(), but it allows the
+ * subsystem to keep deferring probe after built-in drivers have had a chance
+ * to probe. One scenario where that is useful is if built-in drivers rely on
+ * resources that are provided by modular drivers.
+ */
+int driver_deferred_probe_check_state_continue(struct device *dev)
+{
+ int ret;
+
+ ret = __driver_deferred_probe_check_state(dev);
+ if (ret < 0)
+ return ret;
+
return -EPROBE_DEFER;
}
diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c
index f7035fc12b92..09f28479b243 100644
--- a/drivers/base/devcon.c
+++ b/drivers/base/devcon.c
@@ -133,7 +133,7 @@ static struct bus_type *generic_match_buses[] = {
NULL,
};
-static int device_fwnode_match(struct device *dev, void *fwnode)
+static int device_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode;
}
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 857c8f1b876e..4e5ca632f35e 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -73,8 +73,8 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
* return to the caller and not iterate over any more devices.
*/
struct device *driver_find_device(struct device_driver *drv,
- struct device *start, void *data,
- int (*match)(struct device *dev, void *data))
+ struct device *start, const void *data,
+ int (*match)(struct device *dev, const void *data))
{
struct klist_iter i;
struct device *dev;
diff --git a/drivers/base/firmware_loader/Kconfig b/drivers/base/firmware_loader/Kconfig
index 38f2da6f5c2b..3f9e274e2ed3 100644
--- a/drivers/base/firmware_loader/Kconfig
+++ b/drivers/base/firmware_loader/Kconfig
@@ -26,6 +26,9 @@ config FW_LOADER
if FW_LOADER
+config FW_LOADER_PAGED_BUF
+ bool
+
config EXTRA_FIRMWARE
string "Build named firmware blobs into the kernel binary"
help
@@ -67,6 +70,7 @@ config EXTRA_FIRMWARE_DIR
config FW_LOADER_USER_HELPER
bool "Enable the firmware sysfs fallback mechanism"
+ select FW_LOADER_PAGED_BUF
help
This option enables a sysfs loading facility to enable firmware
loading to the kernel through userspace as a fallback mechanism
@@ -151,5 +155,19 @@ config FW_LOADER_USER_HELPER_FALLBACK
If you are unsure about this, say N here.
+config FW_LOADER_COMPRESS
+ bool "Enable compressed firmware support"
+ select FW_LOADER_PAGED_BUF
+ select XZ_DEC
+ help
+ This option enables the support for loading compressed firmware
+ files. The caller of firmware API receives the decompressed file
+ content. The compressed file is loaded as a fallback, only after
+ loading the raw file failed at first.
+
+ Currently only XZ-compressed files are supported, and they have to
+ be compressed with either none or crc32 integrity check type (pass
+ "-C crc32" option to xz command).
+
endif # FW_LOADER
endmenu
diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c
index f962488546b6..62ee90b4db56 100644
--- a/drivers/base/firmware_loader/fallback.c
+++ b/drivers/base/firmware_loader/fallback.c
@@ -219,20 +219,6 @@ static ssize_t firmware_loading_show(struct device *dev,
return sprintf(buf, "%d\n", loading);
}
-/* one pages buffer should be mapped/unmapped only once */
-static int map_fw_priv_pages(struct fw_priv *fw_priv)
-{
- if (!fw_priv->is_paged_buf)
- return 0;
-
- vunmap(fw_priv->data);
- fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 0,
- PAGE_KERNEL_RO);
- if (!fw_priv->data)
- return -ENOMEM;
- return 0;
-}
-
/**
* firmware_loading_store() - set value in the 'loading' control file
* @dev: device pointer
@@ -254,7 +240,6 @@ static ssize_t firmware_loading_store(struct device *dev,
struct fw_priv *fw_priv;
ssize_t written = count;
int loading = simple_strtol(buf, NULL, 10);
- int i;
mutex_lock(&fw_lock);
fw_priv = fw_sysfs->fw_priv;
@@ -265,12 +250,7 @@ static ssize_t firmware_loading_store(struct device *dev,
case 1:
/* discarding any previous partial load */
if (!fw_sysfs_done(fw_priv)) {
- for (i = 0; i < fw_priv->nr_pages; i++)
- __free_page(fw_priv->pages[i]);
- vfree(fw_priv->pages);
- fw_priv->pages = NULL;
- fw_priv->page_array_size = 0;
- fw_priv->nr_pages = 0;
+ fw_free_paged_buf(fw_priv);
fw_state_start(fw_priv);
}
break;
@@ -284,7 +264,7 @@ static ssize_t firmware_loading_store(struct device *dev,
* see the mapped 'buf->data' once the loading
* is completed.
* */
- rc = map_fw_priv_pages(fw_priv);
+ rc = fw_map_paged_buf(fw_priv);
if (rc)
dev_err(dev, "%s: map pages failed\n",
__func__);
@@ -389,40 +369,13 @@ out:
static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
{
- struct fw_priv *fw_priv= fw_sysfs->fw_priv;
- int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
-
- /* If the array of pages is too small, grow it... */
- if (fw_priv->page_array_size < pages_needed) {
- int new_array_size = max(pages_needed,
- fw_priv->page_array_size * 2);
- struct page **new_pages;
+ int err;
- new_pages = vmalloc(array_size(new_array_size, sizeof(void *)));
- if (!new_pages) {
- fw_load_abort(fw_sysfs);
- return -ENOMEM;
- }
- memcpy(new_pages, fw_priv->pages,
- fw_priv->page_array_size * sizeof(void *));
- memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
- (new_array_size - fw_priv->page_array_size));
- vfree(fw_priv->pages);
- fw_priv->pages = new_pages;
- fw_priv->page_array_size = new_array_size;
- }
-
- while (fw_priv->nr_pages < pages_needed) {
- fw_priv->pages[fw_priv->nr_pages] =
- alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
-
- if (!fw_priv->pages[fw_priv->nr_pages]) {
- fw_load_abort(fw_sysfs);
- return -ENOMEM;
- }
- fw_priv->nr_pages++;
- }
- return 0;
+ err = fw_grow_paged_buf(fw_sysfs->fw_priv,
+ PAGE_ALIGN(min_size) >> PAGE_SHIFT);
+ if (err)
+ fw_load_abort(fw_sysfs);
+ return err;
}
/**
@@ -659,7 +612,7 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
/* Also permit LSMs and IMA to fail firmware sysfs fallback */
ret = security_kernel_load_data(LOADING_FIRMWARE);
if (ret < 0)
- return ret;
+ return false;
return fw_force_sysfs_fallback(opt_flags);
}
diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h
index 4c1395f8e7ed..7048a41973ed 100644
--- a/drivers/base/firmware_loader/firmware.h
+++ b/drivers/base/firmware_loader/firmware.h
@@ -64,12 +64,14 @@ struct fw_priv {
void *data;
size_t size;
size_t allocated_size;
-#ifdef CONFIG_FW_LOADER_USER_HELPER
+#ifdef CONFIG_FW_LOADER_PAGED_BUF
bool is_paged_buf;
- bool need_uevent;
struct page **pages;
int nr_pages;
int page_array_size;
+#endif
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+ bool need_uevent;
struct list_head pending_list;
#endif
const char *fw_name;
@@ -133,4 +135,14 @@ static inline void fw_state_done(struct fw_priv *fw_priv)
int assign_fw(struct firmware *fw, struct device *device,
enum fw_opt opt_flags);
+#ifdef CONFIG_FW_LOADER_PAGED_BUF
+void fw_free_paged_buf(struct fw_priv *fw_priv);
+int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
+int fw_map_paged_buf(struct fw_priv *fw_priv);
+#else
+static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
+int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
+int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
+#endif
+
#endif /* __FIRMWARE_LOADER_H */
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 7eaaf5ee5ba6..bf44c79beae9 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -33,6 +33,7 @@
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <linux/security.h>
+#include <linux/xz.h>
#include <generated/utsrelease.h>
@@ -251,15 +252,7 @@ static void __free_fw_priv(struct kref *ref)
list_del(&fw_priv->list);
spin_unlock(&fwc->lock);
-#ifdef CONFIG_FW_LOADER_USER_HELPER
- if (fw_priv->is_paged_buf) {
- int i;
- vunmap(fw_priv->data);
- for (i = 0; i < fw_priv->nr_pages; i++)
- __free_page(fw_priv->pages[i]);
- vfree(fw_priv->pages);
- } else
-#endif
+ fw_free_paged_buf(fw_priv); /* free leftover pages */
if (!fw_priv->allocated_size)
vfree(fw_priv->data);
kfree_const(fw_priv->fw_name);
@@ -274,6 +267,174 @@ static void free_fw_priv(struct fw_priv *fw_priv)
spin_unlock(&fwc->lock);
}
+#ifdef CONFIG_FW_LOADER_PAGED_BUF
+void fw_free_paged_buf(struct fw_priv *fw_priv)
+{
+ int i;
+
+ if (!fw_priv->pages)
+ return;
+
+ for (i = 0; i < fw_priv->nr_pages; i++)
+ __free_page(fw_priv->pages[i]);
+ kvfree(fw_priv->pages);
+ fw_priv->pages = NULL;
+ fw_priv->page_array_size = 0;
+ fw_priv->nr_pages = 0;
+}
+
+int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed)
+{
+ /* If the array of pages is too small, grow it */
+ if (fw_priv->page_array_size < pages_needed) {
+ int new_array_size = max(pages_needed,
+ fw_priv->page_array_size * 2);
+ struct page **new_pages;
+
+ new_pages = kvmalloc_array(new_array_size, sizeof(void *),
+ GFP_KERNEL);
+ if (!new_pages)
+ return -ENOMEM;
+ memcpy(new_pages, fw_priv->pages,
+ fw_priv->page_array_size * sizeof(void *));
+ memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
+ (new_array_size - fw_priv->page_array_size));
+ kvfree(fw_priv->pages);
+ fw_priv->pages = new_pages;
+ fw_priv->page_array_size = new_array_size;
+ }
+
+ while (fw_priv->nr_pages < pages_needed) {
+ fw_priv->pages[fw_priv->nr_pages] =
+ alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+
+ if (!fw_priv->pages[fw_priv->nr_pages])
+ return -ENOMEM;
+ fw_priv->nr_pages++;
+ }
+
+ return 0;
+}
+
+int fw_map_paged_buf(struct fw_priv *fw_priv)
+{
+ /* one pages buffer should be mapped/unmapped only once */
+ if (!fw_priv->pages)
+ return 0;
+
+ vunmap(fw_priv->data);
+ fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 0,
+ PAGE_KERNEL_RO);
+ if (!fw_priv->data)
+ return -ENOMEM;
+
+ /* page table is no longer needed after mapping, let's free */
+ kvfree(fw_priv->pages);
+ fw_priv->pages = NULL;
+
+ return 0;
+}
+#endif
+
+/*
+ * XZ-compressed firmware support
+ */
+#ifdef CONFIG_FW_LOADER_COMPRESS
+/* show an error and return the standard error code */
+static int fw_decompress_xz_error(struct device *dev, enum xz_ret xz_ret)
+{
+ if (xz_ret != XZ_STREAM_END) {
+ dev_warn(dev, "xz decompression failed (xz_ret=%d)\n", xz_ret);
+ return xz_ret == XZ_MEM_ERROR ? -ENOMEM : -EINVAL;
+ }
+ return 0;
+}
+
+/* single-shot decompression onto the pre-allocated buffer */
+static int fw_decompress_xz_single(struct device *dev, struct fw_priv *fw_priv,
+ size_t in_size, const void *in_buffer)
+{
+ struct xz_dec *xz_dec;
+ struct xz_buf xz_buf;
+ enum xz_ret xz_ret;
+
+ xz_dec = xz_dec_init(XZ_SINGLE, (u32)-1);
+ if (!xz_dec)
+ return -ENOMEM;
+
+ xz_buf.in_size = in_size;
+ xz_buf.in = in_buffer;
+ xz_buf.in_pos = 0;
+ xz_buf.out_size = fw_priv->allocated_size;
+ xz_buf.out = fw_priv->data;
+ xz_buf.out_pos = 0;
+
+ xz_ret = xz_dec_run(xz_dec, &xz_buf);
+ xz_dec_end(xz_dec);
+
+ fw_priv->size = xz_buf.out_pos;
+ return fw_decompress_xz_error(dev, xz_ret);
+}
+
+/* decompression on paged buffer and map it */
+static int fw_decompress_xz_pages(struct device *dev, struct fw_priv *fw_priv,
+ size_t in_size, const void *in_buffer)
+{
+ struct xz_dec *xz_dec;
+ struct xz_buf xz_buf;
+ enum xz_ret xz_ret;
+ struct page *page;
+ int err = 0;
+
+ xz_dec = xz_dec_init(XZ_DYNALLOC, (u32)-1);
+ if (!xz_dec)
+ return -ENOMEM;
+
+ xz_buf.in_size = in_size;
+ xz_buf.in = in_buffer;
+ xz_buf.in_pos = 0;
+
+ fw_priv->is_paged_buf = true;
+ fw_priv->size = 0;
+ do {
+ if (fw_grow_paged_buf(fw_priv, fw_priv->nr_pages + 1)) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* decompress onto the new allocated page */
+ page = fw_priv->pages[fw_priv->nr_pages - 1];
+ xz_buf.out = kmap(page);
+ xz_buf.out_pos = 0;
+ xz_buf.out_size = PAGE_SIZE;
+ xz_ret = xz_dec_run(xz_dec, &xz_buf);
+ kunmap(page);
+ fw_priv->size += xz_buf.out_pos;
+ /* partial decompression means either end or error */
+ if (xz_buf.out_pos != PAGE_SIZE)
+ break;
+ } while (xz_ret == XZ_OK);
+
+ err = fw_decompress_xz_error(dev, xz_ret);
+ if (!err)
+ err = fw_map_paged_buf(fw_priv);
+
+ out:
+ xz_dec_end(xz_dec);
+ return err;
+}
+
+static int fw_decompress_xz(struct device *dev, struct fw_priv *fw_priv,
+ size_t in_size, const void *in_buffer)
+{
+ /* if the buffer is pre-allocated, we can perform in single-shot mode */
+ if (fw_priv->data)
+ return fw_decompress_xz_single(dev, fw_priv, in_size, in_buffer);
+ else
+ return fw_decompress_xz_pages(dev, fw_priv, in_size, in_buffer);
+}
+#endif /* CONFIG_FW_LOADER_COMPRESS */
+
/* direct firmware loading support */
static char fw_path_para[256];
static const char * const fw_path[] = {
@@ -293,7 +454,12 @@ module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
static int
-fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
+fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
+ const char *suffix,
+ int (*decompress)(struct device *dev,
+ struct fw_priv *fw_priv,
+ size_t in_size,
+ const void *in_buffer))
{
loff_t size;
int i, len;
@@ -301,9 +467,11 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
char *path;
enum kernel_read_file_id id = READING_FIRMWARE;
size_t msize = INT_MAX;
+ void *buffer = NULL;
/* Already populated data member means we're loading into a buffer */
- if (fw_priv->data) {
+ if (!decompress && fw_priv->data) {
+ buffer = fw_priv->data;
id = READING_FIRMWARE_PREALLOC_BUFFER;
msize = fw_priv->allocated_size;
}
@@ -317,15 +485,15 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
if (!fw_path[i][0])
continue;
- len = snprintf(path, PATH_MAX, "%s/%s",
- fw_path[i], fw_priv->fw_name);
+ len = snprintf(path, PATH_MAX, "%s/%s%s",
+ fw_path[i], fw_priv->fw_name, suffix);
if (len >= PATH_MAX) {
rc = -ENAMETOOLONG;
break;
}
fw_priv->size = 0;
- rc = kernel_read_file_from_path(path, &fw_priv->data, &size,
+ rc = kernel_read_file_from_path(path, &buffer, &size,
msize, id);
if (rc) {
if (rc != -ENOENT)
@@ -336,8 +504,24 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
path);
continue;
}
- dev_dbg(device, "direct-loading %s\n", fw_priv->fw_name);
- fw_priv->size = size;
+ if (decompress) {
+ dev_dbg(device, "f/w decompressing %s\n",
+ fw_priv->fw_name);
+ rc = decompress(device, fw_priv, size, buffer);
+ /* discard the superfluous original content */
+ vfree(buffer);
+ buffer = NULL;
+ if (rc) {
+ fw_free_paged_buf(fw_priv);
+ continue;
+ }
+ } else {
+ dev_dbg(device, "direct-loading %s\n",
+ fw_priv->fw_name);
+ if (!fw_priv->data)
+ fw_priv->data = buffer;
+ fw_priv->size = size;
+ }
fw_state_done(fw_priv);
break;
}
@@ -584,7 +768,13 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (ret <= 0) /* error or already assigned */
goto out;
- ret = fw_get_filesystem_firmware(device, fw->priv);
+ ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
+#ifdef CONFIG_FW_LOADER_COMPRESS
+ if (ret == -ENOENT)
+ ret = fw_get_filesystem_firmware(device, fw->priv, ".xz",
+ fw_decompress_xz);
+#endif
+
if (ret) {
if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device,
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 8598fcbd2a17..aa878fbcf705 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -66,6 +66,7 @@ static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
* @dev: Device for this memory access class
* @list_node: List element in the node's access list
* @access: The access class rank
+ * @hmem_attrs: Heterogeneous memory performance attributes
*/
struct node_access_nodes {
struct device dev;
@@ -673,8 +674,8 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
/**
* register_memory_node_under_compute_node - link memory node to its compute
* node for a given access class.
- * @mem_node: Memory node number
- * @cpu_node: Cpu node number
+ * @mem_nid: Memory node number
+ * @cpu_nid: Cpu node number
* @access: Access class to register
*
* Description:
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 4d1729853d1a..713903290385 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -5,7 +5,7 @@
* Copyright (c) 2002-3 Patrick Mochel
* Copyright (c) 2002-3 Open Source Development Labs
*
- * Please see Documentation/driver-model/platform.txt for more
+ * Please see Documentation/driver-model/platform.rst for more
* information.
*/
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index caac5d24baa4..4bad0614109b 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -132,3 +132,12 @@ config ASPEED_BT_IPMI_BMC
Provides a driver for the BT (Block Transfer) IPMI interface
found on Aspeed SOCs (AST2400 and AST2500). The driver
implements the BMC side of the BT interface.
+
+config IPMB_DEVICE_INTERFACE
+ tristate 'IPMB Interface handler'
+ depends on I2C
+ depends on I2C_SLAVE
+ help
+ Provides a driver for a device (Satellite MC) to
+ receive requests and send responses back to the BMC via
+ the IPMB interface. This module requires I2C support.
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
index 3f06b2062475..0822adc2ec41 100644
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o
obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
+obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o
diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c
new file mode 100644
index 000000000000..57204335c5f5
--- /dev/null
+++ b/drivers/char/ipmi/ipmb_dev_int.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * IPMB driver to receive a request and send a response
+ *
+ * Copyright (C) 2019 Mellanox Techologies, Ltd.
+ *
+ * This was inspired by Brendan Higgins' ipmi-bmc-bt-i2c driver.
+ */
+
+#include <linux/acpi.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+#define MAX_MSG_LEN 128
+#define IPMB_REQUEST_LEN_MIN 7
+#define NETFN_RSP_BIT_MASK 0x4
+#define REQUEST_QUEUE_MAX_LEN 256
+
+#define IPMB_MSG_LEN_IDX 0
+#define RQ_SA_8BIT_IDX 1
+#define NETFN_LUN_IDX 2
+
+#define GET_7BIT_ADDR(addr_8bit) (addr_8bit >> 1)
+#define GET_8BIT_ADDR(addr_7bit) ((addr_7bit << 1) & 0xff)
+
+#define IPMB_MSG_PAYLOAD_LEN_MAX (MAX_MSG_LEN - IPMB_REQUEST_LEN_MIN - 1)
+
+#define SMBUS_MSG_HEADER_LENGTH 2
+#define SMBUS_MSG_IDX_OFFSET (SMBUS_MSG_HEADER_LENGTH + 1)
+
+struct ipmb_msg {
+ u8 len;
+ u8 rs_sa;
+ u8 netfn_rs_lun;
+ u8 checksum1;
+ u8 rq_sa;
+ u8 rq_seq_rq_lun;
+ u8 cmd;
+ u8 payload[IPMB_MSG_PAYLOAD_LEN_MAX];
+ /* checksum2 is included in payload */
+} __packed;
+
+struct ipmb_request_elem {
+ struct list_head list;
+ struct ipmb_msg request;
+};
+
+struct ipmb_dev {
+ struct i2c_client *client;
+ struct miscdevice miscdev;
+ struct ipmb_msg request;
+ struct list_head request_queue;
+ atomic_t request_queue_len;
+ size_t msg_idx;
+ spinlock_t lock;
+ wait_queue_head_t wait_queue;
+ struct mutex file_mutex;
+};
+
+static inline struct ipmb_dev *to_ipmb_dev(struct file *file)
+{
+ return container_of(file->private_data, struct ipmb_dev, miscdev);
+}
+
+static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);
+ struct ipmb_request_elem *queue_elem;
+ struct ipmb_msg msg;
+ ssize_t ret;
+
+ memset(&msg, 0, sizeof(msg));
+
+ spin_lock_irq(&ipmb_dev->lock);
+
+ while (list_empty(&ipmb_dev->request_queue)) {
+ spin_unlock_irq(&ipmb_dev->lock);
+
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ ret = wait_event_interruptible(ipmb_dev->wait_queue,
+ !list_empty(&ipmb_dev->request_queue));
+ if (ret)
+ return ret;
+
+ spin_lock_irq(&ipmb_dev->lock);
+ }
+
+ queue_elem = list_first_entry(&ipmb_dev->request_queue,
+ struct ipmb_request_elem, list);
+ memcpy(&msg, &queue_elem->request, sizeof(msg));
+ list_del(&queue_elem->list);
+ kfree(queue_elem);
+ atomic_dec(&ipmb_dev->request_queue_len);
+
+ spin_unlock_irq(&ipmb_dev->lock);
+
+ count = min_t(size_t, count, msg.len + 1);
+ if (copy_to_user(buf, &msg, count))
+ ret = -EFAULT;
+
+ return ret < 0 ? ret : count;
+}
+
+static ssize_t ipmb_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);
+ u8 rq_sa, netf_rq_lun, msg_len;
+ union i2c_smbus_data data;
+ u8 msg[MAX_MSG_LEN];
+ ssize_t ret;
+
+ if (count > sizeof(msg))
+ return -EINVAL;
+
+ if (copy_from_user(&msg, buf, count))
+ return -EFAULT;
+
+ if (count < msg[0])
+ return -EINVAL;
+
+ rq_sa = GET_7BIT_ADDR(msg[RQ_SA_8BIT_IDX]);
+ netf_rq_lun = msg[NETFN_LUN_IDX];
+
+ if (!(netf_rq_lun & NETFN_RSP_BIT_MASK))
+ return -EINVAL;
+
+ /*
+ * subtract rq_sa and netf_rq_lun from the length of the msg passed to
+ * i2c_smbus_xfer
+ */
+ msg_len = msg[IPMB_MSG_LEN_IDX] - SMBUS_MSG_HEADER_LENGTH;
+ if (msg_len > I2C_SMBUS_BLOCK_MAX)
+ msg_len = I2C_SMBUS_BLOCK_MAX;
+
+ data.block[0] = msg_len;
+ memcpy(&data.block[1], msg + SMBUS_MSG_IDX_OFFSET, msg_len);
+ ret = i2c_smbus_xfer(ipmb_dev->client->adapter, rq_sa,
+ ipmb_dev->client->flags,
+ I2C_SMBUS_WRITE, netf_rq_lun,
+ I2C_SMBUS_BLOCK_DATA, &data);
+
+ return ret ? : count;
+}
+
+static unsigned int ipmb_poll(struct file *file, poll_table *wait)
+{
+ struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);
+ unsigned int mask = POLLOUT;
+
+ mutex_lock(&ipmb_dev->file_mutex);
+ poll_wait(file, &ipmb_dev->wait_queue, wait);
+
+ if (atomic_read(&ipmb_dev->request_queue_len))
+ mask |= POLLIN;
+ mutex_unlock(&ipmb_dev->file_mutex);
+
+ return mask;
+}
+
+static const struct file_operations ipmb_fops = {
+ .owner = THIS_MODULE,
+ .read = ipmb_read,
+ .write = ipmb_write,
+ .poll = ipmb_poll,
+};
+
+/* Called with ipmb_dev->lock held. */
+static void ipmb_handle_request(struct ipmb_dev *ipmb_dev)
+{
+ struct ipmb_request_elem *queue_elem;
+
+ if (atomic_read(&ipmb_dev->request_queue_len) >=
+ REQUEST_QUEUE_MAX_LEN)
+ return;
+
+ queue_elem = kmalloc(sizeof(*queue_elem), GFP_ATOMIC);
+ if (!queue_elem)
+ return;
+
+ memcpy(&queue_elem->request, &ipmb_dev->request,
+ sizeof(struct ipmb_msg));
+ list_add(&queue_elem->list, &ipmb_dev->request_queue);
+ atomic_inc(&ipmb_dev->request_queue_len);
+ wake_up_all(&ipmb_dev->wait_queue);
+}
+
+static u8 ipmb_verify_checksum1(struct ipmb_dev *ipmb_dev, u8 rs_sa)
+{
+ /* The 8 lsb of the sum is 0 when the checksum is valid */
+ return (rs_sa + ipmb_dev->request.netfn_rs_lun +
+ ipmb_dev->request.checksum1);
+}
+
+static bool is_ipmb_request(struct ipmb_dev *ipmb_dev, u8 rs_sa)
+{
+ if (ipmb_dev->msg_idx >= IPMB_REQUEST_LEN_MIN) {
+ if (ipmb_verify_checksum1(ipmb_dev, rs_sa))
+ return false;
+
+ /*
+ * Check whether this is an IPMB request or
+ * response.
+ * The 6 MSB of netfn_rs_lun are dedicated to the netfn
+ * while the remaining bits are dedicated to the lun.
+ * If the LSB of the netfn is cleared, it is associated
+ * with an IPMB request.
+ * If the LSB of the netfn is set, it is associated with
+ * an IPMB response.
+ */
+ if (!(ipmb_dev->request.netfn_rs_lun & NETFN_RSP_BIT_MASK))
+ return true;
+ }
+ return false;
+}
+
+/*
+ * The IPMB protocol only supports I2C Writes so there is no need
+ * to support I2C_SLAVE_READ* events.
+ * This i2c callback function only monitors IPMB request messages
+ * and adds them in a queue, so that they can be handled by
+ * receive_ipmb_request.
+ */
+static int ipmb_slave_cb(struct i2c_client *client,
+ enum i2c_slave_event event, u8 *val)
+{
+ struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client);
+ u8 *buf = (u8 *)&ipmb_dev->request;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipmb_dev->lock, flags);
+ switch (event) {
+ case I2C_SLAVE_WRITE_REQUESTED:
+ memset(&ipmb_dev->request, 0, sizeof(ipmb_dev->request));
+ ipmb_dev->msg_idx = 0;
+
+ /*
+ * At index 0, ipmb_msg stores the length of msg,
+ * skip it for now.
+ * The len will be populated once the whole
+ * buf is populated.
+ *
+ * The I2C bus driver's responsibility is to pass the
+ * data bytes to the backend driver; it does not
+ * forward the i2c slave address.
+ * Since the first byte in the IPMB message is the
+ * address of the responder, it is the responsibility
+ * of the IPMB driver to format the message properly.
+ * So this driver prepends the address of the responder
+ * to the received i2c data before the request message
+ * is handled in userland.
+ */
+ buf[++ipmb_dev->msg_idx] = GET_8BIT_ADDR(client->addr);
+ break;
+
+ case I2C_SLAVE_WRITE_RECEIVED:
+ if (ipmb_dev->msg_idx >= sizeof(struct ipmb_msg))
+ break;
+
+ buf[++ipmb_dev->msg_idx] = *val;
+ break;
+
+ case I2C_SLAVE_STOP:
+ ipmb_dev->request.len = ipmb_dev->msg_idx;
+
+ if (is_ipmb_request(ipmb_dev, GET_8BIT_ADDR(client->addr)))
+ ipmb_handle_request(ipmb_dev);
+ break;
+
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&ipmb_dev->lock, flags);
+
+ return 0;
+}
+
+static int ipmb_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ipmb_dev *ipmb_dev;
+ int ret;
+
+ ipmb_dev = devm_kzalloc(&client->dev, sizeof(*ipmb_dev),
+ GFP_KERNEL);
+ if (!ipmb_dev)
+ return -ENOMEM;
+
+ spin_lock_init(&ipmb_dev->lock);
+ init_waitqueue_head(&ipmb_dev->wait_queue);
+ atomic_set(&ipmb_dev->request_queue_len, 0);
+ INIT_LIST_HEAD(&ipmb_dev->request_queue);
+
+ mutex_init(&ipmb_dev->file_mutex);
+
+ ipmb_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ ipmb_dev->miscdev.name = devm_kasprintf(&client->dev, GFP_KERNEL,
+ "%s%d", "ipmb-",
+ client->adapter->nr);
+ ipmb_dev->miscdev.fops = &ipmb_fops;
+ ipmb_dev->miscdev.parent = &client->dev;
+ ret = misc_register(&ipmb_dev->miscdev);
+ if (ret)
+ return ret;
+
+ ipmb_dev->client = client;
+ i2c_set_clientdata(client, ipmb_dev);
+ ret = i2c_slave_register(client, ipmb_slave_cb);
+ if (ret) {
+ misc_deregister(&ipmb_dev->miscdev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ipmb_remove(struct i2c_client *client)
+{
+ struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client);
+
+ i2c_slave_unregister(client);
+ misc_deregister(&ipmb_dev->miscdev);
+
+ return 0;
+}
+
+static const struct i2c_device_id ipmb_id[] = {
+ { "ipmb-dev", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, ipmb_id);
+
+static const struct acpi_device_id acpi_ipmb_id[] = {
+ { "IPMB0001", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, acpi_ipmb_id);
+
+static struct i2c_driver ipmb_driver = {
+ .driver = {
+ .name = "ipmb-dev",
+ .acpi_match_table = ACPI_PTR(acpi_ipmb_id),
+ },
+ .probe = ipmb_probe,
+ .remove = ipmb_remove,
+ .id_table = ipmb_id,
+};
+module_i2c_driver(ipmb_driver);
+
+MODULE_AUTHOR("Mellanox Technologies");
+MODULE_DESCRIPTION("IPMB driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 1dc10740fc0f..6707659cffd6 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2819,9 +2819,9 @@ static const struct device_type bmc_device_type = {
.groups = bmc_dev_attr_groups,
};
-static int __find_bmc_guid(struct device *dev, void *data)
+static int __find_bmc_guid(struct device *dev, const void *data)
{
- guid_t *guid = data;
+ const guid_t *guid = data;
struct bmc_device *bmc;
int rv;
@@ -2857,9 +2857,9 @@ struct prod_dev_id {
unsigned char device_id;
};
-static int __find_bmc_prod_dev_id(struct device *dev, void *data)
+static int __find_bmc_prod_dev_id(struct device *dev, const void *data)
{
- struct prod_dev_id *cid = data;
+ const struct prod_dev_id *cid = data;
struct bmc_device *bmc;
int rv;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index f124a2d2bb9f..da5b6723329a 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -71,7 +71,7 @@ enum si_intf_state {
static const char * const si_to_str[] = { "invalid", "kcs", "smic", "bt" };
-static int initialized;
+static bool initialized;
/*
* Indexes into stats[] in smi_info below.
@@ -2124,7 +2124,7 @@ static int __init init_ipmi_si(void)
}
skip_fallback_noirq:
- initialized = 1;
+ initialized = true;
mutex_unlock(&smi_infos_lock);
if (type)
diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c
index f2a91c4d8cab..22f6c9b20e9a 100644
--- a/drivers/char/ipmi/ipmi_si_platform.c
+++ b/drivers/char/ipmi/ipmi_si_platform.c
@@ -19,6 +19,7 @@
#include "ipmi_si.h"
#include "ipmi_dmi.h"
+static bool platform_registered;
static bool si_tryplatform = true;
#ifdef CONFIG_ACPI
static bool si_tryacpi = true;
@@ -426,7 +427,7 @@ static int ipmi_remove(struct platform_device *pdev)
return ipmi_si_remove_by_dev(&pdev->dev);
}
-static int pdev_match_name(struct device *dev, void *data)
+static int pdev_match_name(struct device *dev, const void *data)
{
struct platform_device *pdev = to_platform_device(dev);
const char *name = data;
@@ -443,6 +444,7 @@ void ipmi_remove_platform_device_by_name(char *name)
struct platform_device *pdev = to_platform_device(dev);
platform_device_unregister(pdev);
+ put_device(dev);
}
}
@@ -469,9 +471,12 @@ void ipmi_si_platform_init(void)
int rv = platform_driver_register(&ipmi_platform_driver);
if (rv)
pr_err("Unable to register driver: %d\n", rv);
+ else
+ platform_registered = true;
}
void ipmi_si_platform_shutdown(void)
{
- platform_driver_unregister(&ipmi_platform_driver);
+ if (platform_registered)
+ platform_driver_unregister(&ipmi_platform_driver);
}
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index cf8156d6bc07..305fa5054274 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -303,6 +303,7 @@ struct ssif_info {
((unsigned int) atomic_read(&(ssif)->stats[SSIF_STAT_ ## stat]))
static bool initialized;
+static bool platform_registered;
static void return_hosed_msg(struct ssif_info *ssif_info,
struct ipmi_smi_msg *msg);
@@ -2088,6 +2089,8 @@ static int init_ipmi_ssif(void)
rv = platform_driver_register(&ipmi_driver);
if (rv)
pr_err("Unable to register driver: %d\n", rv);
+ else
+ platform_registered = true;
}
ssif_i2c_driver.address_list = ssif_address_list();
@@ -2111,7 +2114,7 @@ static void cleanup_ipmi_ssif(void)
kfree(ssif_i2c_driver.address_list);
- if (ssif_trydmi)
+ if (ssif_trydmi && platform_registered)
platform_driver_unregister(&ipmi_driver);
free_ssif_clients();
diff --git a/drivers/clk/renesas/r8a77470-cpg-mssr.c b/drivers/clk/renesas/r8a77470-cpg-mssr.c
index ab0fb10b6bf0..d81ae65f0d18 100644
--- a/drivers/clk/renesas/r8a77470-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77470-cpg-mssr.c
@@ -175,7 +175,7 @@ static const unsigned int r8a77470_crit_mod_clks[] __initconst = {
*---------------------------------------------------
* 0 0 20 x80 x78 x50
* 0 1 26 x60 x60 x56
- * 1 0 Prohibitted setting
+ * 1 0 Prohibited setting
* 1 1 30 x52 x52 x50
*
* *1 : Table 7.4 indicates VCO output (PLL0 = VCO)
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 22cc7f68ef6e..20a9cb7cb6d3 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -24,6 +24,7 @@
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/list.h>
+#include <linux/dma/mxs-dma.h>
#include <asm/irq.h>
@@ -77,6 +78,7 @@
#define BM_CCW_COMMAND (3 << 0)
#define CCW_CHAIN (1 << 2)
#define CCW_IRQ (1 << 3)
+#define CCW_WAIT4RDY (1 << 5)
#define CCW_DEC_SEM (1 << 6)
#define CCW_WAIT4END (1 << 7)
#define CCW_HALT_ON_TERM (1 << 8)
@@ -477,16 +479,16 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
* ......
* ->device_prep_slave_sg(0);
* ......
- * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ * ->device_prep_slave_sg(DMA_CTRL_ACK);
* ......
* [3] If there are more than two DMA commands in the DMA chain, the code
* should be:
* ......
* ->device_prep_slave_sg(0); // First
* ......
- * ->device_prep_slave_sg(DMA_PREP_INTERRUPT [| DMA_CTRL_ACK]);
+ * ->device_prep_slave_sg(DMA_CTRL_ACK]);
* ......
- * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); // Last
+ * ->device_prep_slave_sg(DMA_CTRL_ACK); // Last
* ......
*/
static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
@@ -500,13 +502,12 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
struct scatterlist *sg;
u32 i, j;
u32 *pio;
- bool append = flags & DMA_PREP_INTERRUPT;
- int idx = append ? mxs_chan->desc_count : 0;
+ int idx = 0;
- if (mxs_chan->status == DMA_IN_PROGRESS && !append)
- return NULL;
+ if (mxs_chan->status == DMA_IN_PROGRESS)
+ idx = mxs_chan->desc_count;
- if (sg_len + (append ? idx : 0) > NUM_CCW) {
+ if (sg_len + idx > NUM_CCW) {
dev_err(mxs_dma->dma_device.dev,
"maximum number of sg exceeded: %d > %d\n",
sg_len, NUM_CCW);
@@ -520,7 +521,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
* If the sg is prepared with append flag set, the sg
* will be appended to the last prepared sg.
*/
- if (append) {
+ if (idx) {
BUG_ON(idx < 1);
ccw = &mxs_chan->ccw[idx - 1];
ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
@@ -541,12 +542,14 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
ccw->bits = 0;
ccw->bits |= CCW_IRQ;
ccw->bits |= CCW_DEC_SEM;
- if (flags & DMA_CTRL_ACK)
+ if (flags & MXS_DMA_CTRL_WAIT4END)
ccw->bits |= CCW_WAIT4END;
ccw->bits |= CCW_HALT_ON_TERM;
ccw->bits |= CCW_TERM_FLUSH;
ccw->bits |= BF_CCW(sg_len, PIO_NUM);
ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND);
+ if (flags & MXS_DMA_CTRL_WAIT4RDY)
+ ccw->bits |= CCW_WAIT4RDY;
} else {
for_each_sg(sgl, sg, sg_len, i) {
if (sg_dma_len(sg) > MAX_XFER_BYTES) {
@@ -573,7 +576,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
ccw->bits &= ~CCW_CHAIN;
ccw->bits |= CCW_IRQ;
ccw->bits |= CCW_DEC_SEM;
- if (flags & DMA_CTRL_ACK)
+ if (flags & MXS_DMA_CTRL_WAIT4END)
ccw->bits |= CCW_WAIT4END;
}
}
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 937a930ce87d..44fd4f9404a9 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* System Control and Management Interface (SCMI) Message Protocol
* driver common header file containing some definitions, structures
diff --git a/drivers/firmware/efi/dev-path-parser.c b/drivers/firmware/efi/dev-path-parser.c
index 85ec99f97841..20123384271c 100644
--- a/drivers/firmware/efi/dev-path-parser.c
+++ b/drivers/firmware/efi/dev-path-parser.c
@@ -17,9 +17,9 @@ struct acpi_hid_uid {
char uid[11]; /* UINT_MAX + null byte */
};
-static int __init match_acpi_dev(struct device *dev, void *data)
+static int __init match_acpi_dev(struct device *dev, const void *data)
{
- struct acpi_hid_uid hid_uid = *(struct acpi_hid_uid *)data;
+ struct acpi_hid_uid hid_uid = *(const struct acpi_hid_uid *)data;
struct acpi_device *adev = to_acpi_device(dev);
if (acpi_match_device_ids(adev, hid_uid.hid))
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 4983827151bf..adbeeefaca92 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: BSD-3-Clause
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Texas Instruments System Control Interface (TISCI) Protocol
*
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 75f64abf9c81..e405309baadc 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -22,11 +22,6 @@ static const struct of_device_id fpga_region_of_match[] = {
};
MODULE_DEVICE_TABLE(of, fpga_region_of_match);
-static int fpga_region_of_node_match(struct device *dev, const void *data)
-{
- return dev->of_node == data;
-}
-
/**
* of_fpga_region_find - find FPGA region
* @np: device node of FPGA Region
@@ -37,7 +32,7 @@ static int fpga_region_of_node_match(struct device *dev, const void *data)
*/
static struct fpga_region *of_fpga_region_find(struct device_node *np)
{
- return fpga_region_class_find(NULL, np, fpga_region_of_node_match);
+ return fpga_region_class_find(NULL, np, device_match_of_node);
}
/**
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
index 6314225dbed0..3611a0571667 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/gpio-cs5535.c
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(mask, "GPIO channel mask.");
/*
* FIXME: convert this singleton driver to use the state container
- * design pattern, see Documentation/driver-model/design-patterns.txt
+ * design pattern, see Documentation/driver-model/design-patterns.rst
*/
static struct cs5535_gpio_chip {
struct gpio_chip chip;
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 80b75501f5c6..ad19df0686c9 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -93,7 +93,7 @@ static struct bus_type mipi_dsi_bus_type = {
.pm = &mipi_dsi_device_pm_ops,
};
-static int of_device_match(struct device *dev, void *data)
+static int of_device_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}
diff --git a/drivers/gpu/drm/i915/.gitignore b/drivers/gpu/drm/i915/.gitignore
deleted file mode 100644
index cff45d81f42f..000000000000
--- a/drivers/gpu/drm/i915/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-header_test_*.c
diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test
index c1c391816fa7..639b596a06a9 100644
--- a/drivers/gpu/drm/i915/Makefile.header-test
+++ b/drivers/gpu/drm/i915/Makefile.header-test
@@ -2,7 +2,7 @@
# Copyright © 2019 Intel Corporation
# Test the headers are compilable as standalone units
-header_test := \
+header-test-$(CONFIG_DRM_I915_WERROR) := \
i915_active_types.h \
i915_gem_context_types.h \
i915_priolist_types.h \
@@ -35,13 +35,3 @@ header_test := \
intel_sprite.h \
intel_tv.h \
intel_workarounds_types.h
-
-quiet_cmd_header_test = HDRTEST $@
- cmd_header_test = echo "\#include \"$(<F)\"" > $@
-
-header_test_%.c: %.h
- $(call cmd,header_test)
-
-i915-$(CONFIG_DRM_I915_WERROR) += $(foreach h,$(header_test),$(patsubst %.h,header_test_%.o,$(h)))
-
-clean-files += $(foreach h,$(header_test),$(patsubst %.h,header_test_%.c,$(h)))
diff --git a/drivers/gpu/drm/i915/i915_mm.c b/drivers/gpu/drm/i915/i915_mm.c
index e4935dd1fd37..c23bb29e6d3e 100644
--- a/drivers/gpu/drm/i915/i915_mm.c
+++ b/drivers/gpu/drm/i915/i915_mm.c
@@ -35,8 +35,7 @@ struct remap_pfn {
pgprot_t prot;
};
-static int remap_pfn(pte_t *pte, pgtable_t token,
- unsigned long addr, void *data)
+static int remap_pfn(pte_t *pte, unsigned long addr, void *data)
{
struct remap_pfn *r = data;
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 826b3f047c0c..cf25f183c4a7 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -2372,10 +2372,10 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
return 0;
}
-static int tegra_dc_match_by_pipe(struct device *dev, void *data)
+static int tegra_dc_match_by_pipe(struct device *dev, const void *data)
{
struct tegra_dc *dc = dev_get_drvdata(dev);
- unsigned int pipe = (unsigned long)data;
+ unsigned int pipe = (unsigned long)(void *)data;
return dc->pipe == pipe;
}
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 1549c7a2f04c..185a577c46f6 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/mutex.h>
+#include <linux/input/elan-i2c-ids.h>
#include "hid-ids.h"
@@ -916,6 +917,8 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
bool hid_ignore(struct hid_device *hdev)
{
+ int i;
+
if (hdev->quirks & HID_QUIRK_NO_IGNORE)
return false;
if (hdev->quirks & HID_QUIRK_IGNORE)
@@ -980,18 +983,15 @@ bool hid_ignore(struct hid_device *hdev)
break;
case USB_VENDOR_ID_ELAN:
/*
- * Many Elan devices have a product id of 0x0401 and are handled
- * by the elan_i2c input driver. But the ACPI HID ELAN0800 dev
- * is not (and cannot be) handled by that driver ->
- * Ignore all 0x0401 devs except for the ELAN0800 dev.
+ * Blacklist of everything that gets handled by the elan_i2c
+ * input driver. This avoids disabling valid touchpads and
+ * other ELAN devices.
*/
- if (hdev->product == 0x0401 &&
- strncmp(hdev->name, "ELAN0800", 8) != 0)
- return true;
- /* Same with product id 0x0400 */
- if (hdev->product == 0x0400 &&
- strncmp(hdev->name, "QTEC0001", 8) != 0)
- return true;
+ if ((hdev->product == 0x0401 || hdev->product == 0x0400))
+ for (i = 0; strlen(elan_acpi_id[i].id); ++i)
+ if (!strncmp(hdev->name, elan_acpi_id[i].id,
+ strlen(elan_acpi_id[i].id)))
+ return true;
break;
}
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 72d5a7cde7ea..894da5abdc55 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -2163,6 +2163,7 @@ static void __exit vmbus_exit(void)
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Microsoft Hyper-V VMBus Driver");
subsys_initcall(hv_acpi_init);
module_exit(vmbus_exit);
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 58bfd6319f65..2463aa7ab4f6 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -525,23 +525,12 @@ static const struct file_operations debug_func_knob_fops = {
static int debug_func_init(void)
{
- struct dentry *file;
int ret;
/* Create debugfs node */
debug_debugfs_dir = debugfs_create_dir("coresight_cpu_debug", NULL);
- if (!debug_debugfs_dir) {
- pr_err("%s: unable to create debugfs directory\n", __func__);
- return -ENOMEM;
- }
-
- file = debugfs_create_file("enable", 0644, debug_debugfs_dir, NULL,
- &debug_func_knob_fops);
- if (!file) {
- pr_err("%s: unable to create enable knob file\n", __func__);
- ret = -ENOMEM;
- goto err;
- }
+ debugfs_create_file("enable", 0644, debug_debugfs_dir, NULL,
+ &debug_func_knob_fops);
/* Register function to be called for panic */
ret = atomic_notifier_chain_register(&panic_notifier_list,
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
index cf580ffbc27c..dad7d96c5943 100644
--- a/drivers/hwtracing/coresight/coresight-platform.c
+++ b/drivers/hwtracing/coresight/coresight-platform.c
@@ -37,7 +37,7 @@ static int coresight_alloc_conns(struct device *dev,
return 0;
}
-int coresight_device_fwnode_match(struct device *dev, void *fwnode)
+int coresight_device_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode;
}
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 8b07fe55395a..7d401790dd7e 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -202,6 +202,6 @@ static inline void *coresight_get_uci_data(const struct amba_id *id)
void coresight_release_platform_data(struct coresight_platform_data *pdata);
-int coresight_device_fwnode_match(struct device *dev, void *fwnode);
+int coresight_device_fwnode_match(struct device *dev, const void *fwnode);
#endif
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 86d1fc2c1bd4..55db77f6410b 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -498,9 +498,9 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
return csdev;
}
-static int coresight_enabled_sink(struct device *dev, void *data)
+static int coresight_enabled_sink(struct device *dev, const void *data)
{
- bool *reset = data;
+ const bool *reset = data;
struct coresight_device *csdev = to_coresight_device(dev);
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
@@ -544,7 +544,7 @@ struct coresight_device *coresight_get_enabled_sink(bool deactivate)
return dev ? to_coresight_device(dev) : NULL;
}
-static int coresight_sink_by_id(struct device *dev, void *data)
+static int coresight_sink_by_id(struct device *dev, const void *data)
{
struct coresight_device *csdev = to_coresight_device(dev);
unsigned long hash;
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 033dce563c99..55922896d862 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -789,10 +789,9 @@ static int intel_th_populate(struct intel_th *th)
return 0;
}
-static int match_devt(struct device *dev, void *data)
+static int match_devt(struct device *dev, const void *data)
{
- dev_t devt = (dev_t)(unsigned long)data;
-
+ dev_t devt = (dev_t)(unsigned long)(void *)data;
return dev->devt == devt;
}
diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c
index 455e1f36a2a3..c7fe3b44a860 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-pci.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c
@@ -457,7 +457,7 @@ static struct pci_driver amd_mp2_pci_driver = {
};
module_pci_driver(amd_mp2_pci_driver);
-static int amd_mp2_device_match(struct device *dev, void *data)
+static int amd_mp2_device_match(struct device *dev, const void *data)
{
return 1;
}
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 1969bfdfe6a4..428a82c3a35f 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -320,7 +320,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
}
EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
-static int i2c_acpi_find_match_adapter(struct device *dev, void *data)
+static int i2c_acpi_find_match_adapter(struct device *dev, const void *data)
{
struct i2c_adapter *adapter = i2c_verify_adapter(dev);
@@ -330,7 +330,7 @@ static int i2c_acpi_find_match_adapter(struct device *dev, void *data)
return ACPI_HANDLE(dev) == (acpi_handle)data;
}
-static int i2c_acpi_find_match_device(struct device *dev, void *data)
+static int i2c_acpi_find_match_device(struct device *dev, const void *data)
{
return ACPI_COMPANION(dev) == data;
}
diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
index 406e5f695a7e..2eb59a260ad4 100644
--- a/drivers/i2c/i2c-core-of.c
+++ b/drivers/i2c/i2c-core-of.c
@@ -112,12 +112,12 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
of_node_put(bus);
}
-static int of_dev_node_match(struct device *dev, void *data)
+static int of_dev_node_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}
-static int of_dev_or_parent_node_match(struct device *dev, void *data)
+static int of_dev_or_parent_node_match(struct device *dev, const void *data)
{
if (dev->of_node == data)
return 1;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 2fb2314548e9..5a8351c9a426 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -90,7 +90,7 @@ static const struct iio_chan_spec
#ifdef CONFIG_OF
-static int iio_dev_node_match(struct device *dev, void *data)
+static int iio_dev_node_match(struct device *dev, const void *data)
{
return dev->of_node == data && dev->type == &iio_device_type;
}
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 829b0c6944d8..61758201d9b2 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -127,7 +127,7 @@ __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size,
res = (void *)pbundle->internal_buffer + pbundle->internal_used;
pbundle->internal_used =
ALIGN(new_used, sizeof(*pbundle->internal_buffer));
- if (flags & __GFP_ZERO)
+ if (want_init_on_alloc(flags))
memset(res, 0, size);
return res;
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
index e068a02122f5..3afd3e9330e7 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -4498,7 +4498,7 @@ static const struct acpi_device_id hns_roce_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match);
-static int hns_roce_node_match(struct device *dev, void *fwnode)
+static int hns_roce_node_match(struct device *dev, const void *fwnode)
{
return dev->fwnode == fwnode;
}
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index ac21c050fdb0..a2b5fbba2d3b 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -808,6 +808,7 @@ static bool joydev_dev_is_blacklisted(struct input_dev *dev)
static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
{
DECLARE_BITMAP(jd_scratch, KEY_CNT);
+ bool ev_match = false;
BUILD_BUG_ON(ABS_CNT > KEY_CNT || EV_CNT > KEY_CNT);
@@ -826,17 +827,36 @@ static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
* considered to be an absolute mouse if the following is
* true:
*
- * 1) Event types are exactly EV_ABS, EV_KEY and EV_SYN.
+ * 1) Event types are exactly
+ * EV_ABS, EV_KEY and EV_SYN
+ * or
+ * EV_ABS, EV_KEY, EV_SYN and EV_MSC
+ * or
+ * EV_ABS, EV_KEY, EV_SYN, EV_MSC and EV_REL.
* 2) Absolute events are exactly ABS_X and ABS_Y.
* 3) Keys are exactly BTN_LEFT, BTN_RIGHT and BTN_MIDDLE.
* 4) Device is not on "Amiga" bus.
*/
bitmap_zero(jd_scratch, EV_CNT);
+ /* VMware VMMouse, HP ILO2 */
__set_bit(EV_ABS, jd_scratch);
__set_bit(EV_KEY, jd_scratch);
__set_bit(EV_SYN, jd_scratch);
- if (!bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ if (bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ ev_match = true;
+
+ /* HP ILO2, AMI BMC firmware */
+ __set_bit(EV_MSC, jd_scratch);
+ if (bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ ev_match = true;
+
+ /* VMware Virtual USB Mouse, QEMU USB Tablet, ATEN BMC firmware */
+ __set_bit(EV_REL, jd_scratch);
+ if (bitmap_equal(jd_scratch, dev->evbit, EV_CNT))
+ ev_match = true;
+
+ if (!ev_match)
return false;
bitmap_zero(jd_scratch, ABS_CNT);
diff --git a/drivers/input/joystick/iforce/Kconfig b/drivers/input/joystick/iforce/Kconfig
index 62dcc5b71641..f002fb88f2e7 100644
--- a/drivers/input/joystick/iforce/Kconfig
+++ b/drivers/input/joystick/iforce/Kconfig
@@ -14,15 +14,15 @@ config JOYSTICK_IFORCE
module will be called iforce.
config JOYSTICK_IFORCE_USB
- bool "I-Force USB joysticks and wheels"
- depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || USB=y) && USB
+ tristate "I-Force USB joysticks and wheels"
+ depends on JOYSTICK_IFORCE && USB
help
Say Y here if you have an I-Force joystick or steering wheel
connected to your USB port.
config JOYSTICK_IFORCE_232
- bool "I-Force Serial joysticks and wheels"
- depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || SERIO=y) && SERIO
+ tristate "I-Force Serial joysticks and wheels"
+ depends on JOYSTICK_IFORCE && SERIO
help
Say Y here if you have an I-Force joystick or steering wheel
connected to your serial (COM) port.
diff --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile
index fa79a49d7ca1..dbbe7c04010d 100644
--- a/drivers/input/joystick/iforce/Makefile
+++ b/drivers/input/joystick/iforce/Makefile
@@ -5,8 +5,7 @@
# By Johann Deneux <johann.deneux@gmail.com>
#
-obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o
-
+obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o
iforce-y := iforce-ff.o iforce-main.o iforce-packets.o
-iforce-$(CONFIG_JOYSTICK_IFORCE_232) += iforce-serio.o
-iforce-$(CONFIG_JOYSTICK_IFORCE_USB) += iforce-usb.o
+obj-$(CONFIG_JOYSTICK_IFORCE_232) += iforce-serio.o
+obj-$(CONFIG_JOYSTICK_IFORCE_USB) += iforce-usb.o
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 2ed7da7d1f3e..4cadebd8b9c4 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -372,12 +372,12 @@ int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, stru
}
switch (effect->u.periodic.waveform) {
- case FF_SQUARE: wave_code = 0x20; break;
- case FF_TRIANGLE: wave_code = 0x21; break;
- case FF_SINE: wave_code = 0x22; break;
- case FF_SAW_UP: wave_code = 0x23; break;
- case FF_SAW_DOWN: wave_code = 0x24; break;
- default: wave_code = 0x20; break;
+ case FF_SQUARE: wave_code = 0x20; break;
+ case FF_TRIANGLE: wave_code = 0x21; break;
+ case FF_SINE: wave_code = 0x22; break;
+ case FF_SAW_UP: wave_code = 0x23; break;
+ case FF_SAW_DOWN: wave_code = 0x24; break;
+ default: wave_code = 0x20; break;
}
if (!old || need_core(old, effect)) {
@@ -476,9 +476,9 @@ int iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, str
int core_err = 0;
switch (effect->type) {
- case FF_SPRING: type = 0x40; break;
- case FF_DAMPER: type = 0x41; break;
- default: return -1;
+ case FF_SPRING: type = 0x40; break;
+ case FF_DAMPER: type = 0x41; break;
+ default: return -1;
}
if (!old || need_condition_modifier(iforce, old, effect)) {
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 55f5b7bb4cac..9a5f90da06ec 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -9,10 +9,11 @@
/*
*/
+#include <asm/unaligned.h>
#include "iforce.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
-MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
+MODULE_DESCRIPTION("Core I-Force joysticks and wheels driver");
MODULE_LICENSE("GPL");
static signed short btn_joystick[] =
@@ -55,6 +56,7 @@ static struct iforce_device iforce_device[] = {
{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce },
+ { 0x06a3, 0xff04, "Saitek R440 Force Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce },
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
@@ -120,22 +122,21 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect,
* Upload the effect
*/
switch (effect->type) {
+ case FF_PERIODIC:
+ ret = iforce_upload_periodic(iforce, effect, old);
+ break;
- case FF_PERIODIC:
- ret = iforce_upload_periodic(iforce, effect, old);
- break;
-
- case FF_CONSTANT:
- ret = iforce_upload_constant(iforce, effect, old);
- break;
+ case FF_CONSTANT:
+ ret = iforce_upload_constant(iforce, effect, old);
+ break;
- case FF_SPRING:
- case FF_DAMPER:
- ret = iforce_upload_condition(iforce, effect, old);
- break;
+ case FF_SPRING:
+ case FF_DAMPER:
+ ret = iforce_upload_condition(iforce, effect, old);
+ break;
- default:
- return -EINVAL;
+ default:
+ return -EINVAL;
}
if (ret == 0) {
@@ -173,15 +174,7 @@ static int iforce_open(struct input_dev *dev)
{
struct iforce *iforce = input_get_drvdata(dev);
- switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
- iforce->irq->dev = iforce->usbdev;
- if (usb_submit_urb(iforce->irq, GFP_KERNEL))
- return -EIO;
- break;
-#endif
- }
+ iforce->xport_ops->start_io(iforce);
if (test_bit(EV_FF, dev->evbit)) {
/* Enable force feedback */
@@ -214,27 +207,17 @@ static void iforce_close(struct input_dev *dev)
!test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags));
}
- switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
- usb_kill_urb(iforce->irq);
- usb_kill_urb(iforce->out);
- usb_kill_urb(iforce->ctrl);
- break;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- case IFORCE_232:
- //TODO: Wait for the last packets to be sent
- break;
-#endif
- }
+ iforce->xport_ops->stop_io(iforce);
}
-int iforce_init_device(struct iforce *iforce)
+int iforce_init_device(struct device *parent, u16 bustype,
+ struct iforce *iforce)
{
struct input_dev *input_dev;
struct ff_device *ff;
- unsigned char c[] = "CEOV";
+ u8 c[] = "CEOV";
+ u8 buf[IFORCE_MAX_LENGTH];
+ size_t len;
int i, error;
int ff_effects = 0;
@@ -252,20 +235,8 @@ int iforce_init_device(struct iforce *iforce)
* Input device fields.
*/
- switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
- input_dev->id.bustype = BUS_USB;
- input_dev->dev.parent = &iforce->usbdev->dev;
- break;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- case IFORCE_232:
- input_dev->id.bustype = BUS_RS232;
- input_dev->dev.parent = &iforce->serio->dev;
- break;
-#endif
- }
+ input_dev->id.bustype = bustype;
+ input_dev->dev.parent = parent;
input_set_drvdata(input_dev, iforce);
@@ -290,7 +261,7 @@ int iforce_init_device(struct iforce *iforce)
*/
for (i = 0; i < 20; i++)
- if (!iforce_get_id_packet(iforce, "O"))
+ if (!iforce_get_id_packet(iforce, 'O', buf, &len))
break;
if (i == 20) { /* 5 seconds */
@@ -304,23 +275,23 @@ int iforce_init_device(struct iforce *iforce)
* Get device info.
*/
- if (!iforce_get_id_packet(iforce, "M"))
- input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'M', buf, &len) || len < 3)
+ input_dev->id.vendor = get_unaligned_le16(buf + 1);
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet M\n");
- if (!iforce_get_id_packet(iforce, "P"))
- input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'P', buf, &len) || len < 3)
+ input_dev->id.product = get_unaligned_le16(buf + 1);
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet P\n");
- if (!iforce_get_id_packet(iforce, "B"))
- iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'B', buf, &len) || len < 3)
+ iforce->device_memory.end = get_unaligned_le16(buf + 1);
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet B\n");
- if (!iforce_get_id_packet(iforce, "N"))
- ff_effects = iforce->edata[1];
+ if (!iforce_get_id_packet(iforce, 'N', buf, &len) || len < 2)
+ ff_effects = buf[1];
else
dev_warn(&iforce->dev->dev, "Device does not respond to id packet N\n");
@@ -336,8 +307,9 @@ int iforce_init_device(struct iforce *iforce)
*/
for (i = 0; c[i]; i++)
- if (!iforce_get_id_packet(iforce, c + i))
- iforce_dump_packet(iforce, "info", iforce->ecmd, iforce->edata);
+ if (!iforce_get_id_packet(iforce, c[i], buf, &len))
+ iforce_dump_packet(iforce, "info",
+ (FF_CMD_QUERY & 0xff00) | len, buf);
/*
* Disable spring, enable force feedback.
@@ -371,34 +343,29 @@ int iforce_init_device(struct iforce *iforce)
signed short t = iforce->type->abs[i];
switch (t) {
+ case ABS_X:
+ case ABS_Y:
+ case ABS_WHEEL:
+ input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
+ set_bit(t, input_dev->ffbit);
+ break;
- case ABS_X:
- case ABS_Y:
- case ABS_WHEEL:
-
- input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
- set_bit(t, input_dev->ffbit);
- break;
-
- case ABS_THROTTLE:
- case ABS_GAS:
- case ABS_BRAKE:
-
- input_set_abs_params(input_dev, t, 0, 255, 0, 0);
- break;
-
- case ABS_RUDDER:
-
- input_set_abs_params(input_dev, t, -128, 127, 0, 0);
- break;
+ case ABS_THROTTLE:
+ case ABS_GAS:
+ case ABS_BRAKE:
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
+ break;
- case ABS_HAT0X:
- case ABS_HAT0Y:
- case ABS_HAT1X:
- case ABS_HAT1Y:
+ case ABS_RUDDER:
+ input_set_abs_params(input_dev, t, -128, 127, 0, 0);
+ break;
- input_set_abs_params(input_dev, t, -1, 1, 0, 0);
- break;
+ case ABS_HAT0X:
+ case ABS_HAT0Y:
+ case ABS_HAT1X:
+ case ABS_HAT1Y:
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+ break;
}
}
@@ -431,35 +398,4 @@ int iforce_init_device(struct iforce *iforce)
fail: input_free_device(input_dev);
return error;
}
-
-static int __init iforce_init(void)
-{
- int err = 0;
-
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- err = usb_register(&iforce_usb_driver);
- if (err)
- return err;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- err = serio_register_driver(&iforce_serio_drv);
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- if (err)
- usb_deregister(&iforce_usb_driver);
-#endif
-#endif
- return err;
-}
-
-static void __exit iforce_exit(void)
-{
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- usb_deregister(&iforce_usb_driver);
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- serio_unregister_driver(&iforce_serio_drv);
-#endif
-}
-
-module_init(iforce_init);
-module_exit(iforce_exit);
+EXPORT_SYMBOL(iforce_init_device);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 42cd9730e4cc..b313e38b2c3a 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -9,6 +9,7 @@
/*
*/
+#include <asm/unaligned.h>
#include "iforce.h"
static struct {
@@ -79,27 +80,12 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
/*
* If necessary, start the transmission
*/
- switch (iforce->bus) {
+ if (empty)
+ iforce->xport_ops->xmit(iforce);
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- case IFORCE_232:
- if (empty)
- iforce_serial_xmit(iforce);
- break;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- case IFORCE_USB:
-
- if (iforce->usbdev && empty &&
- !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
-
- iforce_usb_xmit(iforce);
- }
- break;
-#endif
- }
return 0;
}
+EXPORT_SYMBOL(iforce_send_packet);
/* Start or stop an effect */
int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value)
@@ -133,157 +119,96 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
return -1;
}
-void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
+static void iforce_report_hats_buttons(struct iforce *iforce, u8 *data)
{
struct input_dev *dev = iforce->dev;
int i;
- static int being_used = 0;
- if (being_used)
- dev_warn(&iforce->dev->dev,
- "re-entrant call to iforce_process %d\n", being_used);
- being_used++;
-
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- if (HI(iforce->expect_packet) == HI(cmd)) {
- iforce->expect_packet = 0;
- iforce->ecmd = cmd;
- memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
- }
-#endif
- wake_up(&iforce->wait);
+ input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
+ input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
- if (!iforce->type) {
- being_used--;
- return;
- }
-
- switch (HI(cmd)) {
-
- case 0x01: /* joystick position data */
- case 0x03: /* wheel position data */
- if (HI(cmd) == 1) {
- input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
- input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
- input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
- if (LO(cmd) >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
- input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
- } else {
- input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
- input_report_abs(dev, ABS_GAS, 255 - data[2]);
- input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
- }
+ for (i = 0; iforce->type->btn[i] >= 0; i++)
+ input_report_key(dev, iforce->type->btn[i],
+ data[(i >> 3) + 5] & (1 << (i & 7)));
- input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
- input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
-
- for (i = 0; iforce->type->btn[i] >= 0; i++)
- input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
-
- /* If there are untouched bits left, interpret them as the second hat */
- if (i <= 8) {
- int btns = data[6];
- if (test_bit(ABS_HAT1X, dev->absbit)) {
- if (btns & 8) input_report_abs(dev, ABS_HAT1X, -1);
- else if (btns & 2) input_report_abs(dev, ABS_HAT1X, 1);
- else input_report_abs(dev, ABS_HAT1X, 0);
- }
- if (test_bit(ABS_HAT1Y, dev->absbit)) {
- if (btns & 1) input_report_abs(dev, ABS_HAT1Y, -1);
- else if (btns & 4) input_report_abs(dev, ABS_HAT1Y, 1);
- else input_report_abs(dev, ABS_HAT1Y, 0);
- }
- }
+ /* If there are untouched bits left, interpret them as the second hat */
+ if (i <= 8) {
+ u8 btns = data[6];
- input_sync(dev);
-
- break;
-
- case 0x02: /* status report */
- input_report_key(dev, BTN_DEAD, data[0] & 0x02);
- input_sync(dev);
+ if (test_bit(ABS_HAT1X, dev->absbit)) {
+ if (btns & BIT(3))
+ input_report_abs(dev, ABS_HAT1X, -1);
+ else if (btns & BIT(1))
+ input_report_abs(dev, ABS_HAT1X, 1);
+ else
+ input_report_abs(dev, ABS_HAT1X, 0);
+ }
- /* Check if an effect was just started or stopped */
- i = data[1] & 0x7f;
- if (data[1] & 0x80) {
- if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
- /* Report play event */
- input_report_ff_status(dev, i, FF_STATUS_PLAYING);
- }
- } else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
- /* Report stop event */
- input_report_ff_status(dev, i, FF_STATUS_STOPPED);
- }
- if (LO(cmd) > 3) {
- int j;
- for (j = 3; j < LO(cmd); j += 2)
- mark_core_as_ready(iforce, data[j] | (data[j+1]<<8));
- }
- break;
+ if (test_bit(ABS_HAT1Y, dev->absbit)) {
+ if (btns & BIT(0))
+ input_report_abs(dev, ABS_HAT1Y, -1);
+ else if (btns & BIT(2))
+ input_report_abs(dev, ABS_HAT1Y, 1);
+ else
+ input_report_abs(dev, ABS_HAT1Y, 0);
+ }
}
- being_used--;
}
-int iforce_get_id_packet(struct iforce *iforce, char *packet)
+void iforce_process_packet(struct iforce *iforce,
+ u8 packet_id, u8 *data, size_t len)
{
- switch (iforce->bus) {
+ struct input_dev *dev = iforce->dev;
+ int i, j;
- case IFORCE_USB: {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- int status;
+ switch (packet_id) {
- iforce->cr.bRequest = packet[0];
- iforce->ctrl->dev = iforce->usbdev;
+ case 0x01: /* joystick position data */
+ input_report_abs(dev, ABS_X,
+ (__s16) get_unaligned_le16(data));
+ input_report_abs(dev, ABS_Y,
+ (__s16) get_unaligned_le16(data + 2));
+ input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
- status = usb_submit_urb(iforce->ctrl, GFP_KERNEL);
- if (status) {
- dev_err(&iforce->intf->dev,
- "usb_submit_urb failed %d\n", status);
- return -1;
- }
+ if (len >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
+ input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
- wait_event_interruptible_timeout(iforce->wait,
- iforce->ctrl->status != -EINPROGRESS, HZ);
+ iforce_report_hats_buttons(iforce, data);
- if (iforce->ctrl->status) {
- dev_dbg(&iforce->intf->dev,
- "iforce->ctrl->status = %d\n",
- iforce->ctrl->status);
- usb_unlink_urb(iforce->ctrl);
- return -1;
- }
-#else
- printk(KERN_DEBUG "iforce_get_id_packet: iforce->bus = USB!\n");
-#endif
- }
+ input_sync(dev);
break;
- case IFORCE_232:
+ case 0x03: /* wheel position data */
+ input_report_abs(dev, ABS_WHEEL,
+ (__s16) get_unaligned_le16(data));
+ input_report_abs(dev, ABS_GAS, 255 - data[2]);
+ input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- iforce->expect_packet = FF_CMD_QUERY;
- iforce_send_packet(iforce, FF_CMD_QUERY, packet);
+ iforce_report_hats_buttons(iforce, data);
- wait_event_interruptible_timeout(iforce->wait,
- !iforce->expect_packet, HZ);
+ input_sync(dev);
+ break;
+
+ case 0x02: /* status report */
+ input_report_key(dev, BTN_DEAD, data[0] & 0x02);
+ input_sync(dev);
- if (iforce->expect_packet) {
- iforce->expect_packet = 0;
- return -1;
+ /* Check if an effect was just started or stopped */
+ i = data[1] & 0x7f;
+ if (data[1] & 0x80) {
+ if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
+ /* Report play event */
+ input_report_ff_status(dev, i, FF_STATUS_PLAYING);
+ }
+ } else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
+ /* Report stop event */
+ input_report_ff_status(dev, i, FF_STATUS_STOPPED);
}
-#else
- dev_err(&iforce->dev->dev,
- "iforce_get_id_packet: iforce->bus = SERIO!\n");
-#endif
- break;
- default:
- dev_err(&iforce->dev->dev,
- "iforce_get_id_packet: iforce->bus = %d\n",
- iforce->bus);
+ for (j = 3; j < len; j += 2)
+ mark_core_as_ready(iforce, get_unaligned_le16(data + j));
+
break;
}
-
- return -(iforce->edata[0] != packet[0]);
}
-
+EXPORT_SYMBOL(iforce_process_packet);
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 65a4fe26324f..bbe31e0b759f 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -9,10 +9,26 @@
/*
*/
+#include <linux/serio.h>
#include "iforce.h"
-void iforce_serial_xmit(struct iforce *iforce)
+struct iforce_serio {
+ struct iforce iforce;
+
+ struct serio *serio;
+ int idx, pkt, len, id;
+ u8 csum;
+ u8 expect_packet;
+ u8 cmd_response[IFORCE_MAX_LENGTH];
+ u8 cmd_response_len;
+ u8 data_in[IFORCE_MAX_LENGTH];
+};
+
+static void iforce_serio_xmit(struct iforce *iforce)
{
+ struct iforce_serio *iforce_serio = container_of(iforce,
+ struct iforce_serio,
+ iforce);
unsigned char cs;
int i;
unsigned long flags;
@@ -33,19 +49,20 @@ again:
cs = 0x2b;
- serio_write(iforce->serio, 0x2b);
+ serio_write(iforce_serio->serio, 0x2b);
- serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
+ serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
- serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
+ serio_write(iforce_serio->serio,
+ iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
}
- serio_write(iforce->serio, cs);
+ serio_write(iforce_serio->serio, cs);
if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
goto again;
@@ -55,54 +72,118 @@ again:
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
+static int iforce_serio_get_id(struct iforce *iforce, u8 id,
+ u8 *response_data, size_t *response_len)
+{
+ struct iforce_serio *iforce_serio = container_of(iforce,
+ struct iforce_serio,
+ iforce);
+
+ iforce_serio->expect_packet = HI(FF_CMD_QUERY);
+ iforce_serio->cmd_response_len = 0;
+
+ iforce_send_packet(iforce, FF_CMD_QUERY, &id);
+
+ wait_event_interruptible_timeout(iforce->wait,
+ !iforce_serio->expect_packet, HZ);
+
+ if (iforce_serio->expect_packet) {
+ iforce_serio->expect_packet = 0;
+ return -ETIMEDOUT;
+ }
+
+ if (iforce_serio->cmd_response[0] != id)
+ return -EIO;
+
+ memcpy(response_data, iforce_serio->cmd_response,
+ iforce_serio->cmd_response_len);
+ *response_len = iforce_serio->cmd_response_len;
+
+ return 0;
+}
+
+static int iforce_serio_start_io(struct iforce *iforce)
+{
+ /* No special handling required */
+ return 0;
+}
+
+static void iforce_serio_stop_io(struct iforce *iforce)
+{
+ //TODO: Wait for the last packets to be sent
+}
+
+static const struct iforce_xport_ops iforce_serio_xport_ops = {
+ .xmit = iforce_serio_xmit,
+ .get_id = iforce_serio_get_id,
+ .start_io = iforce_serio_start_io,
+ .stop_io = iforce_serio_stop_io,
+};
+
static void iforce_serio_write_wakeup(struct serio *serio)
{
struct iforce *iforce = serio_get_drvdata(serio);
- iforce_serial_xmit(iforce);
+ iforce_serio_xmit(iforce);
}
static irqreturn_t iforce_serio_irq(struct serio *serio,
- unsigned char data, unsigned int flags)
+ unsigned char data, unsigned int flags)
{
- struct iforce *iforce = serio_get_drvdata(serio);
+ struct iforce_serio *iforce_serio = serio_get_drvdata(serio);
+ struct iforce *iforce = &iforce_serio->iforce;
- if (!iforce->pkt) {
+ if (!iforce_serio->pkt) {
if (data == 0x2b)
- iforce->pkt = 1;
+ iforce_serio->pkt = 1;
goto out;
}
- if (!iforce->id) {
+ if (!iforce_serio->id) {
if (data > 3 && data != 0xff)
- iforce->pkt = 0;
+ iforce_serio->pkt = 0;
else
- iforce->id = data;
+ iforce_serio->id = data;
goto out;
}
- if (!iforce->len) {
+ if (!iforce_serio->len) {
if (data > IFORCE_MAX_LENGTH) {
- iforce->pkt = 0;
- iforce->id = 0;
+ iforce_serio->pkt = 0;
+ iforce_serio->id = 0;
} else {
- iforce->len = data;
+ iforce_serio->len = data;
}
goto out;
}
- if (iforce->idx < iforce->len) {
- iforce->csum += iforce->data[iforce->idx++] = data;
+ if (iforce_serio->idx < iforce_serio->len) {
+ iforce_serio->data_in[iforce_serio->idx++] = data;
+ iforce_serio->csum += data;
goto out;
}
- if (iforce->idx == iforce->len) {
- iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);
- iforce->pkt = 0;
- iforce->id = 0;
- iforce->len = 0;
- iforce->idx = 0;
- iforce->csum = 0;
+ if (iforce_serio->idx == iforce_serio->len) {
+ /* Handle command completion */
+ if (iforce_serio->expect_packet == iforce_serio->id) {
+ iforce_serio->expect_packet = 0;
+ memcpy(iforce_serio->cmd_response,
+ iforce_serio->data_in, IFORCE_MAX_LENGTH);
+ iforce_serio->cmd_response_len = iforce_serio->len;
+
+ /* Signal that command is done */
+ wake_up(&iforce->wait);
+ } else if (likely(iforce->type)) {
+ iforce_process_packet(iforce, iforce_serio->id,
+ iforce_serio->data_in,
+ iforce_serio->len);
+ }
+
+ iforce_serio->pkt = 0;
+ iforce_serio->id = 0;
+ iforce_serio->len = 0;
+ iforce_serio->idx = 0;
+ iforce_serio->csum = 0;
}
out:
return IRQ_HANDLED;
@@ -110,23 +191,23 @@ out:
static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
{
- struct iforce *iforce;
+ struct iforce_serio *iforce_serio;
int err;
- iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL);
- if (!iforce)
+ iforce_serio = kzalloc(sizeof(*iforce_serio), GFP_KERNEL);
+ if (!iforce_serio)
return -ENOMEM;
- iforce->bus = IFORCE_232;
- iforce->serio = serio;
+ iforce_serio->iforce.xport_ops = &iforce_serio_xport_ops;
- serio_set_drvdata(serio, iforce);
+ iforce_serio->serio = serio;
+ serio_set_drvdata(serio, iforce_serio);
err = serio_open(serio, drv);
if (err)
goto fail1;
- err = iforce_init_device(iforce);
+ err = iforce_init_device(&serio->dev, BUS_RS232, &iforce_serio->iforce);
if (err)
goto fail2;
@@ -134,18 +215,18 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
fail2: serio_close(serio);
fail1: serio_set_drvdata(serio, NULL);
- kfree(iforce);
+ kfree(iforce_serio);
return err;
}
static void iforce_serio_disconnect(struct serio *serio)
{
- struct iforce *iforce = serio_get_drvdata(serio);
+ struct iforce_serio *iforce_serio = serio_get_drvdata(serio);
- input_unregister_device(iforce->dev);
+ input_unregister_device(iforce_serio->iforce.dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
- kfree(iforce);
+ kfree(iforce_serio);
}
static const struct serio_device_id iforce_serio_ids[] = {
@@ -171,3 +252,9 @@ struct serio_driver iforce_serio_drv = {
.connect = iforce_serio_connect,
.disconnect = iforce_serio_disconnect,
};
+
+module_serio_driver(iforce_serio_drv);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
+MODULE_DESCRIPTION("RS232 I-Force joysticks and wheels driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index f1569ae8381b..ade376bfb79f 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -9,10 +9,24 @@
/*
*/
+#include <linux/usb.h>
#include "iforce.h"
-void iforce_usb_xmit(struct iforce *iforce)
+struct iforce_usb {
+ struct iforce iforce;
+
+ struct usb_device *usbdev;
+ struct usb_interface *intf;
+ struct urb *irq, *out;
+
+ u8 data_in[IFORCE_MAX_LENGTH] ____cacheline_aligned;
+ u8 data_out[IFORCE_MAX_LENGTH] ____cacheline_aligned;
+};
+
+static void __iforce_usb_xmit(struct iforce *iforce)
{
+ struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
+ iforce);
int n, c;
unsigned long flags;
@@ -24,31 +38,32 @@ void iforce_usb_xmit(struct iforce *iforce)
return;
}
- ((char *)iforce->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
+ ((char *)iforce_usb->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
n = iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
- iforce->out->transfer_buffer_length = n + 1;
- iforce->out->dev = iforce->usbdev;
+ iforce_usb->out->transfer_buffer_length = n + 1;
+ iforce_usb->out->dev = iforce_usb->usbdev;
/* Copy rest of data then */
c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
if (n < c) c=n;
- memcpy(iforce->out->transfer_buffer + 1,
+ memcpy(iforce_usb->out->transfer_buffer + 1,
&iforce->xmit.buf[iforce->xmit.tail],
c);
if (n != c) {
- memcpy(iforce->out->transfer_buffer + 1 + c,
+ memcpy(iforce_usb->out->transfer_buffer + 1 + c,
&iforce->xmit.buf[0],
n-c);
}
XMIT_INC(iforce->xmit.tail, n);
- if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
+ if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) {
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
- dev_warn(&iforce->intf->dev, "usb_submit_urb failed %d\n", n);
+ dev_warn(&iforce_usb->intf->dev,
+ "usb_submit_urb failed %d\n", n);
}
/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -57,10 +72,77 @@ void iforce_usb_xmit(struct iforce *iforce)
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
+static void iforce_usb_xmit(struct iforce *iforce)
+{
+ if (!test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags))
+ __iforce_usb_xmit(iforce);
+}
+
+static int iforce_usb_get_id(struct iforce *iforce, u8 id,
+ u8 *response_data, size_t *response_len)
+{
+ struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
+ iforce);
+ u8 *buf;
+ int status;
+
+ buf = kmalloc(IFORCE_MAX_LENGTH, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ status = usb_control_msg(iforce_usb->usbdev,
+ usb_rcvctrlpipe(iforce_usb->usbdev, 0),
+ id,
+ USB_TYPE_VENDOR | USB_DIR_IN |
+ USB_RECIP_INTERFACE,
+ 0, 0, buf, IFORCE_MAX_LENGTH, HZ);
+ if (status < 0) {
+ dev_err(&iforce_usb->intf->dev,
+ "usb_submit_urb failed: %d\n", status);
+ } else if (buf[0] != id) {
+ status = -EIO;
+ } else {
+ memcpy(response_data, buf, status);
+ *response_len = status;
+ status = 0;
+ }
+
+ kfree(buf);
+ return status;
+}
+
+static int iforce_usb_start_io(struct iforce *iforce)
+{
+ struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
+ iforce);
+
+ if (usb_submit_urb(iforce_usb->irq, GFP_KERNEL))
+ return -EIO;
+
+ return 0;
+}
+
+static void iforce_usb_stop_io(struct iforce *iforce)
+{
+ struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
+ iforce);
+
+ usb_kill_urb(iforce_usb->irq);
+ usb_kill_urb(iforce_usb->out);
+}
+
+static const struct iforce_xport_ops iforce_usb_xport_ops = {
+ .xmit = iforce_usb_xmit,
+ .get_id = iforce_usb_get_id,
+ .start_io = iforce_usb_start_io,
+ .stop_io = iforce_usb_stop_io,
+};
+
static void iforce_usb_irq(struct urb *urb)
{
- struct iforce *iforce = urb->context;
- struct device *dev = &iforce->intf->dev;
+ struct iforce_usb *iforce_usb = urb->context;
+ struct iforce *iforce = &iforce_usb->iforce;
+ struct device *dev = &iforce_usb->intf->dev;
int status;
switch (urb->status) {
@@ -80,11 +162,11 @@ static void iforce_usb_irq(struct urb *urb)
goto exit;
}
- iforce_process_packet(iforce,
- (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1);
+ iforce_process_packet(iforce, iforce_usb->data_in[0],
+ iforce_usb->data_in + 1, urb->actual_length - 1);
exit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
__func__, status);
@@ -92,35 +174,28 @@ exit:
static void iforce_usb_out(struct urb *urb)
{
- struct iforce *iforce = urb->context;
+ struct iforce_usb *iforce_usb = urb->context;
+ struct iforce *iforce = &iforce_usb->iforce;
if (urb->status) {
clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
- dev_dbg(&iforce->intf->dev, "urb->status %d, exiting\n",
+ dev_dbg(&iforce_usb->intf->dev, "urb->status %d, exiting\n",
urb->status);
return;
}
- iforce_usb_xmit(iforce);
+ __iforce_usb_xmit(iforce);
wake_up(&iforce->wait);
}
-static void iforce_usb_ctrl(struct urb *urb)
-{
- struct iforce *iforce = urb->context;
- if (urb->status) return;
- iforce->ecmd = 0xff00 | urb->actual_length;
- wake_up(&iforce->wait);
-}
-
static int iforce_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *epirq, *epout;
- struct iforce *iforce;
+ struct iforce_usb *iforce_usb;
int err = -ENOMEM;
interface = intf->cur_altsetting;
@@ -131,48 +206,45 @@ static int iforce_usb_probe(struct usb_interface *intf,
epirq = &interface->endpoint[0].desc;
epout = &interface->endpoint[1].desc;
- if (!(iforce = kzalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
- goto fail;
-
- if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL)))
+ iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL);
+ if (!iforce_usb)
goto fail;
- if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL)))
+ iforce_usb->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!iforce_usb->irq)
goto fail;
- if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL)))
+ iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!iforce_usb->out)
goto fail;
- iforce->bus = IFORCE_USB;
- iforce->usbdev = dev;
- iforce->intf = intf;
-
- iforce->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
- iforce->cr.wIndex = 0;
- iforce->cr.wLength = cpu_to_le16(16);
+ iforce_usb->iforce.xport_ops = &iforce_usb_xport_ops;
- usb_fill_int_urb(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
- iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
+ iforce_usb->usbdev = dev;
+ iforce_usb->intf = intf;
- usb_fill_int_urb(iforce->out, dev, usb_sndintpipe(dev, epout->bEndpointAddress),
- iforce + 1, 32, iforce_usb_out, iforce, epout->bInterval);
+ usb_fill_int_urb(iforce_usb->irq, dev,
+ usb_rcvintpipe(dev, epirq->bEndpointAddress),
+ iforce_usb->data_in, sizeof(iforce_usb->data_in),
+ iforce_usb_irq, iforce_usb, epirq->bInterval);
- usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
- (void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
+ usb_fill_int_urb(iforce_usb->out, dev,
+ usb_sndintpipe(dev, epout->bEndpointAddress),
+ iforce_usb->data_out, sizeof(iforce_usb->data_out),
+ iforce_usb_out, iforce_usb, epout->bInterval);
- err = iforce_init_device(iforce);
+ err = iforce_init_device(&intf->dev, BUS_USB, &iforce_usb->iforce);
if (err)
goto fail;
- usb_set_intfdata(intf, iforce);
+ usb_set_intfdata(intf, iforce_usb);
return 0;
fail:
- if (iforce) {
- usb_free_urb(iforce->irq);
- usb_free_urb(iforce->out);
- usb_free_urb(iforce->ctrl);
- kfree(iforce);
+ if (iforce_usb) {
+ usb_free_urb(iforce_usb->irq);
+ usb_free_urb(iforce_usb->out);
+ kfree(iforce_usb);
}
return err;
@@ -180,17 +252,16 @@ fail:
static void iforce_usb_disconnect(struct usb_interface *intf)
{
- struct iforce *iforce = usb_get_intfdata(intf);
+ struct iforce_usb *iforce_usb = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
- input_unregister_device(iforce->dev);
+ input_unregister_device(iforce_usb->iforce.dev);
- usb_free_urb(iforce->irq);
- usb_free_urb(iforce->out);
- usb_free_urb(iforce->ctrl);
+ usb_free_urb(iforce_usb->irq);
+ usb_free_urb(iforce_usb->out);
- kfree(iforce);
+ kfree(iforce_usb);
}
static const struct usb_device_id iforce_usb_ids[] = {
@@ -202,6 +273,7 @@ static const struct usb_device_id iforce_usb_ids[] = {
{ USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */
{ USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */
+ { USB_DEVICE(0x06a3, 0xff04) }, /* Saitek R440 Force Wheel */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
@@ -217,3 +289,9 @@ struct usb_driver iforce_usb_driver = {
.disconnect = iforce_usb_disconnect,
.id_table = iforce_usb_ids,
};
+
+module_usb_driver(iforce_usb_driver);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
+MODULE_DESCRIPTION("USB I-Force joysticks and wheels driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index f1681706f526..9cfa460466aa 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -14,8 +14,6 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <linux/serio.h>
#include <linux/circ_buf.h>
#include <linux/mutex.h>
@@ -28,10 +26,6 @@
#define IFORCE_MAX_LENGTH 16
-/* iforce::bus */
-#define IFORCE_232 1
-#define IFORCE_USB 2
-
#define IFORCE_EFFECTS_MAX 32
/* Each force feedback effect is made of one core effect, which can be
@@ -81,27 +75,21 @@ struct iforce_device {
signed short *ff;
};
+struct iforce;
+
+struct iforce_xport_ops {
+ void (*xmit)(struct iforce *iforce);
+ int (*get_id)(struct iforce *iforce, u8 id,
+ u8 *response_data, size_t *response_len);
+ int (*start_io)(struct iforce *iforce);
+ void (*stop_io)(struct iforce *iforce);
+};
+
struct iforce {
struct input_dev *dev; /* Input device interface */
struct iforce_device *type;
- int bus;
-
- unsigned char data[IFORCE_MAX_LENGTH];
- unsigned char edata[IFORCE_MAX_LENGTH];
- u16 ecmd;
- u16 expect_packet;
-
-#ifdef CONFIG_JOYSTICK_IFORCE_232
- struct serio *serio; /* RS232 transfer */
- int idx, pkt, len, id;
- unsigned char csum;
-#endif
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
- struct usb_device *usbdev; /* USB transfer */
- struct usb_interface *intf;
- struct urb *irq, *out, *ctrl;
- struct usb_ctrlrequest cr;
-#endif
+ const struct iforce_xport_ops *xport_ops;
+
spinlock_t xmit_lock;
/* Buffer used for asynchronous sending of bytes to the device */
struct circ_buf xmit;
@@ -127,23 +115,24 @@ struct iforce {
/* Encode a time value */
#define TIME_SCALE(a) (a)
+static inline int iforce_get_id_packet(struct iforce *iforce, u8 id,
+ u8 *response_data, size_t *response_len)
+{
+ return iforce->xport_ops->get_id(iforce, id,
+ response_data, response_len);
+}
/* Public functions */
-/* iforce-serio.c */
-void iforce_serial_xmit(struct iforce *iforce);
-
-/* iforce-usb.c */
-void iforce_usb_xmit(struct iforce *iforce);
-
/* iforce-main.c */
-int iforce_init_device(struct iforce *iforce);
+int iforce_init_device(struct device *parent, u16 bustype,
+ struct iforce *iforce);
/* iforce-packets.c */
int iforce_control_playback(struct iforce*, u16 id, unsigned int);
-void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data);
+void iforce_process_packet(struct iforce *iforce,
+ u8 packet_id, u8 *data, size_t len);
int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data);
void iforce_dump_packet(struct iforce *iforce, char *msg, u16 cmd, unsigned char *data);
-int iforce_get_id_packet(struct iforce *iforce, char *packet);
/* iforce-ff.c */
int iforce_upload_periodic(struct iforce *, struct ff_effect *, struct ff_effect *);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index a23c23979a2e..03f4d152f6b7 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -771,7 +771,6 @@ static int gpio_keys_probe(struct platform_device *pdev)
struct fwnode_handle *child = NULL;
struct gpio_keys_drvdata *ddata;
struct input_dev *input;
- size_t size;
int i, error;
int wakeup = 0;
@@ -781,9 +780,8 @@ static int gpio_keys_probe(struct platform_device *pdev)
return PTR_ERR(pdata);
}
- size = sizeof(struct gpio_keys_drvdata) +
- pdata->nbuttons * sizeof(struct gpio_button_data);
- ddata = devm_kzalloc(dev, size, GFP_KERNEL);
+ ddata = devm_kzalloc(dev, struct_size(ddata, data, pdata->nbuttons),
+ GFP_KERNEL);
if (!ddata) {
dev_err(dev, "failed to allocate state\n");
return -ENOMEM;
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 1eafe6b848ba..465eecfa6b3f 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -165,6 +165,8 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev)
pdata->rep = device_property_present(dev, "autorepeat");
device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
+ device_property_read_string(dev, "label", &pdata->name);
+
device_for_each_child_node(dev, child) {
if (fwnode_property_read_u32(child, "linux,code",
&button->code)) {
@@ -232,7 +234,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
struct gpio_keys_polled_dev *bdev;
struct input_polled_dev *poll_dev;
struct input_dev *input;
- size_t size;
int error;
int i;
@@ -247,9 +248,8 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
return -EINVAL;
}
- size = sizeof(struct gpio_keys_polled_dev) +
- pdata->nbuttons * sizeof(struct gpio_keys_button_data);
- bdev = devm_kzalloc(dev, size, GFP_KERNEL);
+ bdev = devm_kzalloc(dev, struct_size(bdev, data, pdata->nbuttons),
+ GFP_KERNEL);
if (!bdev) {
dev_err(dev, "no memory for private data\n");
return -ENOMEM;
@@ -269,7 +269,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
input = poll_dev->input;
- input->name = pdev->name;
+ input->name = pdata->name ?: pdev->name;
input->phys = DRV_NAME"/input0";
input->id.bustype = BUS_HOST;
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index ae9c51cc85f9..97500a2de2d5 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -422,7 +422,6 @@ static int imx_keypad_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev);
struct imx_keypad *keypad;
struct input_dev *input_dev;
- struct resource *res;
int irq, error, i, row, col;
if (!keymap_data && !pdev->dev.of_node) {
@@ -455,8 +454,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
timer_setup(&keypad->check_matrix_timer,
imx_keypad_check_for_events, 0);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
+ keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(keypad->mmio_base))
return PTR_ERR(keypad->mmio_base);
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index 6da607d3b811..3bbd7e652533 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -266,7 +266,7 @@ static int tca8418_keypad_probe(struct i2c_client *client,
struct tca8418_keypad *keypad_data;
struct input_dev *input;
u32 rows = 0, cols = 0;
- int error, row_shift, max_keys;
+ int error, row_shift;
u8 reg;
/* Check i2c driver capabilities */
@@ -291,7 +291,6 @@ static int tca8418_keypad_probe(struct i2c_client *client,
}
row_shift = get_count_order(cols);
- max_keys = rows << row_shift;
/* Allocate memory for keypad_data and input device */
keypad_data = devm_kzalloc(dev, sizeof(*keypad_data), GFP_KERNEL);
diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index 9d39679372c5..fd355cf59397 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -13,7 +13,6 @@
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/mfd/da9063/core.h>
-#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
#include <linux/mfd/da9062/core.h>
#include <linux/mfd/da9062/registers.h>
@@ -192,8 +191,6 @@ static void da9063_cancel_poll(void *data)
static int da9063_onkey_probe(struct platform_device *pdev)
{
- struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
- struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
struct da9063_onkey *onkey;
const struct of_device_id *match;
int irq;
@@ -220,12 +217,8 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENXIO;
}
- if (pdata)
- onkey->key_power = pdata->key_power;
- else
- onkey->key_power =
- !of_property_read_bool(pdev->dev.of_node,
- "dlg,disable-key-power");
+ onkey->key_power = !of_property_read_bool(pdev->dev.of_node,
+ "dlg,disable-key-power");
onkey->input = devm_input_allocate_device(&pdev->dev);
if (!onkey->input) {
diff --git a/drivers/input/misc/max77650-onkey.c b/drivers/input/misc/max77650-onkey.c
index fbf6caab7217..4d875f2ac13d 100644
--- a/drivers/input/misc/max77650-onkey.c
+++ b/drivers/input/misc/max77650-onkey.c
@@ -119,3 +119,4 @@ module_platform_driver(max77650_onkey_driver);
MODULE_DESCRIPTION("MAXIM 77650/77651 ONKEY driver");
MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:max77650-onkey");
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 420efaab3860..d9b103a81a79 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -34,6 +34,7 @@
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/property.h>
+#include <linux/input/elan-i2c-ids.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h>
@@ -96,6 +97,7 @@ struct elan_tp_data {
u8 max_baseline;
bool baseline_ready;
u8 clickpad;
+ bool middle_button;
};
static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count,
@@ -363,27 +365,62 @@ static unsigned int elan_convert_resolution(u8 val)
static int elan_query_device_parameters(struct elan_tp_data *data)
{
+ struct i2c_client *client = data->client;
unsigned int x_traces, y_traces;
+ u32 x_mm, y_mm;
u8 hw_x_res, hw_y_res;
int error;
- error = data->ops->get_max(data->client, &data->max_x, &data->max_y);
- if (error)
- return error;
-
- error = data->ops->get_num_traces(data->client, &x_traces, &y_traces);
- if (error)
- return error;
+ if (device_property_read_u32(&client->dev,
+ "touchscreen-size-x", &data->max_x) ||
+ device_property_read_u32(&client->dev,
+ "touchscreen-size-y", &data->max_y)) {
+ error = data->ops->get_max(data->client,
+ &data->max_x,
+ &data->max_y);
+ if (error)
+ return error;
+ } else {
+ /* size is the maximum + 1 */
+ --data->max_x;
+ --data->max_y;
+ }
+ if (device_property_read_u32(&client->dev,
+ "elan,x_traces",
+ &x_traces) ||
+ device_property_read_u32(&client->dev,
+ "elan,y_traces",
+ &y_traces)) {
+ error = data->ops->get_num_traces(data->client,
+ &x_traces, &y_traces);
+ if (error)
+ return error;
+ }
data->width_x = data->max_x / x_traces;
data->width_y = data->max_y / y_traces;
- error = data->ops->get_resolution(data->client, &hw_x_res, &hw_y_res);
- if (error)
- return error;
+ if (device_property_read_u32(&client->dev,
+ "touchscreen-x-mm", &x_mm) ||
+ device_property_read_u32(&client->dev,
+ "touchscreen-y-mm", &y_mm)) {
+ error = data->ops->get_resolution(data->client,
+ &hw_x_res, &hw_y_res);
+ if (error)
+ return error;
+
+ data->x_res = elan_convert_resolution(hw_x_res);
+ data->y_res = elan_convert_resolution(hw_y_res);
+ } else {
+ data->x_res = (data->max_x + 1) / x_mm;
+ data->y_res = (data->max_y + 1) / y_mm;
+ }
+
+ if (device_property_read_bool(&client->dev, "elan,clickpad"))
+ data->clickpad = 1;
- data->x_res = elan_convert_resolution(hw_x_res);
- data->y_res = elan_convert_resolution(hw_y_res);
+ if (device_property_read_bool(&client->dev, "elan,middle-button"))
+ data->middle_button = true;
return 0;
}
@@ -923,8 +960,9 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
finger_data += ETP_FINGER_DATA_LEN;
}
- input_report_key(input, BTN_LEFT, tp_info & 0x01);
- input_report_key(input, BTN_RIGHT, tp_info & 0x02);
+ input_report_key(input, BTN_LEFT, tp_info & BIT(0));
+ input_report_key(input, BTN_MIDDLE, tp_info & BIT(2));
+ input_report_key(input, BTN_RIGHT, tp_info & BIT(1));
input_report_abs(input, ABS_DISTANCE, hover_event != 0);
input_mt_report_pointer_emulation(input, true);
input_sync(input);
@@ -1058,10 +1096,13 @@ static int elan_setup_input_device(struct elan_tp_data *data)
__set_bit(EV_ABS, input->evbit);
__set_bit(INPUT_PROP_POINTER, input->propbit);
- if (data->clickpad)
+ if (data->clickpad) {
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- else
+ } else {
__set_bit(BTN_RIGHT, input->keybit);
+ if (data->middle_button)
+ __set_bit(BTN_MIDDLE, input->keybit);
+ }
__set_bit(BTN_LEFT, input->keybit);
/* Set up ST parameters */
@@ -1332,55 +1373,6 @@ static const struct i2c_device_id elan_id[] = {
MODULE_DEVICE_TABLE(i2c, elan_id);
#ifdef CONFIG_ACPI
-static const struct acpi_device_id elan_acpi_id[] = {
- { "ELAN0000", 0 },
- { "ELAN0100", 0 },
- { "ELAN0600", 0 },
- { "ELAN0601", 0 },
- { "ELAN0602", 0 },
- { "ELAN0603", 0 },
- { "ELAN0604", 0 },
- { "ELAN0605", 0 },
- { "ELAN0606", 0 },
- { "ELAN0607", 0 },
- { "ELAN0608", 0 },
- { "ELAN0609", 0 },
- { "ELAN060B", 0 },
- { "ELAN060C", 0 },
- { "ELAN060F", 0 },
- { "ELAN0610", 0 },
- { "ELAN0611", 0 },
- { "ELAN0612", 0 },
- { "ELAN0615", 0 },
- { "ELAN0616", 0 },
- { "ELAN0617", 0 },
- { "ELAN0618", 0 },
- { "ELAN0619", 0 },
- { "ELAN061A", 0 },
- { "ELAN061B", 0 },
- { "ELAN061C", 0 },
- { "ELAN061D", 0 },
- { "ELAN061E", 0 },
- { "ELAN061F", 0 },
- { "ELAN0620", 0 },
- { "ELAN0621", 0 },
- { "ELAN0622", 0 },
- { "ELAN0623", 0 },
- { "ELAN0624", 0 },
- { "ELAN0625", 0 },
- { "ELAN0626", 0 },
- { "ELAN0627", 0 },
- { "ELAN0628", 0 },
- { "ELAN0629", 0 },
- { "ELAN062A", 0 },
- { "ELAN062B", 0 },
- { "ELAN062C", 0 },
- { "ELAN062D", 0 },
- { "ELAN0631", 0 },
- { "ELAN0632", 0 },
- { "ELAN1000", 0 },
- { }
-};
MODULE_DEVICE_TABLE(acpi, elan_acpi_id);
#endif
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index a4345052abd2..2d8434b7b623 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -227,6 +227,52 @@ static void elantech_packet_dump(struct psmouse *psmouse)
}
/*
+ * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in
+ * fw_version for this is based on the following fw_version & caps table:
+ *
+ * Laptop-model: fw_version: caps: buttons:
+ * Acer S3 0x461f00 10, 13, 0e clickpad
+ * Acer S7-392 0x581f01 50, 17, 0d clickpad
+ * Acer V5-131 0x461f02 01, 16, 0c clickpad
+ * Acer V5-551 0x461f00 ? clickpad
+ * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
+ * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
+ * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
+ * Asus TP500LN 0x381f17 10, 14, 0e clickpad
+ * Asus X750JN 0x381f17 10, 14, 0e clickpad
+ * Asus UX31 0x361f00 20, 15, 0e clickpad
+ * Asus UX32VD 0x361f02 00, 15, 0e clickpad
+ * Avatar AVIU-145A2 0x361f00 ? clickpad
+ * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**)
+ * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**)
+ * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
+ * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
+ * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
+ * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
+ * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons
+ * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
+ * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
+ * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
+ * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
+ * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*)
+ * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
+ * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
+ * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
+ * Samsung NP900X3E-A02 0x575f03 ? clickpad
+ * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad
+ * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons
+ * Samsung RF710 0x450f00 ? 2 hw buttons
+ * System76 Pangolin 0x250f01 ? 2 hw buttons
+ * (*) + 3 trackpoint buttons
+ * (**) + 0 trackpoint buttons
+ * Note: Lenovo L430 and Lenovo L530 have the same fw_version/caps
+ */
+static inline int elantech_is_buttonpad(struct elantech_device_info *info)
+{
+ return info->fw_version & 0x001000;
+}
+
+/*
* Interpret complete data packets and report absolute mode input events for
* hardware version 1. (4 byte packets)
*/
@@ -523,7 +569,7 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
/* For clickpads map both buttons to BTN_LEFT */
- if (etd->info.fw_version & 0x001000)
+ if (elantech_is_buttonpad(&etd->info))
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
else
psmouse_report_standard_buttons(dev, packet[0]);
@@ -541,7 +587,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
unsigned char *packet = psmouse->packet;
/* For clickpads map both buttons to BTN_LEFT */
- if (etd->info.fw_version & 0x001000)
+ if (elantech_is_buttonpad(&etd->info))
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
else
psmouse_report_standard_buttons(dev, packet[0]);
@@ -991,88 +1037,6 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
return rc;
}
-static int elantech_set_range(struct psmouse *psmouse,
- unsigned int *x_min, unsigned int *y_min,
- unsigned int *x_max, unsigned int *y_max,
- unsigned int *width)
-{
- struct elantech_data *etd = psmouse->private;
- struct elantech_device_info *info = &etd->info;
- unsigned char param[3];
- unsigned char traces;
-
- switch (info->hw_version) {
- case 1:
- *x_min = ETP_XMIN_V1;
- *y_min = ETP_YMIN_V1;
- *x_max = ETP_XMAX_V1;
- *y_max = ETP_YMAX_V1;
- break;
-
- case 2:
- if (info->fw_version == 0x020800 ||
- info->fw_version == 0x020b00 ||
- info->fw_version == 0x020030) {
- *x_min = ETP_XMIN_V2;
- *y_min = ETP_YMIN_V2;
- *x_max = ETP_XMAX_V2;
- *y_max = ETP_YMAX_V2;
- } else {
- int i;
- int fixed_dpi;
-
- i = (info->fw_version > 0x020800 &&
- info->fw_version < 0x020900) ? 1 : 2;
-
- if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
- return -1;
-
- fixed_dpi = param[1] & 0x10;
-
- if (((info->fw_version >> 16) == 0x14) && fixed_dpi) {
- if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
- return -1;
-
- *x_max = (info->capabilities[1] - i) * param[1] / 2;
- *y_max = (info->capabilities[2] - i) * param[2] / 2;
- } else if (info->fw_version == 0x040216) {
- *x_max = 819;
- *y_max = 405;
- } else if (info->fw_version == 0x040219 || info->fw_version == 0x040215) {
- *x_max = 900;
- *y_max = 500;
- } else {
- *x_max = (info->capabilities[1] - i) * 64;
- *y_max = (info->capabilities[2] - i) * 64;
- }
- }
- break;
-
- case 3:
- if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
- return -1;
-
- *x_max = (0x0f & param[0]) << 8 | param[1];
- *y_max = (0xf0 & param[0]) << 4 | param[2];
- break;
-
- case 4:
- if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
- return -1;
-
- *x_max = (0x0f & param[0]) << 8 | param[1];
- *y_max = (0xf0 & param[0]) << 4 | param[2];
- traces = info->capabilities[1];
- if ((traces < 2) || (traces > *x_max))
- return -1;
-
- *width = *x_max / (traces - 1);
- break;
- }
-
- return 0;
-}
-
/*
* (value from firmware) * 10 + 790 = dpi
* we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
@@ -1099,53 +1063,12 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
return 0;
}
-/*
- * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in
- * fw_version for this is based on the following fw_version & caps table:
- *
- * Laptop-model: fw_version: caps: buttons:
- * Acer S3 0x461f00 10, 13, 0e clickpad
- * Acer S7-392 0x581f01 50, 17, 0d clickpad
- * Acer V5-131 0x461f02 01, 16, 0c clickpad
- * Acer V5-551 0x461f00 ? clickpad
- * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
- * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
- * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
- * Asus TP500LN 0x381f17 10, 14, 0e clickpad
- * Asus X750JN 0x381f17 10, 14, 0e clickpad
- * Asus UX31 0x361f00 20, 15, 0e clickpad
- * Asus UX32VD 0x361f02 00, 15, 0e clickpad
- * Avatar AVIU-145A2 0x361f00 ? clickpad
- * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**)
- * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**)
- * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
- * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
- * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
- * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
- * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons
- * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
- * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
- * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
- * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
- * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*)
- * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
- * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
- * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
- * Samsung NP900X3E-A02 0x575f03 ? clickpad
- * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad
- * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons
- * Samsung RF710 0x450f00 ? 2 hw buttons
- * System76 Pangolin 0x250f01 ? 2 hw buttons
- * (*) + 3 trackpoint buttons
- * (**) + 0 trackpoint buttons
- * Note: Lenovo L430 and Lenovo L530 have the same fw_version/caps
- */
static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
- if (etd->info.fw_version & 0x001000) {
+ if (elantech_is_buttonpad(&etd->info)) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
__clear_bit(BTN_RIGHT, dev->keybit);
}
@@ -1181,16 +1104,6 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
{ }
};
-static const char * const middle_button_pnp_ids[] = {
- "LEN2131", /* ThinkPad P52 w/ NFC */
- "LEN2132", /* ThinkPad P52 */
- "LEN2133", /* ThinkPad P72 w/ NFC */
- "LEN2134", /* ThinkPad P72 */
- "LEN0407",
- "LEN0408",
- NULL
-};
-
/*
* Set the appropriate event bits for the input subsystem
*/
@@ -1199,10 +1112,9 @@ static int elantech_set_input_params(struct psmouse *psmouse)
struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
struct elantech_device_info *info = &etd->info;
- unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
-
- if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
- return -1;
+ unsigned int x_min = info->x_min, y_min = info->y_min,
+ x_max = info->x_max, y_max = info->y_max,
+ width = info->width;
__set_bit(INPUT_PROP_POINTER, dev->propbit);
__set_bit(EV_KEY, dev->evbit);
@@ -1210,8 +1122,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
__clear_bit(EV_REL, dev->evbit);
__set_bit(BTN_LEFT, dev->keybit);
- if (dmi_check_system(elantech_dmi_has_middle_button) ||
- psmouse_matches_pnp_id(psmouse, middle_button_pnp_ids))
+ if (info->has_middle_button)
__set_bit(BTN_MIDDLE, dev->keybit);
__set_bit(BTN_RIGHT, dev->keybit);
@@ -1686,6 +1597,7 @@ static int elantech_query_info(struct psmouse *psmouse,
struct elantech_device_info *info)
{
unsigned char param[3];
+ unsigned char traces;
memset(info, 0, sizeof(*info));
@@ -1754,6 +1666,90 @@ static int elantech_query_info(struct psmouse *psmouse,
}
}
+ /* query range information */
+ switch (info->hw_version) {
+ case 1:
+ info->x_min = ETP_XMIN_V1;
+ info->y_min = ETP_YMIN_V1;
+ info->x_max = ETP_XMAX_V1;
+ info->y_max = ETP_YMAX_V1;
+ break;
+
+ case 2:
+ if (info->fw_version == 0x020800 ||
+ info->fw_version == 0x020b00 ||
+ info->fw_version == 0x020030) {
+ info->x_min = ETP_XMIN_V2;
+ info->y_min = ETP_YMIN_V2;
+ info->x_max = ETP_XMAX_V2;
+ info->y_max = ETP_YMAX_V2;
+ } else {
+ int i;
+ int fixed_dpi;
+
+ i = (info->fw_version > 0x020800 &&
+ info->fw_version < 0x020900) ? 1 : 2;
+
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -EINVAL;
+
+ fixed_dpi = param[1] & 0x10;
+
+ if (((info->fw_version >> 16) == 0x14) && fixed_dpi) {
+ if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+ return -EINVAL;
+
+ info->x_max = (info->capabilities[1] - i) * param[1] / 2;
+ info->y_max = (info->capabilities[2] - i) * param[2] / 2;
+ } else if (info->fw_version == 0x040216) {
+ info->x_max = 819;
+ info->y_max = 405;
+ } else if (info->fw_version == 0x040219 || info->fw_version == 0x040215) {
+ info->x_max = 900;
+ info->y_max = 500;
+ } else {
+ info->x_max = (info->capabilities[1] - i) * 64;
+ info->y_max = (info->capabilities[2] - i) * 64;
+ }
+ }
+ break;
+
+ case 3:
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -EINVAL;
+
+ info->x_max = (0x0f & param[0]) << 8 | param[1];
+ info->y_max = (0xf0 & param[0]) << 4 | param[2];
+ break;
+
+ case 4:
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -EINVAL;
+
+ info->x_max = (0x0f & param[0]) << 8 | param[1];
+ info->y_max = (0xf0 & param[0]) << 4 | param[2];
+ traces = info->capabilities[1];
+ if ((traces < 2) || (traces > info->x_max))
+ return -EINVAL;
+
+ info->width = info->x_max / (traces - 1);
+
+ /* column number of traces */
+ info->x_traces = traces;
+
+ /* row number of traces */
+ traces = info->capabilities[2];
+ if ((traces >= 2) && (traces <= info->y_max))
+ info->y_traces = traces;
+
+ break;
+ }
+
+ /* check for the middle button: DMI matching or new v4 firmwares */
+ info->has_middle_button = dmi_check_system(elantech_dmi_has_middle_button) ||
+ (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) &&
+ !elantech_is_buttonpad(info));
+
return 0;
}
@@ -1780,10 +1776,6 @@ static const char * const i2c_blacklist_pnp_ids[] = {
* These are known to not be working properly as bits are missing
* in elan_i2c.
*/
- "LEN2131", /* ThinkPad P52 w/ NFC */
- "LEN2132", /* ThinkPad P52 */
- "LEN2133", /* ThinkPad P72 w/ NFC */
- "LEN2134", /* ThinkPad P72 */
NULL
};
@@ -1791,17 +1783,45 @@ static int elantech_create_smbus(struct psmouse *psmouse,
struct elantech_device_info *info,
bool leave_breadcrumbs)
{
- const struct property_entry i2c_properties[] = {
- PROPERTY_ENTRY_BOOL("elan,trackpoint"),
- { },
- };
+ struct property_entry i2c_props[11] = {};
struct i2c_board_info smbus_board = {
I2C_BOARD_INFO("elan_i2c", 0x15),
.flags = I2C_CLIENT_HOST_NOTIFY,
};
+ unsigned int idx = 0;
+
+ smbus_board.properties = i2c_props;
+
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-size-x",
+ info->x_max + 1);
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-size-y",
+ info->y_max + 1);
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-min-x",
+ info->x_min);
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-min-y",
+ info->y_min);
+ if (info->x_res)
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-x-mm",
+ (info->x_max + 1) / info->x_res);
+ if (info->y_res)
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-y-mm",
+ (info->y_max + 1) / info->y_res);
if (info->has_trackpoint)
- smbus_board.properties = i2c_properties;
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,trackpoint");
+
+ if (info->has_middle_button)
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,middle-button");
+
+ if (info->x_traces)
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("elan,x_traces",
+ info->x_traces);
+ if (info->y_traces)
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("elan,y_traces",
+ info->y_traces);
+
+ if (elantech_is_buttonpad(info))
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,clickpad");
return psmouse_smbus_init(psmouse, &smbus_board, NULL, 0, false,
leave_breadcrumbs);
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 12ba5af93145..46343998522b 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -141,8 +141,15 @@ struct elantech_device_info {
unsigned char debug;
unsigned char hw_version;
unsigned int fw_version;
+ unsigned int x_min;
+ unsigned int y_min;
+ unsigned int x_max;
+ unsigned int y_max;
unsigned int x_res;
unsigned int y_res;
+ unsigned int x_traces;
+ unsigned int y_traces;
+ unsigned int width;
unsigned int bus;
bool paritycheck;
bool jumpy_cursor;
@@ -150,6 +157,7 @@ struct elantech_device_info {
bool crc_enabled;
bool set_hw_resolution;
bool has_trackpoint;
+ bool has_middle_button;
int (*send_cmd)(struct psmouse *psmouse, unsigned char c,
unsigned char *param);
};
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index b8ec301025b7..1080c0c49815 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -173,6 +173,7 @@ static const char * const smbus_pnp_ids[] = {
"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
"LEN0073", /* X1 Carbon G5 (Elantech) */
"LEN0092", /* X1 Carbon 6 */
+ "LEN0093", /* T480 */
"LEN0096", /* X280 */
"LEN0097", /* X280 -> ALPS trackpoint */
"LEN200f", /* T450s */
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index bb14369e34a7..d20a5d6780d1 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -70,7 +70,6 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
int pitch_y = 0;
int rx_receivers = 0;
int tx_receivers = 0;
- int sensor_flags = 0;
item = rmi_get_register_desc_item(&f12->control_reg_desc, 8);
if (!item) {
@@ -126,10 +125,9 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
offset += 2;
}
- if (rmi_register_desc_has_subpacket(item, 4)) {
- sensor_flags = buf[offset];
+ /* Skip over sensor flags */
+ if (rmi_register_desc_has_subpacket(item, 4))
offset += 1;
- }
sensor->x_mm = (pitch_x * rx_receivers) >> 12;
sensor->y_mm = (pitch_y * tx_receivers) >> 12;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 19378f200c63..4a5f482cf1af 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -256,16 +256,6 @@ enum v4l_dbg_inputs {
MXT_V4L_INPUT_MAX,
};
-static const struct v4l2_file_operations mxt_video_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vb2_fop_release,
- .unlocked_ioctl = video_ioctl2,
- .read = vb2_fop_read,
- .mmap = vb2_fop_mmap,
- .poll = vb2_fop_poll,
-};
-
enum mxt_suspend_mode {
MXT_SUSPEND_DEEP_SLEEP = 0,
MXT_SUSPEND_T9_CTRL = 1,
@@ -1521,7 +1511,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
} else if (config_crc == data->config_crc) {
dev_dbg(dev, "Config CRC 0x%06X: OK\n",
data->config_crc);
- return 0;
+ ret = 0;
+ goto release_raw;
} else {
dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
data->config_crc, config_crc);
@@ -2218,6 +2209,16 @@ recheck:
}
#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
+static const struct v4l2_file_operations mxt_video_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .unlocked_ioctl = video_ioctl2,
+ .read = vb2_fop_read,
+ .mmap = vb2_fop_mmap,
+ .poll = vb2_fop_poll,
+};
+
static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x,
unsigned int y)
{
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index c639ebce914c..3cc4341bbdff 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -27,6 +27,7 @@
#include <linux/gpio/consumer.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
+#include <asm/unaligned.h>
#define WORK_REGISTER_THRESHOLD 0x00
#define WORK_REGISTER_REPORT_RATE 0x08
@@ -228,7 +229,6 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
for (i = 0; i < tsdata->max_support_points; i++) {
u8 *buf = &rdbuf[i * tplen + offset];
- bool down;
type = buf[0] >> 6;
/* ignore Reserved events */
@@ -239,23 +239,19 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN)
continue;
- x = ((buf[0] << 8) | buf[1]) & 0x0fff;
- y = ((buf[2] << 8) | buf[3]) & 0x0fff;
+ x = get_unaligned_be16(buf) & 0x0fff;
+ y = get_unaligned_be16(buf + 2) & 0x0fff;
/* The FT5x26 send the y coordinate first */
if (tsdata->version == EV_FT)
swap(x, y);
id = (buf[2] >> 4) & 0x0f;
- down = type != TOUCH_EVENT_UP;
input_mt_slot(tsdata->input, id);
- input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down);
-
- if (!down)
- continue;
-
- touchscreen_report_pos(tsdata->input, &tsdata->prop, x, y,
- true);
+ if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER,
+ type != TOUCH_EVENT_UP))
+ touchscreen_report_pos(tsdata->input, &tsdata->prop,
+ x, y, true);
}
input_mt_report_pointer_emulation(tsdata->input, true);
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index c6b85ba7f991..2e1404cd09ec 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -28,6 +28,7 @@ struct eeti_ts {
struct input_dev *input;
struct gpio_desc *attn_gpio;
struct touchscreen_properties props;
+ struct mutex mutex;
bool running;
};
@@ -62,42 +63,80 @@ static void eeti_ts_report_event(struct eeti_ts *eeti, u8 *buf)
input_sync(eeti->input);
}
+static int eeti_ts_read(struct eeti_ts *eeti)
+{
+ int len, error;
+ char buf[6];
+
+ len = i2c_master_recv(eeti->client, buf, sizeof(buf));
+ if (len != sizeof(buf)) {
+ error = len < 0 ? len : -EIO;
+ dev_err(&eeti->client->dev,
+ "failed to read touchscreen data: %d\n",
+ error);
+ return error;
+ }
+
+ /* Motion packet */
+ if (buf[0] & 0x80)
+ eeti_ts_report_event(eeti, buf);
+
+ return 0;
+}
+
static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
{
struct eeti_ts *eeti = dev_id;
- int len;
int error;
- char buf[6];
+
+ mutex_lock(&eeti->mutex);
do {
- len = i2c_master_recv(eeti->client, buf, sizeof(buf));
- if (len != sizeof(buf)) {
- error = len < 0 ? len : -EIO;
- dev_err(&eeti->client->dev,
- "failed to read touchscreen data: %d\n",
- error);
+ /*
+ * If we have attention GPIO, trust it. Otherwise we'll read
+ * once and exit. We assume that in this case we are using
+ * level triggered interrupt and it will get raised again
+ * if/when there is more data.
+ */
+ if (eeti->attn_gpio &&
+ !gpiod_get_value_cansleep(eeti->attn_gpio)) {
break;
}
- if (buf[0] & 0x80) {
- /* Motion packet */
- eeti_ts_report_event(eeti, buf);
- }
- } while (eeti->running &&
- eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio));
+ error = eeti_ts_read(eeti);
+ if (error)
+ break;
+
+ } while (eeti->running && eeti->attn_gpio);
+ mutex_unlock(&eeti->mutex);
return IRQ_HANDLED;
}
static void eeti_ts_start(struct eeti_ts *eeti)
{
+ mutex_lock(&eeti->mutex);
+
eeti->running = true;
- wmb();
enable_irq(eeti->client->irq);
+
+ /*
+ * Kick the controller in case we are using edge interrupt and
+ * we missed our edge while interrupt was disabled. We expect
+ * the attention GPIO to be wired in this case.
+ */
+ if (eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio))
+ eeti_ts_read(eeti);
+
+ mutex_unlock(&eeti->mutex);
}
static void eeti_ts_stop(struct eeti_ts *eeti)
{
+ /*
+ * Not locking here, just setting a flag and expect that the
+ * interrupt thread will notice the flag eventually.
+ */
eeti->running = false;
wmb();
disable_irq(eeti->client->irq);
@@ -140,6 +179,8 @@ static int eeti_ts_probe(struct i2c_client *client,
return -ENOMEM;
}
+ mutex_init(&eeti->mutex);
+
input = devm_input_allocate_device(dev);
if (!input) {
dev_err(dev, "Failed to allocate input device.\n");
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
index c10fc594f94d..e04eecd65bbb 100644
--- a/drivers/input/touchscreen/imx6ul_tsc.c
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -364,8 +364,6 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct imx6ul_tsc *tsc;
struct input_dev *input_dev;
- struct resource *tsc_mem;
- struct resource *adc_mem;
int err;
int tsc_irq;
int adc_irq;
@@ -403,16 +401,14 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
return err;
}
- tsc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- tsc->tsc_regs = devm_ioremap_resource(&pdev->dev, tsc_mem);
+ tsc->tsc_regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(tsc->tsc_regs)) {
err = PTR_ERR(tsc->tsc_regs);
dev_err(&pdev->dev, "failed to remap tsc memory: %d\n", err);
return err;
}
- adc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- tsc->adc_regs = devm_ioremap_resource(&pdev->dev, adc_mem);
+ tsc->adc_regs = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(tsc->adc_regs)) {
err = PTR_ERR(tsc->adc_regs);
dev_err(&pdev->dev, "failed to remap adc memory: %d\n", err);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 4f6fe8cc8efa..5875bb1099a8 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1056,8 +1056,6 @@ static int iqs5xx_probe(struct i2c_client *client,
if (!iqs5xx)
return -ENOMEM;
- dev_set_drvdata(&client->dev, iqs5xx);
-
i2c_set_clientdata(client, iqs5xx);
iqs5xx->client = client;
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 2d96cf0023dd..a9a9fabd3968 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2034,7 +2034,7 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
static struct platform_driver arm_smmu_driver;
-static int arm_smmu_match_node(struct device *dev, void *data)
+static int arm_smmu_match_node(struct device *dev, const void *data)
{
return dev->fwnode == data;
}
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 653b6b3dcafb..64977c131ee6 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1426,7 +1426,7 @@ static bool arm_smmu_capable(enum iommu_cap cap)
}
}
-static int arm_smmu_match_node(struct device *dev, void *data)
+static int arm_smmu_match_node(struct device *dev, const void *data)
{
return dev->fwnode == data;
}
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f802255219d3..a7f9c3edbcb2 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -951,8 +951,8 @@ static void __iommu_dma_free(struct device *dev, size_t size, void *cpu_addr)
if (pages)
__iommu_dma_free_pages(pages, count);
- if (page && !dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(alloc_size));
+ if (page)
+ dma_free_contiguous(dev, page, alloc_size);
}
static void iommu_dma_free(struct device *dev, size_t size, void *cpu_addr,
@@ -970,12 +970,7 @@ static void *iommu_dma_alloc_pages(struct device *dev, size_t size,
struct page *page = NULL;
void *cpu_addr;
- if (gfpflags_allow_blocking(gfp))
- page = dma_alloc_from_contiguous(dev, alloc_size >> PAGE_SHIFT,
- get_order(alloc_size),
- gfp & __GFP_NOWARN);
- if (!page)
- page = alloc_pages(gfp, get_order(alloc_size));
+ page = dma_alloc_contiguous(dev, alloc_size, gfp);
if (!page)
return NULL;
@@ -997,8 +992,7 @@ static void *iommu_dma_alloc_pages(struct device *dev, size_t size,
memset(cpu_addr, 0, alloc_size);
return cpu_addr;
out_free_pages:
- if (!dma_release_from_contiguous(dev, page, alloc_size >> PAGE_SHIFT))
- __free_pages(page, get_order(alloc_size));
+ dma_free_contiguous(dev, page, alloc_size);
return NULL;
}
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 01e298f620f3..276065c888bc 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -132,7 +132,7 @@ static void smu_start_cmd(void)
/* Flush command and data to RAM */
faddr = (unsigned long)smu->cmd_buf;
fend = faddr + smu->cmd_buf->length + 2;
- flush_inval_dcache_range(faddr, fend);
+ flush_dcache_range(faddr, fend);
/* We also disable NAP mode for the duration of the command
@@ -194,7 +194,7 @@ static irqreturn_t smu_db_intr(int irq, void *arg)
* reply length (it's only 2 cache lines anyway)
*/
faddr = (unsigned long)smu->cmd_buf;
- flush_inval_dcache_range(faddr, faddr + 256);
+ flush_dcache_range(faddr, faddr + 256);
/* Now check ack */
ack = (~cmd->cmd) & 0xff;
diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c
index a64116586b4c..43b336316fde 100644
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -296,8 +296,6 @@ struct flexrm_mbox {
struct dma_pool *bd_pool;
struct dma_pool *cmpl_pool;
struct dentry *root;
- struct dentry *config;
- struct dentry *stats;
struct mbox_controller controller;
};
@@ -1603,7 +1601,6 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
1 << RING_CMPL_ALIGN_ORDER, 0);
if (!mbox->cmpl_pool) {
ret = -ENOMEM;
- goto fail_destroy_bd_pool;
}
/* Allocate platform MSIs for each ring */
@@ -1624,28 +1621,15 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
/* Create debugfs root entry */
mbox->root = debugfs_create_dir(dev_name(mbox->dev), NULL);
- if (IS_ERR_OR_NULL(mbox->root)) {
- ret = PTR_ERR_OR_ZERO(mbox->root);
- goto fail_free_msis;
- }
/* Create debugfs config entry */
- mbox->config = debugfs_create_devm_seqfile(mbox->dev,
- "config", mbox->root,
- flexrm_debugfs_conf_show);
- if (IS_ERR_OR_NULL(mbox->config)) {
- ret = PTR_ERR_OR_ZERO(mbox->config);
- goto fail_free_debugfs_root;
- }
+ debugfs_create_devm_seqfile(mbox->dev, "config", mbox->root,
+ flexrm_debugfs_conf_show);
/* Create debugfs stats entry */
- mbox->stats = debugfs_create_devm_seqfile(mbox->dev,
- "stats", mbox->root,
- flexrm_debugfs_stats_show);
- if (IS_ERR_OR_NULL(mbox->stats)) {
- ret = PTR_ERR_OR_ZERO(mbox->stats);
- goto fail_free_debugfs_root;
- }
+ debugfs_create_devm_seqfile(mbox->dev, "stats", mbox->root,
+ flexrm_debugfs_stats_show);
+
skip_debugfs:
/* Initialize mailbox controller */
@@ -1676,11 +1660,9 @@ skip_debugfs:
fail_free_debugfs_root:
debugfs_remove_recursive(mbox->root);
-fail_free_msis:
platform_msi_domain_free_irqs(dev);
fail_destroy_cmpl_pool:
dma_pool_destroy(mbox->cmpl_pool);
-fail_destroy_bd_pool:
dma_pool_destroy(mbox->bd_pool);
fail:
return ret;
diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c
index 8513c42f7091..fcb3b18a0678 100644
--- a/drivers/mailbox/bcm-pdc-mailbox.c
+++ b/drivers/mailbox/bcm-pdc-mailbox.c
@@ -395,8 +395,6 @@ struct pdc_state {
*/
struct scatterlist *src_sg[PDC_RING_ENTRIES];
- struct dentry *debugfs_stats; /* debug FS stats file for this PDC */
-
/* counters */
u32 pdc_requests; /* number of request messages submitted */
u32 pdc_replies; /* number of reply messages received */
@@ -501,9 +499,8 @@ static void pdc_setup_debugfs(struct pdc_state *pdcs)
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
/* S_IRUSR == 0400 */
- pdcs->debugfs_stats = debugfs_create_file(spu_stats_name, 0400,
- debugfs_dir, pdcs,
- &pdc_debugfs_stats);
+ debugfs_create_file(spu_stats_name, 0400, debugfs_dir, pdcs,
+ &pdc_debugfs_stats);
}
static void pdc_free_debugfs(void)
@@ -1603,7 +1600,6 @@ static int pdc_probe(struct platform_device *pdev)
if (err)
goto cleanup_buf_pool;
- pdcs->debugfs_stats = NULL;
pdc_setup_debugfs(pdcs);
dev_dbg(dev, "pdc_probe() successful");
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 2a48ea3f1b30..b6b5acc92ca2 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1599,9 +1599,7 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
unsigned long freed;
c = container_of(shrink, struct dm_bufio_client, shrinker);
- if (sc->gfp_mask & __GFP_FS)
- dm_bufio_lock(c);
- else if (!dm_bufio_trylock(c))
+ if (!dm_bufio_trylock(c))
return SHRINK_STOP;
freed = __scan(c, sc->nr_to_scan, sc->gfp_mask);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 1b16d34bb785..d5216bcc4649 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -120,6 +120,10 @@ struct iv_tcw_private {
u8 *whitening;
};
+struct iv_eboiv_private {
+ struct crypto_cipher *tfm;
+};
+
/*
* Crypt: maps a linear range of a block device
* and encrypts / decrypts at the same time.
@@ -159,6 +163,7 @@ struct crypt_config {
struct iv_benbi_private benbi;
struct iv_lmk_private lmk;
struct iv_tcw_private tcw;
+ struct iv_eboiv_private eboiv;
} iv_gen_private;
u64 iv_offset;
unsigned int iv_size;
@@ -291,8 +296,9 @@ static struct crypto_aead *any_tfm_aead(struct crypt_config *cc)
* Note that this encryption scheme is vulnerable to watermarking attacks
* and should be used for old compatible containers access only.
*
- * plumb: unimplemented, see:
- * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
+ * eboiv: Encrypted byte-offset IV (used in Bitlocker in CBC mode)
+ * The IV is encrypted little-endian byte-offset (with the same key
+ * and cipher as the volume).
*/
static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv,
@@ -841,6 +847,67 @@ static int crypt_iv_random_gen(struct crypt_config *cc, u8 *iv,
return 0;
}
+static void crypt_iv_eboiv_dtr(struct crypt_config *cc)
+{
+ struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
+
+ crypto_free_cipher(eboiv->tfm);
+ eboiv->tfm = NULL;
+}
+
+static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti,
+ const char *opts)
+{
+ struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
+ struct crypto_cipher *tfm;
+
+ tfm = crypto_alloc_cipher(cc->cipher, 0, 0);
+ if (IS_ERR(tfm)) {
+ ti->error = "Error allocating crypto tfm for EBOIV";
+ return PTR_ERR(tfm);
+ }
+
+ if (crypto_cipher_blocksize(tfm) != cc->iv_size) {
+ ti->error = "Block size of EBOIV cipher does "
+ "not match IV size of block cipher";
+ crypto_free_cipher(tfm);
+ return -EINVAL;
+ }
+
+ eboiv->tfm = tfm;
+ return 0;
+}
+
+static int crypt_iv_eboiv_init(struct crypt_config *cc)
+{
+ struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
+ int err;
+
+ err = crypto_cipher_setkey(eboiv->tfm, cc->key, cc->key_size);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int crypt_iv_eboiv_wipe(struct crypt_config *cc)
+{
+ /* Called after cc->key is set to random key in crypt_wipe() */
+ return crypt_iv_eboiv_init(cc);
+}
+
+static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
+ struct dm_crypt_request *dmreq)
+{
+ struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
+
+ memset(iv, 0, cc->iv_size);
+ *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector * cc->sector_size);
+ crypto_cipher_encrypt_one(eboiv->tfm, iv, iv);
+
+ return 0;
+}
+
static const struct crypt_iv_operations crypt_iv_plain_ops = {
.generator = crypt_iv_plain_gen
};
@@ -893,6 +960,14 @@ static struct crypt_iv_operations crypt_iv_random_ops = {
.generator = crypt_iv_random_gen
};
+static struct crypt_iv_operations crypt_iv_eboiv_ops = {
+ .ctr = crypt_iv_eboiv_ctr,
+ .dtr = crypt_iv_eboiv_dtr,
+ .init = crypt_iv_eboiv_init,
+ .wipe = crypt_iv_eboiv_wipe,
+ .generator = crypt_iv_eboiv_gen
+};
+
/*
* Integrity extensions
*/
@@ -2158,6 +2233,14 @@ static int crypt_wipe_key(struct crypt_config *cc)
clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
get_random_bytes(&cc->key, cc->key_size);
+
+ /* Wipe IV private keys */
+ if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
+ r = cc->iv_gen_ops->wipe(cc);
+ if (r)
+ return r;
+ }
+
kzfree(cc->key_string);
cc->key_string = NULL;
r = crypt_setkey(cc);
@@ -2288,6 +2371,8 @@ static int crypt_ctr_ivmode(struct dm_target *ti, const char *ivmode)
cc->iv_gen_ops = &crypt_iv_benbi_ops;
else if (strcmp(ivmode, "null") == 0)
cc->iv_gen_ops = &crypt_iv_null_ops;
+ else if (strcmp(ivmode, "eboiv") == 0)
+ cc->iv_gen_ops = &crypt_iv_eboiv_ops;
else if (strcmp(ivmode, "lmk") == 0) {
cc->iv_gen_ops = &crypt_iv_lmk_ops;
/*
@@ -2699,7 +2784,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -EINVAL;
}
- cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
+ cc = kzalloc(struct_size(cc, key, key_size), GFP_KERNEL);
if (!cc) {
ti->error = "Cannot allocate encryption context";
return -ENOMEM;
@@ -3050,14 +3135,8 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv,
memset(cc->key, 0, cc->key_size * sizeof(u8));
return ret;
}
- if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
- if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
- ret = cc->iv_gen_ops->wipe(cc);
- if (ret)
- return ret;
- }
+ if (argc == 2 && !strcasecmp(argv[1], "wipe"))
return crypt_wipe_key(cc);
- }
}
error:
@@ -3094,7 +3173,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
static struct target_type crypt_target = {
.name = "crypt",
- .version = {1, 18, 1},
+ .version = {1, 19, 0},
.module = THIS_MODULE,
.ctr = crypt_ctr,
.dtr = crypt_dtr,
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 44e76cda087a..b1b0de402dfc 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -476,6 +476,9 @@ static int sync_rw_sb(struct dm_integrity_c *ic, int op, int op_flags)
io_loc.sector = ic->start;
io_loc.count = SB_SECTORS;
+ if (op == REQ_OP_WRITE)
+ sb_set_version(ic);
+
return dm_io(&io_req, 1, &io_loc, NULL);
}
@@ -2317,7 +2320,6 @@ static void recalc_write_super(struct dm_integrity_c *ic)
if (dm_integrity_failed(ic))
return;
- sb_set_version(ic);
r = sync_rw_sb(ic, REQ_OP_WRITE, 0);
if (unlikely(r))
dm_integrity_io_error(ic, "writing superblock", r);
@@ -3358,7 +3360,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
goto bad;
}
- crypt_iv = kmalloc(ivsize, GFP_KERNEL);
+ crypt_iv = kzalloc(ivsize, GFP_KERNEL);
if (!crypt_iv) {
*error = "Could not allocate iv";
r = -ENOMEM;
@@ -3387,7 +3389,6 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
sg_set_buf(&sg[i], va, PAGE_SIZE);
}
sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids);
- memset(crypt_iv, 0x00, ivsize);
skcipher_request_set_crypt(req, sg, sg,
PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index e549392e0ea5..99721c76225d 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -40,7 +40,7 @@
*
* Would result in the log looking like this:
*
- * c,a,flush,fuad,b,<other writes>,<next flush>
+ * c,a,b,flush,fuad,<other writes>,<next flush>
*
* This is meant to help expose problems where file systems do not properly wait
* on data being written before invoking a FLUSH. FUA bypasses cache so once it
@@ -699,7 +699,7 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio)
if (discard_bio)
alloc_size = sizeof(struct pending_block);
else
- alloc_size = sizeof(struct pending_block) + sizeof(struct bio_vec) * bio_segments(bio);
+ alloc_size = struct_size(block, vecs, bio_segments(bio));
block = kzalloc(alloc_size, GFP_NOIO);
if (!block) {
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index 5f7063f05ae0..c9e44ac1f9a6 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -115,7 +115,7 @@ static void end_clone_bio(struct bio *clone)
/*
* Update the original request.
- * Do not use blk_end_request() here, because it may complete
+ * Do not use blk_mq_end_request() here, because it may complete
* the original request before the clone, and break the ordering.
*/
if (is_last)
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 3107f2b1988b..63916e1dc569 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1,6 +1,4 @@
/*
- * dm-snapshot.c
- *
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
@@ -134,7 +132,10 @@ struct dm_snapshot {
* - I/O error while merging
* => stop merging; set merge_failed; process I/O normally.
*/
- int merge_failed;
+ bool merge_failed:1;
+
+ bool discard_zeroes_cow:1;
+ bool discard_passdown_origin:1;
/*
* Incoming bios that overlap with chunks being merged must wait
@@ -1173,12 +1174,64 @@ static void stop_merge(struct dm_snapshot *s)
clear_bit(SHUTDOWN_MERGE, &s->state_bits);
}
+static int parse_snapshot_features(struct dm_arg_set *as, struct dm_snapshot *s,
+ struct dm_target *ti)
+{
+ int r;
+ unsigned argc;
+ const char *arg_name;
+
+ static const struct dm_arg _args[] = {
+ {0, 2, "Invalid number of feature arguments"},
+ };
+
+ /*
+ * No feature arguments supplied.
+ */
+ if (!as->argc)
+ return 0;
+
+ r = dm_read_arg_group(_args, as, &argc, &ti->error);
+ if (r)
+ return -EINVAL;
+
+ while (argc && !r) {
+ arg_name = dm_shift_arg(as);
+ argc--;
+
+ if (!strcasecmp(arg_name, "discard_zeroes_cow"))
+ s->discard_zeroes_cow = true;
+
+ else if (!strcasecmp(arg_name, "discard_passdown_origin"))
+ s->discard_passdown_origin = true;
+
+ else {
+ ti->error = "Unrecognised feature requested";
+ r = -EINVAL;
+ break;
+ }
+ }
+
+ if (!s->discard_zeroes_cow && s->discard_passdown_origin) {
+ /*
+ * TODO: really these are disjoint.. but ti->num_discard_bios
+ * and dm_bio_get_target_bio_nr() require rigid constraints.
+ */
+ ti->error = "discard_passdown_origin feature depends on discard_zeroes_cow";
+ r = -EINVAL;
+ }
+
+ return r;
+}
+
/*
- * Construct a snapshot mapping: <origin_dev> <COW-dev> <p|po|n> <chunk-size>
+ * Construct a snapshot mapping:
+ * <origin_dev> <COW-dev> <p|po|n> <chunk-size> [<# feature args> [<arg>]*]
*/
static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_snapshot *s;
+ struct dm_arg_set as;
int i;
int r = -EINVAL;
char *origin_path, *cow_path;
@@ -1186,8 +1239,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
unsigned args_used, num_flush_bios = 1;
fmode_t origin_mode = FMODE_READ;
- if (argc != 4) {
- ti->error = "requires exactly 4 arguments";
+ if (argc < 4) {
+ ti->error = "requires 4 or more arguments";
r = -EINVAL;
goto bad;
}
@@ -1204,6 +1257,13 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
+ as.argc = argc;
+ as.argv = argv;
+ dm_consume_args(&as, 4);
+ r = parse_snapshot_features(&as, s, ti);
+ if (r)
+ goto bad_features;
+
origin_path = argv[0];
argv++;
argc--;
@@ -1289,6 +1349,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->private = s;
ti->num_flush_bios = num_flush_bios;
+ if (s->discard_zeroes_cow)
+ ti->num_discard_bios = (s->discard_passdown_origin ? 2 : 1);
ti->per_io_data_size = sizeof(struct dm_snap_tracked_chunk);
/* Add snapshot to the list of snapshots for this origin */
@@ -1336,29 +1398,22 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
bad_read_metadata:
unregister_snapshot(s);
-
bad_load_and_register:
mempool_exit(&s->pending_pool);
-
bad_pending_pool:
dm_kcopyd_client_destroy(s->kcopyd_client);
-
bad_kcopyd:
dm_exception_table_exit(&s->pending, pending_cache);
dm_exception_table_exit(&s->complete, exception_cache);
-
bad_hash_tables:
dm_exception_store_destroy(s->store);
-
bad_store:
dm_put_device(ti, s->cow);
-
bad_cow:
dm_put_device(ti, s->origin);
-
bad_origin:
+bad_features:
kfree(s);
-
bad:
return r;
}
@@ -1806,6 +1861,37 @@ static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
(bio->bi_iter.bi_sector & s->store->chunk_mask);
}
+static void zero_callback(int read_err, unsigned long write_err, void *context)
+{
+ struct bio *bio = context;
+ struct dm_snapshot *s = bio->bi_private;
+
+ up(&s->cow_count);
+ bio->bi_status = write_err ? BLK_STS_IOERR : 0;
+ bio_endio(bio);
+}
+
+static void zero_exception(struct dm_snapshot *s, struct dm_exception *e,
+ struct bio *bio, chunk_t chunk)
+{
+ struct dm_io_region dest;
+
+ dest.bdev = s->cow->bdev;
+ dest.sector = bio->bi_iter.bi_sector;
+ dest.count = s->store->chunk_size;
+
+ down(&s->cow_count);
+ WARN_ON_ONCE(bio->bi_private);
+ bio->bi_private = s;
+ dm_kcopyd_zero(s->kcopyd_client, 1, &dest, 0, zero_callback, bio);
+}
+
+static bool io_overlaps_chunk(struct dm_snapshot *s, struct bio *bio)
+{
+ return bio->bi_iter.bi_size ==
+ (s->store->chunk_size << SECTOR_SHIFT);
+}
+
static int snapshot_map(struct dm_target *ti, struct bio *bio)
{
struct dm_exception *e;
@@ -1839,10 +1925,43 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
goto out_unlock;
}
+ if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
+ if (s->discard_passdown_origin && dm_bio_get_target_bio_nr(bio)) {
+ /*
+ * passdown discard to origin (without triggering
+ * snapshot exceptions via do_origin; doing so would
+ * defeat the goal of freeing space in origin that is
+ * implied by the "discard_passdown_origin" feature)
+ */
+ bio_set_dev(bio, s->origin->bdev);
+ track_chunk(s, bio, chunk);
+ goto out_unlock;
+ }
+ /* discard to snapshot (target_bio_nr == 0) zeroes exceptions */
+ }
+
/* If the block is already remapped - use that, else remap it */
e = dm_lookup_exception(&s->complete, chunk);
if (e) {
remap_exception(s, e, bio, chunk);
+ if (unlikely(bio_op(bio) == REQ_OP_DISCARD) &&
+ io_overlaps_chunk(s, bio)) {
+ dm_exception_table_unlock(&lock);
+ up_read(&s->lock);
+ zero_exception(s, e, bio, chunk);
+ r = DM_MAPIO_SUBMITTED; /* discard is not issued */
+ goto out;
+ }
+ goto out_unlock;
+ }
+
+ if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
+ /*
+ * If no exception exists, complete discard immediately
+ * otherwise it'll trigger copy-out.
+ */
+ bio_endio(bio);
+ r = DM_MAPIO_SUBMITTED;
goto out_unlock;
}
@@ -1890,9 +2009,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
r = DM_MAPIO_SUBMITTED;
- if (!pe->started &&
- bio->bi_iter.bi_size ==
- (s->store->chunk_size << SECTOR_SHIFT)) {
+ if (!pe->started && io_overlaps_chunk(s, bio)) {
pe->started = 1;
dm_exception_table_unlock(&lock);
@@ -2138,6 +2255,7 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,
{
unsigned sz = 0;
struct dm_snapshot *snap = ti->private;
+ unsigned num_features;
switch (type) {
case STATUSTYPE_INFO:
@@ -2178,8 +2296,16 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,
* make sense.
*/
DMEMIT("%s %s", snap->origin->name, snap->cow->name);
- snap->store->type->status(snap->store, type, result + sz,
- maxlen - sz);
+ sz += snap->store->type->status(snap->store, type, result + sz,
+ maxlen - sz);
+ num_features = snap->discard_zeroes_cow + snap->discard_passdown_origin;
+ if (num_features) {
+ DMEMIT(" %u", num_features);
+ if (snap->discard_zeroes_cow)
+ DMEMIT(" discard_zeroes_cow");
+ if (snap->discard_passdown_origin)
+ DMEMIT(" discard_passdown_origin");
+ }
break;
}
}
@@ -2198,6 +2324,22 @@ static int snapshot_iterate_devices(struct dm_target *ti,
return r;
}
+static void snapshot_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+ struct dm_snapshot *snap = ti->private;
+
+ if (snap->discard_zeroes_cow) {
+ struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
+
+ (void) __find_snapshots_sharing_cow(snap, &snap_src, &snap_dest, NULL);
+ if (snap_src && snap_dest)
+ snap = snap_src;
+
+ /* All discards are split on chunk_size boundary */
+ limits->discard_granularity = snap->store->chunk_size;
+ limits->max_discard_sectors = snap->store->chunk_size;
+ }
+}
/*-----------------------------------------------------------------
* Origin methods
@@ -2522,7 +2664,7 @@ static struct target_type origin_target = {
static struct target_type snapshot_target = {
.name = "snapshot",
- .version = {1, 15, 0},
+ .version = {1, 16, 0},
.module = THIS_MODULE,
.ctr = snapshot_ctr,
.dtr = snapshot_dtr,
@@ -2532,11 +2674,12 @@ static struct target_type snapshot_target = {
.resume = snapshot_resume,
.status = snapshot_status,
.iterate_devices = snapshot_iterate_devices,
+ .io_hints = snapshot_io_hints,
};
static struct target_type merge_target = {
.name = dm_snapshot_merge_target_name,
- .version = {1, 4, 0},
+ .version = {1, 5, 0},
.module = THIS_MODULE,
.ctr = snapshot_ctr,
.dtr = snapshot_dtr,
@@ -2547,6 +2690,7 @@ static struct target_type merge_target = {
.resume = snapshot_merge_resume,
.status = snapshot_status,
.iterate_devices = snapshot_iterate_devices,
+ .io_hints = snapshot_io_hints,
};
static int __init dm_snapshot_init(void)
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 7f0840601737..4c68a7b93d5e 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -2046,16 +2046,19 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
{
- int r;
+ int r = -EINVAL;
struct dm_block *sblock;
struct thin_disk_superblock *disk_super;
pmd_write_lock(pmd);
+ if (pmd->fail_io)
+ goto out;
+
pmd->flags |= THIN_METADATA_NEEDS_CHECK_FLAG;
r = superblock_lock(pmd, &sblock);
if (r) {
- DMERR("couldn't read superblock");
+ DMERR("couldn't lock superblock");
goto out;
}
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c
index 8976f82785bb..2ee14d8a6d31 100644
--- a/drivers/mfd/altera-sysmgr.c
+++ b/drivers/mfd/altera-sysmgr.c
@@ -92,9 +92,9 @@ static struct regmap_config altr_sysmgr_regmap_cfg = {
* Matching function used by driver_find_device().
* Return: True if match is found, otherwise false.
*/
-static int sysmgr_match_phandle(struct device *dev, void *data)
+static int sysmgr_match_phandle(struct device *dev, const void *data)
{
- return dev->of_node == (struct device_node *)data;
+ return dev->of_node == (const struct device_node *)data;
}
/**
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 8ce1e41d632c..b65e585fc8c6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -190,27 +190,6 @@ struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
-static int syscon_match_pdevname(struct device *dev, void *data)
-{
- return !strcmp(dev_name(dev), (const char *)data);
-}
-
-struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
-{
- struct device *dev;
- struct syscon *syscon;
-
- dev = driver_find_device(&syscon_driver.driver, NULL, (void *)s,
- syscon_match_pdevname);
- if (!dev)
- return ERR_PTR(-EPROBE_DEFER);
-
- syscon = dev_get_drvdata(dev);
-
- return syscon->regmap;
-}
-EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname);
-
struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
const char *property)
{
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index a73c9e669d78..5dc0f6093f9d 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -908,11 +908,11 @@ void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx);
#ifdef CONFIG_DEBUG_FS
-int cxl_debugfs_init(void);
+void cxl_debugfs_init(void);
void cxl_debugfs_exit(void);
-int cxl_debugfs_adapter_add(struct cxl *adapter);
+void cxl_debugfs_adapter_add(struct cxl *adapter);
void cxl_debugfs_adapter_remove(struct cxl *adapter);
-int cxl_debugfs_afu_add(struct cxl_afu *afu);
+void cxl_debugfs_afu_add(struct cxl_afu *afu);
void cxl_debugfs_afu_remove(struct cxl_afu *afu);
void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir);
void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, struct dentry *dir);
@@ -921,27 +921,24 @@ void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir);
#else /* CONFIG_DEBUG_FS */
-static inline int __init cxl_debugfs_init(void)
+static inline void __init cxl_debugfs_init(void)
{
- return 0;
}
static inline void cxl_debugfs_exit(void)
{
}
-static inline int cxl_debugfs_adapter_add(struct cxl *adapter)
+static inline void cxl_debugfs_adapter_add(struct cxl *adapter)
{
- return 0;
}
static inline void cxl_debugfs_adapter_remove(struct cxl *adapter)
{
}
-static inline int cxl_debugfs_afu_add(struct cxl_afu *afu)
+static inline void cxl_debugfs_afu_add(struct cxl_afu *afu)
{
- return 0;
}
static inline void cxl_debugfs_afu_remove(struct cxl_afu *afu)
diff --git a/drivers/misc/cxl/debugfs.c b/drivers/misc/cxl/debugfs.c
index 1fda22c24c93..7b987bf498b5 100644
--- a/drivers/misc/cxl/debugfs.c
+++ b/drivers/misc/cxl/debugfs.c
@@ -26,11 +26,11 @@ static int debugfs_io_u64_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_io_x64, debugfs_io_u64_get, debugfs_io_u64_set,
"0x%016llx\n");
-static struct dentry *debugfs_create_io_x64(const char *name, umode_t mode,
- struct dentry *parent, u64 __iomem *value)
+static void debugfs_create_io_x64(const char *name, umode_t mode,
+ struct dentry *parent, u64 __iomem *value)
{
- return debugfs_create_file_unsafe(name, mode, parent,
- (void __force *)value, &fops_io_x64);
+ debugfs_create_file_unsafe(name, mode, parent, (void __force *)value,
+ &fops_io_x64);
}
void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir)
@@ -54,25 +54,22 @@ void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, struct dentry *dir)
debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_TRACE));
}
-int cxl_debugfs_adapter_add(struct cxl *adapter)
+void cxl_debugfs_adapter_add(struct cxl *adapter)
{
struct dentry *dir;
char buf[32];
if (!cxl_debugfs)
- return -ENODEV;
+ return;
snprintf(buf, 32, "card%i", adapter->adapter_num);
dir = debugfs_create_dir(buf, cxl_debugfs);
- if (IS_ERR(dir))
- return PTR_ERR(dir);
adapter->debugfs = dir;
debugfs_create_io_x64("err_ivte", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_ErrIVTE));
if (adapter->native->sl_ops->debugfs_add_adapter_regs)
adapter->native->sl_ops->debugfs_add_adapter_regs(adapter, dir);
- return 0;
}
void cxl_debugfs_adapter_remove(struct cxl *adapter)
@@ -96,18 +93,16 @@ void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir)
debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SLICE_TRACE));
}
-int cxl_debugfs_afu_add(struct cxl_afu *afu)
+void cxl_debugfs_afu_add(struct cxl_afu *afu)
{
struct dentry *dir;
char buf[32];
if (!afu->adapter->debugfs)
- return -ENODEV;
+ return;
snprintf(buf, 32, "psl%i.%i", afu->adapter->adapter_num, afu->slice);
dir = debugfs_create_dir(buf, afu->adapter->debugfs);
- if (IS_ERR(dir))
- return PTR_ERR(dir);
afu->debugfs = dir;
debugfs_create_io_x64("sr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SR_An));
@@ -118,8 +113,6 @@ int cxl_debugfs_afu_add(struct cxl_afu *afu)
if (afu->adapter->native->sl_ops->debugfs_add_afu_regs)
afu->adapter->native->sl_ops->debugfs_add_afu_regs(afu, dir);
-
- return 0;
}
void cxl_debugfs_afu_remove(struct cxl_afu *afu)
@@ -127,19 +120,12 @@ void cxl_debugfs_afu_remove(struct cxl_afu *afu)
debugfs_remove_recursive(afu->debugfs);
}
-int __init cxl_debugfs_init(void)
+void __init cxl_debugfs_init(void)
{
- struct dentry *ent;
-
if (!cpu_has_feature(CPU_FTR_HVMODE))
- return 0;
-
- ent = debugfs_create_dir("cxl", NULL);
- if (IS_ERR(ent))
- return PTR_ERR(ent);
- cxl_debugfs = ent;
+ return;
- return 0;
+ cxl_debugfs = debugfs_create_dir("cxl", NULL);
}
void cxl_debugfs_exit(void)
diff --git a/drivers/misc/genwqe/card_base.c b/drivers/misc/genwqe/card_base.c
index ab7f2cd21c93..1dc6c7c5cbce 100644
--- a/drivers/misc/genwqe/card_base.c
+++ b/drivers/misc/genwqe/card_base.c
@@ -1369,10 +1369,6 @@ static int __init genwqe_init_module(void)
class_genwqe->devnode = genwqe_devnode;
debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL);
- if (!debugfs_genwqe) {
- rc = -ENOMEM;
- goto err_out;
- }
rc = pci_register_driver(&genwqe_driver);
if (rc != 0) {
@@ -1384,7 +1380,6 @@ static int __init genwqe_init_module(void)
err_out0:
debugfs_remove(debugfs_genwqe);
- err_out:
class_destroy(class_genwqe);
return rc;
}
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h
index 2f6dd2f37942..0e902977d35f 100644
--- a/drivers/misc/genwqe/card_base.h
+++ b/drivers/misc/genwqe/card_base.h
@@ -437,7 +437,7 @@ int genwqe_device_create(struct genwqe_dev *cd);
int genwqe_device_remove(struct genwqe_dev *cd);
/* debugfs */
-int genwqe_init_debugfs(struct genwqe_dev *cd);
+void genwqe_init_debugfs(struct genwqe_dev *cd);
void genqwe_exit_debugfs(struct genwqe_dev *cd);
int genwqe_read_softreset(struct genwqe_dev *cd);
diff --git a/drivers/misc/genwqe/card_debugfs.c b/drivers/misc/genwqe/card_debugfs.c
index 49c945d0c488..1b5b82e65268 100644
--- a/drivers/misc/genwqe/card_debugfs.c
+++ b/drivers/misc/genwqe/card_debugfs.c
@@ -316,11 +316,9 @@ static int info_show(struct seq_file *s, void *unused)
DEFINE_SHOW_ATTRIBUTE(info);
-int genwqe_init_debugfs(struct genwqe_dev *cd)
+void genwqe_init_debugfs(struct genwqe_dev *cd)
{
struct dentry *root;
- struct dentry *file;
- int ret;
char card_name[64];
char name[64];
unsigned int i;
@@ -328,153 +326,50 @@ int genwqe_init_debugfs(struct genwqe_dev *cd)
sprintf(card_name, "%s%d_card", GENWQE_DEVNAME, cd->card_idx);
root = debugfs_create_dir(card_name, cd->debugfs_genwqe);
- if (!root) {
- ret = -ENOMEM;
- goto err0;
- }
/* non privileged interfaces are done here */
- file = debugfs_create_file("ddcb_info", S_IRUGO, root, cd,
- &ddcb_info_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("info", S_IRUGO, root, cd,
- &info_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_x64("err_inject", 0666, root, &cd->err_inject);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_u32("ddcb_software_timeout", 0666, root,
- &cd->ddcb_software_timeout);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_u32("kill_timeout", 0666, root,
- &cd->kill_timeout);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
+ debugfs_create_file("ddcb_info", S_IRUGO, root, cd, &ddcb_info_fops);
+ debugfs_create_file("info", S_IRUGO, root, cd, &info_fops);
+ debugfs_create_x64("err_inject", 0666, root, &cd->err_inject);
+ debugfs_create_u32("ddcb_software_timeout", 0666, root,
+ &cd->ddcb_software_timeout);
+ debugfs_create_u32("kill_timeout", 0666, root, &cd->kill_timeout);
/* privileged interfaces follow here */
if (!genwqe_is_privileged(cd)) {
cd->debugfs_root = root;
- return 0;
+ return;
}
- file = debugfs_create_file("curr_regs", S_IRUGO, root, cd,
- &curr_regs_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("curr_dbg_uid0", S_IRUGO, root, cd,
- &curr_dbg_uid0_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("curr_dbg_uid1", S_IRUGO, root, cd,
- &curr_dbg_uid1_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("curr_dbg_uid2", S_IRUGO, root, cd,
- &curr_dbg_uid2_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("prev_regs", S_IRUGO, root, cd,
- &prev_regs_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("prev_dbg_uid0", S_IRUGO, root, cd,
- &prev_dbg_uid0_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("prev_dbg_uid1", S_IRUGO, root, cd,
- &prev_dbg_uid1_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("prev_dbg_uid2", S_IRUGO, root, cd,
- &prev_dbg_uid2_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
+ debugfs_create_file("curr_regs", S_IRUGO, root, cd, &curr_regs_fops);
+ debugfs_create_file("curr_dbg_uid0", S_IRUGO, root, cd,
+ &curr_dbg_uid0_fops);
+ debugfs_create_file("curr_dbg_uid1", S_IRUGO, root, cd,
+ &curr_dbg_uid1_fops);
+ debugfs_create_file("curr_dbg_uid2", S_IRUGO, root, cd,
+ &curr_dbg_uid2_fops);
+ debugfs_create_file("prev_regs", S_IRUGO, root, cd, &prev_regs_fops);
+ debugfs_create_file("prev_dbg_uid0", S_IRUGO, root, cd,
+ &prev_dbg_uid0_fops);
+ debugfs_create_file("prev_dbg_uid1", S_IRUGO, root, cd,
+ &prev_dbg_uid1_fops);
+ debugfs_create_file("prev_dbg_uid2", S_IRUGO, root, cd,
+ &prev_dbg_uid2_fops);
for (i = 0; i < GENWQE_MAX_VFS; i++) {
sprintf(name, "vf%u_jobtimeout_msec", i);
-
- file = debugfs_create_u32(name, 0666, root,
- &cd->vf_jobtimeout_msec[i]);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
+ debugfs_create_u32(name, 0666, root,
+ &cd->vf_jobtimeout_msec[i]);
}
- file = debugfs_create_file("jobtimer", S_IRUGO, root, cd,
- &jtimer_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("queue_working_time", S_IRUGO, root, cd,
- &queue_working_time_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_u32("skip_recovery", 0666, root,
- &cd->skip_recovery);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_u32("use_platform_recovery", 0666, root,
- &cd->use_platform_recovery);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
+ debugfs_create_file("jobtimer", S_IRUGO, root, cd, &jtimer_fops);
+ debugfs_create_file("queue_working_time", S_IRUGO, root, cd,
+ &queue_working_time_fops);
+ debugfs_create_u32("skip_recovery", 0666, root, &cd->skip_recovery);
+ debugfs_create_u32("use_platform_recovery", 0666, root,
+ &cd->use_platform_recovery);
cd->debugfs_root = root;
- return 0;
-err1:
- debugfs_remove_recursive(root);
-err0:
- return ret;
}
void genqwe_exit_debugfs(struct genwqe_dev *cd)
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 3bc51f19c734..0e34c0568fed 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -1301,14 +1301,10 @@ int genwqe_device_create(struct genwqe_dev *cd)
goto err_cdev;
}
- rc = genwqe_init_debugfs(cd);
- if (rc != 0)
- goto err_debugfs;
+ genwqe_init_debugfs(cd);
return 0;
- err_debugfs:
- device_destroy(cd->class_genwqe, cd->devnum_genwqe);
err_cdev:
cdev_del(&cd->cdev_genwqe);
err_add:
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index 756794ac8fd8..66ae6b2a6950 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -121,6 +121,9 @@ static const struct crashtype crashtypes[] = {
CRASHTYPE(READ_AFTER_FREE),
CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
CRASHTYPE(READ_BUDDY_AFTER_FREE),
+ CRASHTYPE(SLAB_FREE_DOUBLE),
+ CRASHTYPE(SLAB_FREE_CROSS),
+ CRASHTYPE(SLAB_FREE_PAGE),
CRASHTYPE(SOFTLOCKUP),
CRASHTYPE(HARDLOCKUP),
CRASHTYPE(SPINLOCKUP),
@@ -388,7 +391,7 @@ static int __init lkdtm_module_init(void)
{
struct crashpoint *crashpoint = NULL;
const struct crashtype *crashtype = NULL;
- int ret = -EINVAL;
+ int ret;
int i;
/* Neither or both of these need to be set */
@@ -427,25 +430,17 @@ static int __init lkdtm_module_init(void)
lkdtm_bugs_init(&recur_count);
lkdtm_perms_init();
lkdtm_usercopy_init();
+ lkdtm_heap_init();
/* Register debugfs interface */
lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
- if (!lkdtm_debugfs_root) {
- pr_err("creating root dir failed\n");
- return -ENODEV;
- }
/* Install debugfs trigger files. */
for (i = 0; i < ARRAY_SIZE(crashpoints); i++) {
struct crashpoint *cur = &crashpoints[i];
- struct dentry *de;
- de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
- cur, &cur->fops);
- if (de == NULL) {
- pr_err("could not create crashpoint %s\n", cur->name);
- goto out_err;
- }
+ debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, cur,
+ &cur->fops);
}
/* Install crashpoint if one was selected. */
@@ -473,6 +468,7 @@ static void __exit lkdtm_module_exit(void)
debugfs_remove_recursive(lkdtm_debugfs_root);
/* Handle test-specific clean-up. */
+ lkdtm_heap_exit();
lkdtm_usercopy_exit();
if (lkdtm_kprobe != NULL)
diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c
index 65026d7de130..3c5cec85edce 100644
--- a/drivers/misc/lkdtm/heap.c
+++ b/drivers/misc/lkdtm/heap.c
@@ -7,6 +7,10 @@
#include <linux/slab.h>
#include <linux/sched.h>
+static struct kmem_cache *double_free_cache;
+static struct kmem_cache *a_cache;
+static struct kmem_cache *b_cache;
+
/*
* This tries to stay within the next largest power-of-2 kmalloc cache
* to avoid actually overwriting anything important if it's not detected
@@ -146,3 +150,71 @@ void lkdtm_READ_BUDDY_AFTER_FREE(void)
kfree(val);
}
+
+void lkdtm_SLAB_FREE_DOUBLE(void)
+{
+ int *val;
+
+ val = kmem_cache_alloc(double_free_cache, GFP_KERNEL);
+ if (!val) {
+ pr_info("Unable to allocate double_free_cache memory.\n");
+ return;
+ }
+
+ /* Just make sure we got real memory. */
+ *val = 0x12345678;
+ pr_info("Attempting double slab free ...\n");
+ kmem_cache_free(double_free_cache, val);
+ kmem_cache_free(double_free_cache, val);
+}
+
+void lkdtm_SLAB_FREE_CROSS(void)
+{
+ int *val;
+
+ val = kmem_cache_alloc(a_cache, GFP_KERNEL);
+ if (!val) {
+ pr_info("Unable to allocate a_cache memory.\n");
+ return;
+ }
+
+ /* Just make sure we got real memory. */
+ *val = 0x12345679;
+ pr_info("Attempting cross-cache slab free ...\n");
+ kmem_cache_free(b_cache, val);
+}
+
+void lkdtm_SLAB_FREE_PAGE(void)
+{
+ unsigned long p = __get_free_page(GFP_KERNEL);
+
+ pr_info("Attempting non-Slab slab free ...\n");
+ kmem_cache_free(NULL, (void *)p);
+ free_page(p);
+}
+
+/*
+ * We have constructors to keep the caches distinctly separated without
+ * needing to boot with "slab_nomerge".
+ */
+static void ctor_double_free(void *region)
+{ }
+static void ctor_a(void *region)
+{ }
+static void ctor_b(void *region)
+{ }
+
+void __init lkdtm_heap_init(void)
+{
+ double_free_cache = kmem_cache_create("lkdtm-heap-double_free",
+ 64, 0, 0, ctor_double_free);
+ a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a);
+ b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b);
+}
+
+void __exit lkdtm_heap_exit(void)
+{
+ kmem_cache_destroy(double_free_cache);
+ kmem_cache_destroy(a_cache);
+ kmem_cache_destroy(b_cache);
+}
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index bbcd370786d4..6a284a87a037 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -29,11 +29,16 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
void lkdtm_UNSET_SMEP(void);
/* lkdtm_heap.c */
+void __init lkdtm_heap_init(void);
+void __exit lkdtm_heap_exit(void);
void lkdtm_OVERWRITE_ALLOCATION(void);
void lkdtm_WRITE_AFTER_FREE(void);
void lkdtm_READ_AFTER_FREE(void);
void lkdtm_WRITE_BUDDY_AFTER_FREE(void);
void lkdtm_READ_BUDDY_AFTER_FREE(void);
+void lkdtm_SLAB_FREE_DOUBLE(void);
+void lkdtm_SLAB_FREE_CROSS(void);
+void lkdtm_SLAB_FREE_PAGE(void);
/* lkdtm_perms.c */
void __init lkdtm_perms_init(void);
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 47cfd5005e1b..a26c716c61a1 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -154,46 +154,21 @@ void mei_dbgfs_deregister(struct mei_device *dev)
*
* @dev: the mei device structure
* @name: the mei device name
- *
- * Return: 0 on success, <0 on failure.
*/
-int mei_dbgfs_register(struct mei_device *dev, const char *name)
+void mei_dbgfs_register(struct mei_device *dev, const char *name)
{
- struct dentry *dir, *f;
+ struct dentry *dir;
dir = debugfs_create_dir(name, NULL);
- if (!dir)
- return -ENOMEM;
-
dev->dbgfs_dir = dir;
- f = debugfs_create_file("meclients", S_IRUSR, dir,
- dev, &mei_dbgfs_meclients_fops);
- if (!f) {
- dev_err(dev->dev, "meclients: registration failed\n");
- goto err;
- }
- f = debugfs_create_file("active", S_IRUSR, dir,
- dev, &mei_dbgfs_active_fops);
- if (!f) {
- dev_err(dev->dev, "active: registration failed\n");
- goto err;
- }
- f = debugfs_create_file("devstate", S_IRUSR, dir,
- dev, &mei_dbgfs_devstate_fops);
- if (!f) {
- dev_err(dev->dev, "devstate: registration failed\n");
- goto err;
- }
- f = debugfs_create_file("allow_fixed_address", S_IRUSR | S_IWUSR, dir,
- &dev->allow_fixed_address,
- &mei_dbgfs_allow_fa_fops);
- if (!f) {
- dev_err(dev->dev, "allow_fixed_address: registration failed\n");
- goto err;
- }
- return 0;
-err:
- mei_dbgfs_deregister(dev);
- return -ENODEV;
+ debugfs_create_file("meclients", S_IRUSR, dir, dev,
+ &mei_dbgfs_meclients_fops);
+ debugfs_create_file("active", S_IRUSR, dir, dev,
+ &mei_dbgfs_active_fops);
+ debugfs_create_file("devstate", S_IRUSR, dir, dev,
+ &mei_dbgfs_devstate_fops);
+ debugfs_create_file("allow_fixed_address", S_IRUSR | S_IWUSR, dir,
+ &dev->allow_fixed_address,
+ &mei_dbgfs_allow_fa_fops);
}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index ad02097d7fee..f894d1f8a53e 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -984,16 +984,10 @@ int mei_register(struct mei_device *dev, struct device *parent)
goto err_dev_create;
}
- ret = mei_dbgfs_register(dev, dev_name(clsdev));
- if (ret) {
- dev_err(clsdev, "cannot register debugfs ret = %d\n", ret);
- goto err_dev_dbgfs;
- }
+ mei_dbgfs_register(dev, dev_name(clsdev));
return 0;
-err_dev_dbgfs:
- device_destroy(mei_class, devno);
err_dev_create:
cdev_del(&dev->cdev);
err_dev_add:
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index fca832fcac57..f71a023aed3c 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -718,13 +718,10 @@ bool mei_hbuf_acquire(struct mei_device *dev);
bool mei_write_is_idle(struct mei_device *dev);
#if IS_ENABLED(CONFIG_DEBUG_FS)
-int mei_dbgfs_register(struct mei_device *dev, const char *name);
+void mei_dbgfs_register(struct mei_device *dev, const char *name);
void mei_dbgfs_deregister(struct mei_device *dev);
#else
-static inline int mei_dbgfs_register(struct mei_device *dev, const char *name)
-{
- return 0;
-}
+static inline void mei_dbgfs_register(struct mei_device *dev, const char *name) {}
static inline void mei_dbgfs_deregister(struct mei_device *dev) {}
#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/misc/mic/card/mic_debugfs.c b/drivers/misc/mic/card/mic_debugfs.c
index bf7a60ccc66c..3ee3d2402634 100644
--- a/drivers/misc/mic/card/mic_debugfs.c
+++ b/drivers/misc/mic/card/mic_debugfs.c
@@ -51,25 +51,13 @@ DEFINE_SHOW_ATTRIBUTE(mic_intr);
*/
void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
{
- struct dentry *d;
-
if (!mic_dbg)
return;
mdrv->dbg_dir = debugfs_create_dir(mdrv->name, mic_dbg);
- if (!mdrv->dbg_dir) {
- dev_err(mdrv->dev, "Cant create dbg_dir %s\n", mdrv->name);
- return;
- }
-
- d = debugfs_create_file("intr_test", 0444, mdrv->dbg_dir,
- mdrv, &mic_intr_fops);
- if (!d) {
- dev_err(mdrv->dev,
- "Cant create dbg intr_test %s\n", mdrv->name);
- return;
- }
+ debugfs_create_file("intr_test", 0444, mdrv->dbg_dir, mdrv,
+ &mic_intr_fops);
}
/**
@@ -89,8 +77,6 @@ void mic_delete_card_debug_dir(struct mic_driver *mdrv)
void __init mic_init_card_debugfs(void)
{
mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!mic_dbg)
- pr_err("can't create debugfs dir\n");
}
/**
diff --git a/drivers/misc/mic/cosm/cosm_debugfs.c b/drivers/misc/mic/cosm/cosm_debugfs.c
index 8e3f4589f16d..2fc9f4bf7001 100644
--- a/drivers/misc/mic/cosm/cosm_debugfs.c
+++ b/drivers/misc/mic/cosm/cosm_debugfs.c
@@ -93,8 +93,6 @@ void cosm_create_debug_dir(struct cosm_device *cdev)
scnprintf(name, sizeof(name), "mic%d", cdev->index);
cdev->dbg_dir = debugfs_create_dir(name, cosm_dbg);
- if (!cdev->dbg_dir)
- return;
debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev,
&log_buf_fops);
@@ -113,8 +111,6 @@ void cosm_delete_debug_dir(struct cosm_device *cdev)
void cosm_init_debugfs(void)
{
cosm_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!cosm_dbg)
- pr_err("can't create debugfs dir\n");
}
void cosm_exit_debugfs(void)
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
index 7ef8efe9552f..8a8e41677501 100644
--- a/drivers/misc/mic/host/mic_debugfs.c
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -113,8 +113,6 @@ void mic_create_debug_dir(struct mic_device *mdev)
scnprintf(name, sizeof(name), "mic%d", mdev->id);
mdev->dbg_dir = debugfs_create_dir(name, mic_dbg);
- if (!mdev->dbg_dir)
- return;
debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev,
&mic_smpt_fops);
@@ -143,8 +141,6 @@ void mic_delete_debug_dir(struct mic_device *mdev)
void __init mic_init_debugfs(void)
{
mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!mic_dbg)
- pr_err("can't create debugfs dir\n");
}
/**
diff --git a/drivers/misc/mic/scif/scif_debugfs.c b/drivers/misc/mic/scif/scif_debugfs.c
index a6820480105a..8fe38e7ca6e6 100644
--- a/drivers/misc/mic/scif/scif_debugfs.c
+++ b/drivers/misc/mic/scif/scif_debugfs.c
@@ -103,11 +103,6 @@ DEFINE_SHOW_ATTRIBUTE(scif_rma);
void __init scif_init_debugfs(void)
{
scif_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!scif_dbg) {
- dev_err(scif_info.mdev.this_device,
- "can't create debugfs dir scif\n");
- return;
- }
debugfs_create_file("scif_dev", 0444, scif_dbg, NULL, &scif_dev_fops);
debugfs_create_file("scif_rma", 0444, scif_dbg, NULL, &scif_rma_fops);
diff --git a/drivers/misc/mic/vop/vop_debugfs.c b/drivers/misc/mic/vop/vop_debugfs.c
index ed59cd75e182..9d4f175f4dd1 100644
--- a/drivers/misc/mic/vop/vop_debugfs.c
+++ b/drivers/misc/mic/vop/vop_debugfs.c
@@ -174,10 +174,6 @@ void vop_init_debugfs(struct vop_info *vi)
snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi->vpdev->dnode);
vi->dbg = debugfs_create_dir(name, NULL);
- if (!vi->dbg) {
- pr_err("can't create debugfs dir vop\n");
- return;
- }
debugfs_create_file("dp", 0444, vi->dbg, vi, &vop_dp_fops);
debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vop_vdev_info_fops);
}
diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c
index 5e65acb8e134..c8e19bfb5ef9 100644
--- a/drivers/misc/ocxl/config.c
+++ b/drivers/misc/ocxl/config.c
@@ -20,11 +20,14 @@
#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_DVSEC_TEMPL_ALL_MEM_SZ 0x3C
+#define OCXL_DVSEC_TEMPL_LPC_MEM_START 0x40
+#define OCXL_DVSEC_TEMPL_WWID 0x48
+#define OCXL_DVSEC_TEMPL_LPC_MEM_SZ 0x58
#define OCXL_MAX_AFU_PER_FUNCTION 64
-#define OCXL_TEMPL_LEN 0x58
+#define OCXL_TEMPL_LEN_1_0 0x58
+#define OCXL_TEMPL_LEN_1_1 0x60
#define OCXL_TEMPL_NAME_LEN 24
#define OCXL_CFG_TIMEOUT 3
@@ -269,34 +272,72 @@ static int read_afu_info(struct pci_dev *dev, struct ocxl_fn_config *fn,
return 0;
}
+/**
+ * Read the template version from the AFU
+ * dev: the device for the AFU
+ * fn: the AFU offsets
+ * len: outputs the template length
+ * version: outputs the major<<8,minor version
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int read_template_version(struct pci_dev *dev, struct ocxl_fn_config *fn,
+ u16 *len, u16 *version)
+{
+ u32 val32;
+ u8 major, minor;
+ int rc;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val32);
+ if (rc)
+ return rc;
+
+ *len = EXTRACT_BITS(val32, 16, 31);
+ major = EXTRACT_BITS(val32, 8, 15);
+ minor = EXTRACT_BITS(val32, 0, 7);
+ *version = (major << 8) + minor;
+ 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;
+ int rc;
+ u16 templ_version;
+ u16 len, expected_len;
pci_write_config_byte(dev,
fn->dvsec_afu_info_pos + OCXL_DVSEC_AFU_INFO_AFU_IDX,
afu_idx);
- rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val);
+
+ rc = read_template_version(dev, fn, &len, &templ_version);
if (rc)
return rc;
- /* AFU index map can have holes */
- if (!val)
+ /* AFU index map can have holes, in which case we read all 0's */
+ if (!templ_version && !len)
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);
+ templ_version >> 8, templ_version & 0xFF);
+
+ switch (templ_version) {
+ case 0x0005: // v0.5 was used prior to the spec approval
+ case 0x0100:
+ expected_len = OCXL_TEMPL_LEN_1_0;
+ break;
+ case 0x0101:
+ expected_len = OCXL_TEMPL_LEN_1_1;
+ break;
+ default:
+ dev_warn(&dev->dev, "Unknown AFU template version %#x\n",
+ templ_version);
+ expected_len = len;
}
+ if (len != expected_len)
+ dev_warn(&dev->dev,
+ "Unexpected template length %#x in AFU information, expected %#x for version %#x\n",
+ len, expected_len, templ_version);
return 1;
}
@@ -434,6 +475,102 @@ static int validate_afu(struct pci_dev *dev, struct ocxl_afu_config *afu)
return 0;
}
+/**
+ * Populate AFU metadata regarding LPC memory
+ * dev: the device for the AFU
+ * fn: the AFU offsets
+ * afu: the AFU struct to populate the LPC metadata into
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int read_afu_lpc_memory_info(struct pci_dev *dev,
+ struct ocxl_fn_config *fn,
+ struct ocxl_afu_config *afu)
+{
+ int rc;
+ u32 val32;
+ u16 templ_version;
+ u16 templ_len;
+ u64 total_mem_size = 0;
+ u64 lpc_mem_size = 0;
+
+ afu->lpc_mem_offset = 0;
+ afu->lpc_mem_size = 0;
+ afu->special_purpose_mem_offset = 0;
+ afu->special_purpose_mem_size = 0;
+ /*
+ * For AFUs following template v1.0, the LPC memory covers the
+ * total memory. Its size is a power of 2.
+ *
+ * For AFUs with template >= v1.01, the total memory size is
+ * still a power of 2, but it is split in 2 parts:
+ * - the LPC memory, whose size can now be anything
+ * - the remainder memory is a special purpose memory, whose
+ * definition is AFU-dependent. It is not accessible through
+ * the usual commands for LPC memory
+ */
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_ALL_MEM_SZ, &val32);
+ if (rc)
+ return rc;
+
+ val32 = EXTRACT_BITS(val32, 0, 7);
+ if (!val32)
+ return 0; /* No LPC memory */
+
+ /*
+ * The configuration space spec allows for a memory size of up
+ * to 2^255 bytes.
+ *
+ * Current generation hardware uses 56-bit physical addresses,
+ * but we won't be able to get near close to that, as we won't
+ * have a hole big enough in the memory map. Let it pass in
+ * the driver for now. We'll get an error from the firmware
+ * when trying to configure something too big.
+ */
+ total_mem_size = 1ull << val32;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_LPC_MEM_START, &val32);
+ if (rc)
+ return rc;
+
+ afu->lpc_mem_offset = val32;
+
+ rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_LPC_MEM_START + 4, &val32);
+ if (rc)
+ return rc;
+
+ afu->lpc_mem_offset |= (u64) val32 << 32;
+
+ rc = read_template_version(dev, fn, &templ_len, &templ_version);
+ if (rc)
+ return rc;
+
+ if (templ_version >= 0x0101) {
+ rc = read_afu_info(dev, fn,
+ OCXL_DVSEC_TEMPL_LPC_MEM_SZ, &val32);
+ if (rc)
+ return rc;
+ lpc_mem_size = val32;
+
+ rc = read_afu_info(dev, fn,
+ OCXL_DVSEC_TEMPL_LPC_MEM_SZ + 4, &val32);
+ if (rc)
+ return rc;
+ lpc_mem_size |= (u64) val32 << 32;
+ } else {
+ lpc_mem_size = total_mem_size;
+ }
+ afu->lpc_mem_size = lpc_mem_size;
+
+ if (lpc_mem_size < total_mem_size) {
+ afu->special_purpose_mem_offset =
+ afu->lpc_mem_offset + lpc_mem_size;
+ afu->special_purpose_mem_size =
+ total_mem_size - lpc_mem_size;
+ }
+ return 0;
+}
+
int ocxl_config_read_afu(struct pci_dev *dev, struct ocxl_fn_config *fn,
struct ocxl_afu_config *afu, u8 afu_idx)
{
@@ -467,10 +604,9 @@ int ocxl_config_read_afu(struct pci_dev *dev, struct ocxl_fn_config *fn,
if (rc)
return rc;
- rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_MEM_SZ, &val32);
+ rc = read_afu_lpc_memory_info(dev, fn, afu);
if (rc)
return rc;
- afu->log_mem_size = EXTRACT_BITS(val32, 0, 7);
rc = read_afu_control(dev, afu);
if (rc)
@@ -487,7 +623,12 @@ int ocxl_config_read_afu(struct pci_dev *dev, struct ocxl_fn_config *fn,
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, " lpc_mem offset = %#llx\n", afu->lpc_mem_offset);
+ dev_dbg(&dev->dev, " lpc_mem size = %#llx\n", afu->lpc_mem_size);
+ dev_dbg(&dev->dev, " special purpose mem offset = %#llx\n",
+ afu->special_purpose_mem_offset);
+ dev_dbg(&dev->dev, " special purpose mem size = %#llx\n",
+ afu->special_purpose_mem_size);
dev_dbg(&dev->dev, " pasid supported (log) = %u\n",
afu->pasid_supported_log);
dev_dbg(&dev->dev, " actag supported = %u\n",
diff --git a/drivers/misc/ocxl/pci.c b/drivers/misc/ocxl/pci.c
index f2a3ef4b9bdd..cb920aa88d3a 100644
--- a/drivers/misc/ocxl/pci.c
+++ b/drivers/misc/ocxl/pci.c
@@ -41,7 +41,7 @@ static int ocxl_probe(struct pci_dev *dev, const struct pci_device_id *id)
return 0;
}
-void ocxl_remove(struct pci_dev *dev)
+static void ocxl_remove(struct pci_dev *dev)
{
struct ocxl_fn *fn;
struct ocxl_afu *afu;
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 18ca938b86e6..a36ed1ff5967 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -748,10 +748,6 @@ static int kim_probe(struct platform_device *pdev)
pr_info("sysfs entries created\n");
kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
- if (!kim_debugfs_dir) {
- pr_err(" debugfs entries creation failed ");
- return 0;
- }
debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
kim_gdata, &version_fops);
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 043eed845246..97b58e7ad901 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -1699,19 +1699,10 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
DEFINE_SHOW_ATTRIBUTE(vmballoon_debug);
-static int __init vmballoon_debugfs_init(struct vmballoon *b)
+static void __init vmballoon_debugfs_init(struct vmballoon *b)
{
- int error;
-
b->dbg_entry = debugfs_create_file("vmmemctl", S_IRUGO, NULL, b,
&vmballoon_debug_fops);
- if (IS_ERR(b->dbg_entry)) {
- error = PTR_ERR(b->dbg_entry);
- pr_err("failed to create debugfs entry, error: %d\n", error);
- return error;
- }
-
- return 0;
}
static void __exit vmballoon_debugfs_exit(struct vmballoon *b)
@@ -1724,9 +1715,8 @@ static void __exit vmballoon_debugfs_exit(struct vmballoon *b)
#else
-static inline int vmballoon_debugfs_init(struct vmballoon *b)
+static inline void vmballoon_debugfs_init(struct vmballoon *b)
{
- return 0;
}
static inline void vmballoon_debugfs_exit(struct vmballoon *b)
@@ -1948,10 +1938,6 @@ static int __init vmballoon_init(void)
if (error)
goto fail;
- error = vmballoon_debugfs_init(&balloon);
- if (error)
- goto fail;
-
/*
* Initialization of compaction must be done after the call to
* balloon_devinfo_init() .
@@ -1971,6 +1957,8 @@ static int __init vmballoon_init(void)
queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
+ vmballoon_debugfs_init(&balloon);
+
return 0;
fail:
vmballoon_unregister_shrinker(&balloon);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index fb31a7f649a3..80a6e2dcd085 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -274,4 +274,6 @@ source "drivers/mtd/spi-nor/Kconfig"
source "drivers/mtd/ubi/Kconfig"
+source "drivers/mtd/hyperbus/Kconfig"
+
endif # MTD
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 806287e80e84..62d649a959e2 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -34,3 +34,4 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ tests/
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/
+obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index c8fa5906bdf9..f4da7bd552e9 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -49,6 +49,16 @@
#define SST49LF008A 0x005a
#define AT49BV6416 0x00d6
+/*
+ * Status Register bit description. Used by flash devices that don't
+ * support DQ polling (e.g. HyperFlash)
+ */
+#define CFI_SR_DRB BIT(7)
+#define CFI_SR_ESB BIT(5)
+#define CFI_SR_PSB BIT(4)
+#define CFI_SR_WBASB BIT(3)
+#define CFI_SR_SLSB BIT(1)
+
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
@@ -97,6 +107,50 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = {
.module = THIS_MODULE
};
+/*
+ * Use status register to poll for Erase/write completion when DQ is not
+ * supported. This is indicated by Bit[1:0] of SoftwareFeatures field in
+ * CFI Primary Vendor-Specific Extended Query table 1.5
+ */
+static int cfi_use_status_reg(struct cfi_private *cfi)
+{
+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
+ u8 poll_mask = CFI_POLL_STATUS_REG | CFI_POLL_DQ;
+
+ return extp->MinorVersion >= '5' &&
+ (extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;
+}
+
+static void cfi_check_err_status(struct map_info *map, struct flchip *chip,
+ unsigned long adr)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ map_word status;
+
+ if (!cfi_use_status_reg(cfi))
+ return;
+
+ cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ status = map_read(map, adr);
+
+ if (map_word_bitsset(map, status, CMD(0x3a))) {
+ unsigned long chipstatus = MERGESTATUS(status);
+
+ if (chipstatus & CFI_SR_ESB)
+ pr_err("%s erase operation failed, status %lx\n",
+ map->name, chipstatus);
+ if (chipstatus & CFI_SR_PSB)
+ pr_err("%s program operation failed, status %lx\n",
+ map->name, chipstatus);
+ if (chipstatus & CFI_SR_WBASB)
+ pr_err("%s buffer program command aborted, status %lx\n",
+ map->name, chipstatus);
+ if (chipstatus & CFI_SR_SLSB)
+ pr_err("%s sector write protected, status %lx\n",
+ map->name, chipstatus);
+ }
+}
/* #define DEBUG_CFI_FEATURES */
@@ -742,10 +796,25 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
* correctly and is therefore not done (particularly with interleaved chips
* as each chip must be checked independently of the others).
*/
-static int __xipram chip_ready(struct map_info *map, unsigned long addr)
+static int __xipram chip_ready(struct map_info *map, struct flchip *chip,
+ unsigned long addr)
{
+ struct cfi_private *cfi = map->fldrv_priv;
map_word d, t;
+ if (cfi_use_status_reg(cfi)) {
+ map_word ready = CMD(CFI_SR_DRB);
+ /*
+ * For chips that support status register, check device
+ * ready bit
+ */
+ cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ d = map_read(map, addr);
+
+ return map_word_andequal(map, d, ready, ready);
+ }
+
d = map_read(map, addr);
t = map_read(map, addr);
@@ -767,10 +836,30 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr)
* as each chip must be checked independently of the others).
*
*/
-static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)
+static int __xipram chip_good(struct map_info *map, struct flchip *chip,
+ unsigned long addr, map_word expected)
{
+ struct cfi_private *cfi = map->fldrv_priv;
map_word oldd, curd;
+ if (cfi_use_status_reg(cfi)) {
+ map_word ready = CMD(CFI_SR_DRB);
+ map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB);
+ /*
+ * For chips that support status register, check device
+ * ready bit and Erase/Program status bit to know if
+ * operation succeeded.
+ */
+ cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ curd = map_read(map, addr);
+
+ if (map_word_andequal(map, curd, ready, ready))
+ return !map_word_bitsset(map, curd, err);
+
+ return 0;
+ }
+
oldd = map_read(map, addr);
curd = map_read(map, addr);
@@ -792,7 +881,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
case FL_STATUS:
for (;;) {
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
break;
if (time_after(jiffies, timeo)) {
@@ -830,7 +919,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
chip->state = FL_ERASE_SUSPENDING;
chip->erase_suspended = 1;
for (;;) {
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
break;
if (time_after(jiffies, timeo)) {
@@ -1362,7 +1451,7 @@ static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr,
/* wait for chip to become ready */
timeo = jiffies + msecs_to_jiffies(2);
for (;;) {
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
break;
if (time_after(jiffies, timeo)) {
@@ -1628,22 +1717,24 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
continue;
}
- if (time_after(jiffies, timeo) && !chip_ready(map, adr)){
+ if (time_after(jiffies, timeo) &&
+ !chip_ready(map, chip, adr)) {
xip_enable(map, chip, adr);
printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
xip_disable(map, chip, adr);
break;
}
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
break;
/* Latency issues. Drop the lock, wait a while and retry */
UDELAY(map, chip, adr, 1);
}
/* Did we succeed? */
- if (!chip_good(map, adr, datum)) {
+ if (!chip_good(map, chip, adr, datum)) {
/* reset on all failures. */
+ cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@@ -1881,10 +1972,11 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
* We check "time_after" and "!chip_good" before checking "chip_good" to avoid
* the failure due to scheduling.
*/
- if (time_after(jiffies, timeo) && !chip_good(map, adr, datum))
+ if (time_after(jiffies, timeo) &&
+ !chip_good(map, chip, adr, datum))
break;
- if (chip_good(map, adr, datum)) {
+ if (chip_good(map, chip, adr, datum)) {
xip_enable(map, chip, adr);
goto op_done;
}
@@ -1901,6 +1993,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
* See e.g.
* http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf
*/
+ cfi_check_err_status(map, chip, adr);
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
@@ -2018,7 +2111,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
* If the driver thinks the chip is idle, and no toggle bits
* are changing, then the chip is actually idle for sure.
*/
- if (chip->state == FL_READY && chip_ready(map, adr))
+ if (chip->state == FL_READY && chip_ready(map, chip, adr))
return 0;
/*
@@ -2035,7 +2128,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
/* wait for the chip to become ready */
for (i = 0; i < jiffies_to_usecs(timeo); i++) {
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
return 0;
udelay(1);
@@ -2099,14 +2192,15 @@ retry:
map_write(map, datum, adr);
for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) {
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
break;
udelay(1);
}
- if (!chip_good(map, adr, datum)) {
+ if (!chip_good(map, chip, adr, datum)) {
/* reset on all failures. */
+ cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@@ -2300,7 +2394,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
chip->erase_suspended = 0;
}
- if (chip_good(map, adr, map_word_ff(map)))
+ if (chip_good(map, chip, adr, map_word_ff(map)))
break;
if (time_after(jiffies, timeo)) {
@@ -2316,6 +2410,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
/* Did we succeed? */
if (ret) {
/* reset on all failures. */
+ cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@@ -2396,7 +2491,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->erase_suspended = 0;
}
- if (chip_good(map, adr, map_word_ff(map)))
+ if (chip_good(map, chip, adr, map_word_ff(map)))
break;
if (time_after(jiffies, timeo)) {
@@ -2412,6 +2507,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
/* Did we succeed? */
if (ret) {
/* reset on all failures. */
+ cfi_check_err_status(map, chip, adr);
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
@@ -2533,8 +2629,6 @@ struct ppb_lock {
int locked;
};
-#define MAX_SECTORS 512
-
#define DO_XXLOCK_ONEBLOCK_LOCK ((void *)1)
#define DO_XXLOCK_ONEBLOCK_UNLOCK ((void *)2)
#define DO_XXLOCK_ONEBLOCK_GETLOCK ((void *)3)
@@ -2589,7 +2683,7 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
*/
timeo = jiffies + msecs_to_jiffies(2000); /* 2s max (un)locking */
for (;;) {
- if (chip_ready(map, adr))
+ if (chip_ready(map, chip, adr))
break;
if (time_after(jiffies, timeo)) {
@@ -2633,6 +2727,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
int i;
int sectors;
int ret;
+ int max_sectors;
/*
* PPB unlocking always unlocks all sectors of the flash chip.
@@ -2640,7 +2735,11 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
* first check the locking status of all sectors and save
* it for future use.
*/
- sect = kcalloc(MAX_SECTORS, sizeof(struct ppb_lock), GFP_KERNEL);
+ max_sectors = 0;
+ for (i = 0; i < mtd->numeraseregions; i++)
+ max_sectors += regions[i].numblocks;
+
+ sect = kcalloc(max_sectors, sizeof(struct ppb_lock), GFP_KERNEL);
if (!sect)
return -ENOMEM;
@@ -2689,9 +2788,9 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
}
sectors++;
- if (sectors >= MAX_SECTORS) {
+ if (sectors >= max_sectors) {
printk(KERN_ERR "Only %d sectors for PPB locking supported!\n",
- MAX_SECTORS);
+ max_sectors);
kfree(sect);
return -EINVAL;
}
diff --git a/drivers/mtd/hyperbus/Kconfig b/drivers/mtd/hyperbus/Kconfig
new file mode 100644
index 000000000000..cff6bbd226f5
--- /dev/null
+++ b/drivers/mtd/hyperbus/Kconfig
@@ -0,0 +1,23 @@
+menuconfig MTD_HYPERBUS
+ tristate "HyperBus support"
+ select MTD_CFI
+ select MTD_MAP_BANK_WIDTH_2
+ select MTD_CFI_AMDSTD
+ select MTD_COMPLEX_MAPPINGS
+ help
+ This is the framework for the HyperBus which can be used by
+ the HyperBus Controller driver to communicate with
+ HyperFlash. See Cypress HyperBus specification for more
+ details
+
+if MTD_HYPERBUS
+
+config HBMC_AM654
+ tristate "HyperBus controller driver for AM65x SoC"
+ select MULTIPLEXER
+ select MUX_MMIO
+ help
+ This is the driver for HyperBus controller on TI's AM65x and
+ other SoCs
+
+endif # MTD_HYPERBUS
diff --git a/drivers/mtd/hyperbus/Makefile b/drivers/mtd/hyperbus/Makefile
new file mode 100644
index 000000000000..8a936e066f48
--- /dev/null
+++ b/drivers/mtd/hyperbus/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_MTD_HYPERBUS) += hyperbus-core.o
+obj-$(CONFIG_HBMC_AM654) += hbmc-am654.o
diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c
new file mode 100644
index 000000000000..08d543b124cd
--- /dev/null
+++ b/drivers/mtd/hyperbus/hbmc-am654.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+// Author: Vignesh Raghavendra <vigneshr@ti.com>
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/hyperbus.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mux/consumer.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+
+#define AM654_HBMC_CALIB_COUNT 25
+
+struct am654_hbmc_priv {
+ struct hyperbus_ctlr ctlr;
+ struct hyperbus_device hbdev;
+ struct mux_control *mux_ctrl;
+};
+
+static int am654_hbmc_calibrate(struct hyperbus_device *hbdev)
+{
+ struct map_info *map = &hbdev->map;
+ struct cfi_private cfi;
+ int count = AM654_HBMC_CALIB_COUNT;
+ int pass_count = 0;
+ int ret;
+
+ cfi.interleave = 1;
+ cfi.device_type = CFI_DEVICETYPE_X16;
+ cfi_send_gen_cmd(0xF0, 0, 0, map, &cfi, cfi.device_type, NULL);
+ cfi_send_gen_cmd(0x98, 0x55, 0, map, &cfi, cfi.device_type, NULL);
+
+ while (count--) {
+ ret = cfi_qry_present(map, 0, &cfi);
+ if (ret)
+ pass_count++;
+ else
+ pass_count = 0;
+ if (pass_count == 5)
+ break;
+ }
+
+ cfi_qry_mode_off(0, map, &cfi);
+
+ return ret;
+}
+
+static const struct hyperbus_ops am654_hbmc_ops = {
+ .calibrate = am654_hbmc_calibrate,
+};
+
+static int am654_hbmc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct am654_hbmc_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ if (of_property_read_bool(dev->of_node, "mux-controls")) {
+ struct mux_control *control = devm_mux_control_get(dev, NULL);
+
+ if (IS_ERR(control))
+ return PTR_ERR(control);
+
+ ret = mux_control_select(control, 1);
+ if (ret) {
+ dev_err(dev, "Failed to select HBMC mux\n");
+ return ret;
+ }
+ priv->mux_ctrl = control;
+ }
+
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(dev);
+ goto disable_pm;
+ }
+
+ priv->ctlr.dev = dev;
+ priv->ctlr.ops = &am654_hbmc_ops;
+ priv->hbdev.ctlr = &priv->ctlr;
+ priv->hbdev.np = of_get_next_child(dev->of_node, NULL);
+ ret = hyperbus_register_device(&priv->hbdev);
+ if (ret) {
+ dev_err(dev, "failed to register controller\n");
+ pm_runtime_put_sync(&pdev->dev);
+ goto disable_pm;
+ }
+
+ return 0;
+disable_pm:
+ pm_runtime_disable(dev);
+ if (priv->mux_ctrl)
+ mux_control_deselect(priv->mux_ctrl);
+ return ret;
+}
+
+static int am654_hbmc_remove(struct platform_device *pdev)
+{
+ struct am654_hbmc_priv *priv = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = hyperbus_unregister_device(&priv->hbdev);
+ if (priv->mux_ctrl)
+ mux_control_deselect(priv->mux_ctrl);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+}
+
+static const struct of_device_id am654_hbmc_dt_ids[] = {
+ {
+ .compatible = "ti,am654-hbmc",
+ },
+ { /* end of table */ }
+};
+
+MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids);
+
+static struct platform_driver am654_hbmc_platform_driver = {
+ .probe = am654_hbmc_probe,
+ .remove = am654_hbmc_remove,
+ .driver = {
+ .name = "hbmc-am654",
+ .of_match_table = am654_hbmc_dt_ids,
+ },
+};
+
+module_platform_driver(am654_hbmc_platform_driver);
+
+MODULE_DESCRIPTION("HBMC driver for AM654 SoC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:hbmc-am654");
+MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
diff --git a/drivers/mtd/hyperbus/hyperbus-core.c b/drivers/mtd/hyperbus/hyperbus-core.c
new file mode 100644
index 000000000000..6af9ea34117d
--- /dev/null
+++ b/drivers/mtd/hyperbus/hyperbus-core.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+// Author: Vignesh Raghavendra <vigneshr@ti.com>
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/hyperbus.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/types.h>
+
+static struct hyperbus_device *map_to_hbdev(struct map_info *map)
+{
+ return container_of(map, struct hyperbus_device, map);
+}
+
+static map_word hyperbus_read16(struct map_info *map, unsigned long addr)
+{
+ struct hyperbus_device *hbdev = map_to_hbdev(map);
+ struct hyperbus_ctlr *ctlr = hbdev->ctlr;
+ map_word read_data;
+
+ read_data.x[0] = ctlr->ops->read16(hbdev, addr);
+
+ return read_data;
+}
+
+static void hyperbus_write16(struct map_info *map, map_word d,
+ unsigned long addr)
+{
+ struct hyperbus_device *hbdev = map_to_hbdev(map);
+ struct hyperbus_ctlr *ctlr = hbdev->ctlr;
+
+ ctlr->ops->write16(hbdev, addr, d.x[0]);
+}
+
+static void hyperbus_copy_from(struct map_info *map, void *to,
+ unsigned long from, ssize_t len)
+{
+ struct hyperbus_device *hbdev = map_to_hbdev(map);
+ struct hyperbus_ctlr *ctlr = hbdev->ctlr;
+
+ ctlr->ops->copy_from(hbdev, to, from, len);
+}
+
+static void hyperbus_copy_to(struct map_info *map, unsigned long to,
+ const void *from, ssize_t len)
+{
+ struct hyperbus_device *hbdev = map_to_hbdev(map);
+ struct hyperbus_ctlr *ctlr = hbdev->ctlr;
+
+ ctlr->ops->copy_to(hbdev, to, from, len);
+}
+
+int hyperbus_register_device(struct hyperbus_device *hbdev)
+{
+ const struct hyperbus_ops *ops;
+ struct hyperbus_ctlr *ctlr;
+ struct device_node *np;
+ struct map_info *map;
+ struct resource res;
+ struct device *dev;
+ int ret;
+
+ if (!hbdev || !hbdev->np || !hbdev->ctlr || !hbdev->ctlr->dev) {
+ pr_err("hyperbus: please fill all the necessary fields!\n");
+ return -EINVAL;
+ }
+
+ np = hbdev->np;
+ ctlr = hbdev->ctlr;
+ if (!of_device_is_compatible(np, "cypress,hyperflash"))
+ return -ENODEV;
+
+ hbdev->memtype = HYPERFLASH;
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return ret;
+
+ dev = ctlr->dev;
+ map = &hbdev->map;
+ map->size = resource_size(&res);
+ map->virt = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(map->virt))
+ return PTR_ERR(map->virt);
+
+ map->name = dev_name(dev);
+ map->bankwidth = 2;
+ map->device_node = np;
+
+ simple_map_init(map);
+ ops = ctlr->ops;
+ if (ops) {
+ if (ops->read16)
+ map->read = hyperbus_read16;
+ if (ops->write16)
+ map->write = hyperbus_write16;
+ if (ops->copy_to)
+ map->copy_to = hyperbus_copy_to;
+ if (ops->copy_from)
+ map->copy_from = hyperbus_copy_from;
+
+ if (ops->calibrate && !ctlr->calibrated) {
+ ret = ops->calibrate(hbdev);
+ if (!ret) {
+ dev_err(dev, "Calibration failed\n");
+ return -ENODEV;
+ }
+ ctlr->calibrated = true;
+ }
+ }
+
+ hbdev->mtd = do_map_probe("cfi_probe", map);
+ if (!hbdev->mtd) {
+ dev_err(dev, "probing of hyperbus device failed\n");
+ return -ENODEV;
+ }
+
+ hbdev->mtd->dev.parent = dev;
+ mtd_set_of_node(hbdev->mtd, np);
+
+ ret = mtd_device_register(hbdev->mtd, NULL, 0);
+ if (ret) {
+ dev_err(dev, "failed to register mtd device\n");
+ map_destroy(hbdev->mtd);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hyperbus_register_device);
+
+int hyperbus_unregister_device(struct hyperbus_device *hbdev)
+{
+ int ret = 0;
+
+ if (hbdev && hbdev->mtd) {
+ ret = mtd_device_unregister(hbdev->mtd);
+ map_destroy(hbdev->mtd);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hyperbus_unregister_device);
+
+MODULE_DESCRIPTION("HyperBus Framework");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 7324ff832b41..170a7221b35f 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -437,7 +437,8 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
return err;
}
-static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+static int concat_xxlock(struct mtd_info *mtd, loff_t ofs, uint64_t len,
+ bool is_lock)
{
struct mtd_concat *concat = CONCAT(mtd);
int i, err = -EINVAL;
@@ -456,7 +457,10 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
else
size = len;
- err = mtd_lock(subdev, ofs, size);
+ if (is_lock)
+ err = mtd_lock(subdev, ofs, size);
+ else
+ err = mtd_unlock(subdev, ofs, size);
if (err)
break;
@@ -471,35 +475,33 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
return err;
}
+static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ return concat_xxlock(mtd, ofs, len, true);
+}
+
static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
+ return concat_xxlock(mtd, ofs, len, false);
+}
+
+static int concat_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
struct mtd_concat *concat = CONCAT(mtd);
- int i, err = 0;
+ int i, err = -EINVAL;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
- uint64_t size;
if (ofs >= subdev->size) {
- size = 0;
ofs -= subdev->size;
continue;
}
- if (ofs + len > subdev->size)
- size = subdev->size - ofs;
- else
- size = len;
-
- err = mtd_unlock(subdev, ofs, size);
- if (err)
- break;
- len -= size;
- if (len == 0)
+ if (ofs + len > subdev->size)
break;
- err = -EINVAL;
- ofs = 0;
+ return mtd_is_locked(subdev, ofs, len);
}
return err;
@@ -704,6 +706,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd._sync = concat_sync;
concat->mtd._lock = concat_lock;
concat->mtd._unlock = concat_unlock;
+ concat->mtd._is_locked = concat_is_locked;
concat->mtd._suspend = concat_suspend;
concat->mtd._resume = concat_resume;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 453242d6cf56..408615f29e57 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1124,6 +1124,9 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
return -EROFS;
if (!len)
return 0;
+ if (!mtd->oops_panic_write)
+ mtd->oops_panic_write = true;
+
return mtd->_panic_write(mtd, to, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_panic_write);
diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
index d759c02d9cb2..a1f8fe1abb10 100644
--- a/drivers/mtd/nand/onenand/onenand_base.c
+++ b/drivers/mtd/nand/onenand/onenand_base.c
@@ -3257,6 +3257,8 @@ static void onenand_check_features(struct mtd_info *mtd)
/* Lock scheme */
switch (density) {
+ case ONENAND_DEVICE_DENSITY_8Gb:
+ this->options |= ONENAND_HAS_NOP_1;
case ONENAND_DEVICE_DENSITY_4Gb:
if (ONENAND_IS_DDP(this))
this->options |= ONENAND_HAS_2PLANE;
@@ -3277,12 +3279,15 @@ static void onenand_check_features(struct mtd_info *mtd)
if ((this->version_id & 0xf) == 0xe)
this->options |= ONENAND_HAS_NOP_1;
}
+ this->options |= ONENAND_HAS_UNLOCK_ALL;
+ break;
case ONENAND_DEVICE_DENSITY_2Gb:
/* 2Gb DDP does not have 2 plane */
if (!ONENAND_IS_DDP(this))
this->options |= ONENAND_HAS_2PLANE;
this->options |= ONENAND_HAS_UNLOCK_ALL;
+ break;
case ONENAND_DEVICE_DENSITY_1Gb:
/* A-Die has all block unlock */
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index 873527753f52..33310b8a6eb8 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -84,6 +84,12 @@ struct brcm_nand_dma_desc {
#define FLASH_DMA_ECC_ERROR (1 << 8)
#define FLASH_DMA_CORR_ERROR (1 << 9)
+/* Bitfields for DMA_MODE */
+#define FLASH_DMA_MODE_STOP_ON_ERROR BIT(1) /* stop in Uncorr ECC error */
+#define FLASH_DMA_MODE_MODE BIT(0) /* link list */
+#define FLASH_DMA_MODE_MASK (FLASH_DMA_MODE_STOP_ON_ERROR | \
+ FLASH_DMA_MODE_MODE)
+
/* 512B flash cache in the NAND controller HW */
#define FC_SHIFT 9U
#define FC_BYTES 512U
@@ -96,6 +102,51 @@ struct brcm_nand_dma_desc {
#define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY)
#define NAND_POLL_STATUS_TIMEOUT_MS 100
+/* flash_dma registers */
+enum flash_dma_reg {
+ FLASH_DMA_REVISION = 0,
+ FLASH_DMA_FIRST_DESC,
+ FLASH_DMA_FIRST_DESC_EXT,
+ FLASH_DMA_CTRL,
+ FLASH_DMA_MODE,
+ FLASH_DMA_STATUS,
+ FLASH_DMA_INTERRUPT_DESC,
+ FLASH_DMA_INTERRUPT_DESC_EXT,
+ FLASH_DMA_ERROR_STATUS,
+ FLASH_DMA_CURRENT_DESC,
+ FLASH_DMA_CURRENT_DESC_EXT,
+};
+
+/* flash_dma registers v1*/
+static const u16 flash_dma_regs_v1[] = {
+ [FLASH_DMA_REVISION] = 0x00,
+ [FLASH_DMA_FIRST_DESC] = 0x04,
+ [FLASH_DMA_FIRST_DESC_EXT] = 0x08,
+ [FLASH_DMA_CTRL] = 0x0c,
+ [FLASH_DMA_MODE] = 0x10,
+ [FLASH_DMA_STATUS] = 0x14,
+ [FLASH_DMA_INTERRUPT_DESC] = 0x18,
+ [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x1c,
+ [FLASH_DMA_ERROR_STATUS] = 0x20,
+ [FLASH_DMA_CURRENT_DESC] = 0x24,
+ [FLASH_DMA_CURRENT_DESC_EXT] = 0x28,
+};
+
+/* flash_dma registers v4 */
+static const u16 flash_dma_regs_v4[] = {
+ [FLASH_DMA_REVISION] = 0x00,
+ [FLASH_DMA_FIRST_DESC] = 0x08,
+ [FLASH_DMA_FIRST_DESC_EXT] = 0x0c,
+ [FLASH_DMA_CTRL] = 0x10,
+ [FLASH_DMA_MODE] = 0x14,
+ [FLASH_DMA_STATUS] = 0x18,
+ [FLASH_DMA_INTERRUPT_DESC] = 0x20,
+ [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x24,
+ [FLASH_DMA_ERROR_STATUS] = 0x28,
+ [FLASH_DMA_CURRENT_DESC] = 0x30,
+ [FLASH_DMA_CURRENT_DESC_EXT] = 0x34,
+};
+
/* Controller feature flags */
enum {
BRCMNAND_HAS_1K_SECTORS = BIT(0),
@@ -128,6 +179,8 @@ struct brcmnand_controller {
/* List of NAND hosts (one for each chip-select) */
struct list_head host_list;
+ /* flash_dma reg */
+ const u16 *flash_dma_offsets;
struct brcm_nand_dma_desc *dma_desc;
dma_addr_t dma_pa;
@@ -151,6 +204,7 @@ struct brcmnand_controller {
u32 nand_cs_nand_xor;
u32 corr_stat_threshold;
u32 flash_dma_mode;
+ bool pio_poll_mode;
};
struct brcmnand_cfg {
@@ -462,7 +516,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
/* Register offsets */
if (ctrl->nand_version >= 0x0702)
ctrl->reg_offsets = brcmnand_regs_v72;
- else if (ctrl->nand_version >= 0x0701)
+ else if (ctrl->nand_version == 0x0701)
ctrl->reg_offsets = brcmnand_regs_v71;
else if (ctrl->nand_version >= 0x0600)
ctrl->reg_offsets = brcmnand_regs_v60;
@@ -507,7 +561,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
}
/* Maximum spare area sector size (per 512B) */
- if (ctrl->nand_version >= 0x0702)
+ if (ctrl->nand_version == 0x0702)
ctrl->max_oob = 128;
else if (ctrl->nand_version >= 0x0600)
ctrl->max_oob = 64;
@@ -538,6 +592,15 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
return 0;
}
+static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl)
+{
+ /* flash_dma register offsets */
+ if (ctrl->nand_version >= 0x0703)
+ ctrl->flash_dma_offsets = flash_dma_regs_v4;
+ else
+ ctrl->flash_dma_offsets = flash_dma_regs_v1;
+}
+
static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl,
enum brcmnand_reg reg)
{
@@ -580,6 +643,54 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
__raw_writel(val, ctrl->nand_fc + word * 4);
}
+static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl)
+{
+
+ /* Clear error addresses */
+ brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
+ brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
+ brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
+ brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
+}
+
+static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl)
+{
+ u64 err_addr;
+
+ err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR);
+ err_addr |= ((u64)(brcmnand_read_reg(ctrl,
+ BRCMNAND_UNCORR_EXT_ADDR)
+ & 0xffff) << 32);
+
+ return err_addr;
+}
+
+static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl)
+{
+ u64 err_addr;
+
+ err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR);
+ err_addr |= ((u64)(brcmnand_read_reg(ctrl,
+ BRCMNAND_CORR_EXT_ADDR)
+ & 0xffff) << 32);
+
+ return err_addr;
+}
+
+static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct brcmnand_host *host = nand_get_controller_data(chip);
+ struct brcmnand_controller *ctrl = host->ctrl;
+
+ brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
+ (host->cs << 16) | ((addr >> 32) & 0xffff));
+ (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
+ brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
+ lower_32_bits(addr));
+ (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+}
+
static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs,
enum brcmnand_cs_reg reg)
{
@@ -612,7 +723,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
int cs = host->cs;
- if (ctrl->nand_version >= 0x0702)
+ if (ctrl->nand_version == 0x0702)
bits = 7;
else if (ctrl->nand_version >= 0x0600)
bits = 6;
@@ -666,7 +777,7 @@ enum {
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
{
- if (ctrl->nand_version >= 0x0702)
+ if (ctrl->nand_version == 0x0702)
return GENMASK(7, 0);
else if (ctrl->nand_version >= 0x0600)
return GENMASK(6, 0);
@@ -796,39 +907,44 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
* Flash DMA
***********************************************************************/
-enum flash_dma_reg {
- FLASH_DMA_REVISION = 0x00,
- FLASH_DMA_FIRST_DESC = 0x04,
- FLASH_DMA_FIRST_DESC_EXT = 0x08,
- FLASH_DMA_CTRL = 0x0c,
- FLASH_DMA_MODE = 0x10,
- FLASH_DMA_STATUS = 0x14,
- FLASH_DMA_INTERRUPT_DESC = 0x18,
- FLASH_DMA_INTERRUPT_DESC_EXT = 0x1c,
- FLASH_DMA_ERROR_STATUS = 0x20,
- FLASH_DMA_CURRENT_DESC = 0x24,
- FLASH_DMA_CURRENT_DESC_EXT = 0x28,
-};
-
static inline bool has_flash_dma(struct brcmnand_controller *ctrl)
{
return ctrl->flash_dma_base;
}
+static inline void disable_ctrl_irqs(struct brcmnand_controller *ctrl)
+{
+ if (ctrl->pio_poll_mode)
+ return;
+
+ if (has_flash_dma(ctrl)) {
+ ctrl->flash_dma_base = 0;
+ disable_irq(ctrl->dma_irq);
+ }
+
+ disable_irq(ctrl->irq);
+ ctrl->pio_poll_mode = true;
+}
+
static inline bool flash_dma_buf_ok(const void *buf)
{
return buf && !is_vmalloc_addr(buf) &&
likely(IS_ALIGNED((uintptr_t)buf, 4));
}
-static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs,
- u32 val)
+static inline void flash_dma_writel(struct brcmnand_controller *ctrl,
+ enum flash_dma_reg dma_reg, u32 val)
{
+ u16 offs = ctrl->flash_dma_offsets[dma_reg];
+
brcmnand_writel(val, ctrl->flash_dma_base + offs);
}
-static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs)
+static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl,
+ enum flash_dma_reg dma_reg)
{
+ u16 offs = ctrl->flash_dma_offsets[dma_reg];
+
return brcmnand_readl(ctrl->flash_dma_base + offs);
}
@@ -931,7 +1047,7 @@ static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
if (section >= sectors)
return -ERANGE;
- oobregion->offset = (section * (sas + 1)) - chip->ecc.bytes;
+ oobregion->offset = ((section + 1) * sas) - chip->ecc.bytes;
oobregion->length = chip->ecc.bytes;
return 0;
@@ -1205,9 +1321,12 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
{
struct brcmnand_controller *ctrl = host->ctrl;
int ret;
+ u64 cmd_addr;
+
+ cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+
+ dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
- dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
- brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
BUG_ON(ctrl->cmd_pending != 0);
ctrl->cmd_pending = cmd;
@@ -1229,15 +1348,42 @@ static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat,
/* intentionally left blank */
}
+static bool brcmstb_nand_wait_for_completion(struct nand_chip *chip)
+{
+ struct brcmnand_host *host = nand_get_controller_data(chip);
+ struct brcmnand_controller *ctrl = host->ctrl;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ bool err = false;
+ int sts;
+
+ if (mtd->oops_panic_write) {
+ /* switch to interrupt polling and PIO mode */
+ disable_ctrl_irqs(ctrl);
+ sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY,
+ NAND_CTRL_RDY, 0);
+ err = (sts < 0) ? true : false;
+ } else {
+ unsigned long timeo = msecs_to_jiffies(
+ NAND_POLL_STATUS_TIMEOUT_MS);
+ /* wait for completion interrupt */
+ sts = wait_for_completion_timeout(&ctrl->done, timeo);
+ err = (sts <= 0) ? true : false;
+ }
+
+ return err;
+}
+
static int brcmnand_waitfunc(struct nand_chip *chip)
{
struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_controller *ctrl = host->ctrl;
- unsigned long timeo = msecs_to_jiffies(100);
+ bool err = false;
dev_dbg(ctrl->dev, "wait on native cmd %d\n", ctrl->cmd_pending);
- if (ctrl->cmd_pending &&
- wait_for_completion_timeout(&ctrl->done, timeo) <= 0) {
+ if (ctrl->cmd_pending)
+ err = brcmstb_nand_wait_for_completion(chip);
+
+ if (err) {
u32 cmd = brcmnand_read_reg(ctrl, BRCMNAND_CMD_START)
>> brcmnand_cmd_shift(ctrl);
@@ -1366,12 +1512,7 @@ static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command,
if (!native_cmd)
return;
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
- (host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
-
+ brcmnand_set_cmd_addr(mtd, addr);
brcmnand_send_cmd(host, native_cmd);
brcmnand_waitfunc(chip);
@@ -1589,20 +1730,10 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
struct brcmnand_controller *ctrl = host->ctrl;
int i, j, ret = 0;
- /* Clear error addresses */
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
-
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
- (host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
+ brcmnand_clear_ecc_addr(ctrl);
for (i = 0; i < trans; i++, addr += FC_BYTES) {
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
- lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+ brcmnand_set_cmd_addr(mtd, addr);
/* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */
brcmnand_send_cmd(host, CMD_PAGE_READ);
brcmnand_waitfunc(chip);
@@ -1622,21 +1753,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
host->hwcfg.sector_size_1k);
if (!ret) {
- *err_addr = brcmnand_read_reg(ctrl,
- BRCMNAND_UNCORR_ADDR) |
- ((u64)(brcmnand_read_reg(ctrl,
- BRCMNAND_UNCORR_EXT_ADDR)
- & 0xffff) << 32);
+ *err_addr = brcmnand_get_uncorrecc_addr(ctrl);
+
if (*err_addr)
ret = -EBADMSG;
}
if (!ret) {
- *err_addr = brcmnand_read_reg(ctrl,
- BRCMNAND_CORR_ADDR) |
- ((u64)(brcmnand_read_reg(ctrl,
- BRCMNAND_CORR_EXT_ADDR)
- & 0xffff) << 32);
+ *err_addr = brcmnand_get_correcc_addr(ctrl);
+
if (*err_addr)
ret = -EUCLEAN;
}
@@ -1703,7 +1828,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf);
try_dmaread:
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0);
+ brcmnand_clear_ecc_addr(ctrl);
if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) {
err = brcmnand_dma_trans(host, addr, buf, trans * FC_BYTES,
@@ -1850,15 +1975,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
goto out;
}
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
- (host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
-
for (i = 0; i < trans; i++, addr += FC_BYTES) {
/* full address MUST be set before populating FC */
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
- lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+ brcmnand_set_cmd_addr(mtd, addr);
if (buf) {
brcmnand_soc_data_bus_prepare(ctrl->soc, false);
@@ -2136,6 +2255,17 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
return -EINVAL;
}
+ if (chip->ecc.mode != NAND_ECC_NONE &&
+ (!chip->ecc.size || !chip->ecc.strength)) {
+ if (chip->base.eccreq.step_size && chip->base.eccreq.strength) {
+ /* use detected ECC parameters */
+ chip->ecc.size = chip->base.eccreq.step_size;
+ chip->ecc.strength = chip->base.eccreq.strength;
+ dev_info(ctrl->dev, "Using ECC step-size %d, strength %d\n",
+ chip->ecc.size, chip->ecc.strength);
+ }
+ }
+
switch (chip->ecc.size) {
case 512:
if (chip->ecc.algo == NAND_ECC_HAMMING)
@@ -2395,6 +2525,7 @@ static const struct of_device_id brcmnand_of_match[] = {
{ .compatible = "brcm,brcmnand-v7.0" },
{ .compatible = "brcm,brcmnand-v7.1" },
{ .compatible = "brcm,brcmnand-v7.2" },
+ { .compatible = "brcm,brcmnand-v7.3" },
{},
};
MODULE_DEVICE_TABLE(of, brcmnand_of_match);
@@ -2481,7 +2612,11 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
goto err;
}
- flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
+ /* initialize the dma version */
+ brcmnand_flash_dma_revision_init(ctrl);
+
+ /* linked-list and stop on error */
+ flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
/* Allocate descriptor(s) */
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 6c7ca41354be..a6964feeec77 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -613,28 +613,20 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
for (op_id = 0; op_id < op->ninstrs; op_id++) {
instr = &op->instrs[op_id];
+ nand_op_trace(" ", instr);
+
switch (instr->type) {
case NAND_OP_CMD_INSTR:
- pr_debug(" ->CMD [0x%02x]\n",
- instr->ctx.cmd.opcode);
-
writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va);
break;
case NAND_OP_ADDR_INSTR:
- pr_debug(" ->ADDR [%d cyc]",
- instr->ctx.addr.naddrs);
-
for (i = 0; i < instr->ctx.addr.naddrs; i++)
writeb_relaxed(instr->ctx.addr.addrs[i],
host->addr_va);
break;
case NAND_OP_DATA_IN_INSTR:
- pr_debug(" ->DATA_IN [%d B%s]\n", instr->ctx.data.len,
- instr->ctx.data.force_8bit ?
- ", force 8-bit" : "");
-
if (host->mode == USE_DMA_ACCESS)
fsmc_read_buf_dma(host, instr->ctx.data.buf.in,
instr->ctx.data.len);
@@ -644,10 +636,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
break;
case NAND_OP_DATA_OUT_INSTR:
- pr_debug(" ->DATA_OUT [%d B%s]\n", instr->ctx.data.len,
- instr->ctx.data.force_8bit ?
- ", force 8-bit" : "");
-
if (host->mode == USE_DMA_ACCESS)
fsmc_write_buf_dma(host,
instr->ctx.data.buf.out,
@@ -658,9 +646,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
break;
case NAND_OP_WAITRDY_INSTR:
- pr_debug(" ->WAITRDY [max %d ms]\n",
- instr->ctx.waitrdy.timeout_ms);
-
ret = nand_soft_waitrdy(chip,
instr->ctx.waitrdy.timeout_ms);
break;
diff --git a/drivers/mtd/nand/raw/gpmi-nand/Makefile b/drivers/mtd/nand/raw/gpmi-nand/Makefile
index 30ceee9704d1..9bd81a31e02e 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/Makefile
+++ b/drivers/mtd/nand/raw/gpmi-nand/Makefile
@@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi_nand.o
gpmi_nand-objs += gpmi-nand.o
-gpmi_nand-objs += gpmi-lib.o
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
deleted file mode 100644
index a8b26d2e793c..000000000000
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
+++ /dev/null
@@ -1,934 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Freescale GPMI NAND Flash Driver
- *
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
- * Copyright (C) 2008 Embedded Alley Solutions, Inc.
- */
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-
-#include "gpmi-nand.h"
-#include "gpmi-regs.h"
-#include "bch-regs.h"
-
-/* Converts time to clock cycles */
-#define TO_CYCLES(duration, period) DIV_ROUND_UP_ULL(duration, period)
-
-#define MXS_SET_ADDR 0x4
-#define MXS_CLR_ADDR 0x8
-/*
- * Clear the bit and poll it cleared. This is usually called with
- * a reset address and mask being either SFTRST(bit 31) or CLKGATE
- * (bit 30).
- */
-static int clear_poll_bit(void __iomem *addr, u32 mask)
-{
- int timeout = 0x400;
-
- /* clear the bit */
- writel(mask, addr + MXS_CLR_ADDR);
-
- /*
- * SFTRST needs 3 GPMI clocks to settle, the reference manual
- * recommends to wait 1us.
- */
- udelay(1);
-
- /* poll the bit becoming clear */
- while ((readl(addr) & mask) && --timeout)
- /* nothing */;
-
- return !timeout;
-}
-
-#define MODULE_CLKGATE (1 << 30)
-#define MODULE_SFTRST (1 << 31)
-/*
- * The current mxs_reset_block() will do two things:
- * [1] enable the module.
- * [2] reset the module.
- *
- * In most of the cases, it's ok.
- * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
- * If you try to soft reset the BCH block, it becomes unusable until
- * the next hard reset. This case occurs in the NAND boot mode. When the board
- * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
- * So If the driver tries to reset the BCH again, the BCH will not work anymore.
- * You will see a DMA timeout in this case. The bug has been fixed
- * in the following chips, such as MX28.
- *
- * To avoid this bug, just add a new parameter `just_enable` for
- * the mxs_reset_block(), and rewrite it here.
- */
-static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
-{
- int ret;
- int timeout = 0x400;
-
- /* clear and poll SFTRST */
- ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
- if (unlikely(ret))
- goto error;
-
- /* clear CLKGATE */
- writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
-
- if (!just_enable) {
- /* set SFTRST to reset the block */
- writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR);
- udelay(1);
-
- /* poll CLKGATE becoming set */
- while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout)
- /* nothing */;
- if (unlikely(!timeout))
- goto error;
- }
-
- /* clear and poll SFTRST */
- ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
- if (unlikely(ret))
- goto error;
-
- /* clear and poll CLKGATE */
- ret = clear_poll_bit(reset_addr, MODULE_CLKGATE);
- if (unlikely(ret))
- goto error;
-
- return 0;
-
-error:
- pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
- return -ETIMEDOUT;
-}
-
-static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
-{
- struct clk *clk;
- int ret;
- int i;
-
- for (i = 0; i < GPMI_CLK_MAX; i++) {
- clk = this->resources.clock[i];
- if (!clk)
- break;
-
- if (v) {
- ret = clk_prepare_enable(clk);
- if (ret)
- goto err_clk;
- } else {
- clk_disable_unprepare(clk);
- }
- }
- return 0;
-
-err_clk:
- for (; i > 0; i--)
- clk_disable_unprepare(this->resources.clock[i - 1]);
- return ret;
-}
-
-int gpmi_enable_clk(struct gpmi_nand_data *this)
-{
- return __gpmi_enable_clk(this, true);
-}
-
-int gpmi_disable_clk(struct gpmi_nand_data *this)
-{
- return __gpmi_enable_clk(this, false);
-}
-
-int gpmi_init(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- int ret;
-
- ret = gpmi_enable_clk(this);
- if (ret)
- return ret;
- ret = gpmi_reset_block(r->gpmi_regs, false);
- if (ret)
- goto err_out;
-
- /*
- * Reset BCH here, too. We got failures otherwise :(
- * See later BCH reset for explanation of MX23 and MX28 handling
- */
- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this));
- if (ret)
- goto err_out;
-
- /* Choose NAND mode. */
- writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR);
-
- /* Set the IRQ polarity. */
- writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
- r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* Disable Write-Protection. */
- writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* Select BCH ECC. */
- writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /*
- * Decouple the chip select from dma channel. We use dma0 for all
- * the chips.
- */
- writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
- gpmi_disable_clk(this);
- return 0;
-err_out:
- gpmi_disable_clk(this);
- return ret;
-}
-
-/* This function is very useful. It is called only when the bug occur. */
-void gpmi_dump_info(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- struct bch_geometry *geo = &this->bch_geometry;
- u32 reg;
- int i;
-
- dev_err(this->dev, "Show GPMI registers :\n");
- for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
- reg = readl(r->gpmi_regs + i * 0x10);
- dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
- }
-
- /* start to print out the BCH info */
- dev_err(this->dev, "Show BCH registers :\n");
- for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
- reg = readl(r->bch_regs + i * 0x10);
- dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
- }
- dev_err(this->dev, "BCH Geometry :\n"
- "GF length : %u\n"
- "ECC Strength : %u\n"
- "Page Size in Bytes : %u\n"
- "Metadata Size in Bytes : %u\n"
- "ECC Chunk Size in Bytes: %u\n"
- "ECC Chunk Count : %u\n"
- "Payload Size in Bytes : %u\n"
- "Auxiliary Size in Bytes: %u\n"
- "Auxiliary Status Offset: %u\n"
- "Block Mark Byte Offset : %u\n"
- "Block Mark Bit Offset : %u\n",
- geo->gf_len,
- geo->ecc_strength,
- geo->page_size,
- geo->metadata_size,
- geo->ecc_chunk_size,
- geo->ecc_chunk_count,
- geo->payload_size,
- geo->auxiliary_size,
- geo->auxiliary_status_offset,
- geo->block_mark_byte_offset,
- geo->block_mark_bit_offset);
-}
-
-/* Configures the geometry for BCH. */
-int bch_set_geometry(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- struct bch_geometry *bch_geo = &this->bch_geometry;
- unsigned int block_count;
- unsigned int block_size;
- unsigned int metadata_size;
- unsigned int ecc_strength;
- unsigned int page_size;
- unsigned int gf_len;
- int ret;
-
- ret = common_nfc_set_geometry(this);
- if (ret)
- return ret;
-
- block_count = bch_geo->ecc_chunk_count - 1;
- block_size = bch_geo->ecc_chunk_size;
- metadata_size = bch_geo->metadata_size;
- ecc_strength = bch_geo->ecc_strength >> 1;
- page_size = bch_geo->page_size;
- gf_len = bch_geo->gf_len;
-
- ret = gpmi_enable_clk(this);
- if (ret)
- return ret;
-
- /*
- * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
- * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
- * and MX28.
- */
- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this));
- if (ret)
- goto err_out;
-
- /* Configure layout 0. */
- writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
- | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
- | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
- | BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
- r->bch_regs + HW_BCH_FLASH0LAYOUT0);
-
- writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
- | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
- | BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
- r->bch_regs + HW_BCH_FLASH0LAYOUT1);
-
- /* Set *all* chip selects to use layout 0. */
- writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
-
- /* Enable interrupts. */
- writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
- r->bch_regs + HW_BCH_CTRL_SET);
-
- gpmi_disable_clk(this);
- return 0;
-err_out:
- gpmi_disable_clk(this);
- return ret;
-}
-
-/*
- * <1> Firstly, we should know what's the GPMI-clock means.
- * The GPMI-clock is the internal clock in the gpmi nand controller.
- * If you set 100MHz to gpmi nand controller, the GPMI-clock's period
- * is 10ns. Mark the GPMI-clock's period as GPMI-clock-period.
- *
- * <2> Secondly, we should know what's the frequency on the nand chip pins.
- * The frequency on the nand chip pins is derived from the GPMI-clock.
- * We can get it from the following equation:
- *
- * F = G / (DS + DH)
- *
- * F : the frequency on the nand chip pins.
- * G : the GPMI clock, such as 100MHz.
- * DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP
- * DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD
- *
- * <3> Thirdly, when the frequency on the nand chip pins is above 33MHz,
- * the nand EDO(extended Data Out) timing could be applied.
- * The GPMI implements a feedback read strobe to sample the read data.
- * The feedback read strobe can be delayed to support the nand EDO timing
- * where the read strobe may deasserts before the read data is valid, and
- * read data is valid for some time after read strobe.
- *
- * The following figure illustrates some aspects of a NAND Flash read:
- *
- * |<---tREA---->|
- * | |
- * | | |
- * |<--tRP-->| |
- * | | |
- * __ ___|__________________________________
- * RDN \________/ |
- * |
- * /---------\
- * Read Data --------------< >---------
- * \---------/
- * | |
- * |<-D->|
- * FeedbackRDN ________ ____________
- * \___________/
- *
- * D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY.
- *
- *
- * <4> Now, we begin to describe how to compute the right RDN_DELAY.
- *
- * 4.1) From the aspect of the nand chip pins:
- * Delay = (tREA + C - tRP) {1}
- *
- * tREA : the maximum read access time.
- * C : a constant to adjust the delay. default is 4000ps.
- * tRP : the read pulse width, which is exactly:
- * tRP = (GPMI-clock-period) * DATA_SETUP
- *
- * 4.2) From the aspect of the GPMI nand controller:
- * Delay = RDN_DELAY * 0.125 * RP {2}
- *
- * RP : the DLL reference period.
- * if (GPMI-clock-period > DLL_THRETHOLD)
- * RP = GPMI-clock-period / 2;
- * else
- * RP = GPMI-clock-period;
- *
- * Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period
- * is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD
- * is 16000ps, but in mx6q, we use 12000ps.
- *
- * 4.3) since {1} equals {2}, we get:
- *
- * (tREA + 4000 - tRP) * 8
- * RDN_DELAY = ----------------------- {3}
- * RP
- */
-static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
- const struct nand_sdr_timings *sdr)
-{
- struct gpmi_nfc_hardware_timing *hw = &this->hw;
- unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
- unsigned int period_ps, reference_period_ps;
- unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
- unsigned int tRP_ps;
- bool use_half_period;
- int sample_delay_ps, sample_delay_factor;
- u16 busy_timeout_cycles;
- u8 wrn_dly_sel;
-
- if (sdr->tRC_min >= 30000) {
- /* ONFI non-EDO modes [0-3] */
- hw->clk_rate = 22000000;
- wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
- } else if (sdr->tRC_min >= 25000) {
- /* ONFI EDO mode 4 */
- hw->clk_rate = 80000000;
- wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
- } else {
- /* ONFI EDO mode 5 */
- hw->clk_rate = 100000000;
- wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
- }
-
- /* SDR core timings are given in picoseconds */
- period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
-
- addr_setup_cycles = TO_CYCLES(sdr->tALS_min, period_ps);
- data_setup_cycles = TO_CYCLES(sdr->tDS_min, period_ps);
- data_hold_cycles = TO_CYCLES(sdr->tDH_min, period_ps);
- busy_timeout_cycles = TO_CYCLES(sdr->tWB_max + sdr->tR_max, period_ps);
-
- hw->timing0 = BF_GPMI_TIMING0_ADDRESS_SETUP(addr_setup_cycles) |
- BF_GPMI_TIMING0_DATA_HOLD(data_hold_cycles) |
- BF_GPMI_TIMING0_DATA_SETUP(data_setup_cycles);
- hw->timing1 = BF_GPMI_TIMING1_BUSY_TIMEOUT(busy_timeout_cycles * 4096);
-
- /*
- * Derive NFC ideal delay from {3}:
- *
- * (tREA + 4000 - tRP) * 8
- * RDN_DELAY = -----------------------
- * RP
- */
- if (period_ps > dll_threshold_ps) {
- use_half_period = true;
- reference_period_ps = period_ps / 2;
- } else {
- use_half_period = false;
- reference_period_ps = period_ps;
- }
-
- tRP_ps = data_setup_cycles * period_ps;
- sample_delay_ps = (sdr->tREA_max + 4000 - tRP_ps) * 8;
- if (sample_delay_ps > 0)
- sample_delay_factor = sample_delay_ps / reference_period_ps;
- else
- sample_delay_factor = 0;
-
- hw->ctrl1n = BF_GPMI_CTRL1_WRN_DLY_SEL(wrn_dly_sel);
- if (sample_delay_factor)
- hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
- BM_GPMI_CTRL1_DLL_ENABLE |
- (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
-}
-
-void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
-{
- struct gpmi_nfc_hardware_timing *hw = &this->hw;
- struct resources *r = &this->resources;
- void __iomem *gpmi_regs = r->gpmi_regs;
- unsigned int dll_wait_time_us;
-
- clk_set_rate(r->clock[0], hw->clk_rate);
-
- writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
- writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
-
- /*
- * Clear several CTRL1 fields, DLL must be disabled when setting
- * RDN_DELAY or HALF_PERIOD.
- */
- writel(BM_GPMI_CTRL1_CLEAR_MASK, gpmi_regs + HW_GPMI_CTRL1_CLR);
- writel(hw->ctrl1n, gpmi_regs + HW_GPMI_CTRL1_SET);
-
- /* Wait 64 clock cycles before using the GPMI after enabling the DLL */
- dll_wait_time_us = USEC_PER_SEC / hw->clk_rate * 64;
- if (!dll_wait_time_us)
- dll_wait_time_us = 1;
-
- /* Wait for the DLL to settle. */
- udelay(dll_wait_time_us);
-}
-
-int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
- const struct nand_data_interface *conf)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- const struct nand_sdr_timings *sdr;
-
- /* Retrieve required NAND timings */
- sdr = nand_get_sdr_timings(conf);
- if (IS_ERR(sdr))
- return PTR_ERR(sdr);
-
- /* Only MX6 GPMI controller can reach EDO timings */
- if (sdr->tRC_min <= 25000 && !GPMI_IS_MX6(this))
- return -ENOTSUPP;
-
- /* Stop here if this call was just a check */
- if (chipnr < 0)
- return 0;
-
- /* Do the actual derivation of the controller timings */
- gpmi_nfc_compute_timings(this, sdr);
-
- this->hw.must_apply_timings = true;
-
- return 0;
-}
-
-/* Clears a BCH interrupt. */
-void gpmi_clear_bch(struct gpmi_nand_data *this)
-{
- struct resources *r = &this->resources;
- writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
-}
-
-/* Returns the Ready/Busy status of the given chip. */
-int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
-{
- struct resources *r = &this->resources;
- uint32_t mask = 0;
- uint32_t reg = 0;
-
- if (GPMI_IS_MX23(this)) {
- mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
- reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
- } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this)) {
- /*
- * In the imx6, all the ready/busy pins are bound
- * together. So we only need to check chip 0.
- */
- if (GPMI_IS_MX6(this))
- chip = 0;
-
- /* MX28 shares the same R/B register as MX6Q. */
- mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
- reg = readl(r->gpmi_regs + HW_GPMI_STAT);
- } else
- dev_err(this->dev, "unknown arch.\n");
- return reg & mask;
-}
-
-int gpmi_send_command(struct gpmi_nand_data *this)
-{
- struct dma_chan *channel = get_dma_chan(this);
- struct dma_async_tx_descriptor *desc;
- struct scatterlist *sgl;
- int chip = this->current_chip;
- int ret;
- u32 pio[3];
-
- /* [1] send out the PIO words */
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
- | BM_GPMI_CTRL0_ADDRESS_INCREMENT
- | BF_GPMI_CTRL0_XFER_COUNT(this->command_length);
- pio[1] = pio[2] = 0;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] send out the COMMAND + ADDRESS string stored in @buffer */
- sgl = &this->cmd_sgl;
-
- sg_init_one(sgl, this->cmd_buffer, this->command_length);
- dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
- desc = dmaengine_prep_slave_sg(channel,
- sgl, 1, DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] submit the DMA */
- ret = start_dma_without_bch_irq(this, desc);
-
- dma_unmap_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
-
- return ret;
-}
-
-int gpmi_send_data(struct gpmi_nand_data *this, const void *buf, int len)
-{
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- int ret;
- uint32_t command_mode;
- uint32_t address;
- u32 pio[2];
-
- /* [1] PIO */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(len);
- pio[1] = 0;
- desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] send DMA request */
- prepare_data_dma(this, buf, len, DMA_TO_DEVICE);
- desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
- 1, DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] submit the DMA */
- ret = start_dma_without_bch_irq(this, desc);
-
- dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_TO_DEVICE);
-
- return ret;
-}
-
-int gpmi_read_data(struct gpmi_nand_data *this, void *buf, int len)
-{
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- int ret;
- u32 pio[2];
- bool direct;
-
- /* [1] : send PIO */
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
- | BF_GPMI_CTRL0_XFER_COUNT(len);
- pio[1] = 0;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] : send DMA request */
- direct = prepare_data_dma(this, buf, len, DMA_FROM_DEVICE);
- desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
- 1, DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] : submit the DMA */
-
- ret = start_dma_without_bch_irq(this, desc);
-
- dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_FROM_DEVICE);
- if (!direct)
- memcpy(buf, this->data_buffer_dma, len);
-
- return ret;
-}
-
-int gpmi_send_page(struct gpmi_nand_data *this,
- dma_addr_t payload, dma_addr_t auxiliary)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- uint32_t command_mode;
- uint32_t address;
- uint32_t ecc_command;
- uint32_t buffer_mask;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- u32 pio[6];
-
- /* A DMA descriptor that does an ECC page read. */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
- ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE;
- buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
- BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(0);
- pio[1] = 0;
- pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
- | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
- | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
- pio[3] = geo->page_size;
- pio[4] = payload;
- pio[5] = auxiliary;
-
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE,
- DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- return start_dma_with_bch_irq(this, desc);
-}
-
-int gpmi_read_page(struct gpmi_nand_data *this,
- dma_addr_t payload, dma_addr_t auxiliary)
-{
- struct bch_geometry *geo = &this->bch_geometry;
- uint32_t command_mode;
- uint32_t address;
- uint32_t ecc_command;
- uint32_t buffer_mask;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *channel = get_dma_chan(this);
- int chip = this->current_chip;
- u32 pio[6];
-
- /* [1] Wait for the chip to report ready. */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(0);
- pio[1] = 0;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio, 2,
- DMA_TRANS_NONE, 0);
- if (!desc)
- return -EINVAL;
-
- /* [2] Enable the BCH block and read. */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
- ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE;
- buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
- | BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
-
- pio[1] = 0;
- pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
- | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
- | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
- pio[3] = geo->page_size;
- pio[4] = payload;
- pio[5] = auxiliary;
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_TRANS_NONE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [3] Disable the BCH block */
- command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
- address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
-
- pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
- | BM_GPMI_CTRL0_WORD_LENGTH
- | BF_GPMI_CTRL0_CS(chip, this)
- | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
- | BF_GPMI_CTRL0_ADDRESS(address)
- | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
- pio[1] = 0;
- pio[2] = 0; /* clear GPMI_HW_GPMI_ECCCTRL, disable the BCH. */
- desc = dmaengine_prep_slave_sg(channel,
- (struct scatterlist *)pio, 3,
- DMA_TRANS_NONE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EINVAL;
-
- /* [4] submit the DMA */
- return start_dma_with_bch_irq(this, desc);
-}
-
-/**
- * gpmi_copy_bits - copy bits from one memory region to another
- * @dst: destination buffer
- * @dst_bit_off: bit offset we're starting to write at
- * @src: source buffer
- * @src_bit_off: bit offset we're starting to read from
- * @nbits: number of bits to copy
- *
- * This functions copies bits from one memory region to another, and is used by
- * the GPMI driver to copy ECC sections which are not guaranteed to be byte
- * aligned.
- *
- * src and dst should not overlap.
- *
- */
-void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
- const u8 *src, size_t src_bit_off,
- size_t nbits)
-{
- size_t i;
- size_t nbytes;
- u32 src_buffer = 0;
- size_t bits_in_src_buffer = 0;
-
- if (!nbits)
- return;
-
- /*
- * Move src and dst pointers to the closest byte pointer and store bit
- * offsets within a byte.
- */
- src += src_bit_off / 8;
- src_bit_off %= 8;
-
- dst += dst_bit_off / 8;
- dst_bit_off %= 8;
-
- /*
- * Initialize the src_buffer value with bits available in the first
- * byte of data so that we end up with a byte aligned src pointer.
- */
- if (src_bit_off) {
- src_buffer = src[0] >> src_bit_off;
- if (nbits >= (8 - src_bit_off)) {
- bits_in_src_buffer += 8 - src_bit_off;
- } else {
- src_buffer &= GENMASK(nbits - 1, 0);
- bits_in_src_buffer += nbits;
- }
- nbits -= bits_in_src_buffer;
- src++;
- }
-
- /* Calculate the number of bytes that can be copied from src to dst. */
- nbytes = nbits / 8;
-
- /* Try to align dst to a byte boundary. */
- if (dst_bit_off) {
- if (bits_in_src_buffer < (8 - dst_bit_off) && nbytes) {
- src_buffer |= src[0] << bits_in_src_buffer;
- bits_in_src_buffer += 8;
- src++;
- nbytes--;
- }
-
- if (bits_in_src_buffer >= (8 - dst_bit_off)) {
- dst[0] &= GENMASK(dst_bit_off - 1, 0);
- dst[0] |= src_buffer << dst_bit_off;
- src_buffer >>= (8 - dst_bit_off);
- bits_in_src_buffer -= (8 - dst_bit_off);
- dst_bit_off = 0;
- dst++;
- if (bits_in_src_buffer > 7) {
- bits_in_src_buffer -= 8;
- dst[0] = src_buffer;
- dst++;
- src_buffer >>= 8;
- }
- }
- }
-
- if (!bits_in_src_buffer && !dst_bit_off) {
- /*
- * Both src and dst pointers are byte aligned, thus we can
- * just use the optimized memcpy function.
- */
- if (nbytes)
- memcpy(dst, src, nbytes);
- } else {
- /*
- * src buffer is not byte aligned, hence we have to copy each
- * src byte to the src_buffer variable before extracting a byte
- * to store in dst.
- */
- for (i = 0; i < nbytes; i++) {
- src_buffer |= src[i] << bits_in_src_buffer;
- dst[i] = src_buffer;
- src_buffer >>= 8;
- }
- }
- /* Update dst and src pointers */
- dst += nbytes;
- src += nbytes;
-
- /*
- * nbits is the number of remaining bits. It should not exceed 8 as
- * we've already copied as much bytes as possible.
- */
- nbits %= 8;
-
- /*
- * If there's no more bits to copy to the destination and src buffer
- * was already byte aligned, then we're done.
- */
- if (!nbits && !bits_in_src_buffer)
- return;
-
- /* Copy the remaining bits to src_buffer */
- if (nbits)
- src_buffer |= (*src & GENMASK(nbits - 1, 0)) <<
- bits_in_src_buffer;
- bits_in_src_buffer += nbits;
-
- /*
- * In case there were not enough bits to get a byte aligned dst buffer
- * prepare the src_buffer variable to match the dst organization (shift
- * src_buffer by dst_bit_off and retrieve the least significant bits
- * from dst).
- */
- if (dst_bit_off)
- src_buffer = (src_buffer << dst_bit_off) |
- (*dst & GENMASK(dst_bit_off - 1, 0));
- bits_in_src_buffer += dst_bit_off;
-
- /*
- * Keep most significant bits from dst if we end up with an unaligned
- * number of bits.
- */
- nbytes = bits_in_src_buffer / 8;
- if (bits_in_src_buffer % 8) {
- src_buffer |= (dst[nbytes] &
- GENMASK(7, bits_in_src_buffer % 8)) <<
- (nbytes * 8);
- nbytes++;
- }
-
- /* Copy the remaining bytes to dst */
- for (i = 0; i < nbytes; i++) {
- dst[i] = src_buffer;
- src_buffer >>= 8;
- }
-}
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 40df20d1adf5..334fe3130285 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -6,6 +6,7 @@
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/sched/task_stack.h>
#include <linux/interrupt.h>
@@ -13,7 +14,10 @@
#include <linux/mtd/partitions.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma/mxs-dma.h>
#include "gpmi-nand.h"
+#include "gpmi-regs.h"
#include "bch-regs.h"
/* Resource names for the GPMI NAND driver. */
@@ -21,149 +25,208 @@
#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch"
#define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch"
-/* add our owner bbt descriptor */
-static uint8_t scan_ff_pattern[] = { 0xff };
-static struct nand_bbt_descr gpmi_bbt_descr = {
- .options = 0,
- .offs = 0,
- .len = 1,
- .pattern = scan_ff_pattern
-};
+/* Converts time to clock cycles */
+#define TO_CYCLES(duration, period) DIV_ROUND_UP_ULL(duration, period)
+#define MXS_SET_ADDR 0x4
+#define MXS_CLR_ADDR 0x8
/*
- * We may change the layout if we can get the ECC info from the datasheet,
- * else we will use all the (page + OOB).
+ * Clear the bit and poll it cleared. This is usually called with
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
+ * (bit 30).
*/
-static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
+static int clear_poll_bit(void __iomem *addr, u32 mask)
{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *geo = &this->bch_geometry;
+ int timeout = 0x400;
- if (section)
- return -ERANGE;
+ /* clear the bit */
+ writel(mask, addr + MXS_CLR_ADDR);
- oobregion->offset = 0;
- oobregion->length = geo->page_size - mtd->writesize;
+ /*
+ * SFTRST needs 3 GPMI clocks to settle, the reference manual
+ * recommends to wait 1us.
+ */
+ udelay(1);
- return 0;
+ /* poll the bit becoming clear */
+ while ((readl(addr) & mask) && --timeout)
+ /* nothing */;
+
+ return !timeout;
}
-static int gpmi_ooblayout_free(struct mtd_info *mtd, int section,
- struct mtd_oob_region *oobregion)
+#define MODULE_CLKGATE (1 << 30)
+#define MODULE_SFTRST (1 << 31)
+/*
+ * The current mxs_reset_block() will do two things:
+ * [1] enable the module.
+ * [2] reset the module.
+ *
+ * In most of the cases, it's ok.
+ * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
+ * If you try to soft reset the BCH block, it becomes unusable until
+ * the next hard reset. This case occurs in the NAND boot mode. When the board
+ * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
+ * So If the driver tries to reset the BCH again, the BCH will not work anymore.
+ * You will see a DMA timeout in this case. The bug has been fixed
+ * in the following chips, such as MX28.
+ *
+ * To avoid this bug, just add a new parameter `just_enable` for
+ * the mxs_reset_block(), and rewrite it here.
+ */
+static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- struct bch_geometry *geo = &this->bch_geometry;
+ int ret;
+ int timeout = 0x400;
+
+ /* clear and poll SFTRST */
+ ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+ if (unlikely(ret))
+ goto error;
+
+ /* clear CLKGATE */
+ writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
+
+ if (!just_enable) {
+ /* set SFTRST to reset the block */
+ writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR);
+ udelay(1);
+
+ /* poll CLKGATE becoming set */
+ while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout)
+ /* nothing */;
+ if (unlikely(!timeout))
+ goto error;
+ }
- if (section)
- return -ERANGE;
+ /* clear and poll SFTRST */
+ ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+ if (unlikely(ret))
+ goto error;
- /* The available oob size we have. */
- if (geo->page_size < mtd->writesize + mtd->oobsize) {
- oobregion->offset = geo->page_size - mtd->writesize;
- oobregion->length = mtd->oobsize - oobregion->offset;
- }
+ /* clear and poll CLKGATE */
+ ret = clear_poll_bit(reset_addr, MODULE_CLKGATE);
+ if (unlikely(ret))
+ goto error;
return 0;
+
+error:
+ pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
+ return -ETIMEDOUT;
}
-static const char * const gpmi_clks_for_mx2x[] = {
- "gpmi_io",
-};
+static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
+{
+ struct clk *clk;
+ int ret;
+ int i;
-static const struct mtd_ooblayout_ops gpmi_ooblayout_ops = {
- .ecc = gpmi_ooblayout_ecc,
- .free = gpmi_ooblayout_free,
-};
+ for (i = 0; i < GPMI_CLK_MAX; i++) {
+ clk = this->resources.clock[i];
+ if (!clk)
+ break;
-static const struct gpmi_devdata gpmi_devdata_imx23 = {
- .type = IS_MX23,
- .bch_max_ecc_strength = 20,
- .max_chain_delay = 16000,
- .clks = gpmi_clks_for_mx2x,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx2x),
-};
+ if (v) {
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ goto err_clk;
+ } else {
+ clk_disable_unprepare(clk);
+ }
+ }
+ return 0;
-static const struct gpmi_devdata gpmi_devdata_imx28 = {
- .type = IS_MX28,
- .bch_max_ecc_strength = 20,
- .max_chain_delay = 16000,
- .clks = gpmi_clks_for_mx2x,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx2x),
-};
+err_clk:
+ for (; i > 0; i--)
+ clk_disable_unprepare(this->resources.clock[i - 1]);
+ return ret;
+}
-static const char * const gpmi_clks_for_mx6[] = {
- "gpmi_io", "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
-};
+static int gpmi_init(struct gpmi_nand_data *this)
+{
+ struct resources *r = &this->resources;
+ int ret;
-static const struct gpmi_devdata gpmi_devdata_imx6q = {
- .type = IS_MX6Q,
- .bch_max_ecc_strength = 40,
- .max_chain_delay = 12000,
- .clks = gpmi_clks_for_mx6,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
-};
+ ret = gpmi_reset_block(r->gpmi_regs, false);
+ if (ret)
+ goto err_out;
-static const struct gpmi_devdata gpmi_devdata_imx6sx = {
- .type = IS_MX6SX,
- .bch_max_ecc_strength = 62,
- .max_chain_delay = 12000,
- .clks = gpmi_clks_for_mx6,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
-};
+ /*
+ * Reset BCH here, too. We got failures otherwise :(
+ * See later BCH reset for explanation of MX23 and MX28 handling
+ */
+ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this));
+ if (ret)
+ goto err_out;
-static const char * const gpmi_clks_for_mx7d[] = {
- "gpmi_io", "gpmi_bch_apb",
-};
+ /* Choose NAND mode. */
+ writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR);
-static const struct gpmi_devdata gpmi_devdata_imx7d = {
- .type = IS_MX7D,
- .bch_max_ecc_strength = 62,
- .max_chain_delay = 12000,
- .clks = gpmi_clks_for_mx7d,
- .clks_count = ARRAY_SIZE(gpmi_clks_for_mx7d),
-};
+ /* Set the IRQ polarity. */
+ writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
+ r->gpmi_regs + HW_GPMI_CTRL1_SET);
-static irqreturn_t bch_irq(int irq, void *cookie)
-{
- struct gpmi_nand_data *this = cookie;
+ /* Disable Write-Protection. */
+ writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET);
- gpmi_clear_bch(this);
- complete(&this->bch_done);
- return IRQ_HANDLED;
+ /* Select BCH ECC. */
+ writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+ /*
+ * Decouple the chip select from dma channel. We use dma0 for all
+ * the chips.
+ */
+ writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+ return 0;
+err_out:
+ return ret;
}
-/*
- * Calculate the ECC strength by hand:
- * E : The ECC strength.
- * G : the length of Galois Field.
- * N : The chunk count of per page.
- * O : the oobsize of the NAND chip.
- * M : the metasize of per page.
- *
- * The formula is :
- * E * G * N
- * ------------ <= (O - M)
- * 8
- *
- * So, we get E by:
- * (O - M) * 8
- * E <= -------------
- * G * N
- */
-static inline int get_ecc_strength(struct gpmi_nand_data *this)
+/* This function is very useful. It is called only when the bug occur. */
+static void gpmi_dump_info(struct gpmi_nand_data *this)
{
+ struct resources *r = &this->resources;
struct bch_geometry *geo = &this->bch_geometry;
- struct mtd_info *mtd = nand_to_mtd(&this->nand);
- int ecc_strength;
+ u32 reg;
+ int i;
- ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
- / (geo->gf_len * geo->ecc_chunk_count);
+ dev_err(this->dev, "Show GPMI registers :\n");
+ for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
+ reg = readl(r->gpmi_regs + i * 0x10);
+ dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+ }
- /* We need the minor even number. */
- return round_down(ecc_strength, 2);
+ /* start to print out the BCH info */
+ dev_err(this->dev, "Show BCH registers :\n");
+ for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
+ reg = readl(r->bch_regs + i * 0x10);
+ dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+ }
+ dev_err(this->dev, "BCH Geometry :\n"
+ "GF length : %u\n"
+ "ECC Strength : %u\n"
+ "Page Size in Bytes : %u\n"
+ "Metadata Size in Bytes : %u\n"
+ "ECC Chunk Size in Bytes: %u\n"
+ "ECC Chunk Count : %u\n"
+ "Payload Size in Bytes : %u\n"
+ "Auxiliary Size in Bytes: %u\n"
+ "Auxiliary Status Offset: %u\n"
+ "Block Mark Byte Offset : %u\n"
+ "Block Mark Bit Offset : %u\n",
+ geo->gf_len,
+ geo->ecc_strength,
+ geo->page_size,
+ geo->metadata_size,
+ geo->ecc_chunk_size,
+ geo->ecc_chunk_count,
+ geo->payload_size,
+ geo->auxiliary_size,
+ geo->auxiliary_status_offset,
+ geo->block_mark_byte_offset,
+ geo->block_mark_bit_offset);
}
static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
@@ -296,6 +359,37 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
return 0;
}
+/*
+ * Calculate the ECC strength by hand:
+ * E : The ECC strength.
+ * G : the length of Galois Field.
+ * N : The chunk count of per page.
+ * O : the oobsize of the NAND chip.
+ * M : the metasize of per page.
+ *
+ * The formula is :
+ * E * G * N
+ * ------------ <= (O - M)
+ * 8
+ *
+ * So, we get E by:
+ * (O - M) * 8
+ * E <= -------------
+ * G * N
+ */
+static inline int get_ecc_strength(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = nand_to_mtd(&this->nand);
+ int ecc_strength;
+
+ ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
+ / (geo->gf_len * geo->ecc_chunk_count);
+
+ /* We need the minor even number. */
+ return round_down(ecc_strength, 2);
+}
+
static int legacy_set_geometry(struct gpmi_nand_data *this)
{
struct bch_geometry *geo = &this->bch_geometry;
@@ -408,7 +502,7 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
return 0;
}
-int common_nfc_set_geometry(struct gpmi_nand_data *this)
+static int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
struct nand_chip *chip = &this->nand;
@@ -430,18 +524,288 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
return 0;
}
-struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
+/* Configures the geometry for BCH. */
+static int bch_set_geometry(struct gpmi_nand_data *this)
+{
+ struct resources *r = &this->resources;
+ int ret;
+
+ ret = common_nfc_set_geometry(this);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_get_sync(this->dev);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
+ * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
+ * and MX28.
+ */
+ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this));
+ if (ret)
+ goto err_out;
+
+ /* Set *all* chip selects to use layout 0. */
+ writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
+
+ ret = 0;
+err_out:
+ pm_runtime_mark_last_busy(this->dev);
+ pm_runtime_put_autosuspend(this->dev);
+
+ return ret;
+}
+
+/*
+ * <1> Firstly, we should know what's the GPMI-clock means.
+ * The GPMI-clock is the internal clock in the gpmi nand controller.
+ * If you set 100MHz to gpmi nand controller, the GPMI-clock's period
+ * is 10ns. Mark the GPMI-clock's period as GPMI-clock-period.
+ *
+ * <2> Secondly, we should know what's the frequency on the nand chip pins.
+ * The frequency on the nand chip pins is derived from the GPMI-clock.
+ * We can get it from the following equation:
+ *
+ * F = G / (DS + DH)
+ *
+ * F : the frequency on the nand chip pins.
+ * G : the GPMI clock, such as 100MHz.
+ * DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP
+ * DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD
+ *
+ * <3> Thirdly, when the frequency on the nand chip pins is above 33MHz,
+ * the nand EDO(extended Data Out) timing could be applied.
+ * The GPMI implements a feedback read strobe to sample the read data.
+ * The feedback read strobe can be delayed to support the nand EDO timing
+ * where the read strobe may deasserts before the read data is valid, and
+ * read data is valid for some time after read strobe.
+ *
+ * The following figure illustrates some aspects of a NAND Flash read:
+ *
+ * |<---tREA---->|
+ * | |
+ * | | |
+ * |<--tRP-->| |
+ * | | |
+ * __ ___|__________________________________
+ * RDN \________/ |
+ * |
+ * /---------\
+ * Read Data --------------< >---------
+ * \---------/
+ * | |
+ * |<-D->|
+ * FeedbackRDN ________ ____________
+ * \___________/
+ *
+ * D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY.
+ *
+ *
+ * <4> Now, we begin to describe how to compute the right RDN_DELAY.
+ *
+ * 4.1) From the aspect of the nand chip pins:
+ * Delay = (tREA + C - tRP) {1}
+ *
+ * tREA : the maximum read access time.
+ * C : a constant to adjust the delay. default is 4000ps.
+ * tRP : the read pulse width, which is exactly:
+ * tRP = (GPMI-clock-period) * DATA_SETUP
+ *
+ * 4.2) From the aspect of the GPMI nand controller:
+ * Delay = RDN_DELAY * 0.125 * RP {2}
+ *
+ * RP : the DLL reference period.
+ * if (GPMI-clock-period > DLL_THRETHOLD)
+ * RP = GPMI-clock-period / 2;
+ * else
+ * RP = GPMI-clock-period;
+ *
+ * Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period
+ * is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD
+ * is 16000ps, but in mx6q, we use 12000ps.
+ *
+ * 4.3) since {1} equals {2}, we get:
+ *
+ * (tREA + 4000 - tRP) * 8
+ * RDN_DELAY = ----------------------- {3}
+ * RP
+ */
+static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
+ const struct nand_sdr_timings *sdr)
+{
+ struct gpmi_nfc_hardware_timing *hw = &this->hw;
+ unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
+ unsigned int period_ps, reference_period_ps;
+ unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
+ unsigned int tRP_ps;
+ bool use_half_period;
+ int sample_delay_ps, sample_delay_factor;
+ u16 busy_timeout_cycles;
+ u8 wrn_dly_sel;
+
+ if (sdr->tRC_min >= 30000) {
+ /* ONFI non-EDO modes [0-3] */
+ hw->clk_rate = 22000000;
+ wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
+ } else if (sdr->tRC_min >= 25000) {
+ /* ONFI EDO mode 4 */
+ hw->clk_rate = 80000000;
+ wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
+ } else {
+ /* ONFI EDO mode 5 */
+ hw->clk_rate = 100000000;
+ wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
+ }
+
+ /* SDR core timings are given in picoseconds */
+ period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
+
+ addr_setup_cycles = TO_CYCLES(sdr->tALS_min, period_ps);
+ data_setup_cycles = TO_CYCLES(sdr->tDS_min, period_ps);
+ data_hold_cycles = TO_CYCLES(sdr->tDH_min, period_ps);
+ busy_timeout_cycles = TO_CYCLES(sdr->tWB_max + sdr->tR_max, period_ps);
+
+ hw->timing0 = BF_GPMI_TIMING0_ADDRESS_SETUP(addr_setup_cycles) |
+ BF_GPMI_TIMING0_DATA_HOLD(data_hold_cycles) |
+ BF_GPMI_TIMING0_DATA_SETUP(data_setup_cycles);
+ hw->timing1 = BF_GPMI_TIMING1_BUSY_TIMEOUT(busy_timeout_cycles * 4096);
+
+ /*
+ * Derive NFC ideal delay from {3}:
+ *
+ * (tREA + 4000 - tRP) * 8
+ * RDN_DELAY = -----------------------
+ * RP
+ */
+ if (period_ps > dll_threshold_ps) {
+ use_half_period = true;
+ reference_period_ps = period_ps / 2;
+ } else {
+ use_half_period = false;
+ reference_period_ps = period_ps;
+ }
+
+ tRP_ps = data_setup_cycles * period_ps;
+ sample_delay_ps = (sdr->tREA_max + 4000 - tRP_ps) * 8;
+ if (sample_delay_ps > 0)
+ sample_delay_factor = sample_delay_ps / reference_period_ps;
+ else
+ sample_delay_factor = 0;
+
+ hw->ctrl1n = BF_GPMI_CTRL1_WRN_DLY_SEL(wrn_dly_sel);
+ if (sample_delay_factor)
+ hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
+ BM_GPMI_CTRL1_DLL_ENABLE |
+ (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
+}
+
+static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
+{
+ struct gpmi_nfc_hardware_timing *hw = &this->hw;
+ struct resources *r = &this->resources;
+ void __iomem *gpmi_regs = r->gpmi_regs;
+ unsigned int dll_wait_time_us;
+
+ clk_set_rate(r->clock[0], hw->clk_rate);
+
+ writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
+ writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
+
+ /*
+ * Clear several CTRL1 fields, DLL must be disabled when setting
+ * RDN_DELAY or HALF_PERIOD.
+ */
+ writel(BM_GPMI_CTRL1_CLEAR_MASK, gpmi_regs + HW_GPMI_CTRL1_CLR);
+ writel(hw->ctrl1n, gpmi_regs + HW_GPMI_CTRL1_SET);
+
+ /* Wait 64 clock cycles before using the GPMI after enabling the DLL */
+ dll_wait_time_us = USEC_PER_SEC / hw->clk_rate * 64;
+ if (!dll_wait_time_us)
+ dll_wait_time_us = 1;
+
+ /* Wait for the DLL to settle. */
+ udelay(dll_wait_time_us);
+}
+
+static int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
+ const struct nand_data_interface *conf)
+{
+ struct gpmi_nand_data *this = nand_get_controller_data(chip);
+ const struct nand_sdr_timings *sdr;
+
+ /* Retrieve required NAND timings */
+ sdr = nand_get_sdr_timings(conf);
+ if (IS_ERR(sdr))
+ return PTR_ERR(sdr);
+
+ /* Only MX6 GPMI controller can reach EDO timings */
+ if (sdr->tRC_min <= 25000 && !GPMI_IS_MX6(this))
+ return -ENOTSUPP;
+
+ /* Stop here if this call was just a check */
+ if (chipnr < 0)
+ return 0;
+
+ /* Do the actual derivation of the controller timings */
+ gpmi_nfc_compute_timings(this, sdr);
+
+ this->hw.must_apply_timings = true;
+
+ return 0;
+}
+
+/* Clears a BCH interrupt. */
+static void gpmi_clear_bch(struct gpmi_nand_data *this)
+{
+ struct resources *r = &this->resources;
+ writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
+}
+
+static struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
{
/* We use the DMA channel 0 to access all the nand chips. */
return this->dma_chans[0];
}
+/* This will be called after the DMA operation is finished. */
+static void dma_irq_callback(void *param)
+{
+ struct gpmi_nand_data *this = param;
+ struct completion *dma_c = &this->dma_done;
+
+ complete(dma_c);
+}
+
+static irqreturn_t bch_irq(int irq, void *cookie)
+{
+ struct gpmi_nand_data *this = cookie;
+
+ gpmi_clear_bch(this);
+ complete(&this->bch_done);
+ return IRQ_HANDLED;
+}
+
+static int gpmi_raw_len_to_len(struct gpmi_nand_data *this, int raw_len)
+{
+ /*
+ * raw_len is the length to read/write including bch data which
+ * we are passed in exec_op. Calculate the data length from it.
+ */
+ if (this->bch)
+ return ALIGN_DOWN(raw_len, this->bch_geometry.ecc_chunk_size);
+ else
+ return raw_len;
+}
+
/* Can we use the upper's buffer directly for DMA? */
-bool prepare_data_dma(struct gpmi_nand_data *this, const void *buf, int len,
- enum dma_data_direction dr)
+static bool prepare_data_dma(struct gpmi_nand_data *this, const void *buf,
+ int raw_len, struct scatterlist *sgl,
+ enum dma_data_direction dr)
{
- struct scatterlist *sgl = &this->data_sgl;
int ret;
+ int len = gpmi_raw_len_to_len(this, raw_len);
/* first try to map the upper buffer directly */
if (virt_addr_valid(buf) && !object_is_on_stack(buf)) {
@@ -457,7 +821,7 @@ map_fail:
/* We have to use our own DMA buffer. */
sg_init_one(sgl, this->data_buffer_dma, len);
- if (dr == DMA_TO_DEVICE)
+ if (dr == DMA_TO_DEVICE && buf != this->data_buffer_dma)
memcpy(this->data_buffer_dma, buf, len);
dma_map_sg(this->dev, sgl, 1, dr);
@@ -465,67 +829,263 @@ map_fail:
return false;
}
-/* This will be called after the DMA operation is finished. */
-static void dma_irq_callback(void *param)
+/**
+ * gpmi_copy_bits - copy bits from one memory region to another
+ * @dst: destination buffer
+ * @dst_bit_off: bit offset we're starting to write at
+ * @src: source buffer
+ * @src_bit_off: bit offset we're starting to read from
+ * @nbits: number of bits to copy
+ *
+ * This functions copies bits from one memory region to another, and is used by
+ * the GPMI driver to copy ECC sections which are not guaranteed to be byte
+ * aligned.
+ *
+ * src and dst should not overlap.
+ *
+ */
+static void gpmi_copy_bits(u8 *dst, size_t dst_bit_off, const u8 *src,
+ size_t src_bit_off, size_t nbits)
{
- struct gpmi_nand_data *this = param;
- struct completion *dma_c = &this->dma_done;
+ size_t i;
+ size_t nbytes;
+ u32 src_buffer = 0;
+ size_t bits_in_src_buffer = 0;
- complete(dma_c);
-}
+ if (!nbits)
+ return;
-int start_dma_without_bch_irq(struct gpmi_nand_data *this,
- struct dma_async_tx_descriptor *desc)
-{
- struct completion *dma_c = &this->dma_done;
- unsigned long timeout;
+ /*
+ * Move src and dst pointers to the closest byte pointer and store bit
+ * offsets within a byte.
+ */
+ src += src_bit_off / 8;
+ src_bit_off %= 8;
- init_completion(dma_c);
+ dst += dst_bit_off / 8;
+ dst_bit_off %= 8;
- desc->callback = dma_irq_callback;
- desc->callback_param = this;
- dmaengine_submit(desc);
- dma_async_issue_pending(get_dma_chan(this));
+ /*
+ * Initialize the src_buffer value with bits available in the first
+ * byte of data so that we end up with a byte aligned src pointer.
+ */
+ if (src_bit_off) {
+ src_buffer = src[0] >> src_bit_off;
+ if (nbits >= (8 - src_bit_off)) {
+ bits_in_src_buffer += 8 - src_bit_off;
+ } else {
+ src_buffer &= GENMASK(nbits - 1, 0);
+ bits_in_src_buffer += nbits;
+ }
+ nbits -= bits_in_src_buffer;
+ src++;
+ }
- /* Wait for the interrupt from the DMA block. */
- timeout = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
- if (!timeout) {
- dev_err(this->dev, "DMA timeout, last DMA\n");
- gpmi_dump_info(this);
- return -ETIMEDOUT;
+ /* Calculate the number of bytes that can be copied from src to dst. */
+ nbytes = nbits / 8;
+
+ /* Try to align dst to a byte boundary. */
+ if (dst_bit_off) {
+ if (bits_in_src_buffer < (8 - dst_bit_off) && nbytes) {
+ src_buffer |= src[0] << bits_in_src_buffer;
+ bits_in_src_buffer += 8;
+ src++;
+ nbytes--;
+ }
+
+ if (bits_in_src_buffer >= (8 - dst_bit_off)) {
+ dst[0] &= GENMASK(dst_bit_off - 1, 0);
+ dst[0] |= src_buffer << dst_bit_off;
+ src_buffer >>= (8 - dst_bit_off);
+ bits_in_src_buffer -= (8 - dst_bit_off);
+ dst_bit_off = 0;
+ dst++;
+ if (bits_in_src_buffer > 7) {
+ bits_in_src_buffer -= 8;
+ dst[0] = src_buffer;
+ dst++;
+ src_buffer >>= 8;
+ }
+ }
+ }
+
+ if (!bits_in_src_buffer && !dst_bit_off) {
+ /*
+ * Both src and dst pointers are byte aligned, thus we can
+ * just use the optimized memcpy function.
+ */
+ if (nbytes)
+ memcpy(dst, src, nbytes);
+ } else {
+ /*
+ * src buffer is not byte aligned, hence we have to copy each
+ * src byte to the src_buffer variable before extracting a byte
+ * to store in dst.
+ */
+ for (i = 0; i < nbytes; i++) {
+ src_buffer |= src[i] << bits_in_src_buffer;
+ dst[i] = src_buffer;
+ src_buffer >>= 8;
+ }
+ }
+ /* Update dst and src pointers */
+ dst += nbytes;
+ src += nbytes;
+
+ /*
+ * nbits is the number of remaining bits. It should not exceed 8 as
+ * we've already copied as much bytes as possible.
+ */
+ nbits %= 8;
+
+ /*
+ * If there's no more bits to copy to the destination and src buffer
+ * was already byte aligned, then we're done.
+ */
+ if (!nbits && !bits_in_src_buffer)
+ return;
+
+ /* Copy the remaining bits to src_buffer */
+ if (nbits)
+ src_buffer |= (*src & GENMASK(nbits - 1, 0)) <<
+ bits_in_src_buffer;
+ bits_in_src_buffer += nbits;
+
+ /*
+ * In case there were not enough bits to get a byte aligned dst buffer
+ * prepare the src_buffer variable to match the dst organization (shift
+ * src_buffer by dst_bit_off and retrieve the least significant bits
+ * from dst).
+ */
+ if (dst_bit_off)
+ src_buffer = (src_buffer << dst_bit_off) |
+ (*dst & GENMASK(dst_bit_off - 1, 0));
+ bits_in_src_buffer += dst_bit_off;
+
+ /*
+ * Keep most significant bits from dst if we end up with an unaligned
+ * number of bits.
+ */
+ nbytes = bits_in_src_buffer / 8;
+ if (bits_in_src_buffer % 8) {
+ src_buffer |= (dst[nbytes] &
+ GENMASK(7, bits_in_src_buffer % 8)) <<
+ (nbytes * 8);
+ nbytes++;
+ }
+
+ /* Copy the remaining bytes to dst */
+ for (i = 0; i < nbytes; i++) {
+ dst[i] = src_buffer;
+ src_buffer >>= 8;
}
- return 0;
}
+/* add our owner bbt descriptor */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr gpmi_bbt_descr = {
+ .options = 0,
+ .offs = 0,
+ .len = 1,
+ .pattern = scan_ff_pattern
+};
+
/*
- * This function is used in BCH reading or BCH writing pages.
- * It will wait for the BCH interrupt as long as ONE second.
- * Actually, we must wait for two interrupts :
- * [1] firstly the DMA interrupt and
- * [2] secondly the BCH interrupt.
+ * We may change the layout if we can get the ECC info from the datasheet,
+ * else we will use all the (page + OOB).
*/
-int start_dma_with_bch_irq(struct gpmi_nand_data *this,
- struct dma_async_tx_descriptor *desc)
+static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
{
- struct completion *bch_c = &this->bch_done;
- unsigned long timeout;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct gpmi_nand_data *this = nand_get_controller_data(chip);
+ struct bch_geometry *geo = &this->bch_geometry;
- /* Prepare to receive an interrupt from the BCH block. */
- init_completion(bch_c);
+ if (section)
+ return -ERANGE;
- /* start the DMA */
- start_dma_without_bch_irq(this, desc);
+ oobregion->offset = 0;
+ oobregion->length = geo->page_size - mtd->writesize;
- /* Wait for the interrupt from the BCH block. */
- timeout = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
- if (!timeout) {
- dev_err(this->dev, "BCH timeout\n");
- gpmi_dump_info(this);
- return -ETIMEDOUT;
+ return 0;
+}
+
+static int gpmi_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct gpmi_nand_data *this = nand_get_controller_data(chip);
+ struct bch_geometry *geo = &this->bch_geometry;
+
+ if (section)
+ return -ERANGE;
+
+ /* The available oob size we have. */
+ if (geo->page_size < mtd->writesize + mtd->oobsize) {
+ oobregion->offset = geo->page_size - mtd->writesize;
+ oobregion->length = mtd->oobsize - oobregion->offset;
}
+
return 0;
}
+static const char * const gpmi_clks_for_mx2x[] = {
+ "gpmi_io",
+};
+
+static const struct mtd_ooblayout_ops gpmi_ooblayout_ops = {
+ .ecc = gpmi_ooblayout_ecc,
+ .free = gpmi_ooblayout_free,
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx23 = {
+ .type = IS_MX23,
+ .bch_max_ecc_strength = 20,
+ .max_chain_delay = 16000,
+ .clks = gpmi_clks_for_mx2x,
+ .clks_count = ARRAY_SIZE(gpmi_clks_for_mx2x),
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx28 = {
+ .type = IS_MX28,
+ .bch_max_ecc_strength = 20,
+ .max_chain_delay = 16000,
+ .clks = gpmi_clks_for_mx2x,
+ .clks_count = ARRAY_SIZE(gpmi_clks_for_mx2x),
+};
+
+static const char * const gpmi_clks_for_mx6[] = {
+ "gpmi_io", "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx6q = {
+ .type = IS_MX6Q,
+ .bch_max_ecc_strength = 40,
+ .max_chain_delay = 12000,
+ .clks = gpmi_clks_for_mx6,
+ .clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx6sx = {
+ .type = IS_MX6SX,
+ .bch_max_ecc_strength = 62,
+ .max_chain_delay = 12000,
+ .clks = gpmi_clks_for_mx6,
+ .clks_count = ARRAY_SIZE(gpmi_clks_for_mx6),
+};
+
+static const char * const gpmi_clks_for_mx7d[] = {
+ "gpmi_io", "gpmi_bch_apb",
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx7d = {
+ .type = IS_MX7D,
+ .bch_max_ecc_strength = 62,
+ .max_chain_delay = 12000,
+ .clks = gpmi_clks_for_mx7d,
+ .clks_count = ARRAY_SIZE(gpmi_clks_for_mx7d),
+};
+
static int acquire_register_block(struct gpmi_nand_data *this,
const char *res_name)
{
@@ -667,68 +1227,20 @@ static void release_resources(struct gpmi_nand_data *this)
release_dma_channels(this);
}
-static int send_page_prepare(struct gpmi_nand_data *this,
- const void *source, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- const void **use_virt, dma_addr_t *use_phys)
-{
- struct device *dev = this->dev;
-
- if (virt_addr_valid(source)) {
- dma_addr_t source_phys;
-
- source_phys = dma_map_single(dev, (void *)source, length,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, source_phys)) {
- if (alt_size < length) {
- dev_err(dev, "Alternate buffer is too small\n");
- return -ENOMEM;
- }
- goto map_failed;
- }
- *use_virt = source;
- *use_phys = source_phys;
- return 0;
- }
-map_failed:
- /*
- * Copy the content of the source buffer into the alternate
- * buffer and set up the return values accordingly.
- */
- memcpy(alt_virt, source, length);
-
- *use_virt = alt_virt;
- *use_phys = alt_phys;
- return 0;
-}
-
-static void send_page_end(struct gpmi_nand_data *this,
- const void *source, unsigned length,
- void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
- const void *used_virt, dma_addr_t used_phys)
-{
- struct device *dev = this->dev;
- if (used_virt == source)
- dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE);
-}
-
static void gpmi_free_dma_buffer(struct gpmi_nand_data *this)
{
struct device *dev = this->dev;
+ struct bch_geometry *geo = &this->bch_geometry;
- if (this->page_buffer_virt && virt_addr_valid(this->page_buffer_virt))
- dma_free_coherent(dev, this->page_buffer_size,
- this->page_buffer_virt,
- this->page_buffer_phys);
- kfree(this->cmd_buffer);
+ if (this->auxiliary_virt && virt_addr_valid(this->auxiliary_virt))
+ dma_free_coherent(dev, geo->auxiliary_size,
+ this->auxiliary_virt,
+ this->auxiliary_phys);
kfree(this->data_buffer_dma);
kfree(this->raw_buffer);
- this->cmd_buffer = NULL;
this->data_buffer_dma = NULL;
this->raw_buffer = NULL;
- this->page_buffer_virt = NULL;
- this->page_buffer_size = 0;
}
/* Allocate the DMA buffers */
@@ -738,11 +1250,6 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
struct device *dev = this->dev;
struct mtd_info *mtd = nand_to_mtd(&this->nand);
- /* [1] Allocate a command buffer. PAGE_SIZE is enough. */
- this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
- if (this->cmd_buffer == NULL)
- goto error_alloc;
-
/*
* [2] Allocate a read/write data buffer.
* The gpmi_alloc_dma_buffer can be called twice.
@@ -756,29 +1263,15 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
if (this->data_buffer_dma == NULL)
goto error_alloc;
- /*
- * [3] Allocate the page buffer.
- *
- * Both the payload buffer and the auxiliary buffer must appear on
- * 32-bit boundaries. We presume the size of the payload buffer is a
- * power of two and is much larger than four, which guarantees the
- * auxiliary buffer will appear on a 32-bit boundary.
- */
- this->page_buffer_size = geo->payload_size + geo->auxiliary_size;
- this->page_buffer_virt = dma_alloc_coherent(dev, this->page_buffer_size,
- &this->page_buffer_phys, GFP_DMA);
- if (!this->page_buffer_virt)
+ this->auxiliary_virt = dma_alloc_coherent(dev, geo->auxiliary_size,
+ &this->auxiliary_phys, GFP_DMA);
+ if (!this->auxiliary_virt)
goto error_alloc;
- this->raw_buffer = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
+ this->raw_buffer = kzalloc((mtd->writesize ?: PAGE_SIZE) + mtd->oobsize, GFP_KERNEL);
if (!this->raw_buffer)
goto error_alloc;
- /* Slice up the page buffer. */
- this->payload_virt = this->page_buffer_virt;
- this->payload_phys = this->page_buffer_phys;
- this->auxiliary_virt = this->payload_virt + geo->payload_size;
- this->auxiliary_phys = this->payload_phys + geo->payload_size;
return 0;
error_alloc:
@@ -786,106 +1279,6 @@ error_alloc:
return -ENOMEM;
}
-static void gpmi_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctrl)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- int ret;
-
- /*
- * Every operation begins with a command byte and a series of zero or
- * more address bytes. These are distinguished by either the Address
- * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
- * asserted. When MTD is ready to execute the command, it will deassert
- * both latch enables.
- *
- * Rather than run a separate DMA operation for every single byte, we
- * queue them up and run a single DMA operation for the entire series
- * of command and data bytes. NAND_CMD_NONE means the END of the queue.
- */
- if ((ctrl & (NAND_ALE | NAND_CLE))) {
- if (data != NAND_CMD_NONE)
- this->cmd_buffer[this->command_length++] = data;
- return;
- }
-
- if (!this->command_length)
- return;
-
- ret = gpmi_send_command(this);
- if (ret)
- dev_err(this->dev, "Chip: %u, Error %d\n",
- this->current_chip, ret);
-
- this->command_length = 0;
-}
-
-static int gpmi_dev_ready(struct nand_chip *chip)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- return gpmi_is_ready(this, this->current_chip);
-}
-
-static void gpmi_select_chip(struct nand_chip *chip, int chipnr)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- int ret;
-
- /*
- * For power consumption matters, disable/enable the clock each time a
- * die is selected/unselected.
- */
- if (this->current_chip < 0 && chipnr >= 0) {
- ret = gpmi_enable_clk(this);
- if (ret)
- dev_err(this->dev, "Failed to enable the clock\n");
- } else if (this->current_chip >= 0 && chipnr < 0) {
- ret = gpmi_disable_clk(this);
- if (ret)
- dev_err(this->dev, "Failed to disable the clock\n");
- }
-
- /*
- * This driver currently supports only one NAND chip. Plus, dies share
- * the same configuration. So once timings have been applied on the
- * controller side, they will not change anymore. When the time will
- * come, the check on must_apply_timings will have to be dropped.
- */
- if (chipnr >= 0 && this->hw.must_apply_timings) {
- this->hw.must_apply_timings = false;
- gpmi_nfc_apply_timings(this);
- }
-
- this->current_chip = chipnr;
-}
-
-static void gpmi_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- dev_dbg(this->dev, "len is %d\n", len);
-
- gpmi_read_data(this, buf, len);
-}
-
-static void gpmi_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
-
- dev_dbg(this->dev, "len is %d\n", len);
-
- gpmi_send_data(this, buf, len);
-}
-
-static uint8_t gpmi_read_byte(struct nand_chip *chip)
-{
- struct gpmi_nand_data *this = nand_get_controller_data(chip);
- uint8_t *buf = this->data_buffer_dma;
-
- gpmi_read_buf(chip, buf, 1);
- return buf[0];
-}
-
/*
* Handles block mark swapping.
* It can be called in swapping the block mark, or swapping it back,
@@ -934,54 +1327,20 @@ static void block_mark_swapping(struct gpmi_nand_data *this,
p[1] = (p[1] & mask) | (from_oob >> (8 - bit));
}
-static int gpmi_ecc_read_page_data(struct nand_chip *chip,
- uint8_t *buf, int oob_required,
- int page)
+static int gpmi_count_bitflips(struct nand_chip *chip, void *buf, int first,
+ int last, int meta)
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
struct mtd_info *mtd = nand_to_mtd(chip);
- dma_addr_t payload_phys;
- unsigned int i;
+ int i;
unsigned char *status;
- unsigned int max_bitflips = 0;
- int ret;
- bool direct = false;
-
- dev_dbg(this->dev, "page number is : %d\n", page);
-
- payload_phys = this->payload_phys;
-
- if (virt_addr_valid(buf)) {
- dma_addr_t dest_phys;
-
- dest_phys = dma_map_single(this->dev, buf, nfc_geo->payload_size,
- DMA_FROM_DEVICE);
- if (!dma_mapping_error(this->dev, dest_phys)) {
- payload_phys = dest_phys;
- direct = true;
- }
- }
-
- /* go! */
- ret = gpmi_read_page(this, payload_phys, this->auxiliary_phys);
-
- if (direct)
- dma_unmap_single(this->dev, payload_phys, nfc_geo->payload_size,
- DMA_FROM_DEVICE);
-
- if (ret) {
- dev_err(this->dev, "Error in ECC-based read: %d\n", ret);
- return ret;
- }
+ unsigned int max_bitflips = 0;
/* Loop over status bytes, accumulating ECC status. */
- status = this->auxiliary_virt + nfc_geo->auxiliary_status_offset;
-
- if (!direct)
- memcpy(buf, this->payload_virt, nfc_geo->payload_size);
+ status = this->auxiliary_virt + ALIGN(meta, 4);
- for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
+ for (i = first; i < last; i++, status++) {
if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
continue;
@@ -1061,6 +1420,50 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
max_bitflips = max_t(unsigned int, max_bitflips, *status);
}
+ return max_bitflips;
+}
+
+static void gpmi_bch_layout_std(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ unsigned int ecc_strength = geo->ecc_strength >> 1;
+ unsigned int gf_len = geo->gf_len;
+ unsigned int block_size = geo->ecc_chunk_size;
+
+ this->bch_flashlayout0 =
+ BF_BCH_FLASH0LAYOUT0_NBLOCKS(geo->ecc_chunk_count - 1) |
+ BF_BCH_FLASH0LAYOUT0_META_SIZE(geo->metadata_size) |
+ BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this) |
+ BF_BCH_FLASH0LAYOUT0_GF(gf_len, this) |
+ BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this);
+
+ this->bch_flashlayout1 =
+ BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(geo->page_size) |
+ BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this) |
+ BF_BCH_FLASH0LAYOUT1_GF(gf_len, this) |
+ BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this);
+}
+
+static int gpmi_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
+{
+ struct gpmi_nand_data *this = nand_get_controller_data(chip);
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct bch_geometry *geo = &this->bch_geometry;
+ unsigned int max_bitflips;
+ int ret;
+
+ gpmi_bch_layout_std(this);
+ this->bch = true;
+
+ ret = nand_read_page_op(chip, page, 0, buf, geo->page_size);
+ if (ret)
+ return ret;
+
+ max_bitflips = gpmi_count_bitflips(chip, buf, 0,
+ geo->ecc_chunk_count,
+ geo->auxiliary_status_offset);
+
/* handle the block mark swapping */
block_mark_swapping(this, buf, this->auxiliary_virt);
@@ -1082,30 +1485,20 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
return max_bitflips;
}
-static int gpmi_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
- int oob_required, int page)
-{
- nand_read_page_op(chip, page, 0, NULL, 0);
-
- return gpmi_ecc_read_page_data(chip, buf, oob_required, page);
-}
-
/* Fake a virtual small page for the subpage read */
static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs,
uint32_t len, uint8_t *buf, int page)
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
- void __iomem *bch_regs = this->resources.bch_regs;
- struct bch_geometry old_geo = this->bch_geometry;
struct bch_geometry *geo = &this->bch_geometry;
int size = chip->ecc.size; /* ECC chunk size */
int meta, n, page_size;
- u32 r1_old, r2_old, r1_new, r2_new;
unsigned int max_bitflips;
+ unsigned int ecc_strength;
int first, last, marker_pos;
int ecc_parity_size;
int col = 0;
- int old_swap_block_mark = this->swap_block_mark;
+ int ret;
/* The size of ECC parity */
ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
@@ -1138,43 +1531,33 @@ static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs,
buf = buf + first * size;
}
- nand_read_page_op(chip, page, col, NULL, 0);
-
- /* Save the old environment */
- r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0);
- r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1);
+ ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
- /* change the BCH registers and bch_geometry{} */
n = last - first + 1;
page_size = meta + (size + ecc_parity_size) * n;
+ ecc_strength = geo->ecc_strength >> 1;
- r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS |
- BM_BCH_FLASH0LAYOUT0_META_SIZE);
- r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1)
- | BF_BCH_FLASH0LAYOUT0_META_SIZE(meta);
- writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0);
+ this->bch_flashlayout0 = BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1) |
+ BF_BCH_FLASH0LAYOUT0_META_SIZE(meta) |
+ BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this) |
+ BF_BCH_FLASH0LAYOUT0_GF(geo->gf_len, this) |
+ BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(geo->ecc_chunk_size, this);
- r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE;
- r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size);
- writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1);
+ this->bch_flashlayout1 = BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) |
+ BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this) |
+ BF_BCH_FLASH0LAYOUT1_GF(geo->gf_len, this) |
+ BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(geo->ecc_chunk_size, this);
- geo->ecc_chunk_count = n;
- geo->payload_size = n * size;
- geo->page_size = page_size;
- geo->auxiliary_status_offset = ALIGN(meta, 4);
+ this->bch = true;
+
+ ret = nand_read_page_op(chip, page, col, buf, page_size);
+ if (ret)
+ return ret;
dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n",
page, offs, len, col, first, n, page_size);
- /* Read the subpage now */
- this->swap_block_mark = false;
- max_bitflips = gpmi_ecc_read_page_data(chip, buf, 0, page);
-
- /* Restore */
- writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0);
- writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1);
- this->bch_geometry = old_geo;
- this->swap_block_mark = old_swap_block_mark;
+ max_bitflips = gpmi_count_bitflips(chip, buf, first, last, meta);
return max_bitflips;
}
@@ -1185,81 +1568,29 @@ static int gpmi_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- const void *payload_virt;
- dma_addr_t payload_phys;
- const void *auxiliary_virt;
- dma_addr_t auxiliary_phys;
- int ret;
+ int ret;
dev_dbg(this->dev, "ecc write page.\n");
- nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+ gpmi_bch_layout_std(this);
+ this->bch = true;
+
+ memcpy(this->auxiliary_virt, chip->oob_poi, nfc_geo->auxiliary_size);
if (this->swap_block_mark) {
/*
- * If control arrives here, we're doing block mark swapping.
- * Since we can't modify the caller's buffers, we must copy them
- * into our own.
- */
- memcpy(this->payload_virt, buf, mtd->writesize);
- payload_virt = this->payload_virt;
- payload_phys = this->payload_phys;
-
- memcpy(this->auxiliary_virt, chip->oob_poi,
- nfc_geo->auxiliary_size);
- auxiliary_virt = this->auxiliary_virt;
- auxiliary_phys = this->auxiliary_phys;
-
- /* Handle block mark swapping. */
- block_mark_swapping(this,
- (void *)payload_virt, (void *)auxiliary_virt);
- } else {
- /*
- * If control arrives here, we're not doing block mark swapping,
- * so we can to try and use the caller's buffers.
+ * When doing bad block marker swapping we must always copy the
+ * input buffer as we can't modify the const buffer.
*/
- ret = send_page_prepare(this,
- buf, mtd->writesize,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- &payload_virt, &payload_phys);
- if (ret) {
- dev_err(this->dev, "Inadequate payload DMA buffer\n");
- return 0;
- }
-
- ret = send_page_prepare(this,
- chip->oob_poi, mtd->oobsize,
- this->auxiliary_virt, this->auxiliary_phys,
- nfc_geo->auxiliary_size,
- &auxiliary_virt, &auxiliary_phys);
- if (ret) {
- dev_err(this->dev, "Inadequate auxiliary DMA buffer\n");
- goto exit_auxiliary;
- }
+ memcpy(this->data_buffer_dma, buf, mtd->writesize);
+ buf = this->data_buffer_dma;
+ block_mark_swapping(this, this->data_buffer_dma,
+ this->auxiliary_virt);
}
- /* Ask the NFC. */
- ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
- if (ret)
- dev_err(this->dev, "Error in ECC-based write: %d\n", ret);
-
- if (!this->swap_block_mark) {
- send_page_end(this, chip->oob_poi, mtd->oobsize,
- this->auxiliary_virt, this->auxiliary_phys,
- nfc_geo->auxiliary_size,
- auxiliary_virt, auxiliary_phys);
-exit_auxiliary:
- send_page_end(this, buf, mtd->writesize,
- this->payload_virt, this->payload_phys,
- nfc_geo->payload_size,
- payload_virt, payload_phys);
- }
+ ret = nand_prog_page_op(chip, page, 0, buf, nfc_geo->page_size);
- if (ret)
- return ret;
-
- return nand_prog_page_end_op(chip);
+ return ret;
}
/*
@@ -1326,14 +1657,16 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
+ int ret;
- dev_dbg(this->dev, "page number is %d\n", page);
/* clear the OOB buffer */
memset(chip->oob_poi, ~0, mtd->oobsize);
/* Read out the conventional OOB. */
- nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
- chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
+ ret = nand_read_page_op(chip, page, mtd->writesize, chip->oob_poi,
+ mtd->oobsize);
+ if (ret)
+ return ret;
/*
* Now, we want to make sure the block mark is correct. In the
@@ -1342,8 +1675,9 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page)
*/
if (GPMI_IS_MX23(this)) {
/* Read the block mark into the first byte of the OOB buffer. */
- nand_read_page_op(chip, page, 0, NULL, 0);
- chip->oob_poi[0] = chip->legacy.read_byte(chip);
+ ret = nand_read_page_op(chip, page, 0, chip->oob_poi, 1);
+ if (ret)
+ return ret;
}
return 0;
@@ -1392,9 +1726,12 @@ static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf,
size_t oob_byte_off;
uint8_t *oob = chip->oob_poi;
int step;
+ int ret;
- nand_read_page_op(chip, page, 0, tmp_buf,
- mtd->writesize + mtd->oobsize);
+ ret = nand_read_page_op(chip, page, 0, tmp_buf,
+ mtd->writesize + mtd->oobsize);
+ if (ret)
+ return ret;
/*
* If required, swap the bad block marker and the data stored in the
@@ -1606,13 +1943,12 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
unsigned int stride;
unsigned int page;
u8 *buffer = nand_get_data_buf(chip);
- int saved_chip_number;
int found_an_ncb_fingerprint = false;
+ int ret;
/* Compute the number of strides in a search area. */
search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
- saved_chip_number = this->current_chip;
nand_select_target(chip, 0);
/*
@@ -1630,8 +1966,10 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
* Read the NCB fingerprint. The fingerprint is four bytes long
* and starts in the 12th byte of the page.
*/
- nand_read_page_op(chip, page, 12, NULL, 0);
- chip->legacy.read_buf(chip, buffer, strlen(fingerprint));
+ ret = nand_read_page_op(chip, page, 12, buffer,
+ strlen(fingerprint));
+ if (ret)
+ continue;
/* Look for the fingerprint. */
if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
@@ -1641,10 +1979,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
}
- if (saved_chip_number >= 0)
- nand_select_target(chip, saved_chip_number);
- else
- nand_deselect_target(chip);
+ nand_deselect_target(chip);
if (found_an_ncb_fingerprint)
dev_dbg(dev, "\tFound a fingerprint\n");
@@ -1668,7 +2003,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
unsigned int stride;
unsigned int page;
u8 *buffer = nand_get_data_buf(chip);
- int saved_chip_number;
int status;
/* Compute the search area geometry. */
@@ -1685,8 +2019,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
dev_dbg(dev, "\tin Strides: %u\n", search_area_size_in_strides);
dev_dbg(dev, "\tin Pages : %u\n", search_area_size_in_pages);
- /* Select chip 0. */
- saved_chip_number = this->current_chip;
nand_select_target(chip, 0);
/* Loop over blocks in the first search area, erasing them. */
@@ -1718,11 +2050,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
dev_err(dev, "[%s] Write failed.\n", __func__);
}
- /* Deselect chip 0. */
- if (saved_chip_number >= 0)
- nand_select_target(chip, saved_chip_number);
- else
- nand_deselect_target(chip);
+ nand_deselect_target(chip);
return 0;
}
@@ -1773,10 +2101,13 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
/* Send the command to read the conventional block mark. */
nand_select_target(chip, chipnr);
- nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
- block_mark = chip->legacy.read_byte(chip);
+ ret = nand_read_page_op(chip, page, mtd->writesize, &block_mark,
+ 1);
nand_deselect_target(chip);
+ if (ret)
+ continue;
+
/*
* Check if the block is marked bad. If so, we need to mark it
* again, but this time the result will be a mark in the
@@ -1890,9 +2221,330 @@ static int gpmi_nand_attach_chip(struct nand_chip *chip)
return 0;
}
+static struct gpmi_transfer *get_next_transfer(struct gpmi_nand_data *this)
+{
+ struct gpmi_transfer *transfer = &this->transfers[this->ntransfers];
+
+ this->ntransfers++;
+
+ if (this->ntransfers == GPMI_MAX_TRANSFERS)
+ return NULL;
+
+ return transfer;
+}
+
+static struct dma_async_tx_descriptor *gpmi_chain_command(
+ struct gpmi_nand_data *this, u8 cmd, const u8 *addr, int naddr)
+{
+ struct dma_chan *channel = get_dma_chan(this);
+ struct dma_async_tx_descriptor *desc;
+ struct gpmi_transfer *transfer;
+ int chip = this->nand.cur_cs;
+ u32 pio[3];
+
+ /* [1] send out the PIO words */
+ pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
+ | BM_GPMI_CTRL0_WORD_LENGTH
+ | BF_GPMI_CTRL0_CS(chip, this)
+ | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+ | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
+ | BM_GPMI_CTRL0_ADDRESS_INCREMENT
+ | BF_GPMI_CTRL0_XFER_COUNT(naddr + 1);
+ pio[1] = 0;
+ pio[2] = 0;
+ desc = mxs_dmaengine_prep_pio(channel, pio, ARRAY_SIZE(pio),
+ DMA_TRANS_NONE, 0);
+ if (!desc)
+ return NULL;
+
+ transfer = get_next_transfer(this);
+ if (!transfer)
+ return NULL;
+
+ transfer->cmdbuf[0] = cmd;
+ if (naddr)
+ memcpy(&transfer->cmdbuf[1], addr, naddr);
+
+ sg_init_one(&transfer->sgl, transfer->cmdbuf, naddr + 1);
+ dma_map_sg(this->dev, &transfer->sgl, 1, DMA_TO_DEVICE);
+
+ transfer->direction = DMA_TO_DEVICE;
+
+ desc = dmaengine_prep_slave_sg(channel, &transfer->sgl, 1, DMA_MEM_TO_DEV,
+ MXS_DMA_CTRL_WAIT4END);
+ return desc;
+}
+
+static struct dma_async_tx_descriptor *gpmi_chain_wait_ready(
+ struct gpmi_nand_data *this)
+{
+ struct dma_chan *channel = get_dma_chan(this);
+ u32 pio[2];
+
+ pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY)
+ | BM_GPMI_CTRL0_WORD_LENGTH
+ | BF_GPMI_CTRL0_CS(this->nand.cur_cs, this)
+ | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+ | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
+ | BF_GPMI_CTRL0_XFER_COUNT(0);
+ pio[1] = 0;
+
+ return mxs_dmaengine_prep_pio(channel, pio, 2, DMA_TRANS_NONE,
+ MXS_DMA_CTRL_WAIT4END | MXS_DMA_CTRL_WAIT4RDY);
+}
+
+static struct dma_async_tx_descriptor *gpmi_chain_data_read(
+ struct gpmi_nand_data *this, void *buf, int raw_len, bool *direct)
+{
+ struct dma_async_tx_descriptor *desc;
+ struct dma_chan *channel = get_dma_chan(this);
+ struct gpmi_transfer *transfer;
+ u32 pio[6] = {};
+
+ transfer = get_next_transfer(this);
+ if (!transfer)
+ return NULL;
+
+ transfer->direction = DMA_FROM_DEVICE;
+
+ *direct = prepare_data_dma(this, buf, raw_len, &transfer->sgl,
+ DMA_FROM_DEVICE);
+
+ pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
+ | BM_GPMI_CTRL0_WORD_LENGTH
+ | BF_GPMI_CTRL0_CS(this->nand.cur_cs, this)
+ | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+ | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
+ | BF_GPMI_CTRL0_XFER_COUNT(raw_len);
+
+ if (this->bch) {
+ pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
+ | BF_GPMI_ECCCTRL_ECC_CMD(BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE)
+ | BF_GPMI_ECCCTRL_BUFFER_MASK(BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
+ | BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY);
+ pio[3] = raw_len;
+ pio[4] = transfer->sgl.dma_address;
+ pio[5] = this->auxiliary_phys;
+ }
+
+ desc = mxs_dmaengine_prep_pio(channel, pio, ARRAY_SIZE(pio),
+ DMA_TRANS_NONE, 0);
+ if (!desc)
+ return NULL;
+
+ if (!this->bch)
+ desc = dmaengine_prep_slave_sg(channel, &transfer->sgl, 1,
+ DMA_DEV_TO_MEM,
+ MXS_DMA_CTRL_WAIT4END);
+
+ return desc;
+}
+
+static struct dma_async_tx_descriptor *gpmi_chain_data_write(
+ struct gpmi_nand_data *this, const void *buf, int raw_len)
+{
+ struct dma_chan *channel = get_dma_chan(this);
+ struct dma_async_tx_descriptor *desc;
+ struct gpmi_transfer *transfer;
+ u32 pio[6] = {};
+
+ transfer = get_next_transfer(this);
+ if (!transfer)
+ return NULL;
+
+ transfer->direction = DMA_TO_DEVICE;
+
+ prepare_data_dma(this, buf, raw_len, &transfer->sgl, DMA_TO_DEVICE);
+
+ pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
+ | BM_GPMI_CTRL0_WORD_LENGTH
+ | BF_GPMI_CTRL0_CS(this->nand.cur_cs, this)
+ | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+ | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
+ | BF_GPMI_CTRL0_XFER_COUNT(raw_len);
+
+ if (this->bch) {
+ pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
+ | BF_GPMI_ECCCTRL_ECC_CMD(BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE)
+ | BF_GPMI_ECCCTRL_BUFFER_MASK(BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
+ BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY);
+ pio[3] = raw_len;
+ pio[4] = transfer->sgl.dma_address;
+ pio[5] = this->auxiliary_phys;
+ }
+
+ desc = mxs_dmaengine_prep_pio(channel, pio, ARRAY_SIZE(pio),
+ DMA_TRANS_NONE,
+ (this->bch ? MXS_DMA_CTRL_WAIT4END : 0));
+ if (!desc)
+ return NULL;
+
+ if (!this->bch)
+ desc = dmaengine_prep_slave_sg(channel, &transfer->sgl, 1,
+ DMA_MEM_TO_DEV,
+ MXS_DMA_CTRL_WAIT4END);
+
+ return desc;
+}
+
+static int gpmi_nfc_exec_op(struct nand_chip *chip,
+ const struct nand_operation *op,
+ bool check_only)
+{
+ const struct nand_op_instr *instr;
+ struct gpmi_nand_data *this = nand_get_controller_data(chip);
+ struct dma_async_tx_descriptor *desc = NULL;
+ int i, ret, buf_len = 0, nbufs = 0;
+ u8 cmd = 0;
+ void *buf_read = NULL;
+ const void *buf_write = NULL;
+ bool direct = false;
+ struct completion *completion;
+ unsigned long to;
+
+ this->ntransfers = 0;
+ for (i = 0; i < GPMI_MAX_TRANSFERS; i++)
+ this->transfers[i].direction = DMA_NONE;
+
+ ret = pm_runtime_get_sync(this->dev);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * This driver currently supports only one NAND chip. Plus, dies share
+ * the same configuration. So once timings have been applied on the
+ * controller side, they will not change anymore. When the time will
+ * come, the check on must_apply_timings will have to be dropped.
+ */
+ if (this->hw.must_apply_timings) {
+ this->hw.must_apply_timings = false;
+ gpmi_nfc_apply_timings(this);
+ }
+
+ dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
+
+ for (i = 0; i < op->ninstrs; i++) {
+ instr = &op->instrs[i];
+
+ nand_op_trace(" ", instr);
+
+ switch (instr->type) {
+ case NAND_OP_WAITRDY_INSTR:
+ desc = gpmi_chain_wait_ready(this);
+ break;
+ case NAND_OP_CMD_INSTR:
+ cmd = instr->ctx.cmd.opcode;
+
+ /*
+ * When this command has an address cycle chain it
+ * together with the address cycle
+ */
+ if (i + 1 != op->ninstrs &&
+ op->instrs[i + 1].type == NAND_OP_ADDR_INSTR)
+ continue;
+
+ desc = gpmi_chain_command(this, cmd, NULL, 0);
+
+ break;
+ case NAND_OP_ADDR_INSTR:
+ desc = gpmi_chain_command(this, cmd, instr->ctx.addr.addrs,
+ instr->ctx.addr.naddrs);
+ break;
+ case NAND_OP_DATA_OUT_INSTR:
+ buf_write = instr->ctx.data.buf.out;
+ buf_len = instr->ctx.data.len;
+ nbufs++;
+
+ desc = gpmi_chain_data_write(this, buf_write, buf_len);
+
+ break;
+ case NAND_OP_DATA_IN_INSTR:
+ if (!instr->ctx.data.len)
+ break;
+ buf_read = instr->ctx.data.buf.in;
+ buf_len = instr->ctx.data.len;
+ nbufs++;
+
+ desc = gpmi_chain_data_read(this, buf_read, buf_len,
+ &direct);
+ break;
+ }
+
+ if (!desc) {
+ ret = -ENXIO;
+ goto unmap;
+ }
+ }
+
+ dev_dbg(this->dev, "%s setup done\n", __func__);
+
+ if (nbufs > 1) {
+ dev_err(this->dev, "Multiple data instructions not supported\n");
+ ret = -EINVAL;
+ goto unmap;
+ }
+
+ if (this->bch) {
+ writel(this->bch_flashlayout0,
+ this->resources.bch_regs + HW_BCH_FLASH0LAYOUT0);
+ writel(this->bch_flashlayout1,
+ this->resources.bch_regs + HW_BCH_FLASH0LAYOUT1);
+ }
+
+ if (this->bch && buf_read) {
+ writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
+ this->resources.bch_regs + HW_BCH_CTRL_SET);
+ completion = &this->bch_done;
+ } else {
+ desc->callback = dma_irq_callback;
+ desc->callback_param = this;
+ completion = &this->dma_done;
+ }
+
+ init_completion(completion);
+
+ dmaengine_submit(desc);
+ dma_async_issue_pending(get_dma_chan(this));
+
+ to = wait_for_completion_timeout(completion, msecs_to_jiffies(1000));
+ if (!to) {
+ dev_err(this->dev, "DMA timeout, last DMA\n");
+ gpmi_dump_info(this);
+ ret = -ETIMEDOUT;
+ goto unmap;
+ }
+
+ writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
+ this->resources.bch_regs + HW_BCH_CTRL_CLR);
+ gpmi_clear_bch(this);
+
+ ret = 0;
+
+unmap:
+ for (i = 0; i < this->ntransfers; i++) {
+ struct gpmi_transfer *transfer = &this->transfers[i];
+
+ if (transfer->direction != DMA_NONE)
+ dma_unmap_sg(this->dev, &transfer->sgl, 1,
+ transfer->direction);
+ }
+
+ if (!ret && buf_read && !direct)
+ memcpy(buf_read, this->data_buffer_dma,
+ gpmi_raw_len_to_len(this, buf_len));
+
+ this->bch = false;
+
+ pm_runtime_mark_last_busy(this->dev);
+ pm_runtime_put_autosuspend(this->dev);
+
+ return ret;
+}
+
static const struct nand_controller_ops gpmi_nand_controller_ops = {
.attach_chip = gpmi_nand_attach_chip,
.setup_data_interface = gpmi_setup_data_interface,
+ .exec_op = gpmi_nfc_exec_op,
};
static int gpmi_nand_init(struct gpmi_nand_data *this)
@@ -1901,9 +2553,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
- /* init current chip */
- this->current_chip = -1;
-
/* init the MTD data structures */
mtd->name = "gpmi-nand";
mtd->dev.parent = this->dev;
@@ -1911,14 +2560,8 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
/* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
nand_set_controller_data(chip, this);
nand_set_flash_node(chip, this->pdev->dev.of_node);
- chip->legacy.select_chip = gpmi_select_chip;
- chip->legacy.cmd_ctrl = gpmi_cmd_ctrl;
- chip->legacy.dev_ready = gpmi_dev_ready;
- chip->legacy.read_byte = gpmi_read_byte;
- chip->legacy.read_buf = gpmi_read_buf;
- chip->legacy.write_buf = gpmi_write_buf;
- chip->badblock_pattern = &gpmi_bbt_descr;
chip->legacy.block_markbad = gpmi_block_markbad;
+ chip->badblock_pattern = &gpmi_bbt_descr;
chip->options |= NAND_NO_SUBPAGE_WRITE;
/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
@@ -1934,7 +2577,10 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
if (ret)
goto err_out;
- chip->legacy.dummy_controller.ops = &gpmi_nand_controller_ops;
+ nand_controller_init(&this->base);
+ this->base.ops = &gpmi_nand_controller_ops;
+ chip->controller = &this->base;
+
ret = nand_scan(chip, GPMI_IS_MX6(this) ? 2 : 1);
if (ret)
goto err_out;
@@ -2004,6 +2650,16 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_acquire_resources;
+ ret = __gpmi_enable_clk(this, true);
+ if (ret)
+ goto exit_nfc_init;
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
ret = gpmi_init(this);
if (ret)
goto exit_nfc_init;
@@ -2012,11 +2668,16 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_nfc_init;
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
dev_info(this->dev, "driver registered.\n");
return 0;
exit_nfc_init:
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
release_resources(this);
exit_acquire_resources:
@@ -2027,6 +2688,9 @@ static int gpmi_nand_remove(struct platform_device *pdev)
{
struct gpmi_nand_data *this = platform_get_drvdata(pdev);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
nand_release(&this->nand);
gpmi_free_dma_buffer(this);
release_resources(this);
@@ -2069,8 +2733,23 @@ static int gpmi_pm_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
+static int __maybe_unused gpmi_runtime_suspend(struct device *dev)
+{
+ struct gpmi_nand_data *this = dev_get_drvdata(dev);
+
+ return __gpmi_enable_clk(this, false);
+}
+
+static int __maybe_unused gpmi_runtime_resume(struct device *dev)
+{
+ struct gpmi_nand_data *this = dev_get_drvdata(dev);
+
+ return __gpmi_enable_clk(this, true);
+}
+
static const struct dev_pm_ops gpmi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
+ SET_RUNTIME_PM_OPS(gpmi_runtime_suspend, gpmi_runtime_resume, NULL)
};
static struct platform_driver gpmi_nand_driver = {
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
index a804a4a5bd46..fdc5ed7de083 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
@@ -103,6 +103,14 @@ struct gpmi_nfc_hardware_timing {
u32 ctrl1n;
};
+#define GPMI_MAX_TRANSFERS 8
+
+struct gpmi_transfer {
+ u8 cmdbuf[8];
+ struct scatterlist sgl;
+ enum dma_data_direction direction;
+};
+
struct gpmi_nand_data {
/* Devdata */
const struct gpmi_devdata *devdata;
@@ -126,25 +134,18 @@ struct gpmi_nand_data {
struct boot_rom_geometry rom_geometry;
/* MTD / NAND */
+ struct nand_controller base;
struct nand_chip nand;
- /* General-use Variables */
- int current_chip;
- unsigned int command_length;
+ struct gpmi_transfer transfers[GPMI_MAX_TRANSFERS];
+ int ntransfers;
- struct scatterlist cmd_sgl;
- char *cmd_buffer;
+ bool bch;
+ uint32_t bch_flashlayout0;
+ uint32_t bch_flashlayout1;
- struct scatterlist data_sgl;
char *data_buffer_dma;
- void *page_buffer_virt;
- dma_addr_t page_buffer_phys;
- unsigned int page_buffer_size;
-
- void *payload_virt;
- dma_addr_t payload_phys;
-
void *auxiliary_virt;
dma_addr_t auxiliary_phys;
@@ -154,45 +155,8 @@ struct gpmi_nand_data {
#define DMA_CHANS 8
struct dma_chan *dma_chans[DMA_CHANS];
struct completion dma_done;
-
- /* private */
- void *private;
};
-/* Common Services */
-int common_nfc_set_geometry(struct gpmi_nand_data *);
-struct dma_chan *get_dma_chan(struct gpmi_nand_data *);
-bool prepare_data_dma(struct gpmi_nand_data *, const void *buf, int len,
- enum dma_data_direction dr);
-int start_dma_without_bch_irq(struct gpmi_nand_data *,
- struct dma_async_tx_descriptor *);
-int start_dma_with_bch_irq(struct gpmi_nand_data *,
- struct dma_async_tx_descriptor *);
-
-/* GPMI-NAND helper function library */
-int gpmi_init(struct gpmi_nand_data *);
-void gpmi_clear_bch(struct gpmi_nand_data *);
-void gpmi_dump_info(struct gpmi_nand_data *);
-int bch_set_geometry(struct gpmi_nand_data *);
-int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
-int gpmi_send_command(struct gpmi_nand_data *);
-int gpmi_enable_clk(struct gpmi_nand_data *this);
-int gpmi_disable_clk(struct gpmi_nand_data *this);
-int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
- const struct nand_data_interface *conf);
-void gpmi_nfc_apply_timings(struct gpmi_nand_data *this);
-int gpmi_read_data(struct gpmi_nand_data *, void *buf, int len);
-int gpmi_send_data(struct gpmi_nand_data *, const void *buf, int len);
-
-int gpmi_send_page(struct gpmi_nand_data *,
- dma_addr_t payload, dma_addr_t auxiliary);
-int gpmi_read_page(struct gpmi_nand_data *,
- dma_addr_t payload, dma_addr_t auxiliary);
-
-void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
- const u8 *src, size_t src_bit_off,
- size_t nbits);
-
/* BCH : Status Block Completion Codes */
#define STATUS_GOOD 0x00
#define STATUS_ERASED 0xff
diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
index 0f90e060dae8..74595b644b7c 100644
--- a/drivers/mtd/nand/raw/mtk_ecc.c
+++ b/drivers/mtd/nand/raw/mtk_ecc.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0 OR MIT
/*
* MTK ECC controller driver.
* Copyright (C) 2016 MediaTek Inc.
@@ -596,4 +596,4 @@ module_platform_driver(mtk_ecc_driver);
MODULE_AUTHOR("Xiaolei Li <xiaolei.li@mediatek.com>");
MODULE_DESCRIPTION("MTK Nand ECC Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/mtd/nand/raw/mtk_ecc.h b/drivers/mtd/nand/raw/mtk_ecc.h
index aa52e94c771d..0e48c36e6ca0 100644
--- a/drivers/mtd/nand/raw/mtk_ecc.h
+++ b/drivers/mtd/nand/raw/mtk_ecc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/*
* MTK SDG1 ECC controller
*
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index dceff28c9a31..373d47d1ba4c 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0 OR MIT
/*
* MTK NAND Flash controller driver.
* Copyright (C) 2016 MediaTek Inc.
@@ -79,6 +79,10 @@
#define NFI_FDMM(x) (0xA4 + (x) * sizeof(u32) * 2)
#define NFI_FDM_MAX_SIZE (8)
#define NFI_FDM_MIN_SIZE (1)
+#define NFI_DEBUG_CON1 (0x220)
+#define STROBE_MASK GENMASK(4, 3)
+#define STROBE_SHIFT (3)
+#define MAX_STROBE_DLY (3)
#define NFI_MASTER_STA (0x224)
#define MASTER_STA_MASK (0x0FFF)
#define NFI_EMPTY_THRESH (0x23C)
@@ -150,6 +154,8 @@ struct mtk_nfc {
struct list_head chips;
u8 *buffer;
+
+ unsigned long assigned_cs;
};
/*
@@ -500,7 +506,8 @@ static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
{
struct mtk_nfc *nfc = nand_get_controller_data(chip);
const struct nand_sdr_timings *timings;
- u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt;
+ u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst = 0, trlt = 0;
+ u32 temp, tsel = 0;
timings = nand_get_sdr_timings(conf);
if (IS_ERR(timings))
@@ -536,14 +543,53 @@ static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
twh = DIV_ROUND_UP(twh * rate, 1000000) - 1;
twh &= 0xf;
- twst = timings->tWP_min / 1000;
+ /* Calculate real WE#/RE# hold time in nanosecond */
+ temp = (twh + 1) * 1000000 / rate;
+ /* nanosecond to picosecond */
+ temp *= 1000;
+
+ /*
+ * WE# low level time should be expaned to meet WE# pulse time
+ * and WE# cycle time at the same time.
+ */
+ if (temp < timings->tWC_min)
+ twst = timings->tWC_min - temp;
+ twst = max(timings->tWP_min, twst) / 1000;
twst = DIV_ROUND_UP(twst * rate, 1000000) - 1;
twst &= 0xf;
- trlt = max(timings->tREA_max, timings->tRP_min) / 1000;
+ /*
+ * RE# low level time should be expaned to meet RE# pulse time
+ * and RE# cycle time at the same time.
+ */
+ if (temp < timings->tRC_min)
+ trlt = timings->tRC_min - temp;
+ trlt = max(trlt, timings->tRP_min) / 1000;
trlt = DIV_ROUND_UP(trlt * rate, 1000000) - 1;
trlt &= 0xf;
+ /* Calculate RE# pulse time in nanosecond. */
+ temp = (trlt + 1) * 1000000 / rate;
+ /* nanosecond to picosecond */
+ temp *= 1000;
+ /*
+ * If RE# access time is bigger than RE# pulse time,
+ * delay sampling data timing.
+ */
+ if (temp < timings->tREA_max) {
+ tsel = timings->tREA_max / 1000;
+ tsel = DIV_ROUND_UP(tsel * rate, 1000000);
+ tsel -= (trlt + 1);
+ if (tsel > MAX_STROBE_DLY) {
+ trlt += tsel - MAX_STROBE_DLY;
+ tsel = MAX_STROBE_DLY;
+ }
+ }
+ temp = nfi_readl(nfc, NFI_DEBUG_CON1);
+ temp &= ~STROBE_MASK;
+ temp |= tsel << STROBE_SHIFT;
+ nfi_writel(nfc, temp, NFI_DEBUG_CON1);
+
/*
* ACCON: access timing control register
* -------------------------------------
@@ -835,19 +881,21 @@ static int mtk_nfc_write_oob_std(struct nand_chip *chip, int page)
return mtk_nfc_write_page_raw(chip, NULL, 1, page);
}
-static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
+static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 start,
+ u32 sectors)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mtk_nfc *nfc = nand_get_controller_data(chip);
struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
struct mtk_ecc_stats stats;
+ u32 reg_size = mtk_nand->fdm.reg_size;
int rc, i;
rc = nfi_readl(nfc, NFI_STA) & STA_EMP_PAGE;
if (rc) {
memset(buf, 0xff, sectors * chip->ecc.size);
for (i = 0; i < sectors; i++)
- memset(oob_ptr(chip, i), 0xff, mtk_nand->fdm.reg_size);
+ memset(oob_ptr(chip, start + i), 0xff, reg_size);
return 0;
}
@@ -867,7 +915,7 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
u32 spare = mtk_nand->spare_per_sector;
u32 column, sectors, start, end, reg;
dma_addr_t addr;
- int bitflips;
+ int bitflips = 0;
size_t len;
u8 *buf;
int rc;
@@ -934,14 +982,11 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
if (rc < 0) {
dev_err(nfc->dev, "subpage done timeout\n");
bitflips = -EIO;
- } else {
- bitflips = 0;
- if (!raw) {
- rc = mtk_ecc_wait_done(nfc->ecc, ECC_DECODE);
- bitflips = rc < 0 ? -ETIMEDOUT :
- mtk_nfc_update_ecc_stats(mtd, buf, sectors);
- mtk_nfc_read_fdm(chip, start, sectors);
- }
+ } else if (!raw) {
+ rc = mtk_ecc_wait_done(nfc->ecc, ECC_DECODE);
+ bitflips = rc < 0 ? -ETIMEDOUT :
+ mtk_nfc_update_ecc_stats(mtd, buf, start, sectors);
+ mtk_nfc_read_fdm(chip, start, sectors);
}
dma_unmap_single(nfc->dev, addr, len, DMA_FROM_DEVICE);
@@ -1315,6 +1360,17 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
dev_err(dev, "reg property failure : %d\n", ret);
return ret;
}
+
+ if (tmp >= MTK_NAND_MAX_NSELS) {
+ dev_err(dev, "invalid CS: %u\n", tmp);
+ return -EINVAL;
+ }
+
+ if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
+ dev_err(dev, "CS %u already assigned\n", tmp);
+ return -EINVAL;
+ }
+
chip->sels[i] = tmp;
}
@@ -1589,6 +1645,6 @@ static struct platform_driver mtk_nfc_driver = {
module_platform_driver(mtk_nfc_driver);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Xiaolei Li <xiaolei.li@mediatek.com>");
MODULE_DESCRIPTION("MTK Nand Flash Controller Driver");
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6eb131292eb2..91f046d4d452 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -2111,35 +2111,7 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
if (instr == &ctx->subop.instrs[0])
prefix = " ->";
- switch (instr->type) {
- case NAND_OP_CMD_INSTR:
- pr_debug("%sCMD [0x%02x]\n", prefix,
- instr->ctx.cmd.opcode);
- break;
- case NAND_OP_ADDR_INSTR:
- pr_debug("%sADDR [%d cyc: %*ph]\n", prefix,
- instr->ctx.addr.naddrs,
- instr->ctx.addr.naddrs < 64 ?
- instr->ctx.addr.naddrs : 64,
- instr->ctx.addr.addrs);
- break;
- case NAND_OP_DATA_IN_INSTR:
- pr_debug("%sDATA_IN [%d B%s]\n", prefix,
- instr->ctx.data.len,
- instr->ctx.data.force_8bit ?
- ", force 8-bit" : "");
- break;
- case NAND_OP_DATA_OUT_INSTR:
- pr_debug("%sDATA_OUT [%d B%s]\n", prefix,
- instr->ctx.data.len,
- instr->ctx.data.force_8bit ?
- ", force 8-bit" : "");
- break;
- case NAND_OP_WAITRDY_INSTR:
- pr_debug("%sWAITRDY [max %d ms]\n", prefix,
- instr->ctx.waitrdy.timeout_ms);
- break;
- }
+ nand_op_trace(prefix, instr);
if (instr == &ctx->subop.instrs[ctx->subop.ninstrs - 1])
prefix = " ";
@@ -2152,6 +2124,22 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
}
#endif
+static int nand_op_parser_cmp_ctx(const struct nand_op_parser_ctx *a,
+ const struct nand_op_parser_ctx *b)
+{
+ if (a->subop.ninstrs < b->subop.ninstrs)
+ return -1;
+ else if (a->subop.ninstrs > b->subop.ninstrs)
+ return 1;
+
+ if (a->subop.last_instr_end_off < b->subop.last_instr_end_off)
+ return -1;
+ else if (a->subop.last_instr_end_off > b->subop.last_instr_end_off)
+ return 1;
+
+ return 0;
+}
+
/**
* nand_op_parser_exec_op - exec_op parser
* @chip: the NAND chip
@@ -2186,32 +2174,40 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
unsigned int i;
while (ctx.subop.instrs < op->instrs + op->ninstrs) {
- int ret;
+ const struct nand_op_parser_pattern *pattern;
+ struct nand_op_parser_ctx best_ctx;
+ int ret, best_pattern = -1;
for (i = 0; i < parser->npatterns; i++) {
- const struct nand_op_parser_pattern *pattern;
+ struct nand_op_parser_ctx test_ctx = ctx;
pattern = &parser->patterns[i];
- if (!nand_op_parser_match_pat(pattern, &ctx))
+ if (!nand_op_parser_match_pat(pattern, &test_ctx))
continue;
- nand_op_parser_trace(&ctx);
-
- if (check_only)
- break;
-
- ret = pattern->exec(chip, &ctx.subop);
- if (ret)
- return ret;
+ if (best_pattern >= 0 &&
+ nand_op_parser_cmp_ctx(&test_ctx, &best_ctx) <= 0)
+ continue;
- break;
+ best_pattern = i;
+ best_ctx = test_ctx;
}
- if (i == parser->npatterns) {
+ if (best_pattern < 0) {
pr_debug("->exec_op() parser: pattern not found!\n");
return -ENOTSUPP;
}
+ ctx = best_ctx;
+ nand_op_parser_trace(&ctx);
+
+ if (!check_only) {
+ pattern = &parser->patterns[best_pattern];
+ ret = pattern->exec(chip, &ctx.subop);
+ if (ret)
+ return ret;
+ }
+
/*
* Update the context structure by pointing to the start of the
* next subop.
diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c
index 55aa4c1cd414..17527310c3a1 100644
--- a/drivers/mtd/nand/raw/nand_bch.c
+++ b/drivers/mtd/nand/raw/nand_bch.c
@@ -170,7 +170,7 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
goto fail;
}
- nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
+ nbc->eccmask = kzalloc(eccbytes, GFP_KERNEL);
nbc->errloc = kmalloc_array(t, sizeof(*nbc->errloc), GFP_KERNEL);
if (!nbc->eccmask || !nbc->errloc)
goto fail;
@@ -182,7 +182,6 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
goto fail;
memset(erased_page, 0xff, eccsize);
- memset(nbc->eccmask, 0, eccbytes);
encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask);
kfree(erased_page);
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index fad57c378dd2..58511aeb0c9a 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -8,6 +8,50 @@
#include "internals.h"
+#define MACRONIX_READ_RETRY_BIT BIT(0)
+#define MACRONIX_NUM_READ_RETRY_MODES 6
+
+struct nand_onfi_vendor_macronix {
+ u8 reserved;
+ u8 reliability_func;
+} __packed;
+
+static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
+{
+ u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+
+ if (!chip->parameters.supports_set_get_features ||
+ !test_bit(ONFI_FEATURE_ADDR_READ_RETRY,
+ chip->parameters.set_feature_list))
+ return -ENOTSUPP;
+
+ feature[0] = mode;
+ return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
+}
+
+static void macronix_nand_onfi_init(struct nand_chip *chip)
+{
+ struct nand_parameters *p = &chip->parameters;
+ struct nand_onfi_vendor_macronix *mxic;
+
+ if (!p->onfi)
+ return;
+
+ mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
+ if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
+ return;
+
+ chip->read_retries = MACRONIX_NUM_READ_RETRY_MODES;
+ chip->setup_read_retry = macronix_nand_setup_read_retry;
+
+ if (p->supports_set_get_features) {
+ bitmap_set(p->set_feature_list,
+ ONFI_FEATURE_ADDR_READ_RETRY, 1);
+ bitmap_set(p->get_feature_list,
+ ONFI_FEATURE_ADDR_READ_RETRY, 1);
+ }
+}
+
/*
* Macronix AC series does not support using SET/GET_FEATURES to change
* the timings unlike what is declared in the parameter page. Unflag
@@ -56,6 +100,7 @@ static int macronix_nand_init(struct nand_chip *chip)
chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
macronix_nand_fix_broken_get_timings(chip);
+ macronix_nand_onfi_init(chip);
return 0;
}
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 999ca6a66036..e63acc077c18 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -37,6 +37,8 @@
/* Max ECC buffer length */
#define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
+#define FMC2_TIMEOUT_MS 1000
+
/* Timings */
#define FMC2_THIZ 1
#define FMC2_TIO 8000
@@ -530,7 +532,8 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
int ret;
ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
- sr, sr & FMC2_SR_NWRF, 10, 1000);
+ sr, sr & FMC2_SR_NWRF, 10,
+ FMC2_TIMEOUT_MS);
if (ret) {
dev_err(fmc2->dev, "ham timeout\n");
return ret;
@@ -611,7 +614,7 @@ static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
/* Wait until the BCH code is ready */
if (!wait_for_completion_timeout(&fmc2->complete,
- msecs_to_jiffies(1000))) {
+ msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
dev_err(fmc2->dev, "bch timeout\n");
stm32_fmc2_disable_bch_irq(fmc2);
return -ETIMEDOUT;
@@ -696,7 +699,7 @@ static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat,
/* Wait until the decoding error is ready */
if (!wait_for_completion_timeout(&fmc2->complete,
- msecs_to_jiffies(1000))) {
+ msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
dev_err(fmc2->dev, "bch timeout\n");
stm32_fmc2_disable_bch_irq(fmc2);
return -ETIMEDOUT;
@@ -969,7 +972,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
/* Wait end of sequencer transfer */
if (!wait_for_completion_timeout(&fmc2->complete,
- msecs_to_jiffies(1000))) {
+ msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
dev_err(fmc2->dev, "seq timeout\n");
stm32_fmc2_disable_seq_irq(fmc2);
dmaengine_terminate_all(dma_ch);
@@ -981,7 +984,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
/* Wait DMA data transfer completion */
if (!wait_for_completion_timeout(&fmc2->dma_data_complete,
- msecs_to_jiffies(100))) {
+ msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
dev_err(fmc2->dev, "data DMA timeout\n");
dmaengine_terminate_all(dma_ch);
ret = -ETIMEDOUT;
@@ -990,7 +993,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
/* Wait DMA ECC transfer completion */
if (!write_data && !raw) {
if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete,
- msecs_to_jiffies(100))) {
+ msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
dev_err(fmc2->dev, "ECC DMA timeout\n");
dmaengine_terminate_all(fmc2->dma_ecc_ch);
ret = -ETIMEDOUT;
@@ -1909,6 +1912,12 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ if (irq != -EPROBE_DEFER)
+ dev_err(dev, "IRQ error missing or invalid\n");
+ return irq;
+ }
+
ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
dev_name(dev), fmc2);
if (ret) {
diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
index 753125082640..9662b9c1d5a9 100644
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
-spinand-objs := core.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
+spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 4c15bb58c623..89f6beefb01c 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -511,12 +511,12 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
if (ret == -EBADMSG) {
ecc_failed = true;
mtd->ecc_stats.failed++;
- ret = 0;
} else {
mtd->ecc_stats.corrected += ret;
max_bitflips = max_t(unsigned int, max_bitflips, ret);
}
+ ret = 0;
ops->retlen += iter.req.datalen;
ops->oobretlen += iter.req.ooblen;
}
@@ -757,6 +757,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = {
&gigadevice_spinand_manufacturer,
&macronix_spinand_manufacturer,
&micron_spinand_manufacturer,
+ &paragon_spinand_manufacturer,
&toshiba_spinand_manufacturer,
&winbond_spinand_manufacturer,
};
@@ -845,7 +846,7 @@ spinand_select_op_variant(struct spinand_device *spinand,
*/
int spinand_match_and_init(struct spinand_device *spinand,
const struct spinand_info *table,
- unsigned int table_size, u8 devid)
+ unsigned int table_size, u16 devid)
{
struct nand_device *nand = spinand_to_nand(spinand);
unsigned int i;
diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
index e6c646007cda..e99d425aa93f 100644
--- a/drivers/mtd/nand/spi/gigadevice.c
+++ b/drivers/mtd/nand/spi/gigadevice.c
@@ -9,11 +9,17 @@
#include <linux/mtd/spinand.h>
#define SPINAND_MFR_GIGADEVICE 0xC8
+
#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
#define GD5FXGQ4UEXXG_REG_STATUS2 0xf0
+#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
+#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
+#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4)
+#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4)
+
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -22,6 +28,14 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+static SPINAND_OP_VARIANTS(read_cache_variants_f,
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
+
static SPINAND_OP_VARIANTS(write_cache_variants,
SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
SPINAND_PROG_LOAD(true, 0, NULL, 0));
@@ -59,6 +73,11 @@ static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section,
return 0;
}
+static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
+ .ecc = gd5fxgq4xa_ooblayout_ecc,
+ .free = gd5fxgq4xa_ooblayout_free,
+};
+
static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
u8 status)
{
@@ -83,7 +102,7 @@ static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
return -EINVAL;
}
-static int gd5fxgq4uexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
+static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *region)
{
if (section)
@@ -95,7 +114,7 @@ static int gd5fxgq4uexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
return 0;
}
-static int gd5fxgq4uexxg_ooblayout_free(struct mtd_info *mtd, int section,
+static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *region)
{
if (section)
@@ -108,6 +127,11 @@ static int gd5fxgq4uexxg_ooblayout_free(struct mtd_info *mtd, int section,
return 0;
}
+static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
+ .ecc = gd5fxgq4_variant2_ooblayout_ecc,
+ .free = gd5fxgq4_variant2_ooblayout_free,
+};
+
static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
u8 status)
{
@@ -150,15 +174,25 @@ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
return -EINVAL;
}
-static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
- .ecc = gd5fxgq4xa_ooblayout_ecc,
- .free = gd5fxgq4xa_ooblayout_free,
-};
+static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+{
+ switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
+ case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
+ return 0;
-static const struct mtd_ooblayout_ops gd5fxgq4uexxg_ooblayout = {
- .ecc = gd5fxgq4uexxg_ooblayout_ecc,
- .free = gd5fxgq4uexxg_ooblayout_free,
-};
+ case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
+ return 3;
+
+ case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
+ return -EBADMSG;
+
+ default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
+ return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
+ }
+
+ return -EINVAL;
+}
static const struct spinand_info gigadevice_spinand_table[] = {
SPINAND_INFO("GD5F1GQ4xA", 0xF1,
@@ -195,25 +229,40 @@ static const struct spinand_info gigadevice_spinand_table[] = {
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&gd5fxgq4uexxg_ooblayout,
+ SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
gd5fxgq4uexxg_ecc_get_status)),
+ SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
+ gd5fxgq4ufxxg_ecc_get_status)),
};
static int gigadevice_spinand_detect(struct spinand_device *spinand)
{
u8 *id = spinand->id.data;
+ u16 did;
int ret;
/*
- * For GD NANDs, There is an address byte needed to shift in before IDs
- * are read out, so the first byte in raw_id is dummy.
+ * Earlier GDF5-series devices (A,E) return [0][MID][DID]
+ * Later (F) devices return [MID][DID1][DID2]
*/
- if (id[1] != SPINAND_MFR_GIGADEVICE)
+
+ if (id[0] == SPINAND_MFR_GIGADEVICE)
+ did = (id[1] << 8) + id[2];
+ else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE)
+ did = id[2];
+ else
return 0;
ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
ARRAY_SIZE(gigadevice_spinand_table),
- id[2]);
+ did);
if (ret)
return ret;
diff --git a/drivers/mtd/nand/spi/paragon.c b/drivers/mtd/nand/spi/paragon.c
new file mode 100644
index 000000000000..52307681cbd0
--- /dev/null
+++ b/drivers/mtd/nand/spi/paragon.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Jeff Kletsky
+ *
+ * Author: Jeff Kletsky <git-commits@allycomm.com>
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/mtd/spinand.h>
+
+
+#define SPINAND_MFR_PARAGON 0xa1
+
+
+#define PN26G0XA_STATUS_ECC_BITMASK (3 << 4)
+
+#define PN26G0XA_STATUS_ECC_NONE_DETECTED (0 << 4)
+#define PN26G0XA_STATUS_ECC_1_7_CORRECTED (1 << 4)
+#define PN26G0XA_STATUS_ECC_ERRORED (2 << 4)
+#define PN26G0XA_STATUS_ECC_8_CORRECTED (3 << 4)
+
+
+static SPINAND_OP_VARIANTS(read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants,
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants,
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+
+static int pn26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section > 3)
+ return -ERANGE;
+
+ region->offset = 6 + (15 * section); /* 4 BBM + 2 user bytes */
+ region->length = 13;
+
+ return 0;
+}
+
+static int pn26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section > 4)
+ return -ERANGE;
+
+ if (section == 4) {
+ region->offset = 64;
+ region->length = 64;
+ } else {
+ region->offset = 4 + (15 * section);
+ region->length = 2;
+ }
+
+ return 0;
+}
+
+static int pn26g0xa_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+{
+ switch (status & PN26G0XA_STATUS_ECC_BITMASK) {
+ case PN26G0XA_STATUS_ECC_NONE_DETECTED:
+ return 0;
+
+ case PN26G0XA_STATUS_ECC_1_7_CORRECTED:
+ return 7; /* Return upper limit by convention */
+
+ case PN26G0XA_STATUS_ECC_8_CORRECTED:
+ return 8;
+
+ case PN26G0XA_STATUS_ECC_ERRORED:
+ return -EBADMSG;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
+ .ecc = pn26g0xa_ooblayout_ecc,
+ .free = pn26g0xa_ooblayout_free,
+};
+
+
+static const struct spinand_info paragon_spinand_table[] = {
+ SPINAND_INFO("PN26G01A", 0xe1,
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&pn26g0xa_ooblayout,
+ pn26g0xa_ecc_get_status)),
+ SPINAND_INFO("PN26G02A", 0xe2,
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&pn26g0xa_ooblayout,
+ pn26g0xa_ecc_get_status)),
+};
+
+static int paragon_spinand_detect(struct spinand_device *spinand)
+{
+ u8 *id = spinand->id.data;
+ int ret;
+
+ /* Read ID returns [0][MID][DID] */
+
+ if (id[1] != SPINAND_MFR_PARAGON)
+ return 0;
+
+ ret = spinand_match_and_init(spinand, paragon_spinand_table,
+ ARRAY_SIZE(paragon_spinand_table),
+ id[2]);
+ if (ret)
+ return ret;
+
+ return 1;
+}
+
+static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
+ .detect = paragon_spinand_detect,
+};
+
+const struct spinand_manufacturer paragon_spinand_manufacturer = {
+ .id = SPINAND_MFR_PARAGON,
+ .name = "Paragon",
+ .ops = &paragon_spinand_manuf_ops,
+};
diff --git a/drivers/mtd/parsers/afs.c b/drivers/mtd/parsers/afs.c
index f24d768eee30..752b6cf005f7 100644
--- a/drivers/mtd/parsers/afs.c
+++ b/drivers/mtd/parsers/afs.c
@@ -371,8 +371,7 @@ static int parse_afs_partitions(struct mtd_info *mtd,
out_free_parts:
while (i >= 0) {
- if (parts[i].name)
- kfree(parts[i].name);
+ kfree(parts[i].name);
i--;
}
kfree(parts);
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 8e14248d2720..6de83277ce8b 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -105,11 +105,4 @@ config SPI_INTEL_SPI_PLATFORM
To compile this driver as a module, choose M here: the module
will be called intel-spi-platform.
-config SPI_STM32_QUADSPI
- tristate "STM32 Quad SPI controller"
- depends on ARCH_STM32 || COMPILE_TEST
- help
- This enables support for the STM32 Quad SPI controller.
- We only connect the NOR to this controller.
-
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 189a15cca3ec..9c5ed03cdc19 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -8,4 +8,3 @@ obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o
obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o
-obj-$(CONFIG_SPI_STM32_QUADSPI) += stm32-quadspi.o
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
index 67ade2c81b21..67f15a1f16fd 100644
--- a/drivers/mtd/spi-nor/cadence-quadspi.c
+++ b/drivers/mtd/spi-nor/cadence-quadspi.c
@@ -23,6 +23,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/sched.h>
#include <linux/spi/spi.h>
#include <linux/timer.h>
@@ -1325,6 +1326,7 @@ static int cqspi_probe(struct platform_device *pdev)
struct cqspi_st *cqspi;
struct resource *res;
struct resource *res_ahb;
+ struct reset_control *rstc, *rstc_ocp;
const struct cqspi_driver_platdata *ddata;
int ret;
int irq;
@@ -1391,6 +1393,25 @@ static int cqspi_probe(struct platform_device *pdev)
goto probe_clk_failed;
}
+ /* Obtain QSPI reset control */
+ rstc = devm_reset_control_get_optional_exclusive(dev, "qspi");
+ if (IS_ERR(rstc)) {
+ dev_err(dev, "Cannot get QSPI reset.\n");
+ return PTR_ERR(rstc);
+ }
+
+ rstc_ocp = devm_reset_control_get_optional_exclusive(dev, "qspi-ocp");
+ if (IS_ERR(rstc_ocp)) {
+ dev_err(dev, "Cannot get QSPI OCP reset.\n");
+ return PTR_ERR(rstc_ocp);
+ }
+
+ reset_control_assert(rstc);
+ reset_control_deassert(rstc);
+
+ reset_control_assert(rstc_ocp);
+ reset_control_deassert(rstc_ocp);
+
cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
ddata = of_device_get_match_data(dev);
if (ddata && (ddata->quirks & CQSPI_NEEDS_WR_DELAY))
diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/intel-spi-pci.c
index 5e2344768d53..b83c4ab6cd9f 100644
--- a/drivers/mtd/spi-nor/intel-spi-pci.c
+++ b/drivers/mtd/spi-nor/intel-spi-pci.c
@@ -64,6 +64,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info },
{ },
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 0c2ec1c21434..03cc788511d5 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -200,7 +200,7 @@ struct sfdp_header {
* register does not modify status register 2.
* - 101b: QE is bit 1 of status register 2. Status register 1 is read using
* Read Status instruction 05h. Status register2 is read using
- * instruction 35h. QE is set via Writ Status instruction 01h with
+ * instruction 35h. QE is set via Write Status instruction 01h with
* two data bytes where bit 1 of the second byte is one.
* [...]
*/
@@ -1776,6 +1776,28 @@ static int spi_nor_spansion_clear_sr_bp(struct spi_nor *nor)
.flags = SPI_NOR_NO_FR | SPI_S3AN,
static int
+is25lp256_post_bfpt_fixups(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
+{
+ /*
+ * IS25LP256 supports 4B opcodes, but the BFPT advertises a
+ * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width.
+ * Overwrite the address width advertised by the BFPT.
+ */
+ if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
+ BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
+ nor->addr_width = 4;
+
+ return 0;
+}
+
+static struct spi_nor_fixups is25lp256_fixups = {
+ .post_bfpt = is25lp256_post_bfpt_fixups,
+};
+
+static int
mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
@@ -1916,7 +1938,8 @@ static const struct flash_info spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ) },
{ "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_4B_OPCODES) },
+ SPI_NOR_4B_OPCODES)
+ .fixups = &is25lp256_fixups },
{ "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128,
@@ -1969,6 +1992,9 @@ static const struct flash_info spi_nor_ids[] = {
{ "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
{ "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
{ "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+ { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+ NO_CHIP_ERASE) },
{ "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
/* Micron */
@@ -2085,6 +2111,11 @@ static const struct flash_info spi_nor_ids[] = {
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{ "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
+ {
+ "w25q16jv-im/jm", INFO(0xef7015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
{ "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) },
{ "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) },
{ "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) },
@@ -2151,7 +2182,7 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
- dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);
+ dev_err(nor->dev, "error %d reading JEDEC ID\n", tmp);
return ERR_PTR(tmp);
}
diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c
deleted file mode 100644
index 33534f9e296b..000000000000
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ /dev/null
@@ -1,707 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for stm32 quadspi controller
- *
- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
- * Author(s): Ludovic Barre author <ludovic.barre@st.com>.
- */
-#include <linux/clk.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/spi-nor.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-#include <linux/sizes.h>
-
-#define QUADSPI_CR 0x00
-#define CR_EN BIT(0)
-#define CR_ABORT BIT(1)
-#define CR_DMAEN BIT(2)
-#define CR_TCEN BIT(3)
-#define CR_SSHIFT BIT(4)
-#define CR_DFM BIT(6)
-#define CR_FSEL BIT(7)
-#define CR_FTHRES_SHIFT 8
-#define CR_FTHRES_MASK GENMASK(12, 8)
-#define CR_FTHRES(n) (((n) << CR_FTHRES_SHIFT) & CR_FTHRES_MASK)
-#define CR_TEIE BIT(16)
-#define CR_TCIE BIT(17)
-#define CR_FTIE BIT(18)
-#define CR_SMIE BIT(19)
-#define CR_TOIE BIT(20)
-#define CR_PRESC_SHIFT 24
-#define CR_PRESC_MASK GENMASK(31, 24)
-#define CR_PRESC(n) (((n) << CR_PRESC_SHIFT) & CR_PRESC_MASK)
-
-#define QUADSPI_DCR 0x04
-#define DCR_CSHT_SHIFT 8
-#define DCR_CSHT_MASK GENMASK(10, 8)
-#define DCR_CSHT(n) (((n) << DCR_CSHT_SHIFT) & DCR_CSHT_MASK)
-#define DCR_FSIZE_SHIFT 16
-#define DCR_FSIZE_MASK GENMASK(20, 16)
-#define DCR_FSIZE(n) (((n) << DCR_FSIZE_SHIFT) & DCR_FSIZE_MASK)
-
-#define QUADSPI_SR 0x08
-#define SR_TEF BIT(0)
-#define SR_TCF BIT(1)
-#define SR_FTF BIT(2)
-#define SR_SMF BIT(3)
-#define SR_TOF BIT(4)
-#define SR_BUSY BIT(5)
-#define SR_FLEVEL_SHIFT 8
-#define SR_FLEVEL_MASK GENMASK(13, 8)
-
-#define QUADSPI_FCR 0x0c
-#define FCR_CTCF BIT(1)
-
-#define QUADSPI_DLR 0x10
-
-#define QUADSPI_CCR 0x14
-#define CCR_INST_SHIFT 0
-#define CCR_INST_MASK GENMASK(7, 0)
-#define CCR_INST(n) (((n) << CCR_INST_SHIFT) & CCR_INST_MASK)
-#define CCR_IMODE_NONE (0U << 8)
-#define CCR_IMODE_1 (1U << 8)
-#define CCR_IMODE_2 (2U << 8)
-#define CCR_IMODE_4 (3U << 8)
-#define CCR_ADMODE_NONE (0U << 10)
-#define CCR_ADMODE_1 (1U << 10)
-#define CCR_ADMODE_2 (2U << 10)
-#define CCR_ADMODE_4 (3U << 10)
-#define CCR_ADSIZE_SHIFT 12
-#define CCR_ADSIZE_MASK GENMASK(13, 12)
-#define CCR_ADSIZE(n) (((n) << CCR_ADSIZE_SHIFT) & CCR_ADSIZE_MASK)
-#define CCR_ABMODE_NONE (0U << 14)
-#define CCR_ABMODE_1 (1U << 14)
-#define CCR_ABMODE_2 (2U << 14)
-#define CCR_ABMODE_4 (3U << 14)
-#define CCR_ABSIZE_8 (0U << 16)
-#define CCR_ABSIZE_16 (1U << 16)
-#define CCR_ABSIZE_24 (2U << 16)
-#define CCR_ABSIZE_32 (3U << 16)
-#define CCR_DCYC_SHIFT 18
-#define CCR_DCYC_MASK GENMASK(22, 18)
-#define CCR_DCYC(n) (((n) << CCR_DCYC_SHIFT) & CCR_DCYC_MASK)
-#define CCR_DMODE_NONE (0U << 24)
-#define CCR_DMODE_1 (1U << 24)
-#define CCR_DMODE_2 (2U << 24)
-#define CCR_DMODE_4 (3U << 24)
-#define CCR_FMODE_INDW (0U << 26)
-#define CCR_FMODE_INDR (1U << 26)
-#define CCR_FMODE_APM (2U << 26)
-#define CCR_FMODE_MM (3U << 26)
-
-#define QUADSPI_AR 0x18
-#define QUADSPI_ABR 0x1c
-#define QUADSPI_DR 0x20
-#define QUADSPI_PSMKR 0x24
-#define QUADSPI_PSMAR 0x28
-#define QUADSPI_PIR 0x2c
-#define QUADSPI_LPTR 0x30
-#define LPTR_DFT_TIMEOUT 0x10
-
-#define FSIZE_VAL(size) (__fls(size) - 1)
-
-#define STM32_MAX_MMAP_SZ SZ_256M
-#define STM32_MAX_NORCHIP 2
-
-#define STM32_QSPI_FIFO_SZ 32
-#define STM32_QSPI_FIFO_TIMEOUT_US 30000
-#define STM32_QSPI_BUSY_TIMEOUT_US 100000
-
-struct stm32_qspi_flash {
- struct spi_nor nor;
- struct stm32_qspi *qspi;
- u32 cs;
- u32 fsize;
- u32 presc;
- u32 read_mode;
- bool registered;
- u32 prefetch_limit;
-};
-
-struct stm32_qspi {
- struct device *dev;
- void __iomem *io_base;
- void __iomem *mm_base;
- resource_size_t mm_size;
- u32 nor_num;
- struct clk *clk;
- u32 clk_rate;
- struct stm32_qspi_flash flash[STM32_MAX_NORCHIP];
- struct completion cmd_completion;
-
- /*
- * to protect device configuration, could be different between
- * 2 flash access (bk1, bk2)
- */
- struct mutex lock;
-};
-
-struct stm32_qspi_cmd {
- u8 addr_width;
- u8 dummy;
- bool tx_data;
- u8 opcode;
- u32 framemode;
- u32 qspimode;
- u32 addr;
- size_t len;
- void *buf;
-};
-
-static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi)
-{
- u32 cr;
- int err = 0;
-
- if (readl_relaxed(qspi->io_base + QUADSPI_SR) & SR_TCF)
- return 0;
-
- reinit_completion(&qspi->cmd_completion);
- cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
- writel_relaxed(cr | CR_TCIE, qspi->io_base + QUADSPI_CR);
-
- if (!wait_for_completion_interruptible_timeout(&qspi->cmd_completion,
- msecs_to_jiffies(1000)))
- err = -ETIMEDOUT;
-
- writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
- return err;
-}
-
-static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi)
-{
- u32 sr;
-
- return readl_relaxed_poll_timeout(qspi->io_base + QUADSPI_SR, sr,
- !(sr & SR_BUSY), 10,
- STM32_QSPI_BUSY_TIMEOUT_US);
-}
-
-static void stm32_qspi_set_framemode(struct spi_nor *nor,
- struct stm32_qspi_cmd *cmd, bool read)
-{
- u32 dmode = CCR_DMODE_1;
-
- cmd->framemode = CCR_IMODE_1;
-
- if (read) {
- switch (nor->read_proto) {
- default:
- case SNOR_PROTO_1_1_1:
- dmode = CCR_DMODE_1;
- break;
- case SNOR_PROTO_1_1_2:
- dmode = CCR_DMODE_2;
- break;
- case SNOR_PROTO_1_1_4:
- dmode = CCR_DMODE_4;
- break;
- }
- }
-
- cmd->framemode |= cmd->tx_data ? dmode : 0;
- cmd->framemode |= cmd->addr_width ? CCR_ADMODE_1 : 0;
-}
-
-static void stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
-{
- *val = readb_relaxed(addr);
-}
-
-static void stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
-{
- writeb_relaxed(*val, addr);
-}
-
-static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
- const struct stm32_qspi_cmd *cmd)
-{
- void (*tx_fifo)(u8 *, void __iomem *);
- u32 len = cmd->len, sr;
- u8 *buf = cmd->buf;
- int ret;
-
- if (cmd->qspimode == CCR_FMODE_INDW)
- tx_fifo = stm32_qspi_write_fifo;
- else
- tx_fifo = stm32_qspi_read_fifo;
-
- while (len--) {
- ret = readl_relaxed_poll_timeout(qspi->io_base + QUADSPI_SR,
- sr, (sr & SR_FTF), 10,
- STM32_QSPI_FIFO_TIMEOUT_US);
- if (ret) {
- dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr);
- return ret;
- }
- tx_fifo(buf++, qspi->io_base + QUADSPI_DR);
- }
-
- return 0;
-}
-
-static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
- const struct stm32_qspi_cmd *cmd)
-{
- memcpy_fromio(cmd->buf, qspi->mm_base + cmd->addr, cmd->len);
- return 0;
-}
-
-static int stm32_qspi_tx(struct stm32_qspi *qspi,
- const struct stm32_qspi_cmd *cmd)
-{
- if (!cmd->tx_data)
- return 0;
-
- if (cmd->qspimode == CCR_FMODE_MM)
- return stm32_qspi_tx_mm(qspi, cmd);
-
- return stm32_qspi_tx_poll(qspi, cmd);
-}
-
-static int stm32_qspi_send(struct stm32_qspi_flash *flash,
- const struct stm32_qspi_cmd *cmd)
-{
- struct stm32_qspi *qspi = flash->qspi;
- u32 ccr, dcr, cr;
- u32 last_byte;
- int err;
-
- err = stm32_qspi_wait_nobusy(qspi);
- if (err)
- goto abort;
-
- dcr = readl_relaxed(qspi->io_base + QUADSPI_DCR) & ~DCR_FSIZE_MASK;
- dcr |= DCR_FSIZE(flash->fsize);
- writel_relaxed(dcr, qspi->io_base + QUADSPI_DCR);
-
- cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
- cr &= ~CR_PRESC_MASK & ~CR_FSEL;
- cr |= CR_PRESC(flash->presc);
- cr |= flash->cs ? CR_FSEL : 0;
- writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
-
- if (cmd->tx_data)
- writel_relaxed(cmd->len - 1, qspi->io_base + QUADSPI_DLR);
-
- ccr = cmd->framemode | cmd->qspimode;
-
- if (cmd->dummy)
- ccr |= CCR_DCYC(cmd->dummy);
-
- if (cmd->addr_width)
- ccr |= CCR_ADSIZE(cmd->addr_width - 1);
-
- ccr |= CCR_INST(cmd->opcode);
- writel_relaxed(ccr, qspi->io_base + QUADSPI_CCR);
-
- if (cmd->addr_width && cmd->qspimode != CCR_FMODE_MM)
- writel_relaxed(cmd->addr, qspi->io_base + QUADSPI_AR);
-
- err = stm32_qspi_tx(qspi, cmd);
- if (err)
- goto abort;
-
- if (cmd->qspimode != CCR_FMODE_MM) {
- err = stm32_qspi_wait_cmd(qspi);
- if (err)
- goto abort;
- writel_relaxed(FCR_CTCF, qspi->io_base + QUADSPI_FCR);
- } else {
- last_byte = cmd->addr + cmd->len;
- if (last_byte > flash->prefetch_limit)
- goto abort;
- }
-
- return err;
-
-abort:
- cr = readl_relaxed(qspi->io_base + QUADSPI_CR) | CR_ABORT;
- writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
-
- if (err)
- dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
-
- return err;
-}
-
-static int stm32_qspi_read_reg(struct spi_nor *nor,
- u8 opcode, u8 *buf, int len)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct device *dev = flash->qspi->dev;
- struct stm32_qspi_cmd cmd;
-
- dev_dbg(dev, "read_reg: cmd:%#.2x buf:%pK len:%#x\n", opcode, buf, len);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = opcode;
- cmd.tx_data = true;
- cmd.len = len;
- cmd.buf = buf;
- cmd.qspimode = CCR_FMODE_INDR;
-
- stm32_qspi_set_framemode(nor, &cmd, false);
-
- return stm32_qspi_send(flash, &cmd);
-}
-
-static int stm32_qspi_write_reg(struct spi_nor *nor, u8 opcode,
- u8 *buf, int len)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct device *dev = flash->qspi->dev;
- struct stm32_qspi_cmd cmd;
-
- dev_dbg(dev, "write_reg: cmd:%#.2x buf:%pK len:%#x\n", opcode, buf, len);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = opcode;
- cmd.tx_data = !!(buf && len > 0);
- cmd.len = len;
- cmd.buf = buf;
- cmd.qspimode = CCR_FMODE_INDW;
-
- stm32_qspi_set_framemode(nor, &cmd, false);
-
- return stm32_qspi_send(flash, &cmd);
-}
-
-static ssize_t stm32_qspi_read(struct spi_nor *nor, loff_t from, size_t len,
- u_char *buf)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct stm32_qspi *qspi = flash->qspi;
- struct stm32_qspi_cmd cmd;
- int err;
-
- dev_dbg(qspi->dev, "read(%#.2x): buf:%pK from:%#.8x len:%#zx\n",
- nor->read_opcode, buf, (u32)from, len);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = nor->read_opcode;
- cmd.addr_width = nor->addr_width;
- cmd.addr = (u32)from;
- cmd.tx_data = true;
- cmd.dummy = nor->read_dummy;
- cmd.len = len;
- cmd.buf = buf;
- cmd.qspimode = flash->read_mode;
-
- stm32_qspi_set_framemode(nor, &cmd, true);
- err = stm32_qspi_send(flash, &cmd);
-
- return err ? err : len;
-}
-
-static ssize_t stm32_qspi_write(struct spi_nor *nor, loff_t to, size_t len,
- const u_char *buf)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct device *dev = flash->qspi->dev;
- struct stm32_qspi_cmd cmd;
- int err;
-
- dev_dbg(dev, "write(%#.2x): buf:%p to:%#.8x len:%#zx\n",
- nor->program_opcode, buf, (u32)to, len);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = nor->program_opcode;
- cmd.addr_width = nor->addr_width;
- cmd.addr = (u32)to;
- cmd.tx_data = true;
- cmd.len = len;
- cmd.buf = (void *)buf;
- cmd.qspimode = CCR_FMODE_INDW;
-
- stm32_qspi_set_framemode(nor, &cmd, false);
- err = stm32_qspi_send(flash, &cmd);
-
- return err ? err : len;
-}
-
-static int stm32_qspi_erase(struct spi_nor *nor, loff_t offs)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct device *dev = flash->qspi->dev;
- struct stm32_qspi_cmd cmd;
-
- dev_dbg(dev, "erase(%#.2x):offs:%#x\n", nor->erase_opcode, (u32)offs);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = nor->erase_opcode;
- cmd.addr_width = nor->addr_width;
- cmd.addr = (u32)offs;
- cmd.qspimode = CCR_FMODE_INDW;
-
- stm32_qspi_set_framemode(nor, &cmd, false);
-
- return stm32_qspi_send(flash, &cmd);
-}
-
-static irqreturn_t stm32_qspi_irq(int irq, void *dev_id)
-{
- struct stm32_qspi *qspi = (struct stm32_qspi *)dev_id;
- u32 cr, sr, fcr = 0;
-
- cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
- sr = readl_relaxed(qspi->io_base + QUADSPI_SR);
-
- if ((cr & CR_TCIE) && (sr & SR_TCF)) {
- /* tx complete */
- fcr |= FCR_CTCF;
- complete(&qspi->cmd_completion);
- } else {
- dev_info_ratelimited(qspi->dev, "spurious interrupt\n");
- }
-
- writel_relaxed(fcr, qspi->io_base + QUADSPI_FCR);
-
- return IRQ_HANDLED;
-}
-
-static int stm32_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct stm32_qspi *qspi = flash->qspi;
-
- mutex_lock(&qspi->lock);
- return 0;
-}
-
-static void stm32_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
-{
- struct stm32_qspi_flash *flash = nor->priv;
- struct stm32_qspi *qspi = flash->qspi;
-
- mutex_unlock(&qspi->lock);
-}
-
-static int stm32_qspi_flash_setup(struct stm32_qspi *qspi,
- struct device_node *np)
-{
- struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ |
- SNOR_HWCAPS_READ_FAST |
- SNOR_HWCAPS_PP,
- };
- u32 width, presc, cs_num, max_rate = 0;
- struct stm32_qspi_flash *flash;
- struct mtd_info *mtd;
- int ret;
-
- of_property_read_u32(np, "reg", &cs_num);
- if (cs_num >= STM32_MAX_NORCHIP)
- return -EINVAL;
-
- of_property_read_u32(np, "spi-max-frequency", &max_rate);
- if (!max_rate)
- return -EINVAL;
-
- presc = DIV_ROUND_UP(qspi->clk_rate, max_rate) - 1;
-
- if (of_property_read_u32(np, "spi-rx-bus-width", &width))
- width = 1;
-
- if (width == 4)
- hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
- else if (width == 2)
- hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
- else if (width != 1)
- return -EINVAL;
-
- flash = &qspi->flash[cs_num];
- flash->qspi = qspi;
- flash->cs = cs_num;
- flash->presc = presc;
-
- flash->nor.dev = qspi->dev;
- spi_nor_set_flash_node(&flash->nor, np);
- flash->nor.priv = flash;
- mtd = &flash->nor.mtd;
-
- flash->nor.read = stm32_qspi_read;
- flash->nor.write = stm32_qspi_write;
- flash->nor.erase = stm32_qspi_erase;
- flash->nor.read_reg = stm32_qspi_read_reg;
- flash->nor.write_reg = stm32_qspi_write_reg;
- flash->nor.prepare = stm32_qspi_prep;
- flash->nor.unprepare = stm32_qspi_unprep;
-
- writel_relaxed(LPTR_DFT_TIMEOUT, qspi->io_base + QUADSPI_LPTR);
-
- writel_relaxed(CR_PRESC(presc) | CR_FTHRES(3) | CR_TCEN | CR_SSHIFT
- | CR_EN, qspi->io_base + QUADSPI_CR);
-
- /*
- * in stm32 qspi controller, QUADSPI_DCR register has a fsize field
- * which define the size of nor flash.
- * if fsize is NULL, the controller can't sent spi-nor command.
- * set a temporary value just to discover the nor flash with
- * "spi_nor_scan". After, the right value (mtd->size) can be set.
- */
- flash->fsize = FSIZE_VAL(SZ_1K);
-
- ret = spi_nor_scan(&flash->nor, NULL, &hwcaps);
- if (ret) {
- dev_err(qspi->dev, "device scan failed\n");
- return ret;
- }
-
- flash->fsize = FSIZE_VAL(mtd->size);
- flash->prefetch_limit = mtd->size - STM32_QSPI_FIFO_SZ;
-
- flash->read_mode = CCR_FMODE_MM;
- if (mtd->size > qspi->mm_size)
- flash->read_mode = CCR_FMODE_INDR;
-
- writel_relaxed(DCR_CSHT(1), qspi->io_base + QUADSPI_DCR);
-
- ret = mtd_device_register(mtd, NULL, 0);
- if (ret) {
- dev_err(qspi->dev, "mtd device parse failed\n");
- return ret;
- }
-
- flash->registered = true;
-
- dev_dbg(qspi->dev, "read mm:%s cs:%d bus:%d\n",
- flash->read_mode == CCR_FMODE_MM ? "yes" : "no", cs_num, width);
-
- return 0;
-}
-
-static void stm32_qspi_mtd_free(struct stm32_qspi *qspi)
-{
- int i;
-
- for (i = 0; i < STM32_MAX_NORCHIP; i++)
- if (qspi->flash[i].registered)
- mtd_device_unregister(&qspi->flash[i].nor.mtd);
-}
-
-static int stm32_qspi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *flash_np;
- struct reset_control *rstc;
- struct stm32_qspi *qspi;
- struct resource *res;
- int ret, irq;
-
- qspi = devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL);
- if (!qspi)
- return -ENOMEM;
-
- qspi->nor_num = of_get_child_count(dev->of_node);
- if (!qspi->nor_num || qspi->nor_num > STM32_MAX_NORCHIP)
- return -ENODEV;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi");
- qspi->io_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(qspi->io_base))
- return PTR_ERR(qspi->io_base);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm");
- qspi->mm_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(qspi->mm_base))
- return PTR_ERR(qspi->mm_base);
-
- qspi->mm_size = resource_size(res);
-
- irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
- dev_name(dev), qspi);
- if (ret) {
- dev_err(dev, "failed to request irq\n");
- return ret;
- }
-
- init_completion(&qspi->cmd_completion);
-
- qspi->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(qspi->clk))
- return PTR_ERR(qspi->clk);
-
- qspi->clk_rate = clk_get_rate(qspi->clk);
- if (!qspi->clk_rate)
- return -EINVAL;
-
- ret = clk_prepare_enable(qspi->clk);
- if (ret) {
- dev_err(dev, "can not enable the clock\n");
- return ret;
- }
-
- rstc = devm_reset_control_get_exclusive(dev, NULL);
- if (!IS_ERR(rstc)) {
- reset_control_assert(rstc);
- udelay(2);
- reset_control_deassert(rstc);
- }
-
- qspi->dev = dev;
- platform_set_drvdata(pdev, qspi);
- mutex_init(&qspi->lock);
-
- for_each_available_child_of_node(dev->of_node, flash_np) {
- ret = stm32_qspi_flash_setup(qspi, flash_np);
- if (ret) {
- dev_err(dev, "unable to setup flash chip\n");
- goto err_flash;
- }
- }
-
- return 0;
-
-err_flash:
- mutex_destroy(&qspi->lock);
- stm32_qspi_mtd_free(qspi);
-
- clk_disable_unprepare(qspi->clk);
- return ret;
-}
-
-static int stm32_qspi_remove(struct platform_device *pdev)
-{
- struct stm32_qspi *qspi = platform_get_drvdata(pdev);
-
- /* disable qspi */
- writel_relaxed(0, qspi->io_base + QUADSPI_CR);
-
- stm32_qspi_mtd_free(qspi);
- mutex_destroy(&qspi->lock);
-
- clk_disable_unprepare(qspi->clk);
- return 0;
-}
-
-static const struct of_device_id stm32_qspi_match[] = {
- {.compatible = "st,stm32f469-qspi"},
- {}
-};
-MODULE_DEVICE_TABLE(of, stm32_qspi_match);
-
-static struct platform_driver stm32_qspi_driver = {
- .probe = stm32_qspi_probe,
- .remove = stm32_qspi_remove,
- .driver = {
- .name = "stm32-quadspi",
- .of_match_table = stm32_qspi_match,
- },
-};
-module_platform_driver(stm32_qspi_driver);
-
-MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics STM32 quad spi driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 27709f866c23..232e8cc96f6d 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -14,7 +14,7 @@
#include <linux/of_platform.h>
#include <linux/if_bridge.h>
#include <linux/mdio.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/etherdevice.h>
#include "qca8k.h"
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
index a76529a7662d..c2e92786608b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
@@ -1054,14 +1054,12 @@ static void cudbg_t4_fwcache(struct cudbg_init *pdbg_init,
}
}
-static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
- struct cudbg_buffer *dbg_buff,
- struct cudbg_error *cudbg_err,
- u8 mem_type)
+static unsigned long cudbg_mem_region_size(struct cudbg_init *pdbg_init,
+ struct cudbg_error *cudbg_err,
+ u8 mem_type)
{
struct adapter *padap = pdbg_init->adap;
struct cudbg_meminfo mem_info;
- unsigned long size;
u8 mc_idx;
int rc;
@@ -1075,7 +1073,16 @@ static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
if (rc)
return rc;
- size = mem_info.avail[mc_idx].limit - mem_info.avail[mc_idx].base;
+ return mem_info.avail[mc_idx].limit - mem_info.avail[mc_idx].base;
+}
+
+static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
+ struct cudbg_buffer *dbg_buff,
+ struct cudbg_error *cudbg_err,
+ u8 mem_type)
+{
+ unsigned long size = cudbg_mem_region_size(pdbg_init, cudbg_err, mem_type);
+
return cudbg_read_fw_mem(pdbg_init, dbg_buff, mem_type, size,
cudbg_err);
}
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 625635771b83..d60452845539 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -899,7 +899,6 @@ static int hip04_mac_probe(struct platform_device *pdev)
struct of_phandle_args arg;
struct net_device *ndev;
struct hip04_priv *priv;
- struct resource *res;
int irq;
int ret;
@@ -912,16 +911,14 @@ static int hip04_mac_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev);
SET_NETDEV_DEV(ndev, &pdev->dev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(d, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base);
goto init_fail;
}
#if defined(CONFIG_HI13X1_GMAC)
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- priv->sysctrl_base = devm_ioremap_resource(d, res);
+ priv->sysctrl_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(priv->sysctrl_base)) {
ret = PTR_ERR(priv->sysctrl_base);
goto init_fail;
diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c
index d2e019d89a6f..689f18e3100f 100644
--- a/drivers/net/ethernet/hisilicon/hisi_femac.c
+++ b/drivers/net/ethernet/hisilicon/hisi_femac.c
@@ -781,7 +781,6 @@ static int hisi_femac_drv_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
- struct resource *res;
struct net_device *ndev;
struct hisi_femac_priv *priv;
struct phy_device *phy;
@@ -799,15 +798,13 @@ static int hisi_femac_drv_probe(struct platform_device *pdev)
priv->dev = dev;
priv->ndev = ndev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->port_base = devm_ioremap_resource(dev, res);
+ priv->port_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->port_base)) {
ret = PTR_ERR(priv->port_base);
goto out_free_netdev;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- priv->glb_base = devm_ioremap_resource(dev, res);
+ priv->glb_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(priv->glb_base)) {
ret = PTR_ERR(priv->glb_base);
goto out_free_netdev;
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index 89ef764e1c4b..349970557c52 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -1097,7 +1097,6 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
const struct of_device_id *of_id = NULL;
struct net_device *ndev;
struct hix5hd2_priv *priv;
- struct resource *res;
struct mii_bus *bus;
const char *mac_addr;
int ret;
@@ -1119,15 +1118,13 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
}
priv->hw_cap = (unsigned long)of_id->data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base);
goto out_free_netdev;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- priv->ctrl_base = devm_ioremap_resource(dev, res);
+ priv->ctrl_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(priv->ctrl_base)) {
ret = PTR_ERR(priv->ctrl_base);
goto out_free_netdev;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index 09c16d88172e..bb6586d0e5af 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -754,7 +754,7 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
return (void *)misc_op;
}
-static int hns_dsaf_dev_match(struct device *dev, void *fwnode)
+static int hns_dsaf_dev_match(struct device *dev, const void *fwnode)
{
return dev->fwnode == fwnode;
}
diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c
index 918cab1c61cd..3e863a71c513 100644
--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -417,7 +417,6 @@ static int hns_mdio_probe(struct platform_device *pdev)
{
struct hns_mdio_device *mdio_dev;
struct mii_bus *new_bus;
- struct resource *res;
int ret = -ENODEV;
if (!pdev) {
@@ -442,8 +441,7 @@ static int hns_mdio_probe(struct platform_device *pdev)
new_bus->priv = mdio_dev;
new_bus->parent = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mdio_dev->vbase = devm_ioremap_resource(&pdev->dev, res);
+ mdio_dev->vbase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mdio_dev->vbase)) {
ret = PTR_ERR(mdio_dev->vbase);
return ret;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 28ec0d57941d..41c90f2ddb31 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -2286,7 +2286,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
struct ice_hw *hw;
int err;
- /* this driver uses devres, see Documentation/driver-model/devres.txt */
+ /* this driver uses devres, see Documentation/driver-model/devres.rst */
err = pcim_enable_device(pdev);
if (err)
return err;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index c6be599ed94d..bab94f763e2c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -723,7 +723,7 @@ struct mtk_soc_data {
#define MTK_MAX_DEVS 2
#define MTK_SGMII_PHYSPEED_AN BIT(31)
-#define MTK_SGMII_PHYSPEED_MASK GENMASK(0, 2)
+#define MTK_SGMII_PHYSPEED_MASK GENMASK(2, 0)
#define MTK_SGMII_PHYSPEED_1000 BIT(0)
#define MTK_SGMII_PHYSPEED_2500 BIT(1)
#define MTK_HAS_FLAGS(flags, _x) (((flags) & (_x)) == (_x))
diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 136f90ce5a65..ff509d42d818 100644
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -82,7 +82,7 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id)
return -EINVAL;
regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
- val &= ~GENMASK(2, 3);
+ val &= ~GENMASK(3, 2);
mode = ss->flags[id] & MTK_SGMII_PHYSPEED_MASK;
val |= (mode == MTK_SGMII_PHYSPEED_1000) ? 0 : BIT(2);
regmap_write(ss->regmap[id], ss->ana_rgc3, val);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h
index 879321b21616..d787bc0a4155 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h
@@ -81,7 +81,6 @@ mlx5e_ktls_type_check(struct mlx5_core_dev *mdev,
struct tls_crypto_info *crypto_info) { return false; }
#endif
-#ifdef CONFIG_MLX5_FPGA_TLS
enum {
MLX5_ACCEL_TLS_TX = BIT(0),
MLX5_ACCEL_TLS_RX = BIT(1),
@@ -103,6 +102,7 @@ struct mlx5_ifc_tls_flow_bits {
u8 reserved_at_2[0x1e];
};
+#ifdef CONFIG_MLX5_FPGA_TLS
int mlx5_accel_tls_add_flow(struct mlx5_core_dev *mdev, void *flow,
struct tls_crypto_info *crypto_info,
u32 start_offload_tcp_sn, u32 *p_swid,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 263558875f20..79d93d6c7d7a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -305,6 +305,7 @@ enum {
MLX5E_RQ_STATE_ENABLED,
MLX5E_RQ_STATE_AM,
MLX5E_RQ_STATE_NO_CSUM_COMPLETE,
+ MLX5E_RQ_STATE_CSUM_FULL, /* cqe_csum_full hw bit is set */
};
struct mlx5e_cq {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
index 476dd97f7f2f..f3d98748b211 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
@@ -142,22 +142,20 @@ static int mlx5e_tx_reporter_timeout_recover(struct mlx5e_txqsq *sq)
{
struct mlx5_eq_comp *eq = sq->cq.mcq.eq;
u32 eqe_count;
- int ret;
netdev_err(sq->channel->netdev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
eq->core.eqn, eq->core.cons_index, eq->core.irqn);
eqe_count = mlx5_eq_poll_irq_disabled(eq);
- ret = eqe_count ? false : true;
if (!eqe_count) {
clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
- return ret;
+ return -EIO;
}
netdev_err(sq->channel->netdev, "Recover %d eqes on EQ 0x%x\n",
eqe_count, eq->core.eqn);
sq->channel->stats->eq_rearm++;
- return ret;
+ return 0;
}
int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq)
@@ -264,13 +262,13 @@ static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state);
if (err)
- break;
+ goto unlock;
err = mlx5e_tx_reporter_build_diagnose_output(fmsg, sq->sqn,
state,
netif_xmit_stopped(sq->txq));
if (err)
- break;
+ goto unlock;
}
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
index 5c08891806f0..ea032f54197e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
@@ -25,23 +25,17 @@ static void
fill_static_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
{
struct tls_crypto_info *crypto_info = priv_tx->crypto_info;
+ struct tls12_crypto_info_aes_gcm_128 *info;
char *initial_rn, *gcm_iv;
u16 salt_sz, rec_seq_sz;
char *salt, *rec_seq;
u8 tls_version;
- switch (crypto_info->cipher_type) {
- case TLS_CIPHER_AES_GCM_128: {
- struct tls12_crypto_info_aes_gcm_128 *info =
- (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
-
- EXTRACT_INFO_FIELDS;
- break;
- }
- default:
- WARN_ON(1);
+ if (WARN_ON(crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128))
return;
- }
+
+ info = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
+ EXTRACT_INFO_FIELDS;
gcm_iv = MLX5_ADDR_OF(tls_static_params, ctx, gcm_iv);
initial_rn = MLX5_ADDR_OF(tls_static_params, ctx, initial_record_number);
@@ -234,24 +228,18 @@ tx_post_resync_params(struct mlx5e_txqsq *sq,
u64 rcd_sn)
{
struct tls_crypto_info *crypto_info = priv_tx->crypto_info;
+ struct tls12_crypto_info_aes_gcm_128 *info;
__be64 rn_be = cpu_to_be64(rcd_sn);
bool skip_static_post;
u16 rec_seq_sz;
char *rec_seq;
- switch (crypto_info->cipher_type) {
- case TLS_CIPHER_AES_GCM_128: {
- struct tls12_crypto_info_aes_gcm_128 *info =
- (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
-
- rec_seq = info->rec_seq;
- rec_seq_sz = sizeof(info->rec_seq);
- break;
- }
- default:
- WARN_ON(1);
+ if (WARN_ON(crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128))
return;
- }
+
+ info = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
+ rec_seq = info->rec_seq;
+ rec_seq_sz = sizeof(info->rec_seq);
skip_static_post = !memcmp(rec_seq, &rn_be, rec_seq_sz);
if (!skip_static_post)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 6d0ae87c8ded..47eea6b3a1c3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -889,6 +889,9 @@ int mlx5e_open_rq(struct mlx5e_channel *c, struct mlx5e_params *params,
if (err)
goto err_destroy_rq;
+ if (MLX5_CAP_ETH(c->mdev, cqe_checksum_full))
+ __set_bit(MLX5E_RQ_STATE_CSUM_FULL, &c->rq.state);
+
if (params->rx_dim_enabled)
__set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
@@ -3390,10 +3393,9 @@ static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
return 0;
}
-static int mlx5e_setup_tc_mqprio(struct net_device *netdev,
+static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv,
struct tc_mqprio_qopt *mqprio)
{
- struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_channels new_channels = {};
u8 tc = mqprio->num_tc;
int err = 0;
@@ -3475,7 +3477,7 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
priv, priv, true);
#endif
case TC_SETUP_QDISC_MQPRIO:
- return mlx5e_setup_tc_mqprio(dev, type_data);
+ return mlx5e_setup_tc_mqprio(priv, type_data);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 10ef90a7bddd..7245d287633d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1175,6 +1175,8 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
}
}
+static LIST_HEAD(mlx5e_rep_block_cb_list);
+
static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -1182,7 +1184,8 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return flow_block_cb_setup_simple(type_data, NULL,
+ return flow_block_cb_setup_simple(type_data,
+ &mlx5e_rep_block_cb_list,
mlx5e_rep_setup_tc_cb,
priv, priv, true);
default:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 56a2f4666c47..ac6e586d403d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -923,8 +923,14 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP))
goto csum_unnecessary;
+ stats->csum_complete++;
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum = csum_unfold((__force __sum16)cqe->check_sum);
+
+ if (test_bit(MLX5E_RQ_STATE_CSUM_FULL, &rq->state))
+ return; /* CQE csum covers all received bytes */
+
+ /* csum might need some fixups ...*/
if (network_depth > ETH_HLEN)
/* CQE csum is calculated from the IP header and does
* not cover VLAN headers (if present). This will add
@@ -935,7 +941,6 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
skb->csum);
mlx5e_skb_padding_csum(skb, network_depth, proto, stats);
- stats->csum_complete++;
return;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 7281f8d6cba6..3b04d8927fb1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -1946,11 +1946,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
esw->enabled_vports = 0;
esw->mode = MLX5_ESWITCH_NONE;
esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
- if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
- MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
- else
- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
dev->priv.eswitch = esw;
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 8ed4497929b9..957d9b09dc3f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -1785,8 +1785,8 @@ static int esw_vport_add_ingress_acl_modify_metadata(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
u8 action[MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)] = {};
+ static const struct mlx5_flow_spec spec = {};
struct mlx5_flow_act flow_act = {};
- struct mlx5_flow_spec spec = {};
int err = 0;
MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
@@ -2131,6 +2131,12 @@ int esw_offloads_init(struct mlx5_eswitch *esw)
{
int err;
+ if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat) &&
+ MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, decap))
+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
+ else
+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
+
err = esw_offloads_steering_init(esw);
if (err)
return err;
@@ -2187,6 +2193,7 @@ void esw_offloads_cleanup(struct mlx5_eswitch *esw)
if (mlx5_eswitch_vport_match_metadata_enabled(esw))
mlx5_eswitch_disable_passing_vport_metadata(esw);
esw_offloads_steering_cleanup(esw);
+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
}
static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index faf197d53743..6bfaaab362dc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -711,7 +711,9 @@ static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u8 port_num,
prof->init(mdev, netdev, prof, ipriv);
- mlx5e_attach_netdev(epriv);
+ err = mlx5e_attach_netdev(epriv);
+ if (err)
+ goto detach;
netif_carrier_off(netdev);
/* set rdma_netdev func pointers */
@@ -727,6 +729,11 @@ static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u8 port_num,
return 0;
+detach:
+ prof->cleanup(epriv);
+ if (ipriv->sub_interface)
+ return err;
+ mlx5e_destroy_mdev_resources(mdev);
destroy_ht:
mlx5i_pkey_qpn_ht_cleanup(netdev);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
index be69c1d7941a..48b5c847b642 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c
@@ -98,27 +98,12 @@ static int mlx5_set_entropy(struct mlx5_tun_entropy *tun_entropy,
*/
if (entropy_flags.gre_calc_supported &&
reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) {
- /* Other applications may change the global FW entropy
- * calculations settings. Check that the current entropy value
- * is the negative of the updated value.
- */
- if (entropy_flags.force_enabled &&
- enable == entropy_flags.gre_calc_enabled) {
- mlx5_core_warn(tun_entropy->mdev,
- "Unexpected GRE entropy calc setting - expected %d",
- !entropy_flags.gre_calc_enabled);
- return -EOPNOTSUPP;
- }
- err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev, enable,
- entropy_flags.force_supported);
+ if (!entropy_flags.force_supported)
+ return 0;
+ err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev,
+ enable, !enable);
if (err)
return err;
- /* if we turn on the entropy we don't need to force it anymore */
- if (entropy_flags.force_supported && enable) {
- err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev, 1, 0);
- if (err)
- return err;
- }
} else if (entropy_flags.calc_supported) {
/* Other applications may change the global FW entropy
* calculations settings. Check that the current entropy value
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 7e725fa60347..faa8ba012a37 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -368,15 +368,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
break;
default:
- /* Other ethtype - we need check the masks for the
- * remainder of the key to ensure we can offload.
- */
- if (nfp_flower_check_higher_than_mac(flow)) {
- NL_SET_ERR_MSG_MOD(extack, "unsupported offload: non IPv4/IPv6 offload with L3/L4 matches not supported");
- return -EOPNOTSUPP;
- }
- break;
+ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: match on given EtherType is not supported");
+ return -EOPNOTSUPP;
}
+ } else if (nfp_flower_check_higher_than_mac(flow)) {
+ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: cannot match above L2 without specified EtherType");
+ return -EOPNOTSUPP;
}
if (basic.mask && basic.mask->ip_proto) {
@@ -389,18 +386,15 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
key_layer |= NFP_FLOWER_LAYER_TP;
key_size += sizeof(struct nfp_flower_tp_ports);
break;
- default:
- /* Other ip proto - we need check the masks for the
- * remainder of the key to ensure we can offload.
- */
- if (nfp_flower_check_higher_than_l3(flow)) {
- NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unknown IP protocol with L4 matches not supported");
- return -EOPNOTSUPP;
- }
- break;
}
}
+ if (!(key_layer & NFP_FLOWER_LAYER_TP) &&
+ nfp_flower_check_higher_than_l3(flow)) {
+ NL_SET_ERR_MSG_MOD(extack, "unsupported offload: cannot match on L4 information without specified IP protocol type");
+ return -EOPNOTSUPP;
+ }
+
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
struct flow_match_tcp tcp;
u32 tcp_flags;
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 10429b05f932..9f0b9a9e63b3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -123,7 +123,7 @@
#define ETDES1_BUFFER2_SIZE_SHIFT 16
/* Extended Receive descriptor definitions */
-#define ERDES4_IP_PAYLOAD_TYPE_MASK GENMASK(2, 6)
+#define ERDES4_IP_PAYLOAD_TYPE_MASK GENMASK(6, 2)
#define ERDES4_IP_HDR_ERR BIT(3)
#define ERDES4_IP_PAYLOAD_ERR BIT(4)
#define ERDES4_IP_CSUM_BYPASSED BIT(5)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 2856f3fe5266..4083019c547a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -192,7 +192,7 @@ static const struct emac_variant emac_variant_h6 = {
/* Used in RX_CTL1*/
#define EMAC_RX_MD BIT(1)
-#define EMAC_RX_TH_MASK GENMASK(4, 5)
+#define EMAC_RX_TH_MASK GENMASK(5, 4)
#define EMAC_RX_TH_32 0
#define EMAC_RX_TH_64 (0x1 << 4)
#define EMAC_RX_TH_96 (0x2 << 4)
@@ -203,7 +203,7 @@ static const struct emac_variant emac_variant_h6 = {
/* Used in TX_CTL1*/
#define EMAC_TX_MD BIT(1)
#define EMAC_TX_NEXT_FRM BIT(2)
-#define EMAC_TX_TH_MASK GENMASK(8, 10)
+#define EMAC_TX_TH_MASK GENMASK(10, 8)
#define EMAC_TX_TH_64 0
#define EMAC_TX_TH_128 (0x1 << 8)
#define EMAC_TX_TH_192 (0x2 << 8)
diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c
index 48e0924259f5..4e184eecc8e1 100644
--- a/drivers/net/ethernet/ti/cpsw-phy-sel.c
+++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c
@@ -151,9 +151,9 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv,
}
static struct platform_driver cpsw_phy_sel_driver;
-static int match(struct device *dev, void *data)
+static int match(struct device *dev, const void *data)
{
- struct device_node *node = (struct device_node *)data;
+ const struct device_node *node = (const struct device_node *)data;
return dev->of_node == node &&
dev->driver == &cpsw_phy_sel_driver.driver;
}
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 0ca2a1a254de..a65edd2770e6 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -138,8 +138,8 @@ struct submit_info {
struct cpdma_chan *chan;
int directed;
void *token;
- void *data;
- int flags;
+ void *data_virt;
+ dma_addr_t data_dma;
int len;
};
@@ -1043,12 +1043,12 @@ static int cpdma_chan_submit_si(struct submit_info *si)
mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
cpdma_desc_to_port(chan, mode, si->directed);
- if (si->flags & CPDMA_DMA_EXT_MAP) {
- buffer = (dma_addr_t)si->data;
+ if (si->data_dma) {
+ buffer = si->data_dma;
dma_sync_single_for_device(ctlr->dev, buffer, len, chan->dir);
swlen |= CPDMA_DMA_EXT_MAP;
} else {
- buffer = dma_map_single(ctlr->dev, si->data, len, chan->dir);
+ buffer = dma_map_single(ctlr->dev, si->data_virt, len, chan->dir);
ret = dma_mapping_error(ctlr->dev, buffer);
if (ret) {
cpdma_desc_free(ctlr->pool, desc, 1);
@@ -1086,10 +1086,10 @@ int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
si.chan = chan;
si.token = token;
- si.data = data;
+ si.data_virt = data;
+ si.data_dma = 0;
si.len = len;
si.directed = directed;
- si.flags = 0;
spin_lock_irqsave(&chan->lock, flags);
if (chan->state == CPDMA_STATE_TEARDOWN) {
@@ -1111,10 +1111,10 @@ int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
si.chan = chan;
si.token = token;
- si.data = (void *)data;
+ si.data_virt = NULL;
+ si.data_dma = data;
si.len = len;
si.directed = directed;
- si.flags = CPDMA_DMA_EXT_MAP;
spin_lock_irqsave(&chan->lock, flags);
if (chan->state == CPDMA_STATE_TEARDOWN) {
@@ -1136,10 +1136,10 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
si.chan = chan;
si.token = token;
- si.data = data;
+ si.data_virt = data;
+ si.data_dma = 0;
si.len = len;
si.directed = directed;
- si.flags = 0;
spin_lock_irqsave(&chan->lock, flags);
if (chan->state != CPDMA_STATE_ACTIVE) {
@@ -1161,10 +1161,10 @@ int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,
si.chan = chan;
si.token = token;
- si.data = (void *)data;
+ si.data_virt = NULL;
+ si.data_dma = data;
si.len = len;
si.directed = directed;
- si.flags = CPDMA_DMA_EXT_MAP;
spin_lock_irqsave(&chan->lock, flags);
if (chan->state != CPDMA_STATE_ACTIVE) {
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 5f4ece0d5a73..ae27be85e363 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1371,7 +1371,7 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
return -EOPNOTSUPP;
}
-static int match_first_device(struct device *dev, void *data)
+static int match_first_device(struct device *dev, const void *data)
{
if (dev->parent && dev->parent->of_node)
return of_device_is_compatible(dev->parent->of_node,
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index c50a9772f4af..8479a440527b 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -694,10 +694,10 @@ err_out:
* should provide a "tc35815-mac" device with a MAC address in its
* platform_data.
*/
-static int tc35815_mac_match(struct device *dev, void *data)
+static int tc35815_mac_match(struct device *dev, const void *data)
{
struct platform_device *plat_dev = to_platform_device(dev);
- struct pci_dev *pci_dev = data;
+ const struct pci_dev *pci_dev = data;
unsigned int id = pci_dev->irq;
return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 53878908adf4..6b5cb87f3866 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -56,19 +56,19 @@ EXPORT_SYMBOL_GPL(phy_10gbit_features);
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
EXPORT_SYMBOL_GPL(phy_10gbit_fec_features);
-static const int phy_basic_ports_array[] = {
+const int phy_basic_ports_array[3] = {
ETHTOOL_LINK_MODE_Autoneg_BIT,
ETHTOOL_LINK_MODE_TP_BIT,
ETHTOOL_LINK_MODE_MII_BIT,
};
EXPORT_SYMBOL_GPL(phy_basic_ports_array);
-static const int phy_fibre_port_array[] = {
+const int phy_fibre_port_array[1] = {
ETHTOOL_LINK_MODE_FIBRE_BIT,
};
EXPORT_SYMBOL_GPL(phy_fibre_port_array);
-static const int phy_all_ports_features_array[] = {
+const int phy_all_ports_features_array[7] = {
ETHTOOL_LINK_MODE_Autoneg_BIT,
ETHTOOL_LINK_MODE_TP_BIT,
ETHTOOL_LINK_MODE_MII_BIT,
diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c
index bd3c80b0bc77..de3b57d09d0c 100644
--- a/drivers/net/ppp/ppp_mppe.c
+++ b/drivers/net/ppp/ppp_mppe.c
@@ -64,7 +64,6 @@ MODULE_AUTHOR("Frank Cusack <fcusack@fcusack.com>");
MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE));
-MODULE_SOFTDEP("pre: arc4");
MODULE_VERSION("1.0.2");
#define SHA1_PAD_SIZE 40
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 81caa3782ec0..3bdda1c98339 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -598,7 +598,7 @@ enum ht_channel_width {
HT_CHANNEL_WIDTH_MAX,
};
-/* Ref: 802.11i sepc D10.0 7.3.2.25.1
+/* Ref: 802.11i spec D10.0 7.3.2.25.1
* Cipher Suites Encryption Algorithms
*/
enum rt_enc_alg {
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index c7892c3da91f..ac5d945be88a 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -76,7 +76,7 @@ static struct bus_type nvmem_bus_type = {
.name = "nvmem",
};
-static int of_nvmem_match(struct device *dev, void *nvmem_np)
+static int of_nvmem_match(struct device *dev, const void *nvmem_np)
{
return dev->of_node == nvmem_np;
}
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 3b67896d9d74..44f53496cab1 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -281,7 +281,7 @@ unregister:
EXPORT_SYMBOL(of_mdiobus_register);
/* Helper function for of_phy_find_device */
-static int of_phy_match(struct device *dev, void *phy_np)
+static int of_phy_match(struct device *dev, const void *phy_np)
{
return dev->of_node == phy_np;
}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index efbff44581b3..7801e25e6895 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -37,7 +37,7 @@ static const struct of_device_id of_skipped_node_table[] = {
{} /* Empty terminated list */
};
-static int of_dev_node_match(struct device *dev, void *data)
+static int of_dev_node_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0e8e2c186f50..f9ef7ad3f75d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -64,7 +64,7 @@ static struct resource *get_pci_domain_busn_res(int domain_nr)
return &r->res;
}
-static int find_anything(struct device *dev, void *data)
+static int find_anything(struct device *dev, const void *data)
{
return 1;
}
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 5c7922612733..7f4e65872b8d 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -236,10 +236,10 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
}
EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
-static int match_pci_dev_by_id(struct device *dev, void *data)
+static int match_pci_dev_by_id(struct device *dev, const void *data)
{
struct pci_dev *pdev = to_pci_dev(dev);
- struct pci_device_id *id = data;
+ const struct pci_device_id *id = data;
if (pci_match_one_device(id, pdev))
return 1;
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
index 068729bf4f86..ea8962645e49 100644
--- a/drivers/pinctrl/aspeed/Makefile
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -2,6 +2,6 @@
# Aspeed pinctrl support
ccflags-y += $(call cc-option,-Woverride-init)
-obj-$(CONFIG_PINCTRL_ASPEED) += pinctrl-aspeed.o
+obj-$(CONFIG_PINCTRL_ASPEED) += pinctrl-aspeed.o pinmux-aspeed.o
obj-$(CONFIG_PINCTRL_ASPEED_G4) += pinctrl-aspeed-g4.o
obj-$(CONFIG_PINCTRL_ASPEED_G5) += pinctrl-aspeed-g5.o
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
index 73e2c9c0e549..384396cbb22d 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
@@ -18,9 +18,35 @@
#include "../core.h"
#include "../pinctrl-utils.h"
+#include "pinmux-aspeed.h"
#include "pinctrl-aspeed.h"
/*
+ * The "Multi-function Pins Mapping and Control" table in the SoC datasheet
+ * references registers by the device/offset mnemonic. The register macros
+ * below are named the same way to ease transcription and verification (as
+ * opposed to naming them e.g. PINMUX_CTRL_[0-9]). Further, signal expressions
+ * reference registers beyond those dedicated to pinmux, such as the system
+ * reset control and MAC clock configuration registers.
+ */
+#define SCU2C 0x2C /* Misc. Control Register */
+#define SCU3C 0x3C /* System Reset Control/Status Register */
+#define SCU48 0x48 /* MAC Interface Clock Delay Setting */
+#define HW_STRAP1 0x70 /* AST2400 strapping is 33 bits, is split */
+#define HW_REVISION_ID 0x7C /* Silicon revision ID register */
+#define SCU80 0x80 /* Multi-function Pin Control #1 */
+#define SCU84 0x84 /* Multi-function Pin Control #2 */
+#define SCU88 0x88 /* Multi-function Pin Control #3 */
+#define SCU8C 0x8C /* Multi-function Pin Control #4 */
+#define SCU90 0x90 /* Multi-function Pin Control #5 */
+#define SCU94 0x94 /* Multi-function Pin Control #6 */
+#define SCUA0 0xA0 /* Multi-function Pin Control #7 */
+#define SCUA4 0xA4 /* Multi-function Pin Control #8 */
+#define SCUA8 0xA8 /* Multi-function Pin Control #9 */
+#define SCUAC 0xAC /* Multi-function Pin Control #10 */
+#define HW_STRAP2 0xD0 /* Strapping */
+
+/*
* Uses undefined macros for symbol naming and references, eg GPIOA0, MAC1LINK,
* TIMER3 etc.
*
@@ -2386,13 +2412,73 @@ static const struct aspeed_pin_config aspeed_g4_configs[] = {
{ PIN_CONFIG_INPUT_DEBOUNCE, { C14, B14 }, SCUA8, 27 },
};
+static int aspeed_g4_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr,
+ bool enable)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < expr->ndescs; i++) {
+ const struct aspeed_sig_desc *desc = &expr->descs[i];
+ u32 pattern = enable ? desc->enable : desc->disable;
+ u32 val = (pattern << __ffs(desc->mask));
+
+ if (!ctx->maps[desc->ip])
+ return -ENODEV;
+
+ /*
+ * Strap registers are configured in hardware or by early-boot
+ * firmware. Treat them as read-only despite that we can write
+ * them. This may mean that certain functions cannot be
+ * deconfigured and is the reason we re-evaluate after writing
+ * all descriptor bits.
+ *
+ * Port D and port E GPIO loopback modes are the only exception
+ * as those are commonly used with front-panel buttons to allow
+ * normal operation of the host when the BMC is powered off or
+ * fails to boot. Once the BMC has booted, the loopback mode
+ * must be disabled for the BMC to control host power-on and
+ * reset.
+ */
+ if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP1 &&
+ !(desc->mask & (BIT(21) | BIT(22))))
+ continue;
+
+ if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP2)
+ continue;
+
+ ret = regmap_update_bits(ctx->maps[desc->ip], desc->reg,
+ desc->mask, val);
+
+ if (ret)
+ return ret;
+ }
+
+ ret = aspeed_sig_expr_eval(ctx, expr, enable);
+ if (ret < 0)
+ return ret;
+
+ if (!ret)
+ return -EPERM;
+
+ return 0;
+}
+
+static const struct aspeed_pinmux_ops aspeed_g4_ops = {
+ .set = aspeed_g4_sig_expr_set,
+};
+
static struct aspeed_pinctrl_data aspeed_g4_pinctrl_data = {
.pins = aspeed_g4_pins,
.npins = ARRAY_SIZE(aspeed_g4_pins),
- .groups = aspeed_g4_groups,
- .ngroups = ARRAY_SIZE(aspeed_g4_groups),
- .functions = aspeed_g4_functions,
- .nfunctions = ARRAY_SIZE(aspeed_g4_functions),
+ .pinmux = {
+ .ops = &aspeed_g4_ops,
+ .groups = aspeed_g4_groups,
+ .ngroups = ARRAY_SIZE(aspeed_g4_groups),
+ .functions = aspeed_g4_functions,
+ .nfunctions = ARRAY_SIZE(aspeed_g4_functions),
+ },
.configs = aspeed_g4_configs,
.nconfigs = ARRAY_SIZE(aspeed_g4_configs),
};
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index aa7e148b38bb..053101f795a2 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -21,6 +21,32 @@
#include "../pinctrl-utils.h"
#include "pinctrl-aspeed.h"
+/*
+ * The "Multi-function Pins Mapping and Control" table in the SoC datasheet
+ * references registers by the device/offset mnemonic. The register macros
+ * below are named the same way to ease transcription and verification (as
+ * opposed to naming them e.g. PINMUX_CTRL_[0-9]). Further, signal expressions
+ * reference registers beyond those dedicated to pinmux, such as the system
+ * reset control and MAC clock configuration registers. The AST2500 goes a step
+ * further and references registers in the graphics IP block.
+ */
+#define SCU2C 0x2C /* Misc. Control Register */
+#define SCU3C 0x3C /* System Reset Control/Status Register */
+#define SCU48 0x48 /* MAC Interface Clock Delay Setting */
+#define HW_STRAP1 0x70 /* AST2400 strapping is 33 bits, is split */
+#define HW_REVISION_ID 0x7C /* Silicon revision ID register */
+#define SCU80 0x80 /* Multi-function Pin Control #1 */
+#define SCU84 0x84 /* Multi-function Pin Control #2 */
+#define SCU88 0x88 /* Multi-function Pin Control #3 */
+#define SCU8C 0x8C /* Multi-function Pin Control #4 */
+#define SCU90 0x90 /* Multi-function Pin Control #5 */
+#define SCU94 0x94 /* Multi-function Pin Control #6 */
+#define SCUA0 0xA0 /* Multi-function Pin Control #7 */
+#define SCUA4 0xA4 /* Multi-function Pin Control #8 */
+#define SCUA8 0xA8 /* Multi-function Pin Control #9 */
+#define SCUAC 0xAC /* Multi-function Pin Control #10 */
+#define HW_STRAP2 0xD0 /* Strapping */
+
#define ASPEED_G5_NR_PINS 236
#define COND1 { ASPEED_IP_SCU, SCU90, BIT(6), 0, 0 }
@@ -573,6 +599,8 @@ SS_PIN_DECL(N3, GPIOJ2, SGPMO);
SIG_EXPR_LIST_DECL_SINGLE(SGPMI, SGPM, SIG_DESC_SET(SCU84, 11));
SS_PIN_DECL(N4, GPIOJ3, SGPMI);
+FUNC_GROUP_DECL(SGPM, R2, L2, N3, N4);
+
#define N5 76
SIG_EXPR_LIST_DECL_SINGLE(VGAHS, VGAHS, SIG_DESC_SET(SCU84, 12));
SIG_EXPR_LIST_DECL_SINGLE(DASHN5, DASHN5, SIG_DESC_SET(SCU94, 8));
@@ -2123,6 +2151,7 @@ static const struct aspeed_pin_group aspeed_g5_groups[] = {
ASPEED_PINCTRL_GROUP(SD2),
ASPEED_PINCTRL_GROUP(SDA1),
ASPEED_PINCTRL_GROUP(SDA2),
+ ASPEED_PINCTRL_GROUP(SGPM),
ASPEED_PINCTRL_GROUP(SGPS1),
ASPEED_PINCTRL_GROUP(SGPS2),
ASPEED_PINCTRL_GROUP(SIOONCTRL),
@@ -2292,6 +2321,7 @@ static const struct aspeed_pin_function aspeed_g5_functions[] = {
ASPEED_PINCTRL_FUNC(SD2),
ASPEED_PINCTRL_FUNC(SDA1),
ASPEED_PINCTRL_FUNC(SDA2),
+ ASPEED_PINCTRL_FUNC(SGPM),
ASPEED_PINCTRL_FUNC(SGPS1),
ASPEED_PINCTRL_FUNC(SGPS2),
ASPEED_PINCTRL_FUNC(SIOONCTRL),
@@ -2477,13 +2507,98 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
{ PIN_CONFIG_INPUT_DEBOUNCE, { A20, B19 }, SCUA8, 27 },
};
+/**
+ * Configure a pin's signal by applying an expression's descriptor state for
+ * all descriptors in the expression.
+ *
+ * @ctx: The pinmux context
+ * @expr: The expression associated with the function whose signal is to be
+ * configured
+ * @enable: true to enable an function's signal through a pin's signal
+ * expression, false to disable the function's signal
+ *
+ * Return: 0 if the expression is configured as requested and a negative error
+ * code otherwise
+ */
+static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr,
+ bool enable)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < expr->ndescs; i++) {
+ const struct aspeed_sig_desc *desc = &expr->descs[i];
+ u32 pattern = enable ? desc->enable : desc->disable;
+ u32 val = (pattern << __ffs(desc->mask));
+
+ if (!ctx->maps[desc->ip])
+ return -ENODEV;
+
+ /*
+ * Strap registers are configured in hardware or by early-boot
+ * firmware. Treat them as read-only despite that we can write
+ * them. This may mean that certain functions cannot be
+ * deconfigured and is the reason we re-evaluate after writing
+ * all descriptor bits.
+ *
+ * Port D and port E GPIO loopback modes are the only exception
+ * as those are commonly used with front-panel buttons to allow
+ * normal operation of the host when the BMC is powered off or
+ * fails to boot. Once the BMC has booted, the loopback mode
+ * must be disabled for the BMC to control host power-on and
+ * reset.
+ */
+ if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP1 &&
+ !(desc->mask & (BIT(21) | BIT(22))))
+ continue;
+
+ if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP2)
+ continue;
+
+ /* On AST2500, Set bits in SCU70 are cleared from SCU7C */
+ if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP1) {
+ u32 value = ~val & desc->mask;
+
+ if (value) {
+ ret = regmap_write(ctx->maps[desc->ip],
+ HW_REVISION_ID, value);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ ret = regmap_update_bits(ctx->maps[desc->ip], desc->reg,
+ desc->mask, val);
+
+ if (ret)
+ return ret;
+ }
+
+ ret = aspeed_sig_expr_eval(ctx, expr, enable);
+ if (ret < 0)
+ return ret;
+
+ if (!ret)
+ return -EPERM;
+
+ return 0;
+}
+
+static const struct aspeed_pinmux_ops aspeed_g5_ops = {
+ .set = aspeed_g5_sig_expr_set,
+};
+
static struct aspeed_pinctrl_data aspeed_g5_pinctrl_data = {
.pins = aspeed_g5_pins,
.npins = ARRAY_SIZE(aspeed_g5_pins),
- .groups = aspeed_g5_groups,
- .ngroups = ARRAY_SIZE(aspeed_g5_groups),
- .functions = aspeed_g5_functions,
- .nfunctions = ARRAY_SIZE(aspeed_g5_functions),
+ .pinmux = {
+ .ops = &aspeed_g5_ops,
+ .groups = aspeed_g5_groups,
+ .ngroups = ARRAY_SIZE(aspeed_g5_groups),
+ .functions = aspeed_g5_functions,
+ .nfunctions = ARRAY_SIZE(aspeed_g5_functions),
+ },
.configs = aspeed_g5_configs,
.nconfigs = ARRAY_SIZE(aspeed_g5_configs),
};
@@ -2539,7 +2654,7 @@ static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "No GFX phandle found, some mux configurations may fail\n");
map = NULL;
}
- aspeed_g5_pinctrl_data.maps[ASPEED_IP_GFX] = map;
+ aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_GFX] = map;
node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
if (node) {
@@ -2553,7 +2668,7 @@ static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
map = NULL;
}
of_node_put(node);
- aspeed_g5_pinctrl_data.maps[ASPEED_IP_LPC] = map;
+ aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_LPC] = map;
return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
&aspeed_g5_pinctrl_data);
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index 4c775b8ffdc4..535db3de490b 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -10,17 +10,11 @@
#include "../core.h"
#include "pinctrl-aspeed.h"
-static const char *const aspeed_pinmux_ips[] = {
- [ASPEED_IP_SCU] = "SCU",
- [ASPEED_IP_GFX] = "GFX",
- [ASPEED_IP_LPC] = "LPC",
-};
-
int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- return pdata->ngroups;
+ return pdata->pinmux.ngroups;
}
const char *aspeed_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
@@ -28,7 +22,7 @@ const char *aspeed_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- return pdata->groups[group].name;
+ return pdata->pinmux.groups[group].name;
}
int aspeed_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
@@ -37,8 +31,8 @@ int aspeed_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- *pins = &pdata->groups[group].pins[0];
- *npins = pdata->groups[group].npins;
+ *pins = &pdata->pinmux.groups[group].pins[0];
+ *npins = pdata->pinmux.groups[group].npins;
return 0;
}
@@ -53,7 +47,7 @@ int aspeed_pinmux_get_fn_count(struct pinctrl_dev *pctldev)
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- return pdata->nfunctions;
+ return pdata->pinmux.nfunctions;
}
const char *aspeed_pinmux_get_fn_name(struct pinctrl_dev *pctldev,
@@ -61,7 +55,7 @@ const char *aspeed_pinmux_get_fn_name(struct pinctrl_dev *pctldev,
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- return pdata->functions[function].name;
+ return pdata->pinmux.functions[function].name;
}
int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
@@ -71,208 +65,38 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
{
struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- *groups = pdata->functions[function].groups;
- *num_groups = pdata->functions[function].ngroups;
+ *groups = pdata->pinmux.functions[function].groups;
+ *num_groups = pdata->pinmux.functions[function].ngroups;
return 0;
}
-static inline void aspeed_sig_desc_print_val(
- const struct aspeed_sig_desc *desc, bool enable, u32 rv)
-{
- pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
- aspeed_pinmux_ips[desc->ip], desc->reg,
- desc->mask, enable ? desc->enable : desc->disable,
- (rv & desc->mask) >> __ffs(desc->mask), rv);
-}
-
-/**
- * Query the enabled or disabled state of a signal descriptor
- *
- * @desc: The signal descriptor of interest
- * @enabled: True to query the enabled state, false to query disabled state
- * @map: The IP block's regmap instance
- *
- * Return: 1 if the descriptor's bitfield is configured to the state
- * selected by @enabled, 0 if not, and less than zero if an unrecoverable
- * failure occurred
- *
- * Evaluation of descriptor state is non-trivial in that it is not a binary
- * outcome: The bitfields can be greater than one bit in size and thus can take
- * a value that is neither the enabled nor disabled state recorded in the
- * descriptor (typically this means a different function to the one of interest
- * is enabled). Thus we must explicitly test for either condition as required.
- */
-static int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
- bool enabled, struct regmap *map)
+static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr)
{
int ret;
- unsigned int raw;
- u32 want;
- if (!map)
- return -ENODEV;
-
- ret = regmap_read(map, desc->reg, &raw);
- if (ret)
- return ret;
-
- aspeed_sig_desc_print_val(desc, enabled, raw);
- want = enabled ? desc->enable : desc->disable;
-
- return ((raw & desc->mask) >> __ffs(desc->mask)) == want;
-}
-
-/**
- * Query the enabled or disabled state for a mux function's signal on a pin
- *
- * @expr: An expression controlling the signal for a mux function on a pin
- * @enabled: True to query the enabled state, false to query disabled state
- * @maps: The list of regmap instances
- *
- * Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
- * and less than zero if an unrecoverable failure occurred.
- *
- * A mux function is enabled or disabled if the function's signal expression
- * for each pin in the function's pin group evaluates true for the desired
- * state. An signal expression evaluates true if all of its associated signal
- * descriptors evaluate true for the desired state.
- *
- * If an expression's state is described by more than one bit, either through
- * multi-bit bitfields in a single signal descriptor or through multiple signal
- * descriptors of a single bit then it is possible for the expression to be in
- * neither the enabled nor disabled state. Thus we must explicitly test for
- * either condition as required.
- */
-static int aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
- bool enabled, struct regmap * const *maps)
-{
- int i;
- int ret;
-
- for (i = 0; i < expr->ndescs; i++) {
- const struct aspeed_sig_desc *desc = &expr->descs[i];
-
- ret = aspeed_sig_desc_eval(desc, enabled, maps[desc->ip]);
- if (ret <= 0)
- return ret;
- }
-
- return 1;
-}
-
-/**
- * Configure a pin's signal by applying an expression's descriptor state for
- * all descriptors in the expression.
- *
- * @expr: The expression associated with the function whose signal is to be
- * configured
- * @enable: true to enable an function's signal through a pin's signal
- * expression, false to disable the function's signal
- * @maps: The list of regmap instances for pinmux register access.
- *
- * Return: 0 if the expression is configured as requested and a negative error
- * code otherwise
- */
-static int aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
- bool enable, struct regmap * const *maps)
-{
- int ret;
- int i;
-
- for (i = 0; i < expr->ndescs; i++) {
- const struct aspeed_sig_desc *desc = &expr->descs[i];
- u32 pattern = enable ? desc->enable : desc->disable;
- u32 val = (pattern << __ffs(desc->mask));
-
- if (!maps[desc->ip])
- return -ENODEV;
-
- /*
- * Strap registers are configured in hardware or by early-boot
- * firmware. Treat them as read-only despite that we can write
- * them. This may mean that certain functions cannot be
- * deconfigured and is the reason we re-evaluate after writing
- * all descriptor bits.
- *
- * Port D and port E GPIO loopback modes are the only exception
- * as those are commonly used with front-panel buttons to allow
- * normal operation of the host when the BMC is powered off or
- * fails to boot. Once the BMC has booted, the loopback mode
- * must be disabled for the BMC to control host power-on and
- * reset.
- */
- if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP1 &&
- !(desc->mask & (BIT(21) | BIT(22))))
- continue;
-
- if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP2)
- continue;
-
- /* On AST2500, Set bits in SCU7C are cleared from SCU70 */
- if (desc->ip == ASPEED_IP_SCU && desc->reg == HW_STRAP1) {
- unsigned int rev_id;
-
- ret = regmap_read(maps[ASPEED_IP_SCU],
- HW_REVISION_ID, &rev_id);
- if (ret < 0)
- return ret;
-
- if (0x04 == (rev_id >> 24)) {
- u32 value = ~val & desc->mask;
-
- if (value) {
- ret = regmap_write(maps[desc->ip],
- HW_REVISION_ID, value);
- if (ret < 0)
- return ret;
- }
- }
- }
-
- ret = regmap_update_bits(maps[desc->ip], desc->reg,
- desc->mask, val);
-
- if (ret)
- return ret;
- }
-
- ret = aspeed_sig_expr_eval(expr, enable, maps);
- if (ret < 0)
- return ret;
-
- if (!ret)
- return -EPERM;
-
- return 0;
-}
-
-static int aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
- struct regmap * const *maps)
-{
- int ret;
-
- ret = aspeed_sig_expr_eval(expr, true, maps);
+ ret = aspeed_sig_expr_eval(ctx, expr, true);
if (ret < 0)
return ret;
if (!ret)
- return aspeed_sig_expr_set(expr, true, maps);
+ return aspeed_sig_expr_set(ctx, expr, true);
return 0;
}
-static int aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
- struct regmap * const *maps)
+static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr)
{
int ret;
- ret = aspeed_sig_expr_eval(expr, true, maps);
+ ret = aspeed_sig_expr_eval(ctx, expr, true);
if (ret < 0)
return ret;
if (ret)
- return aspeed_sig_expr_set(expr, false, maps);
+ return aspeed_sig_expr_set(ctx, expr, false);
return 0;
}
@@ -280,13 +104,13 @@ static int aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
/**
* Disable a signal on a pin by disabling all provided signal expressions.
*
+ * @ctx: The pinmux context
* @exprs: The list of signal expressions (from a priority level on a pin)
- * @maps: The list of regmap instances for pinmux register access.
*
* Return: 0 if all expressions are disabled, otherwise a negative error code
*/
-static int aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
- struct regmap * const *maps)
+static int aspeed_disable_sig(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr **exprs)
{
int ret = 0;
@@ -294,7 +118,7 @@ static int aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
return true;
while (*exprs && !ret) {
- ret = aspeed_sig_expr_disable(*exprs, maps);
+ ret = aspeed_sig_expr_disable(ctx, *exprs);
exprs++;
}
@@ -395,9 +219,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
int ret;
const struct aspeed_pinctrl_data *pdata =
pinctrl_dev_get_drvdata(pctldev);
- const struct aspeed_pin_group *pgroup = &pdata->groups[group];
+ const struct aspeed_pin_group *pgroup = &pdata->pinmux.groups[group];
const struct aspeed_pin_function *pfunc =
- &pdata->functions[function];
+ &pdata->pinmux.functions[function];
for (i = 0; i < pgroup->npins; i++) {
int pin = pgroup->pins[i];
@@ -423,7 +247,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
if (expr)
break;
- ret = aspeed_disable_sig(funcs, pdata->maps);
+ ret = aspeed_disable_sig(&pdata->pinmux, funcs);
if (ret)
return ret;
@@ -443,7 +267,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
return -ENXIO;
}
- ret = aspeed_sig_expr_enable(expr, pdata->maps);
+ ret = aspeed_sig_expr_enable(&pdata->pinmux, expr);
if (ret)
return ret;
}
@@ -500,7 +324,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
if (aspeed_gpio_in_exprs(funcs))
break;
- ret = aspeed_disable_sig(funcs, pdata->maps);
+ ret = aspeed_disable_sig(&pdata->pinmux, funcs);
if (ret)
return ret;
@@ -531,7 +355,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
* If GPIO is not the lowest priority signal type, assume there is only
* one expression defined to enable the GPIO function
*/
- return aspeed_sig_expr_enable(expr, pdata->maps);
+ return aspeed_sig_expr_enable(&pdata->pinmux, expr);
}
int aspeed_pinctrl_probe(struct platform_device *pdev,
@@ -547,12 +371,14 @@ int aspeed_pinctrl_probe(struct platform_device *pdev,
return -ENODEV;
}
- pdata->maps[ASPEED_IP_SCU] = syscon_node_to_regmap(parent->of_node);
- if (IS_ERR(pdata->maps[ASPEED_IP_SCU])) {
+ pdata->scu = syscon_node_to_regmap(parent->of_node);
+ if (IS_ERR(pdata->scu)) {
dev_err(&pdev->dev, "No regmap for syscon pincontroller parent\n");
- return PTR_ERR(pdata->maps[ASPEED_IP_SCU]);
+ return PTR_ERR(pdata->scu);
}
+ pdata->pinmux.maps[ASPEED_IP_SCU] = pdata->scu;
+
pctl = pinctrl_register(pdesc, &pdev->dev, pdata);
if (IS_ERR(pctl)) {
@@ -587,7 +413,9 @@ static inline const struct aspeed_pin_config *find_pinconf_config(
return NULL;
}
-/**
+/*
+ * Aspeed pin configuration description.
+ *
* @param: pinconf configuration parameter
* @arg: The supported argument for @param, or -1 if any value is supported
* @val: The register value to write to configure @arg for @param
@@ -661,7 +489,7 @@ int aspeed_pin_config_get(struct pinctrl_dev *pctldev, unsigned int offset,
if (!pconf)
return -ENOTSUPP;
- rc = regmap_read(pdata->maps[ASPEED_IP_SCU], pconf->reg, &val);
+ rc = regmap_read(pdata->scu, pconf->reg, &val);
if (rc < 0)
return rc;
@@ -716,8 +544,8 @@ int aspeed_pin_config_set(struct pinctrl_dev *pctldev, unsigned int offset,
val = pmap->val << pconf->bit;
- rc = regmap_update_bits(pdata->maps[ASPEED_IP_SCU], pconf->reg,
- BIT(pconf->bit), val);
+ rc = regmap_update_bits(pdata->scu, pconf->reg,
+ BIT(pconf->bit), val);
if (rc < 0)
return rc;
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
index 4b06ddbc6aec..a5d83986f32e 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
@@ -12,504 +12,7 @@
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/regmap.h>
-/*
- * The ASPEED SoCs provide typically more than 200 pins for GPIO and other
- * functions. The SoC function enabled on a pin is determined on a priority
- * basis where a given pin can provide a number of different signal types.
- *
- * The signal active on a pin is described by both a priority level and
- * compound logical expressions involving multiple operators, registers and
- * bits. Some difficulty arises as the pin's function bit masks for each
- * priority level are frequently not the same (i.e. cannot just flip a bit to
- * change from a high to low priority signal), or even in the same register.
- * Further, not all signals can be unmuxed, as some expressions depend on
- * values in the hardware strapping register (which is treated as read-only).
- *
- * SoC Multi-function Pin Expression Examples
- * ------------------------------------------
- *
- * Here are some sample mux configurations from the AST2400 and AST2500
- * datasheets to illustrate the corner cases, roughly in order of least to most
- * corner. The signal priorities are in decending order from P0 (highest).
- *
- * D6 is a pin with a single function (beside GPIO); a high priority signal
- * that participates in one function:
- *
- * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
- * -----+---------+-----------+-----------------------------+-----------+---------------+----------
- * D6 GPIOA0 MAC1LINK SCU80[0]=1 GPIOA0
- * -----+---------+-----------+-----------------------------+-----------+---------------+----------
- *
- * C5 is a multi-signal pin (high and low priority signals). Here we touch
- * different registers for the different functions that enable each signal:
- *
- * -----+---------+-----------+-----------------------------+-----------+---------------+----------
- * C5 GPIOA4 SCL9 SCU90[22]=1 TIMER5 SCU80[4]=1 GPIOA4
- * -----+---------+-----------+-----------------------------+-----------+---------------+----------
- *
- * E19 is a single-signal pin with two functions that influence the active
- * signal. In this case both bits have the same meaning - enable a dedicated
- * LPC reset pin. However it's not always the case that the bits in the
- * OR-relationship have the same meaning.
- *
- * -----+---------+-----------+-----------------------------+-----------+---------------+----------
- * E19 GPIOB4 LPCRST# SCU80[12]=1 | Strap[14]=1 GPIOB4
- * -----+---------+-----------+-----------------------------+-----------+---------------+----------
- *
- * For example, pin B19 has a low-priority signal that's enabled by two
- * distinct SoC functions: A specific SIOPBI bit in register SCUA4, and an ACPI
- * bit in the STRAP register. The ACPI bit configures signals on pins in
- * addition to B19. Both of the low priority functions as well as the high
- * priority function must be disabled for GPIOF1 to be used.
- *
- * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
- * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
- * B19 GPIOF1 NDCD4 SCU80[25]=1 SIOPBI# SCUA4[12]=1 | Strap[19]=0 GPIOF1
- * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
- *
- * For pin E18, the SoC ANDs the expected state of three bits to determine the
- * pin's active signal:
- *
- * * SCU3C[3]: Enable external SOC reset function
- * * SCU80[15]: Enable SPICS1# or EXTRST# function pin
- * * SCU90[31]: Select SPI interface CS# output
- *
- * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
- * E18 GPIOB7 EXTRST# SCU3C[3]=1 & SCU80[15]=1 & SCU90[31]=0 SPICS1# SCU3C[3]=1 & SCU80[15]=1 & SCU90[31]=1 GPIOB7
- * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
- *
- * (Bits SCU3C[3] and SCU80[15] appear to only be used in the expressions for
- * selecting the signals on pin E18)
- *
- * Pin T5 is a multi-signal pin with a more complex configuration:
- *
- * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
- * -----+---------+-----------+------------------------------+-----------+---------------+----------
- * T5 GPIOL1 VPIDE SCU90[5:4]!=0 & SCU84[17]=1 NDCD1 SCU84[17]=1 GPIOL1
- * -----+---------+-----------+------------------------------+-----------+---------------+----------
- *
- * The high priority signal configuration is best thought of in terms of its
- * exploded form, with reference to the SCU90[5:4] bits:
- *
- * * SCU90[5:4]=00: disable
- * * SCU90[5:4]=01: 18 bits (R6/G6/B6) video mode.
- * * SCU90[5:4]=10: 24 bits (R8/G8/B8) video mode.
- * * SCU90[5:4]=11: 30 bits (R10/G10/B10) video mode.
- *
- * Re-writing:
- *
- * -----+---------+-----------+------------------------------+-----------+---------------+----------
- * T5 GPIOL1 VPIDE (SCU90[5:4]=1 & SCU84[17]=1) NDCD1 SCU84[17]=1 GPIOL1
- * | (SCU90[5:4]=2 & SCU84[17]=1)
- * | (SCU90[5:4]=3 & SCU84[17]=1)
- * -----+---------+-----------+------------------------------+-----------+---------------+----------
- *
- * For reference the SCU84[17] bit configure the "UART1 NDCD1 or Video VPIDE
- * function pin", where the signal itself is determined by whether SCU94[5:4]
- * is disabled or in one of the 18, 24 or 30bit video modes.
- *
- * Other video-input-related pins require an explicit state in SCU90[5:4], e.g.
- * W1 and U5:
- *
- * -----+---------+-----------+------------------------------+-----------+---------------+----------
- * W1 GPIOL6 VPIB0 SCU90[5:4]=3 & SCU84[22]=1 TXD1 SCU84[22]=1 GPIOL6
- * U5 GPIOL7 VPIB1 SCU90[5:4]=3 & SCU84[23]=1 RXD1 SCU84[23]=1 GPIOL7
- * -----+---------+-----------+------------------------------+-----------+---------------+----------
- *
- * The examples of T5 and W1 are particularly fertile, as they also demonstrate
- * that despite operating as part of the video input bus each signal needs to
- * be enabled individually via it's own SCU84 (in the cases of T5 and W1)
- * register bit. This is a little crazy if the bus doesn't have optional
- * signals, but is used to decent effect with some of the UARTs where not all
- * signals are required. However, this isn't done consistently - UART1 is
- * enabled on a per-pin basis, and by contrast, all signals for UART6 are
- * enabled by a single bit.
- *
- * Further, the high and low priority signals listed in the table above share
- * a configuration bit. The VPI signals should operate in concert in a single
- * function, but the UART signals should retain the ability to be configured
- * independently. This pushes the implementation down the path of tagging a
- * signal's expressions with the function they participate in, rather than
- * defining masks affecting multiple signals per function. The latter approach
- * fails in this instance where applying the configuration for the UART pin of
- * interest will stomp on the state of other UART signals when disabling the
- * VPI functions on the current pin.
- *
- * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
- * -----+------------+-----------+---------------------------+-----------+---------------+------------
- * A12 RGMII1TXCK GPIOT0 SCUA0[0]=1 RMII1TXEN Strap[6]=0 RGMII1TXCK
- * B12 RGMII1TXCTL GPIOT1 SCUA0[1]=1 – Strap[6]=0 RGMII1TXCTL
- * -----+------------+-----------+---------------------------+-----------+---------------+------------
- *
- * A12 demonstrates that the "Other" signal isn't always GPIO - in this case
- * GPIOT0 is a high-priority signal and RGMII1TXCK is Other. Thus, GPIO
- * should be treated like any other signal type with full function expression
- * requirements, and not assumed to be the default case. Separately, GPIOT0 and
- * GPIOT1's signal descriptor bits are distinct, therefore we must iterate all
- * pins in the function's group to disable the higher-priority signals such
- * that the signal for the function of interest is correctly enabled.
- *
- * Finally, three priority levels aren't always enough; the AST2500 brings with
- * it 18 pins of five priority levels, however the 18 pins only use three of
- * the five priority levels.
- *
- * Ultimately the requirement to control pins in the examples above drive the
- * design:
- *
- * * Pins provide signals according to functions activated in the mux
- * configuration
- *
- * * Pins provide up to five signal types in a priority order
- *
- * * For priorities levels defined on a pin, each priority provides one signal
- *
- * * Enabling lower priority signals requires higher priority signals be
- * disabled
- *
- * * A function represents a set of signals; functions are distinct if their
- * sets of signals are not equal
- *
- * * Signals participate in one or more functions
- *
- * * A function is described by an expression of one or more signal
- * descriptors, which compare bit values in a register
- *
- * * A signal expression is the smallest set of signal descriptors whose
- * comparisons must evaluate 'true' for a signal to be enabled on a pin.
- *
- * * A function's signal is active on a pin if evaluating all signal
- * descriptors in the pin's signal expression for the function yields a 'true'
- * result
- *
- * * A signal at a given priority on a given pin is active if any of the
- * functions in which the signal participates are active, and no higher
- * priority signal on the pin is active
- *
- * * GPIO is configured per-pin
- *
- * And so:
- *
- * * To disable a signal, any function(s) activating the signal must be
- * disabled
- *
- * * Each pin must know the signal expressions of functions in which it
- * participates, for the purpose of enabling the Other function. This is done
- * by deactivating all functions that activate higher priority signals on the
- * pin.
- *
- * As a concrete example:
- *
- * * T5 provides three signals types: VPIDE, NDCD1 and GPIO
- *
- * * The VPIDE signal participates in 3 functions: VPI18, VPI24 and VPI30
- *
- * * The NDCD1 signal participates in just its own NDCD1 function
- *
- * * VPIDE is high priority, NDCD1 is low priority, and GPIOL1 is the least
- * prioritised
- *
- * * The prerequisit for activating the NDCD1 signal is that the VPI18, VPI24
- * and VPI30 functions all be disabled
- *
- * * Similarly, all of VPI18, VPI24, VPI30 and NDCD1 functions must be disabled
- * to provide GPIOL6
- *
- * Considerations
- * --------------
- *
- * If pinctrl allows us to allocate a pin we can configure a function without
- * concern for the function of already allocated pins, if pin groups are
- * created with respect to the SoC functions in which they participate. This is
- * intuitive, but it did not feel obvious from the bit/pin relationships.
- *
- * Conversely, failing to allocate all pins in a group indicates some bits (as
- * well as pins) required for the group's configuration will already be in use,
- * likely in a way that's inconsistent with the requirements of the failed
- * group.
- */
-
-#define ASPEED_IP_SCU 0
-#define ASPEED_IP_GFX 1
-#define ASPEED_IP_LPC 2
-#define ASPEED_NR_PINMUX_IPS 3
-
-/*
- * The "Multi-function Pins Mapping and Control" table in the SoC datasheet
- * references registers by the device/offset mnemonic. The register macros
- * below are named the same way to ease transcription and verification (as
- * opposed to naming them e.g. PINMUX_CTRL_[0-9]). Further, signal expressions
- * reference registers beyond those dedicated to pinmux, such as the system
- * reset control and MAC clock configuration registers. The AST2500 goes a step
- * further and references registers in the graphics IP block, but that isn't
- * handled yet.
- */
-#define SCU2C 0x2C /* Misc. Control Register */
-#define SCU3C 0x3C /* System Reset Control/Status Register */
-#define SCU48 0x48 /* MAC Interface Clock Delay Setting */
-#define HW_STRAP1 0x70 /* AST2400 strapping is 33 bits, is split */
-#define HW_REVISION_ID 0x7C /* Silicon revision ID register */
-#define SCU80 0x80 /* Multi-function Pin Control #1 */
-#define SCU84 0x84 /* Multi-function Pin Control #2 */
-#define SCU88 0x88 /* Multi-function Pin Control #3 */
-#define SCU8C 0x8C /* Multi-function Pin Control #4 */
-#define SCU90 0x90 /* Multi-function Pin Control #5 */
-#define SCU94 0x94 /* Multi-function Pin Control #6 */
-#define SCUA0 0xA0 /* Multi-function Pin Control #7 */
-#define SCUA4 0xA4 /* Multi-function Pin Control #8 */
-#define SCUA8 0xA8 /* Multi-function Pin Control #9 */
-#define SCUAC 0xAC /* Multi-function Pin Control #10 */
-#define HW_STRAP2 0xD0 /* Strapping */
-
- /**
- * A signal descriptor, which describes the register, bits and the
- * enable/disable values that should be compared or written.
- *
- * @ip: The IP block identifier, used as an index into the regmap array in
- * struct aspeed_pinctrl_data
- * @reg: The register offset with respect to the base address of the IP block
- * @mask: The mask to apply to the register. The lowest set bit of the mask is
- * used to derive the shift value.
- * @enable: The value that enables the function. Value should be in the LSBs,
- * not at the position of the mask.
- * @disable: The value that disables the function. Value should be in the
- * LSBs, not at the position of the mask.
- */
-struct aspeed_sig_desc {
- unsigned int ip;
- unsigned int reg;
- u32 mask;
- u32 enable;
- u32 disable;
-};
-
-/**
- * Describes a signal expression. The expression is evaluated by ANDing the
- * evaluation of the descriptors.
- *
- * @signal: The signal name for the priority level on the pin. If the signal
- * type is GPIO, then the signal name must begin with the string
- * "GPIO", e.g. GPIOA0, GPIOT4 etc.
- * @function: The name of the function the signal participates in for the
- * associated expression
- * @ndescs: The number of signal descriptors in the expression
- * @descs: Pointer to an array of signal descriptors that comprise the
- * function expression
- */
-struct aspeed_sig_expr {
- const char *signal;
- const char *function;
- int ndescs;
- const struct aspeed_sig_desc *descs;
-};
-
-/**
- * A struct capturing the list of expressions enabling signals at each priority
- * for a given pin. The signal configuration for a priority level is evaluated
- * by ORing the evaluation of the signal expressions in the respective
- * priority's list.
- *
- * @name: A name for the pin
- * @prios: A pointer to an array of expression list pointers
- *
- */
-struct aspeed_pin_desc {
- const char *name;
- const struct aspeed_sig_expr ***prios;
-};
-
-/* Macro hell */
-
-#define SIG_DESC_IP_BIT(ip, reg, idx, val) \
- { ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
-
-/**
- * Short-hand macro for describing an SCU descriptor enabled by the state of
- * one bit. The disable value is derived.
- *
- * @reg: The signal's associated register, offset from base
- * @idx: The signal's bit index in the register
- * @val: The value (0 or 1) that enables the function
- */
-#define SIG_DESC_BIT(reg, idx, val) \
- SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
-
-#define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
-
-/**
- * A further short-hand macro expanding to an SCU descriptor enabled by a set
- * bit.
- *
- * @reg: The register, offset from base
- * @idx: The bit index in the register
- */
-#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
-
-#define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
-#define SIG_DESC_LIST_DECL(sig, func, ...) \
- static const struct aspeed_sig_desc SIG_DESC_LIST_SYM(sig, func)[] = \
- { __VA_ARGS__ }
-
-#define SIG_EXPR_SYM(sig, func) sig_expr_ ## sig ## _ ## func
-#define SIG_EXPR_DECL_(sig, func) \
- static const struct aspeed_sig_expr SIG_EXPR_SYM(sig, func) = \
- { \
- .signal = #sig, \
- .function = #func, \
- .ndescs = ARRAY_SIZE(SIG_DESC_LIST_SYM(sig, func)), \
- .descs = &(SIG_DESC_LIST_SYM(sig, func))[0], \
- }
-
-/**
- * Declare a signal expression.
- *
- * @sig: A macro symbol name for the signal (is subjected to stringification
- * and token pasting)
- * @func: The function in which the signal is participating
- * @...: Signal descriptors that define the signal expression
- *
- * For example, the following declares the ROMD8 signal for the ROM16 function:
- *
- * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
- *
- * And with multiple signal descriptors:
- *
- * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
- * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
- */
-#define SIG_EXPR_DECL(sig, func, ...) \
- SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
- SIG_EXPR_DECL_(sig, func)
-
-/**
- * Declare a pointer to a signal expression
- *
- * @sig: The macro symbol name for the signal (subjected to token pasting)
- * @func: The macro symbol name for the function (subjected to token pasting)
- */
-#define SIG_EXPR_PTR(sig, func) (&SIG_EXPR_SYM(sig, func))
-
-#define SIG_EXPR_LIST_SYM(sig) sig_exprs_ ## sig
-
-/**
- * Declare a signal expression list for reference in a struct aspeed_pin_prio.
- *
- * @sig: A macro symbol name for the signal (is subjected to token pasting)
- * @...: Signal expression structure pointers (use SIG_EXPR_PTR())
- *
- * For example, the 16-bit ROM bus can be enabled by one of two possible signal
- * expressions:
- *
- * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
- * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
- * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
- * SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
- * SIG_EXPR_PTR(ROMD8, ROM16S));
- */
-#define SIG_EXPR_LIST_DECL(sig, ...) \
- static const struct aspeed_sig_expr *SIG_EXPR_LIST_SYM(sig)[] = \
- { __VA_ARGS__, NULL }
-
-/**
- * A short-hand macro for declaring a function expression and an expression
- * list with a single function.
- *
- * @func: A macro symbol name for the function (is subjected to token pasting)
- * @...: Function descriptors that define the function expression
- *
- * For example, signal NCTS6 participates in its own function with one group:
- *
- * SIG_EXPR_LIST_DECL_SINGLE(NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
- */
-#define SIG_EXPR_LIST_DECL_SINGLE(sig, func, ...) \
- SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
- SIG_EXPR_DECL_(sig, func); \
- SIG_EXPR_LIST_DECL(sig, SIG_EXPR_PTR(sig, func))
-
-#define SIG_EXPR_LIST_DECL_DUAL(sig, f0, f1) \
- SIG_EXPR_LIST_DECL(sig, SIG_EXPR_PTR(sig, f0), SIG_EXPR_PTR(sig, f1))
-
-#define SIG_EXPR_LIST_PTR(sig) (&SIG_EXPR_LIST_SYM(sig)[0])
-
-#define PIN_EXPRS_SYM(pin) pin_exprs_ ## pin
-#define PIN_EXPRS_PTR(pin) (&PIN_EXPRS_SYM(pin)[0])
-#define PIN_SYM(pin) pin_ ## pin
-
-#define MS_PIN_DECL_(pin, ...) \
- static const struct aspeed_sig_expr **PIN_EXPRS_SYM(pin)[] = \
- { __VA_ARGS__, NULL }; \
- static const struct aspeed_pin_desc PIN_SYM(pin) = \
- { #pin, PIN_EXPRS_PTR(pin) }
-
-/**
- * Declare a multi-signal pin
- *
- * @pin: The pin number
- * @other: Macro name for "other" functionality (subjected to stringification)
- * @high: Macro name for the highest priority signal functions
- * @low: Macro name for the low signal functions
- *
- * For example:
- *
- * #define A8 56
- * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
- * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
- * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
- * SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
- * SIG_EXPR_PTR(ROMD8, ROM16S));
- * SIG_EXPR_LIST_DECL_SINGLE(NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
- * MS_PIN_DECL(A8, GPIOH0, ROMD8, NCTS6);
- */
-#define MS_PIN_DECL(pin, other, high, low) \
- SIG_EXPR_LIST_DECL_SINGLE(other, other); \
- MS_PIN_DECL_(pin, \
- SIG_EXPR_LIST_PTR(high), \
- SIG_EXPR_LIST_PTR(low), \
- SIG_EXPR_LIST_PTR(other))
-
-#define PIN_GROUP_SYM(func) pins_ ## func
-#define FUNC_GROUP_SYM(func) groups_ ## func
-#define FUNC_GROUP_DECL(func, ...) \
- static const int PIN_GROUP_SYM(func)[] = { __VA_ARGS__ }; \
- static const char *FUNC_GROUP_SYM(func)[] = { #func }
-
-/**
- * Declare a single signal pin
- *
- * @pin: The pin number
- * @other: Macro name for "other" functionality (subjected to stringification)
- * @sig: Macro name for the signal (subjected to stringification)
- *
- * For example:
- *
- * #define E3 80
- * SIG_EXPR_LIST_DECL_SINGLE(SCL5, I2C5, I2C5_DESC);
- * SS_PIN_DECL(E3, GPIOK0, SCL5);
- */
-#define SS_PIN_DECL(pin, other, sig) \
- SIG_EXPR_LIST_DECL_SINGLE(other, other); \
- MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(sig), SIG_EXPR_LIST_PTR(other))
-
-/**
- * Single signal, single function pin declaration
- *
- * @pin: The pin number
- * @other: Macro name for "other" functionality (subjected to stringification)
- * @sig: Macro name for the signal (subjected to stringification)
- * @...: Signal descriptors that define the function expression
- *
- * For example:
- *
- * SSSF_PIN_DECL(A4, GPIOA2, TIMER3, SIG_DESC_SET(SCU80, 2));
- */
-#define SSSF_PIN_DECL(pin, other, sig, ...) \
- SIG_EXPR_LIST_DECL_SINGLE(sig, sig, __VA_ARGS__); \
- SIG_EXPR_LIST_DECL_SINGLE(other, other); \
- MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(sig), SIG_EXPR_LIST_PTR(other)); \
- FUNC_GROUP_DECL(sig, pin)
-
-#define GPIO_PIN_DECL(pin, gpio) \
- SIG_EXPR_LIST_DECL_SINGLE(gpio, gpio); \
- MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
+#include "pinmux-aspeed.h"
/**
* @param The pinconf parameter type
@@ -525,22 +28,6 @@ struct aspeed_pin_config {
u8 value;
};
-struct aspeed_pinctrl_data {
- struct regmap *maps[ASPEED_NR_PINMUX_IPS];
-
- const struct pinctrl_pin_desc *pins;
- const unsigned int npins;
-
- const struct aspeed_pin_group *groups;
- const unsigned int ngroups;
-
- const struct aspeed_pin_function *functions;
- const unsigned int nfunctions;
-
- const struct aspeed_pin_config *configs;
- const unsigned int nconfigs;
-};
-
#define ASPEED_PINCTRL_PIN(name_) \
[name_] = { \
.number = name_, \
@@ -548,30 +35,19 @@ struct aspeed_pinctrl_data {
.drv_data = (void *) &(PIN_SYM(name_)) \
}
-struct aspeed_pin_group {
- const char *name;
- const unsigned int *pins;
+struct aspeed_pinctrl_data {
+ struct regmap *scu;
+
+ const struct pinctrl_pin_desc *pins;
const unsigned int npins;
-};
-#define ASPEED_PINCTRL_GROUP(name_) { \
- .name = #name_, \
- .pins = &(PIN_GROUP_SYM(name_))[0], \
- .npins = ARRAY_SIZE(PIN_GROUP_SYM(name_)), \
-}
+ const struct aspeed_pin_config *configs;
+ const unsigned int nconfigs;
-struct aspeed_pin_function {
- const char *name;
- const char *const *groups;
- unsigned int ngroups;
+ struct aspeed_pinmux_data pinmux;
};
-#define ASPEED_PINCTRL_FUNC(name_, ...) { \
- .name = #name_, \
- .groups = &FUNC_GROUP_SYM(name_)[0], \
- .ngroups = ARRAY_SIZE(FUNC_GROUP_SYM(name_)), \
-}
-
+/* Aspeed pinctrl helpers */
int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev);
const char *aspeed_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
unsigned int group);
diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.c b/drivers/pinctrl/aspeed/pinmux-aspeed.c
new file mode 100644
index 000000000000..5b0fe178ccf2
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinmux-aspeed.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (C) 2019 IBM Corp. */
+
+/* Pieces to enable drivers to implement the .set callback */
+
+#include "pinmux-aspeed.h"
+
+const char *const aspeed_pinmux_ips[] = {
+ [ASPEED_IP_SCU] = "SCU",
+ [ASPEED_IP_GFX] = "GFX",
+ [ASPEED_IP_LPC] = "LPC",
+};
+
+static inline void aspeed_sig_desc_print_val(
+ const struct aspeed_sig_desc *desc, bool enable, u32 rv)
+{
+ pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
+ aspeed_pinmux_ips[desc->ip], desc->reg,
+ desc->mask, enable ? desc->enable : desc->disable,
+ (rv & desc->mask) >> __ffs(desc->mask), rv);
+}
+
+/**
+ * Query the enabled or disabled state of a signal descriptor
+ *
+ * @desc: The signal descriptor of interest
+ * @enabled: True to query the enabled state, false to query disabled state
+ * @map: The IP block's regmap instance
+ *
+ * Return: 1 if the descriptor's bitfield is configured to the state
+ * selected by @enabled, 0 if not, and less than zero if an unrecoverable
+ * failure occurred
+ *
+ * Evaluation of descriptor state is non-trivial in that it is not a binary
+ * outcome: The bitfields can be greater than one bit in size and thus can take
+ * a value that is neither the enabled nor disabled state recorded in the
+ * descriptor (typically this means a different function to the one of interest
+ * is enabled). Thus we must explicitly test for either condition as required.
+ */
+int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
+ bool enabled, struct regmap *map)
+{
+ int ret;
+ unsigned int raw;
+ u32 want;
+
+ if (!map)
+ return -ENODEV;
+
+ ret = regmap_read(map, desc->reg, &raw);
+ if (ret)
+ return ret;
+
+ aspeed_sig_desc_print_val(desc, enabled, raw);
+ want = enabled ? desc->enable : desc->disable;
+
+ return ((raw & desc->mask) >> __ffs(desc->mask)) == want;
+}
+
+/**
+ * Query the enabled or disabled state for a mux function's signal on a pin
+ *
+ * @ctx: The driver context for the pinctrl IP
+ * @expr: An expression controlling the signal for a mux function on a pin
+ * @enabled: True to query the enabled state, false to query disabled state
+ *
+ * Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
+ * and less than zero if an unrecoverable failure occurred.
+ *
+ * A mux function is enabled or disabled if the function's signal expression
+ * for each pin in the function's pin group evaluates true for the desired
+ * state. An signal expression evaluates true if all of its associated signal
+ * descriptors evaluate true for the desired state.
+ *
+ * If an expression's state is described by more than one bit, either through
+ * multi-bit bitfields in a single signal descriptor or through multiple signal
+ * descriptors of a single bit then it is possible for the expression to be in
+ * neither the enabled nor disabled state. Thus we must explicitly test for
+ * either condition as required.
+ */
+int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr, bool enabled)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < expr->ndescs; i++) {
+ const struct aspeed_sig_desc *desc = &expr->descs[i];
+
+ ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
+ if (ret <= 0)
+ return ret;
+ }
+
+ return 1;
+}
diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.h b/drivers/pinctrl/aspeed/pinmux-aspeed.h
new file mode 100644
index 000000000000..329d54d48667
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinmux-aspeed.h
@@ -0,0 +1,735 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2019 IBM Corp. */
+
+#ifndef ASPEED_PINMUX_H
+#define ASPEED_PINMUX_H
+
+#include <linux/regmap.h>
+#include <stdbool.h>
+
+/*
+ * The ASPEED SoCs provide typically more than 200 pins for GPIO and other
+ * functions. The SoC function enabled on a pin is determined on a priority
+ * basis where a given pin can provide a number of different signal types.
+ *
+ * The signal active on a pin is described by both a priority level and
+ * compound logical expressions involving multiple operators, registers and
+ * bits. Some difficulty arises as the pin's function bit masks for each
+ * priority level are frequently not the same (i.e. cannot just flip a bit to
+ * change from a high to low priority signal), or even in the same register.
+ * Further, not all signals can be unmuxed, as some expressions depend on
+ * values in the hardware strapping register (which may be treated as
+ * read-only).
+ *
+ * SoC Multi-function Pin Expression Examples
+ * ------------------------------------------
+ *
+ * Here are some sample mux configurations from the AST2400 and AST2500
+ * datasheets to illustrate the corner cases, roughly in order of least to most
+ * corner. The signal priorities are in decending order from P0 (highest).
+ *
+ * D6 is a pin with a single function (beside GPIO); a high priority signal
+ * that participates in one function:
+ *
+ * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
+ * -----+---------+-----------+-----------------------------+-----------+---------------+----------
+ * D6 GPIOA0 MAC1LINK SCU80[0]=1 GPIOA0
+ * -----+---------+-----------+-----------------------------+-----------+---------------+----------
+ *
+ * C5 is a multi-signal pin (high and low priority signals). Here we touch
+ * different registers for the different functions that enable each signal:
+ *
+ * -----+---------+-----------+-----------------------------+-----------+---------------+----------
+ * C5 GPIOA4 SCL9 SCU90[22]=1 TIMER5 SCU80[4]=1 GPIOA4
+ * -----+---------+-----------+-----------------------------+-----------+---------------+----------
+ *
+ * E19 is a single-signal pin with two functions that influence the active
+ * signal. In this case both bits have the same meaning - enable a dedicated
+ * LPC reset pin. However it's not always the case that the bits in the
+ * OR-relationship have the same meaning.
+ *
+ * -----+---------+-----------+-----------------------------+-----------+---------------+----------
+ * E19 GPIOB4 LPCRST# SCU80[12]=1 | Strap[14]=1 GPIOB4
+ * -----+---------+-----------+-----------------------------+-----------+---------------+----------
+ *
+ * For example, pin B19 has a low-priority signal that's enabled by two
+ * distinct SoC functions: A specific SIOPBI bit in register SCUA4, and an ACPI
+ * bit in the STRAP register. The ACPI bit configures signals on pins in
+ * addition to B19. Both of the low priority functions as well as the high
+ * priority function must be disabled for GPIOF1 to be used.
+ *
+ * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
+ * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
+ * B19 GPIOF1 NDCD4 SCU80[25]=1 SIOPBI# SCUA4[12]=1 | Strap[19]=0 GPIOF1
+ * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
+ *
+ * For pin E18, the SoC ANDs the expected state of three bits to determine the
+ * pin's active signal:
+ *
+ * * SCU3C[3]: Enable external SOC reset function
+ * * SCU80[15]: Enable SPICS1# or EXTRST# function pin
+ * * SCU90[31]: Select SPI interface CS# output
+ *
+ * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
+ * E18 GPIOB7 EXTRST# SCU3C[3]=1 & SCU80[15]=1 & SCU90[31]=0 SPICS1# SCU3C[3]=1 & SCU80[15]=1 & SCU90[31]=1 GPIOB7
+ * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
+ *
+ * (Bits SCU3C[3] and SCU80[15] appear to only be used in the expressions for
+ * selecting the signals on pin E18)
+ *
+ * Pin T5 is a multi-signal pin with a more complex configuration:
+ *
+ * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
+ * -----+---------+-----------+------------------------------+-----------+---------------+----------
+ * T5 GPIOL1 VPIDE SCU90[5:4]!=0 & SCU84[17]=1 NDCD1 SCU84[17]=1 GPIOL1
+ * -----+---------+-----------+------------------------------+-----------+---------------+----------
+ *
+ * The high priority signal configuration is best thought of in terms of its
+ * exploded form, with reference to the SCU90[5:4] bits:
+ *
+ * * SCU90[5:4]=00: disable
+ * * SCU90[5:4]=01: 18 bits (R6/G6/B6) video mode.
+ * * SCU90[5:4]=10: 24 bits (R8/G8/B8) video mode.
+ * * SCU90[5:4]=11: 30 bits (R10/G10/B10) video mode.
+ *
+ * Re-writing:
+ *
+ * -----+---------+-----------+------------------------------+-----------+---------------+----------
+ * T5 GPIOL1 VPIDE (SCU90[5:4]=1 & SCU84[17]=1) NDCD1 SCU84[17]=1 GPIOL1
+ * | (SCU90[5:4]=2 & SCU84[17]=1)
+ * | (SCU90[5:4]=3 & SCU84[17]=1)
+ * -----+---------+-----------+------------------------------+-----------+---------------+----------
+ *
+ * For reference the SCU84[17] bit configure the "UART1 NDCD1 or Video VPIDE
+ * function pin", where the signal itself is determined by whether SCU94[5:4]
+ * is disabled or in one of the 18, 24 or 30bit video modes.
+ *
+ * Other video-input-related pins require an explicit state in SCU90[5:4], e.g.
+ * W1 and U5:
+ *
+ * -----+---------+-----------+------------------------------+-----------+---------------+----------
+ * W1 GPIOL6 VPIB0 SCU90[5:4]=3 & SCU84[22]=1 TXD1 SCU84[22]=1 GPIOL6
+ * U5 GPIOL7 VPIB1 SCU90[5:4]=3 & SCU84[23]=1 RXD1 SCU84[23]=1 GPIOL7
+ * -----+---------+-----------+------------------------------+-----------+---------------+----------
+ *
+ * The examples of T5 and W1 are particularly fertile, as they also demonstrate
+ * that despite operating as part of the video input bus each signal needs to
+ * be enabled individually via it's own SCU84 (in the cases of T5 and W1)
+ * register bit. This is a little crazy if the bus doesn't have optional
+ * signals, but is used to decent effect with some of the UARTs where not all
+ * signals are required. However, this isn't done consistently - UART1 is
+ * enabled on a per-pin basis, and by contrast, all signals for UART6 are
+ * enabled by a single bit.
+ *
+ * Further, the high and low priority signals listed in the table above share
+ * a configuration bit. The VPI signals should operate in concert in a single
+ * function, but the UART signals should retain the ability to be configured
+ * independently. This pushes the implementation down the path of tagging a
+ * signal's expressions with the function they participate in, rather than
+ * defining masks affecting multiple signals per function. The latter approach
+ * fails in this instance where applying the configuration for the UART pin of
+ * interest will stomp on the state of other UART signals when disabling the
+ * VPI functions on the current pin.
+ *
+ * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
+ * -----+------------+-----------+---------------------------+-----------+---------------+------------
+ * A12 RGMII1TXCK GPIOT0 SCUA0[0]=1 RMII1TXEN Strap[6]=0 RGMII1TXCK
+ * B12 RGMII1TXCTL GPIOT1 SCUA0[1]=1 – Strap[6]=0 RGMII1TXCTL
+ * -----+------------+-----------+---------------------------+-----------+---------------+------------
+ *
+ * A12 demonstrates that the "Other" signal isn't always GPIO - in this case
+ * GPIOT0 is a high-priority signal and RGMII1TXCK is Other. Thus, GPIO
+ * should be treated like any other signal type with full function expression
+ * requirements, and not assumed to be the default case. Separately, GPIOT0 and
+ * GPIOT1's signal descriptor bits are distinct, therefore we must iterate all
+ * pins in the function's group to disable the higher-priority signals such
+ * that the signal for the function of interest is correctly enabled.
+ *
+ * Finally, three priority levels aren't always enough; the AST2500 brings with
+ * it 18 pins of five priority levels, however the 18 pins only use three of
+ * the five priority levels.
+ *
+ * Ultimately the requirement to control pins in the examples above drive the
+ * design:
+ *
+ * * Pins provide signals according to functions activated in the mux
+ * configuration
+ *
+ * * Pins provide up to five signal types in a priority order
+ *
+ * * For priorities levels defined on a pin, each priority provides one signal
+ *
+ * * Enabling lower priority signals requires higher priority signals be
+ * disabled
+ *
+ * * A function represents a set of signals; functions are distinct if their
+ * sets of signals are not equal
+ *
+ * * Signals participate in one or more functions
+ *
+ * * A function is described by an expression of one or more signal
+ * descriptors, which compare bit values in a register
+ *
+ * * A signal expression is the smallest set of signal descriptors whose
+ * comparisons must evaluate 'true' for a signal to be enabled on a pin.
+ *
+ * * A signal participating in a function is active on a pin if evaluating all
+ * signal descriptors in the pin's signal expression for the function yields
+ * a 'true' result
+ *
+ * * A signal at a given priority on a given pin is active if any of the
+ * functions in which the signal participates are active, and no higher
+ * priority signal on the pin is active
+ *
+ * * GPIO is configured per-pin
+ *
+ * And so:
+ *
+ * * To disable a signal, any function(s) activating the signal must be
+ * disabled
+ *
+ * * Each pin must know the signal expressions of functions in which it
+ * participates, for the purpose of enabling the Other function. This is done
+ * by deactivating all functions that activate higher priority signals on the
+ * pin.
+ *
+ * As a concrete example:
+ *
+ * * T5 provides three signals types: VPIDE, NDCD1 and GPIO
+ *
+ * * The VPIDE signal participates in 3 functions: VPI18, VPI24 and VPI30
+ *
+ * * The NDCD1 signal participates in just its own NDCD1 function
+ *
+ * * VPIDE is high priority, NDCD1 is low priority, and GPIOL1 is the least
+ * prioritised
+ *
+ * * The prerequisit for activating the NDCD1 signal is that the VPI18, VPI24
+ * and VPI30 functions all be disabled
+ *
+ * * Similarly, all of VPI18, VPI24, VPI30 and NDCD1 functions must be disabled
+ * to provide GPIOL6
+ *
+ * Considerations
+ * --------------
+ *
+ * If pinctrl allows us to allocate a pin we can configure a function without
+ * concern for the function of already allocated pins, if pin groups are
+ * created with respect to the SoC functions in which they participate. This is
+ * intuitive, but it did not feel obvious from the bit/pin relationships.
+ *
+ * Conversely, failing to allocate all pins in a group indicates some bits (as
+ * well as pins) required for the group's configuration will already be in use,
+ * likely in a way that's inconsistent with the requirements of the failed
+ * group.
+ *
+ * Implementation
+ * --------------
+ *
+ * Beyond the documentation below the various structures and helper macros that
+ * allow the implementation to hang together are defined. The macros are fairly
+ * dense, so below we walk through some raw examples of the configuration
+ * tables in an effort to clarify the concepts.
+ *
+ * The complexity of configuring the mux combined with the scale of the pins
+ * and functions was a concern, so the table design along with the macro jungle
+ * is an attempt to address it. The rough principles of the approach are:
+ *
+ * 1. Use a data-driven solution rather than embedding state into code
+ * 2. Minimise editing to the specifics of the given mux configuration
+ * 3. Detect as many errors as possible at compile time
+ *
+ * Addressing point 3 leads to naming of symbols in terms of the four
+ * properties associated with a given mux configuration: The pin, the signal,
+ * the group and the function. In this way copy/paste errors cause duplicate
+ * symbols to be defined, which prevents successful compilation. Failing to
+ * properly parent the tables leads to unused symbol warnings, and use of
+ * designated initialisers and additional warnings ensures that there are
+ * no override errors in the pin, group and function arrays.
+ *
+ * Addressing point 2 drives the development of the macro jungle, as it
+ * centralises the definition noise at the cost of taking some time to
+ * understand.
+ *
+ * Here's a complete, concrete "pre-processed" example of the table structures
+ * used to describe the D6 ball from the examples above:
+ *
+ * ```
+ * static const struct aspeed_sig_desc sig_descs_MAC1LINK_MAC1LINK[] = {
+ * {
+ * .ip = ASPEED_IP_SCU,
+ * .reg = 0x80,
+ * .mask = BIT(0),
+ * .enable = 1,
+ * .disable = 0
+ * },
+ * };
+ *
+ * static const struct aspeed_sig_expr sig_expr_MAC1LINK_MAC1LINK = {
+ * .signal = "MAC1LINK",
+ * .function = "MAC1LINK",
+ * .ndescs = ARRAY_SIZE(sig_descs_MAC1LINK_MAC1LINK),
+ * .descs = &(sig_descs_MAC1LINK_MAC1LINK)[0],
+ * };
+ *
+ * static const struct aspeed_sig_expr *sig_exprs_MAC1LINK_MAC1LINK[] = {
+ * &sig_expr_MAC1LINK_MAC1LINK,
+ * NULL,
+ * };
+ *
+ * static const struct aspeed_sig_desc sig_descs_GPIOA0_GPIOA0[] = { };
+ *
+ * static const struct aspeed_sig_expr sig_expr_GPIOA0_GPIOA0 = {
+ * .signal = "GPIOA0",
+ * .function = "GPIOA0",
+ * .ndescs = ARRAY_SIZE(sig_descs_GPIOA0_GPIOA0),
+ * .descs = &(sig_descs_GPIOA0_GPIOA0)[0],
+ * };
+ *
+ * static const struct aspeed_sig_expr *sig_exprs_GPIOA0_GPIOA0[] = {
+ * &sig_expr_GPIOA0_GPIOA0,
+ * NULL
+ * };
+ *
+ * static const struct aspeed_sig_expr **pin_exprs_0[] = {
+ * sig_exprs_MAC1LINK_MAC1LINK,
+ * sig_exprs_GPIOA0_GPIOA0,
+ * NULL
+ * };
+ *
+ * static const struct aspeed_pin_desc pin_0 = { "0", (&pin_exprs_0[0]) };
+ * static const int group_pins_MAC1LINK[] = { 0 };
+ * static const char *func_groups_MAC1LINK[] = { "MAC1LINK" };
+ *
+ * static struct pinctrl_pin_desc aspeed_g4_pins[] = {
+ * [0] = { .number = 0, .name = "D6", .drv_data = &pin_0 },
+ * };
+ *
+ * static const struct aspeed_pin_group aspeed_g4_groups[] = {
+ * {
+ * .name = "MAC1LINK",
+ * .pins = &(group_pins_MAC1LINK)[0],
+ * .npins = ARRAY_SIZE(group_pins_MAC1LINK),
+ * },
+ * };
+ *
+ * static const struct aspeed_pin_function aspeed_g4_functions[] = {
+ * {
+ * .name = "MAC1LINK",
+ * .groups = &func_groups_MAC1LINK[0],
+ * .ngroups = ARRAY_SIZE(func_groups_MAC1LINK),
+ * },
+ * };
+ * ```
+ *
+ * At the end of the day much of the above code is compressed into the
+ * following two lines:
+ *
+ * ```
+ * #define D6 0
+ * SSSF_PIN_DECL(D6, GPIOA0, MAC1LINK, SIG_DESC_SET(SCU80, 0));
+ * ```
+ *
+ * The two examples below show just the differences from the example above.
+ *
+ * Ball E18 demonstrates a function, EXTRST, that requires multiple descriptors
+ * be set for it to be muxed:
+ *
+ * ```
+ * static const struct aspeed_sig_desc sig_descs_EXTRST_EXTRST[] = {
+ * {
+ * .ip = ASPEED_IP_SCU,
+ * .reg = 0x3C,
+ * .mask = BIT(3),
+ * .enable = 1,
+ * .disable = 0
+ * },
+ * {
+ * .ip = ASPEED_IP_SCU,
+ * .reg = 0x80,
+ * .mask = BIT(15),
+ * .enable = 1,
+ * .disable = 0
+ * },
+ * {
+ * .ip = ASPEED_IP_SCU,
+ * .reg = 0x90,
+ * .mask = BIT(31),
+ * .enable = 0,
+ * .disable = 1
+ * },
+ * };
+ *
+ * static const struct aspeed_sig_expr sig_expr_EXTRST_EXTRST = {
+ * .signal = "EXTRST",
+ * .function = "EXTRST",
+ * .ndescs = ARRAY_SIZE(sig_descs_EXTRST_EXTRST),
+ * .descs = &(sig_descs_EXTRST_EXTRST)[0],
+ * };
+ * ...
+ * ```
+ *
+ * For ball E19, we have multiple functions enabling a single signal, LPCRST#.
+ * The data structures look like:
+ *
+ * static const struct aspeed_sig_desc sig_descs_LPCRST_LPCRST[] = {
+ * {
+ * .ip = ASPEED_IP_SCU,
+ * .reg = 0x80,
+ * .mask = BIT(12),
+ * .enable = 1,
+ * .disable = 0
+ * },
+ * };
+ *
+ * static const struct aspeed_sig_expr sig_expr_LPCRST_LPCRST = {
+ * .signal = "LPCRST",
+ * .function = "LPCRST",
+ * .ndescs = ARRAY_SIZE(sig_descs_LPCRST_LPCRST),
+ * .descs = &(sig_descs_LPCRST_LPCRST)[0],
+ * };
+ *
+ * static const struct aspeed_sig_desc sig_descs_LPCRST_LPCRSTS[] = {
+ * {
+ * .ip = ASPEED_IP_SCU,
+ * .reg = 0x70,
+ * .mask = BIT(14),
+ * .enable = 1,
+ * .disable = 0
+ * },
+ * };
+ *
+ * static const struct aspeed_sig_expr sig_expr_LPCRST_LPCRSTS = {
+ * .signal = "LPCRST",
+ * .function = "LPCRSTS",
+ * .ndescs = ARRAY_SIZE(sig_descs_LPCRST_LPCRSTS),
+ * .descs = &(sig_descs_LPCRST_LPCRSTS)[0],
+ * };
+ *
+ * static const struct aspeed_sig_expr *sig_exprs_LPCRST_LPCRST[] = {
+ * &sig_expr_LPCRST_LPCRST,
+ * &sig_expr_LPCRST_LPCRSTS,
+ * NULL,
+ * };
+ * ...
+ * ```
+ *
+ * Both expressions listed in the sig_exprs_LPCRST_LPCRST array need to be set
+ * to disabled for the associated GPIO to be muxed.
+ *
+ */
+
+#define ASPEED_IP_SCU 0
+#define ASPEED_IP_GFX 1
+#define ASPEED_IP_LPC 2
+#define ASPEED_NR_PINMUX_IPS 3
+
+ /**
+ * A signal descriptor, which describes the register, bits and the
+ * enable/disable values that should be compared or written.
+ *
+ * @ip: The IP block identifier, used as an index into the regmap array in
+ * struct aspeed_pinctrl_data
+ * @reg: The register offset with respect to the base address of the IP block
+ * @mask: The mask to apply to the register. The lowest set bit of the mask is
+ * used to derive the shift value.
+ * @enable: The value that enables the function. Value should be in the LSBs,
+ * not at the position of the mask.
+ * @disable: The value that disables the function. Value should be in the
+ * LSBs, not at the position of the mask.
+ */
+struct aspeed_sig_desc {
+ unsigned int ip;
+ unsigned int reg;
+ u32 mask;
+ u32 enable;
+ u32 disable;
+};
+
+/**
+ * Describes a signal expression. The expression is evaluated by ANDing the
+ * evaluation of the descriptors.
+ *
+ * @signal: The signal name for the priority level on the pin. If the signal
+ * type is GPIO, then the signal name must begin with the string
+ * "GPIO", e.g. GPIOA0, GPIOT4 etc.
+ * @function: The name of the function the signal participates in for the
+ * associated expression
+ * @ndescs: The number of signal descriptors in the expression
+ * @descs: Pointer to an array of signal descriptors that comprise the
+ * function expression
+ */
+struct aspeed_sig_expr {
+ const char *signal;
+ const char *function;
+ int ndescs;
+ const struct aspeed_sig_desc *descs;
+};
+
+/**
+ * A struct capturing the list of expressions enabling signals at each priority
+ * for a given pin. The signal configuration for a priority level is evaluated
+ * by ORing the evaluation of the signal expressions in the respective
+ * priority's list.
+ *
+ * @name: A name for the pin
+ * @prios: A pointer to an array of expression list pointers
+ *
+ */
+struct aspeed_pin_desc {
+ const char *name;
+ const struct aspeed_sig_expr ***prios;
+};
+
+/* Macro hell */
+
+#define SIG_DESC_IP_BIT(ip, reg, idx, val) \
+ { ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
+
+/**
+ * Short-hand macro for describing an SCU descriptor enabled by the state of
+ * one bit. The disable value is derived.
+ *
+ * @reg: The signal's associated register, offset from base
+ * @idx: The signal's bit index in the register
+ * @val: The value (0 or 1) that enables the function
+ */
+#define SIG_DESC_BIT(reg, idx, val) \
+ SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
+
+#define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
+
+/**
+ * A further short-hand macro expanding to an SCU descriptor enabled by a set
+ * bit.
+ *
+ * @reg: The register, offset from base
+ * @idx: The bit index in the register
+ */
+#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
+
+#define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
+#define SIG_DESC_LIST_DECL(sig, func, ...) \
+ static const struct aspeed_sig_desc SIG_DESC_LIST_SYM(sig, func)[] = \
+ { __VA_ARGS__ }
+
+#define SIG_EXPR_SYM(sig, func) sig_expr_ ## sig ## _ ## func
+#define SIG_EXPR_DECL_(sig, func) \
+ static const struct aspeed_sig_expr SIG_EXPR_SYM(sig, func) = \
+ { \
+ .signal = #sig, \
+ .function = #func, \
+ .ndescs = ARRAY_SIZE(SIG_DESC_LIST_SYM(sig, func)), \
+ .descs = &(SIG_DESC_LIST_SYM(sig, func))[0], \
+ }
+
+/**
+ * Declare a signal expression.
+ *
+ * @sig: A macro symbol name for the signal (is subjected to stringification
+ * and token pasting)
+ * @func: The function in which the signal is participating
+ * @...: Signal descriptors that define the signal expression
+ *
+ * For example, the following declares the ROMD8 signal for the ROM16 function:
+ *
+ * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
+ *
+ * And with multiple signal descriptors:
+ *
+ * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
+ * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
+ */
+#define SIG_EXPR_DECL(sig, func, ...) \
+ SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
+ SIG_EXPR_DECL_(sig, func)
+
+/**
+ * Declare a pointer to a signal expression
+ *
+ * @sig: The macro symbol name for the signal (subjected to token pasting)
+ * @func: The macro symbol name for the function (subjected to token pasting)
+ */
+#define SIG_EXPR_PTR(sig, func) (&SIG_EXPR_SYM(sig, func))
+
+#define SIG_EXPR_LIST_SYM(sig) sig_exprs_ ## sig
+
+/**
+ * Declare a signal expression list for reference in a struct aspeed_pin_prio.
+ *
+ * @sig: A macro symbol name for the signal (is subjected to token pasting)
+ * @...: Signal expression structure pointers (use SIG_EXPR_PTR())
+ *
+ * For example, the 16-bit ROM bus can be enabled by one of two possible signal
+ * expressions:
+ *
+ * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
+ * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
+ * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
+ * SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
+ * SIG_EXPR_PTR(ROMD8, ROM16S));
+ */
+#define SIG_EXPR_LIST_DECL(sig, ...) \
+ static const struct aspeed_sig_expr *SIG_EXPR_LIST_SYM(sig)[] = \
+ { __VA_ARGS__, NULL }
+
+/**
+ * A short-hand macro for declaring a function expression and an expression
+ * list with a single function.
+ *
+ * @func: A macro symbol name for the function (is subjected to token pasting)
+ * @...: Function descriptors that define the function expression
+ *
+ * For example, signal NCTS6 participates in its own function with one group:
+ *
+ * SIG_EXPR_LIST_DECL_SINGLE(NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
+ */
+#define SIG_EXPR_LIST_DECL_SINGLE(sig, func, ...) \
+ SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
+ SIG_EXPR_DECL_(sig, func); \
+ SIG_EXPR_LIST_DECL(sig, SIG_EXPR_PTR(sig, func))
+
+#define SIG_EXPR_LIST_DECL_DUAL(sig, f0, f1) \
+ SIG_EXPR_LIST_DECL(sig, SIG_EXPR_PTR(sig, f0), SIG_EXPR_PTR(sig, f1))
+
+#define SIG_EXPR_LIST_PTR(sig) (&SIG_EXPR_LIST_SYM(sig)[0])
+
+#define PIN_EXPRS_SYM(pin) pin_exprs_ ## pin
+#define PIN_EXPRS_PTR(pin) (&PIN_EXPRS_SYM(pin)[0])
+#define PIN_SYM(pin) pin_ ## pin
+
+#define MS_PIN_DECL_(pin, ...) \
+ static const struct aspeed_sig_expr **PIN_EXPRS_SYM(pin)[] = \
+ { __VA_ARGS__, NULL }; \
+ static const struct aspeed_pin_desc PIN_SYM(pin) = \
+ { #pin, PIN_EXPRS_PTR(pin) }
+
+/**
+ * Declare a multi-signal pin
+ *
+ * @pin: The pin number
+ * @other: Macro name for "other" functionality (subjected to stringification)
+ * @high: Macro name for the highest priority signal functions
+ * @low: Macro name for the low signal functions
+ *
+ * For example:
+ *
+ * #define A8 56
+ * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
+ * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
+ * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
+ * SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
+ * SIG_EXPR_PTR(ROMD8, ROM16S));
+ * SIG_EXPR_LIST_DECL_SINGLE(NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
+ * MS_PIN_DECL(A8, GPIOH0, ROMD8, NCTS6);
+ */
+#define MS_PIN_DECL(pin, other, high, low) \
+ SIG_EXPR_LIST_DECL_SINGLE(other, other); \
+ MS_PIN_DECL_(pin, \
+ SIG_EXPR_LIST_PTR(high), \
+ SIG_EXPR_LIST_PTR(low), \
+ SIG_EXPR_LIST_PTR(other))
+
+#define PIN_GROUP_SYM(func) pins_ ## func
+#define FUNC_GROUP_SYM(func) groups_ ## func
+#define FUNC_GROUP_DECL(func, ...) \
+ static const int PIN_GROUP_SYM(func)[] = { __VA_ARGS__ }; \
+ static const char *FUNC_GROUP_SYM(func)[] = { #func }
+
+/**
+ * Declare a single signal pin
+ *
+ * @pin: The pin number
+ * @other: Macro name for "other" functionality (subjected to stringification)
+ * @sig: Macro name for the signal (subjected to stringification)
+ *
+ * For example:
+ *
+ * #define E3 80
+ * SIG_EXPR_LIST_DECL_SINGLE(SCL5, I2C5, I2C5_DESC);
+ * SS_PIN_DECL(E3, GPIOK0, SCL5);
+ */
+#define SS_PIN_DECL(pin, other, sig) \
+ SIG_EXPR_LIST_DECL_SINGLE(other, other); \
+ MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(sig), SIG_EXPR_LIST_PTR(other))
+
+/**
+ * Single signal, single function pin declaration
+ *
+ * @pin: The pin number
+ * @other: Macro name for "other" functionality (subjected to stringification)
+ * @sig: Macro name for the signal (subjected to stringification)
+ * @...: Signal descriptors that define the function expression
+ *
+ * For example:
+ *
+ * SSSF_PIN_DECL(A4, GPIOA2, TIMER3, SIG_DESC_SET(SCU80, 2));
+ */
+#define SSSF_PIN_DECL(pin, other, sig, ...) \
+ SIG_EXPR_LIST_DECL_SINGLE(sig, sig, __VA_ARGS__); \
+ SIG_EXPR_LIST_DECL_SINGLE(other, other); \
+ MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(sig), SIG_EXPR_LIST_PTR(other)); \
+ FUNC_GROUP_DECL(sig, pin)
+
+#define GPIO_PIN_DECL(pin, gpio) \
+ SIG_EXPR_LIST_DECL_SINGLE(gpio, gpio); \
+ MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
+
+struct aspeed_pin_group {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned int npins;
+};
+
+#define ASPEED_PINCTRL_GROUP(name_) { \
+ .name = #name_, \
+ .pins = &(PIN_GROUP_SYM(name_))[0], \
+ .npins = ARRAY_SIZE(PIN_GROUP_SYM(name_)), \
+}
+
+struct aspeed_pin_function {
+ const char *name;
+ const char *const *groups;
+ unsigned int ngroups;
+};
+
+#define ASPEED_PINCTRL_FUNC(name_, ...) { \
+ .name = #name_, \
+ .groups = &FUNC_GROUP_SYM(name_)[0], \
+ .ngroups = ARRAY_SIZE(FUNC_GROUP_SYM(name_)), \
+}
+
+struct aspeed_pinmux_data;
+
+struct aspeed_pinmux_ops {
+ int (*set)(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr, bool enabled);
+};
+
+struct aspeed_pinmux_data {
+ struct regmap *maps[ASPEED_NR_PINMUX_IPS];
+
+ const struct aspeed_pinmux_ops *ops;
+
+ const struct aspeed_pin_group *groups;
+ const unsigned int ngroups;
+
+ const struct aspeed_pin_function *functions;
+ const unsigned int nfunctions;
+};
+
+int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, bool enabled,
+ struct regmap *map);
+
+int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr,
+ bool enabled);
+
+static inline int aspeed_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+ const struct aspeed_sig_expr *expr,
+ bool enabled)
+{
+ return ctx->ops->set(ctx, expr, enabled);
+}
+
+#endif /* ASPEED_PINMUX_H */
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index 97284c3f9e83..dcf7df797af7 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -18,11 +18,15 @@ config PINCTRL_BCM281XX
framework. GPIO is provided by a separate GPIO driver.
config PINCTRL_BCM2835
- bool
+ bool "Broadcom BCM2835 GPIO (with PINCONF) driver"
+ depends on OF && (ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST)
select PINMUX
select PINCONF
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
+ default ARCH_BCM2835 || ARCH_BRCMSTB
+ help
+ Say Y here to enable the Broadcom BCM2835 GPIO driver.
config PINCTRL_IPROC_GPIO
bool "Broadcom iProc GPIO (with PINCONF) driver"
diff --git a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c
index 4b5cf0e0f16e..2bf6af7df7d9 100644
--- a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c
+++ b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c
@@ -1048,6 +1048,8 @@ static int ns2_pinmux_probe(struct platform_device *pdev)
return PTR_ERR(pinctrl->base0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -EINVAL;
pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!pinctrl->base1) {
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l35.c b/drivers/pinctrl/cirrus/pinctrl-cs47l35.c
index 06b59160783d..53a8eab19aad 100644
--- a/drivers/pinctrl/cirrus/pinctrl-cs47l35.c
+++ b/drivers/pinctrl/cirrus/pinctrl-cs47l35.c
@@ -1,12 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Pinctrl for Cirrus Logic CS47L35
*
* Copyright (C) 2016-2017 Cirrus Logic
- *
- * 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.
*/
#include <linux/err.h>
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l85.c b/drivers/pinctrl/cirrus/pinctrl-cs47l85.c
index 0a322e2a0fde..e08c7992d252 100644
--- a/drivers/pinctrl/cirrus/pinctrl-cs47l85.c
+++ b/drivers/pinctrl/cirrus/pinctrl-cs47l85.c
@@ -1,12 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Pinctrl for Cirrus Logic CS47L85
*
* Copyright (C) 2016-2017 Cirrus Logic
- *
- * 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.
*/
#include <linux/err.h>
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l90.c b/drivers/pinctrl/cirrus/pinctrl-cs47l90.c
index fc38f579f492..3151f107adc4 100644
--- a/drivers/pinctrl/cirrus/pinctrl-cs47l90.c
+++ b/drivers/pinctrl/cirrus/pinctrl-cs47l90.c
@@ -1,12 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Pinctrl for Cirrus Logic CS47L90
*
* Copyright (C) 2016-2017 Cirrus Logic
- *
- * 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.
*/
#include <linux/err.h>
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera-core.c b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
index 7c9694593f79..c6b9f65f2362 100644
--- a/drivers/pinctrl/cirrus/pinctrl-madera-core.c
+++ b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
@@ -1,12 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Pinctrl for Cirrus Logic Madera codecs
*
* Copyright (C) 2016-2018 Cirrus Logic
- *
- * 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.
*/
#include <linux/err.h>
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera.h b/drivers/pinctrl/cirrus/pinctrl-madera.h
index 8000f4f832a1..4ae13918316f 100644
--- a/drivers/pinctrl/cirrus/pinctrl-madera.h
+++ b/drivers/pinctrl/cirrus/pinctrl-madera.h
@@ -1,12 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Pinctrl for Cirrus Logic Madera codecs
*
* Copyright (C) 2016-2017 Cirrus Logic
- *
- * 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.
*/
#ifndef PINCTRL_MADERA_H
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index a64849a9d1b0..b70df27874d1 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(pinctrl_dev_get_drvdata);
*/
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname)
{
- struct pinctrl_dev *pctldev = NULL;
+ struct pinctrl_dev *pctldev;
if (!devname)
return NULL;
@@ -177,29 +177,6 @@ const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
return desc->name;
}
-/**
- * pin_is_valid() - check if pin exists on controller
- * @pctldev: the pin control device to check the pin on
- * @pin: pin to check, use the local pin controller index number
- *
- * This tells us whether a certain pin exist on a certain pin controller or
- * not. Pin lists may be sparse, so some pins may not exist.
- */
-bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
-{
- struct pin_desc *pindesc;
-
- if (pin < 0)
- return false;
-
- mutex_lock(&pctldev->mutex);
- pindesc = pin_desc_get(pctldev, pin);
- mutex_unlock(&pctldev->mutex);
-
- return pindesc != NULL;
-}
-EXPORT_SYMBOL_GPL(pin_is_valid);
-
/* Deletes a range of pin descriptors */
static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pins,
@@ -311,7 +288,7 @@ static inline int gpio_to_pin(struct pinctrl_gpio_range *range,
static struct pinctrl_gpio_range *
pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
{
- struct pinctrl_gpio_range *range = NULL;
+ struct pinctrl_gpio_range *range;
mutex_lock(&pctldev->mutex);
/* Loop over the ranges */
@@ -391,7 +368,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
struct pinctrl_dev **outdev,
struct pinctrl_gpio_range **outrange)
{
- struct pinctrl_dev *pctldev = NULL;
+ struct pinctrl_dev *pctldev;
mutex_lock(&pinctrldev_list_mutex);
@@ -1215,6 +1192,15 @@ struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,
}
EXPORT_SYMBOL_GPL(pinctrl_lookup_state);
+static void pinctrl_link_add(struct pinctrl_dev *pctldev,
+ struct device *consumer)
+{
+ if (pctldev->desc->link_consumers)
+ device_link_add(consumer, pctldev->dev,
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+}
+
/**
* pinctrl_commit_state() - select/activate/program a pinctrl state to HW
* @p: the pinctrl handle for the device that requests configuration
@@ -1260,6 +1246,10 @@ static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
if (ret < 0) {
goto unapply_new_state;
}
+
+ /* Do not link hogs (circular dependency) */
+ if (p != setting->pctldev->p)
+ pinctrl_link_add(setting->pctldev, p->dev);
}
p->state = state;
@@ -1665,7 +1655,7 @@ DEFINE_SHOW_ATTRIBUTE(pinctrl_groups);
static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
- struct pinctrl_gpio_range *range = NULL;
+ struct pinctrl_gpio_range *range;
seq_puts(s, "GPIO ranges handled:\n");
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index f7e354f85518..88ddbb2e30de 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -112,12 +112,11 @@ static int dt_to_map_one_config(struct pinctrl *p,
np_pctldev = of_get_next_parent(np_pctldev);
if (!np_pctldev || of_node_is_root(np_pctldev)) {
of_node_put(np_pctldev);
- ret = driver_deferred_probe_check_state(p->dev);
/* keep deferring if modules are enabled unless we've timed out */
- if (IS_ENABLED(CONFIG_MODULES) && !allow_default && ret == -ENODEV)
- ret = -EPROBE_DEFER;
+ if (IS_ENABLED(CONFIG_MODULES) && !allow_default)
+ return driver_deferred_probe_check_state_continue(p->dev);
- return ret;
+ return driver_deferred_probe_check_state(p->dev);
}
/* If we're creating a hog we can use the passed pctldev */
if (hog_pctldev && (np_pctldev == p->dev->of_node)) {
diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig
index aeab0d9af23e..5f4058033ec6 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -130,6 +130,13 @@ config PINCTRL_IMX8MM
help
Say Y here to enable the imx8mm pinctrl driver
+config PINCTRL_IMX8MN
+ bool "IMX8MN pinctrl driver"
+ depends on ARCH_MXC && ARM64
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx8mn pinctrl driver
+
config PINCTRL_IMX8MQ
bool "IMX8MQ pinctrl driver"
depends on ARCH_MXC && ARM64
diff --git a/drivers/pinctrl/freescale/Makefile b/drivers/pinctrl/freescale/Makefile
index 02020a76bd9c..78e9140c13e3 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PINCTRL_IMX6UL) += pinctrl-imx6ul.o
obj-$(CONFIG_PINCTRL_IMX7D) += pinctrl-imx7d.o
obj-$(CONFIG_PINCTRL_IMX7ULP) += pinctrl-imx7ulp.o
obj-$(CONFIG_PINCTRL_IMX8MM) += pinctrl-imx8mm.o
+obj-$(CONFIG_PINCTRL_IMX8MN) += pinctrl-imx8mn.o
obj-$(CONFIG_PINCTRL_IMX8MQ) += pinctrl-imx8mq.o
obj-$(CONFIG_PINCTRL_IMX8QM) += pinctrl-imx8qm.o
obj-$(CONFIG_PINCTRL_IMX8QXP) += pinctrl-imx8qxp.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mn.c b/drivers/pinctrl/freescale/pinctrl-imx8mn.c
new file mode 100644
index 000000000000..100ed8c1039a
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mn.c
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018-2019 NXP
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-imx.h"
+
+enum imx8mn_pads {
+ MX8MN_PAD_RESERVE0 = 0,
+ MX8MN_PAD_RESERVE1 = 1,
+ MX8MN_PAD_RESERVE2 = 2,
+ MX8MN_PAD_RESERVE3 = 3,
+ MX8MN_PAD_RESERVE4 = 4,
+ MX8MN_PAD_RESERVE5 = 5,
+ MX8MN_PAD_RESERVE6 = 6,
+ MX8MN_PAD_RESERVE7 = 7,
+ MX8MN_IOMUXC_BOOT_MODE2 = 8,
+ MX8MN_IOMUXC_BOOT_MODE3 = 9,
+ MX8MN_IOMUXC_GPIO1_IO00 = 10,
+ MX8MN_IOMUXC_GPIO1_IO01 = 11,
+ MX8MN_IOMUXC_GPIO1_IO02 = 12,
+ MX8MN_IOMUXC_GPIO1_IO03 = 13,
+ MX8MN_IOMUXC_GPIO1_IO04 = 14,
+ MX8MN_IOMUXC_GPIO1_IO05 = 15,
+ MX8MN_IOMUXC_GPIO1_IO06 = 16,
+ MX8MN_IOMUXC_GPIO1_IO07 = 17,
+ MX8MN_IOMUXC_GPIO1_IO08 = 18,
+ MX8MN_IOMUXC_GPIO1_IO09 = 19,
+ MX8MN_IOMUXC_GPIO1_IO10 = 20,
+ MX8MN_IOMUXC_GPIO1_IO11 = 21,
+ MX8MN_IOMUXC_GPIO1_IO12 = 22,
+ MX8MN_IOMUXC_GPIO1_IO13 = 23,
+ MX8MN_IOMUXC_GPIO1_IO14 = 24,
+ MX8MN_IOMUXC_GPIO1_IO15 = 25,
+ MX8MN_IOMUXC_ENET_MDC = 26,
+ MX8MN_IOMUXC_ENET_MDIO = 27,
+ MX8MN_IOMUXC_ENET_TD3 = 28,
+ MX8MN_IOMUXC_ENET_TD2 = 29,
+ MX8MN_IOMUXC_ENET_TD1 = 30,
+ MX8MN_IOMUXC_ENET_TD0 = 31,
+ MX8MN_IOMUXC_ENET_TX_CTL = 32,
+ MX8MN_IOMUXC_ENET_TXC = 33,
+ MX8MN_IOMUXC_ENET_RX_CTL = 34,
+ MX8MN_IOMUXC_ENET_RXC = 35,
+ MX8MN_IOMUXC_ENET_RD0 = 36,
+ MX8MN_IOMUXC_ENET_RD1 = 37,
+ MX8MN_IOMUXC_ENET_RD2 = 38,
+ MX8MN_IOMUXC_ENET_RD3 = 39,
+ MX8MN_IOMUXC_SD1_CLK = 40,
+ MX8MN_IOMUXC_SD1_CMD = 41,
+ MX8MN_IOMUXC_SD1_DATA0 = 42,
+ MX8MN_IOMUXC_SD1_DATA1 = 43,
+ MX8MN_IOMUXC_SD1_DATA2 = 44,
+ MX8MN_IOMUXC_SD1_DATA3 = 45,
+ MX8MN_IOMUXC_SD1_DATA4 = 46,
+ MX8MN_IOMUXC_SD1_DATA5 = 47,
+ MX8MN_IOMUXC_SD1_DATA6 = 48,
+ MX8MN_IOMUXC_SD1_DATA7 = 49,
+ MX8MN_IOMUXC_SD1_RESET_B = 50,
+ MX8MN_IOMUXC_SD1_STROBE = 51,
+ MX8MN_IOMUXC_SD2_CD_B = 52,
+ MX8MN_IOMUXC_SD2_CLK = 53,
+ MX8MN_IOMUXC_SD2_CMD = 54,
+ MX8MN_IOMUXC_SD2_DATA0 = 55,
+ MX8MN_IOMUXC_SD2_DATA1 = 56,
+ MX8MN_IOMUXC_SD2_DATA2 = 57,
+ MX8MN_IOMUXC_SD2_DATA3 = 58,
+ MX8MN_IOMUXC_SD2_RESET_B = 59,
+ MX8MN_IOMUXC_SD2_WP = 60,
+ MX8MN_IOMUXC_NAND_ALE = 61,
+ MX8MN_IOMUXC_NAND_CE0 = 62,
+ MX8MN_IOMUXC_NAND_CE1 = 63,
+ MX8MN_IOMUXC_NAND_CE2 = 64,
+ MX8MN_IOMUXC_NAND_CE3 = 65,
+ MX8MN_IOMUXC_NAND_CLE = 66,
+ MX8MN_IOMUXC_NAND_DATA00 = 67,
+ MX8MN_IOMUXC_NAND_DATA01 = 68,
+ MX8MN_IOMUXC_NAND_DATA02 = 69,
+ MX8MN_IOMUXC_NAND_DATA03 = 70,
+ MX8MN_IOMUXC_NAND_DATA04 = 71,
+ MX8MN_IOMUXC_NAND_DATA05 = 72,
+ MX8MN_IOMUXC_NAND_DATA06 = 73,
+ MX8MN_IOMUXC_NAND_DATA07 = 74,
+ MX8MN_IOMUXC_NAND_DQS = 75,
+ MX8MN_IOMUXC_NAND_RE_B = 76,
+ MX8MN_IOMUXC_NAND_READY_B = 77,
+ MX8MN_IOMUXC_NAND_WE_B = 78,
+ MX8MN_IOMUXC_NAND_WP_B = 79,
+ MX8MN_IOMUXC_SAI5_RXFS = 80,
+ MX8MN_IOMUXC_SAI5_RXC = 81,
+ MX8MN_IOMUXC_SAI5_RXD0 = 82,
+ MX8MN_IOMUXC_SAI5_RXD1 = 83,
+ MX8MN_IOMUXC_SAI5_RXD2 = 84,
+ MX8MN_IOMUXC_SAI5_RXD3 = 85,
+ MX8MN_IOMUXC_SAI5_MCLK = 86,
+ MX8MN_IOMUXC_SAI1_RXFS = 87,
+ MX8MN_IOMUXC_SAI1_RXC = 88,
+ MX8MN_IOMUXC_SAI1_RXD0 = 89,
+ MX8MN_IOMUXC_SAI1_RXD1 = 90,
+ MX8MN_IOMUXC_SAI1_RXD2 = 91,
+ MX8MN_IOMUXC_SAI1_RXD3 = 92,
+ MX8MN_IOMUXC_SAI1_RXD4 = 93,
+ MX8MN_IOMUXC_SAI1_RXD5 = 94,
+ MX8MN_IOMUXC_SAI1_RXD6 = 95,
+ MX8MN_IOMUXC_SAI1_RXD7 = 96,
+ MX8MN_IOMUXC_SAI1_TXFS = 97,
+ MX8MN_IOMUXC_SAI1_TXC = 98,
+ MX8MN_IOMUXC_SAI1_TXD0 = 99,
+ MX8MN_IOMUXC_SAI1_TXD1 = 100,
+ MX8MN_IOMUXC_SAI1_TXD2 = 101,
+ MX8MN_IOMUXC_SAI1_TXD3 = 102,
+ MX8MN_IOMUXC_SAI1_TXD4 = 103,
+ MX8MN_IOMUXC_SAI1_TXD5 = 104,
+ MX8MN_IOMUXC_SAI1_TXD6 = 105,
+ MX8MN_IOMUXC_SAI1_TXD7 = 106,
+ MX8MN_IOMUXC_SAI1_MCLK = 107,
+ MX8MN_IOMUXC_SAI2_RXFS = 108,
+ MX8MN_IOMUXC_SAI2_RXC = 109,
+ MX8MN_IOMUXC_SAI2_RXD0 = 110,
+ MX8MN_IOMUXC_SAI2_TXFS = 111,
+ MX8MN_IOMUXC_SAI2_TXC = 112,
+ MX8MN_IOMUXC_SAI2_TXD0 = 113,
+ MX8MN_IOMUXC_SAI2_MCLK = 114,
+ MX8MN_IOMUXC_SAI3_RXFS = 115,
+ MX8MN_IOMUXC_SAI3_RXC = 116,
+ MX8MN_IOMUXC_SAI3_RXD = 117,
+ MX8MN_IOMUXC_SAI3_TXFS = 118,
+ MX8MN_IOMUXC_SAI3_TXC = 119,
+ MX8MN_IOMUXC_SAI3_TXD = 120,
+ MX8MN_IOMUXC_SAI3_MCLK = 121,
+ MX8MN_IOMUXC_SPDIF_TX = 122,
+ MX8MN_IOMUXC_SPDIF_RX = 123,
+ MX8MN_IOMUXC_SPDIF_EXT_CLK = 124,
+ MX8MN_IOMUXC_ECSPI1_SCLK = 125,
+ MX8MN_IOMUXC_ECSPI1_MOSI = 126,
+ MX8MN_IOMUXC_ECSPI1_MISO = 127,
+ MX8MN_IOMUXC_ECSPI1_SS0 = 128,
+ MX8MN_IOMUXC_ECSPI2_SCLK = 129,
+ MX8MN_IOMUXC_ECSPI2_MOSI = 130,
+ MX8MN_IOMUXC_ECSPI2_MISO = 131,
+ MX8MN_IOMUXC_ECSPI2_SS0 = 132,
+ MX8MN_IOMUXC_I2C1_SCL = 133,
+ MX8MN_IOMUXC_I2C1_SDA = 134,
+ MX8MN_IOMUXC_I2C2_SCL = 135,
+ MX8MN_IOMUXC_I2C2_SDA = 136,
+ MX8MN_IOMUXC_I2C3_SCL = 137,
+ MX8MN_IOMUXC_I2C3_SDA = 138,
+ MX8MN_IOMUXC_I2C4_SCL = 139,
+ MX8MN_IOMUXC_I2C4_SDA = 140,
+ MX8MN_IOMUXC_UART1_RXD = 141,
+ MX8MN_IOMUXC_UART1_TXD = 142,
+ MX8MN_IOMUXC_UART2_RXD = 143,
+ MX8MN_IOMUXC_UART2_TXD = 144,
+ MX8MN_IOMUXC_UART3_RXD = 145,
+ MX8MN_IOMUXC_UART3_TXD = 146,
+ MX8MN_IOMUXC_UART4_RXD = 147,
+ MX8MN_IOMUXC_UART4_TXD = 148,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx8mn_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE1),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE2),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE3),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE4),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE5),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE6),
+ IMX_PINCTRL_PIN(MX8MN_PAD_RESERVE7),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_BOOT_MODE2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_BOOT_MODE3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO00),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO01),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO02),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO03),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO04),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO05),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO06),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO07),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO08),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO09),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO10),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO11),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO12),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO13),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO14),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_GPIO1_IO15),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_MDC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_MDIO),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_TD3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_TD2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_TD1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_TD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_TX_CTL),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_TXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_RX_CTL),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_RXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_RD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_RD1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_RD2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ENET_RD3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_CLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_CMD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA4),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA5),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA6),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_DATA7),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_RESET_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD1_STROBE),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_CD_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_CLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_CMD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_DATA0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_DATA1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_DATA2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_DATA3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_RESET_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SD2_WP),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_ALE),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_CE0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_CE1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_CE2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_CE3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_CLE),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA00),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA01),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA02),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA03),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA04),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA05),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA06),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DATA07),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_DQS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_RE_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_READY_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_WE_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_NAND_WP_B),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_RXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_RXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_RXD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_RXD1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_RXD2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_RXD3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI5_MCLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD4),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD5),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD6),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_RXD7),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD1),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD2),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD3),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD4),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD5),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD6),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_TXD7),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI1_MCLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_RXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_RXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_RXD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_TXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_TXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_TXD0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI2_MCLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_RXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_RXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_RXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_TXFS),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_TXC),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_TXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SAI3_MCLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SPDIF_TX),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SPDIF_RX),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_SPDIF_EXT_CLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI1_SCLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI1_MOSI),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI1_MISO),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI1_SS0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI2_SCLK),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI2_MOSI),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI2_MISO),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_ECSPI2_SS0),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C1_SCL),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C1_SDA),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C2_SCL),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C2_SDA),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C3_SCL),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C3_SDA),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C4_SCL),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_I2C4_SDA),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART1_RXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART1_TXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART2_RXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART2_TXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART3_RXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART3_TXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART4_RXD),
+ IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART4_TXD),
+};
+
+static struct imx_pinctrl_soc_info imx8mn_pinctrl_info = {
+ .pins = imx8mn_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx8mn_pinctrl_pads),
+ .gpr_compatible = "fsl,imx8mn-iomuxc-gpr",
+};
+
+static const struct of_device_id imx8mn_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx8mn-iomuxc", .data = &imx8mn_pinctrl_info, },
+ { /* sentinel */ }
+};
+
+static int imx8mn_pinctrl_probe(struct platform_device *pdev)
+{
+ return imx_pinctrl_probe(pdev, &imx8mn_pinctrl_info);
+}
+
+static struct platform_driver imx8mn_pinctrl_driver = {
+ .driver = {
+ .name = "imx8mn-pinctrl",
+ .of_match_table = of_match_ptr(imx8mn_pinctrl_of_match),
+ .suppress_bind_attrs = true,
+ },
+ .probe = imx8mn_pinctrl_probe,
+};
+
+static int __init imx8mn_pinctrl_init(void)
+{
+ return platform_driver_register(&imx8mn_pinctrl_driver);
+}
+arch_initcall(imx8mn_pinctrl_init);
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 18d9ad504194..e5a112a8e067 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -24,6 +24,8 @@
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include "pinctrl-intel.h"
+
/* memory mapped register offsets */
#define BYT_CONF0_REG 0x000
#define BYT_CONF1_REG 0x004
@@ -35,6 +37,7 @@
/* BYT_CONF0_REG register bits */
#define BYT_IODEN BIT(31)
#define BYT_DIRECT_IRQ_EN BIT(27)
+#define BYT_TRIG_MASK GENMASK(26, 24)
#define BYT_TRIG_NEG BIT(26)
#define BYT_TRIG_POS BIT(25)
#define BYT_TRIG_LVL BIT(24)
@@ -43,31 +46,28 @@
#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_MASK GENMASK(10, 9)
#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_ASSIGN_SHIFT 7
-#define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT)
+#define BYT_PULL_ASSIGN_MASK GENMASK(8, 7)
#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT)
#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT)
-#define BYT_PIN_MUX 0x07
+#define BYT_PIN_MUX GENMASK(2, 0)
/* BYT_VAL_REG register bits */
+#define BYT_DIR_MASK GENMASK(2, 1)
#define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/
#define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/
#define BYT_LEVEL BIT(0)
-#define BYT_DIR_MASK (BIT(1) | BIT(2))
-#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24))
-
-#define BYT_CONF0_RESTORE_MASK (BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | \
- BYT_PIN_MUX)
+#define BYT_CONF0_RESTORE_MASK (BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | BYT_PIN_MUX)
#define BYT_VAL_RESTORE_MASK (BYT_DIR_MASK | BYT_LEVEL)
/* BYT_DEBOUNCE_REG bits */
-#define BYT_DEBOUNCE_PULSE_MASK 0x7
+#define BYT_DEBOUNCE_PULSE_MASK GENMASK(2, 0)
#define BYT_DEBOUNCE_PULSE_375US 1
#define BYT_DEBOUNCE_PULSE_750US 2
#define BYT_DEBOUNCE_PULSE_1500US 3
@@ -91,40 +91,13 @@
* does not find a match for the requested function.
*/
#define BYT_DEFAULT_GPIO_MUX 0
+#define BYT_ALTER_GPIO_MUX 1
struct byt_gpio_pin_context {
u32 conf0;
u32 val;
};
-struct byt_simple_func_mux {
- const char *name;
- unsigned short func;
-};
-
-struct byt_mixed_func_mux {
- const char *name;
- const unsigned short *func_values;
-};
-
-struct byt_pingroup {
- const char *name;
- const unsigned int *pins;
- size_t npins;
- unsigned short has_simple_funcs;
- union {
- const struct byt_simple_func_mux *simple_funcs;
- const struct byt_mixed_func_mux *mixed_funcs;
- };
- size_t nfuncs;
-};
-
-struct byt_function {
- const char *name;
- const char * const *groups;
- size_t ngroups;
-};
-
struct byt_community {
unsigned int pin_base;
size_t npins;
@@ -132,47 +105,6 @@ struct byt_community {
void __iomem *reg_base;
};
-#define SIMPLE_FUNC(n, f) \
- { \
- .name = (n), \
- .func = (f), \
- }
-#define MIXED_FUNC(n, f) \
- { \
- .name = (n), \
- .func_values = (f), \
- }
-
-#define PIN_GROUP_SIMPLE(n, p, f) \
- { \
- .name = (n), \
- .pins = (p), \
- .npins = ARRAY_SIZE((p)), \
- .has_simple_funcs = 1, \
- { \
- .simple_funcs = (f), \
- }, \
- .nfuncs = ARRAY_SIZE((f)), \
- }
-#define PIN_GROUP_MIXED(n, p, f) \
- { \
- .name = (n), \
- .pins = (p), \
- .npins = ARRAY_SIZE((p)), \
- .has_simple_funcs = 0, \
- { \
- .mixed_funcs = (f), \
- }, \
- .nfuncs = ARRAY_SIZE((f)), \
- }
-
-#define FUNCTION(n, g) \
- { \
- .name = (n), \
- .groups = (g), \
- .ngroups = ARRAY_SIZE((g)), \
- }
-
#define COMMUNITY(p, n, map) \
{ \
.pin_base = (p), \
@@ -184,9 +116,9 @@ struct byt_pinctrl_soc_data {
const char *uid;
const struct pinctrl_pin_desc *pins;
size_t npins;
- const struct byt_pingroup *groups;
+ const struct intel_pingroup *groups;
size_t ngroups;
- const struct byt_function *functions;
+ const struct intel_function *functions;
size_t nfunctions;
const struct byt_community *communities;
size_t ncommunities;
@@ -326,20 +258,11 @@ static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
/* SCORE groups */
static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
-static const struct byt_simple_func_mux byt_score_uart_mux[] = {
- SIMPLE_FUNC("uart", 1),
-};
static const unsigned int byt_score_pwm0_pins[] = { 94 };
static const unsigned int byt_score_pwm1_pins[] = { 95 };
-static const struct byt_simple_func_mux byt_score_pwm_mux[] = {
- SIMPLE_FUNC("pwm", 1),
-};
static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
-static const struct byt_simple_func_mux byt_score_spi_mux[] = {
- SIMPLE_FUNC("spi", 1),
-};
static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
@@ -348,50 +271,29 @@ static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
-static const struct byt_simple_func_mux byt_score_i2c_mux[] = {
- SIMPLE_FUNC("i2c", 1),
-};
static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
-static const struct byt_simple_func_mux byt_score_ssp_mux[] = {
- SIMPLE_FUNC("ssp", 1),
-};
static const unsigned int byt_score_sdcard_pins[] = {
7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
};
-static const unsigned short byt_score_sdcard_mux_values[] = {
+static const unsigned int byt_score_sdcard_mux_values[] = {
2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
-static const struct byt_mixed_func_mux byt_score_sdcard_mux[] = {
- MIXED_FUNC("sdcard", byt_score_sdcard_mux_values),
-};
static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
-static const struct byt_simple_func_mux byt_score_sdio_mux[] = {
- SIMPLE_FUNC("sdio", 1),
-};
static const unsigned int byt_score_emmc_pins[] = {
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
};
-static const struct byt_simple_func_mux byt_score_emmc_mux[] = {
- SIMPLE_FUNC("emmc", 1),
-};
static const unsigned int byt_score_ilb_lpc_pins[] = {
42, 43, 44, 45, 46, 47, 48, 49, 50,
};
-static const struct byt_simple_func_mux byt_score_lpc_mux[] = {
- SIMPLE_FUNC("lpc", 1),
-};
static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
-static const struct byt_simple_func_mux byt_score_sata_mux[] = {
- SIMPLE_FUNC("sata", 1),
-};
static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
@@ -399,70 +301,37 @@ static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
static const unsigned int byt_score_plt_clk3_pins[] = { 99 };
static const unsigned int byt_score_plt_clk4_pins[] = { 100 };
static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
-static const struct byt_simple_func_mux byt_score_plt_clk_mux[] = {
- SIMPLE_FUNC("plt_clk", 1),
-};
static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
-static const struct byt_simple_func_mux byt_score_smbus_mux[] = {
- SIMPLE_FUNC("smbus", 1),
-};
-static const struct byt_pingroup byt_score_groups[] = {
- PIN_GROUP_SIMPLE("uart1_grp",
- byt_score_uart1_pins, byt_score_uart_mux),
- PIN_GROUP_SIMPLE("uart2_grp",
- byt_score_uart2_pins, byt_score_uart_mux),
- PIN_GROUP_SIMPLE("pwm0_grp",
- byt_score_pwm0_pins, byt_score_pwm_mux),
- PIN_GROUP_SIMPLE("pwm1_grp",
- byt_score_pwm1_pins, byt_score_pwm_mux),
- PIN_GROUP_SIMPLE("ssp2_grp",
- byt_score_ssp2_pins, byt_score_pwm_mux),
- PIN_GROUP_SIMPLE("sio_spi_grp",
- byt_score_sio_spi_pins, byt_score_spi_mux),
- PIN_GROUP_SIMPLE("i2c5_grp",
- byt_score_i2c5_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c6_grp",
- byt_score_i2c6_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c4_grp",
- byt_score_i2c4_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c3_grp",
- byt_score_i2c3_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c2_grp",
- byt_score_i2c2_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c1_grp",
- byt_score_i2c1_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c0_grp",
- byt_score_i2c0_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("ssp0_grp",
- byt_score_ssp0_pins, byt_score_ssp_mux),
- PIN_GROUP_SIMPLE("ssp1_grp",
- byt_score_ssp1_pins, byt_score_ssp_mux),
- PIN_GROUP_MIXED("sdcard_grp",
- byt_score_sdcard_pins, byt_score_sdcard_mux),
- PIN_GROUP_SIMPLE("sdio_grp",
- byt_score_sdio_pins, byt_score_sdio_mux),
- PIN_GROUP_SIMPLE("emmc_grp",
- byt_score_emmc_pins, byt_score_emmc_mux),
- PIN_GROUP_SIMPLE("lpc_grp",
- byt_score_ilb_lpc_pins, byt_score_lpc_mux),
- PIN_GROUP_SIMPLE("sata_grp",
- byt_score_sata_pins, byt_score_sata_mux),
- PIN_GROUP_SIMPLE("plt_clk0_grp",
- byt_score_plt_clk0_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk1_grp",
- byt_score_plt_clk1_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk2_grp",
- byt_score_plt_clk2_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk3_grp",
- byt_score_plt_clk3_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk4_grp",
- byt_score_plt_clk4_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk5_grp",
- byt_score_plt_clk5_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("smbus_grp",
- byt_score_smbus_pins, byt_score_smbus_mux),
+static const struct intel_pingroup byt_score_groups[] = {
+ PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
+ PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
+ PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
+ PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
+ PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
+ PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
+ PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
+ PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
+ PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
+ PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
+ PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
+ PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
+ PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
+ PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
+ PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
+ PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
+ PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
+ PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
+ PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
+ PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
+ PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
+ PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
+ PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
+ PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
+ PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
+ PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
+ PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
};
static const char * const byt_score_uart_groups[] = {
@@ -496,10 +365,9 @@ static const char * const byt_score_gpio_groups[] = {
"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
-
};
-static const struct byt_function byt_score_functions[] = {
+static const struct intel_function byt_score_functions[] = {
FUNCTION("uart", byt_score_uart_groups),
FUNCTION("pwm", byt_score_pwm_groups),
FUNCTION("ssp", byt_score_ssp_groups),
@@ -588,38 +456,30 @@ static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
};
static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
-static const struct byt_simple_func_mux byt_sus_usb_oc_mux[] = {
- SIMPLE_FUNC("usb", 0),
- SIMPLE_FUNC("gpio", 1),
-};
+static const unsigned int byt_sus_usb_over_current_mode_values[] = { 0, 0 };
+static const unsigned int byt_sus_usb_over_current_gpio_mode_values[] = { 1, 1 };
static const unsigned int byt_sus_usb_ulpi_pins[] = {
14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
};
-static const unsigned short byt_sus_usb_ulpi_mode_values[] = {
+static const unsigned int byt_sus_usb_ulpi_mode_values[] = {
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
-static const unsigned short byt_sus_usb_ulpi_gpio_mode_values[] = {
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-static const struct byt_mixed_func_mux byt_sus_usb_ulpi_mux[] = {
- MIXED_FUNC("usb", byt_sus_usb_ulpi_mode_values),
- MIXED_FUNC("gpio", byt_sus_usb_ulpi_gpio_mode_values),
+static const unsigned int byt_sus_usb_ulpi_gpio_mode_values[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
-static const struct byt_simple_func_mux byt_sus_pcu_spi_mux[] = {
- SIMPLE_FUNC("spi", 0),
- SIMPLE_FUNC("gpio", 1),
-};
+static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 };
+static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 };
-static const struct byt_pingroup byt_sus_groups[] = {
- PIN_GROUP_SIMPLE("usb_oc_grp",
- byt_sus_usb_over_current_pins, byt_sus_usb_oc_mux),
- PIN_GROUP_MIXED("usb_ulpi_grp",
- byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mux),
- PIN_GROUP_SIMPLE("pcu_spi_grp",
- byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mux),
+static const struct intel_pingroup byt_sus_groups[] = {
+ PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values),
+ PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values),
+ PIN_GROUP("pcu_spi_grp", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mode_values),
+ PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
+ PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
+ PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
};
static const char * const byt_sus_usb_groups[] = {
@@ -627,10 +487,10 @@ static const char * const byt_sus_usb_groups[] = {
};
static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
static const char * const byt_sus_gpio_groups[] = {
- "usb_oc_grp", "usb_ulpi_grp", "pcu_spi_grp",
+ "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
};
-static const struct byt_function byt_sus_functions[] = {
+static const struct intel_function byt_sus_functions[] = {
FUNCTION("usb", byt_sus_usb_groups),
FUNCTION("spi", byt_sus_spi_groups),
FUNCTION("gpio", byt_sus_gpio_groups),
@@ -810,41 +670,9 @@ static int byt_get_function_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int byt_get_group_simple_mux(const struct byt_pingroup group,
- const char *func_name,
- unsigned short *func)
-{
- int i;
-
- for (i = 0; i < group.nfuncs; i++) {
- if (!strcmp(group.simple_funcs[i].name, func_name)) {
- *func = group.simple_funcs[i].func;
- return 0;
- }
- }
-
- return 1;
-}
-
-static int byt_get_group_mixed_mux(const struct byt_pingroup group,
- const char *func_name,
- const unsigned short **func)
-{
- int i;
-
- for (i = 0; i < group.nfuncs; i++) {
- if (!strcmp(group.mixed_funcs[i].name, func_name)) {
- *func = group.mixed_funcs[i].func_values;
- return 0;
- }
- }
-
- return 1;
-}
-
static void byt_set_group_simple_mux(struct byt_gpio *vg,
- const struct byt_pingroup group,
- unsigned short func)
+ const struct intel_pingroup group,
+ unsigned int func)
{
unsigned long flags;
int i;
@@ -873,8 +701,8 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
}
static void byt_set_group_mixed_mux(struct byt_gpio *vg,
- const struct byt_pingroup group,
- const unsigned short *func)
+ const struct intel_pingroup group,
+ const unsigned int *func)
{
unsigned long flags;
int i;
@@ -906,23 +734,15 @@ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
unsigned int group_selector)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
- const struct byt_function func = vg->soc_data->functions[func_selector];
- const struct byt_pingroup group = vg->soc_data->groups[group_selector];
- const unsigned short *mixed_func;
- unsigned short simple_func;
- int ret = 1;
-
- if (group.has_simple_funcs)
- ret = byt_get_group_simple_mux(group, func.name, &simple_func);
- else
- ret = byt_get_group_mixed_mux(group, func.name, &mixed_func);
+ const struct intel_function func = vg->soc_data->functions[func_selector];
+ const struct intel_pingroup group = vg->soc_data->groups[group_selector];
- if (ret)
+ if (group.modes)
+ byt_set_group_mixed_mux(vg, group, group.modes);
+ else if (!strcmp(func.name, "gpio"))
byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
- else if (group.has_simple_funcs)
- byt_set_group_simple_mux(vg, group, simple_func);
else
- byt_set_group_mixed_mux(vg, group, mixed_func);
+ byt_set_group_simple_mux(vg, group, group.mode);
return 0;
}
@@ -932,14 +752,14 @@ static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned int offset)
/* SCORE pin 92-93 */
if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
offset >= 92 && offset <= 93)
- return 1;
+ return BYT_ALTER_GPIO_MUX;
/* SUS pin 11-21 */
if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
offset >= 11 && offset <= 21)
- return 1;
+ return BYT_ALTER_GPIO_MUX;
- return 0;
+ return BYT_DEFAULT_GPIO_MUX;
}
static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
index 2c7409ed16fa..9a74d5025be6 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
@@ -583,6 +583,7 @@ static struct platform_driver mt8183_pinctrl_driver = {
.driver = {
.name = "mt8183-pinctrl",
.of_match_table = mt8183_pinctrl_of_match,
+ .pm = &mtk_paris_pinctrl_pm_ops,
},
.probe = mt8183_pinctrl_probe,
};
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index d3b34e9a7507..923264d0e9ef 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -926,3 +926,22 @@ int mtk_paris_pinctrl_probe(struct platform_device *pdev,
return 0;
}
+
+static int mtk_paris_pinctrl_suspend(struct device *device)
+{
+ struct mtk_pinctrl *pctl = dev_get_drvdata(device);
+
+ return mtk_eint_do_suspend(pctl->eint);
+}
+
+static int mtk_paris_pinctrl_resume(struct device *device)
+{
+ struct mtk_pinctrl *pctl = dev_get_drvdata(device);
+
+ return mtk_eint_do_resume(pctl->eint);
+}
+
+const struct dev_pm_ops mtk_paris_pinctrl_pm_ops = {
+ .suspend_noirq = mtk_paris_pinctrl_suspend,
+ .resume_noirq = mtk_paris_pinctrl_resume,
+};
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h
index 37146caa667d..3d43771074e6 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.h
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.h
@@ -60,4 +60,6 @@
int mtk_paris_pinctrl_probe(struct platform_device *pdev,
const struct mtk_pin_soc *soc);
+extern const struct dev_pm_ops mtk_paris_pinctrl_pm_ops;
+
#endif /* __PINCTRL_PARIS_H */
diff --git a/drivers/pinctrl/meson/pinctrl-meson-g12a.c b/drivers/pinctrl/meson/pinctrl-meson-g12a.c
index d494492e98e9..3475cd7bd2af 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-g12a.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-g12a.c
@@ -1304,28 +1304,28 @@ static struct meson_pmx_func meson_g12a_aobus_functions[] = {
};
static struct meson_bank meson_g12a_periphs_banks[] = {
- /* name first last irq pullen pull dir out in */
- BANK("Z", GPIOZ_0, GPIOZ_15, 12, 27,
- 4, 0, 4, 0, 12, 0, 13, 0, 14, 0),
- BANK("H", GPIOH_0, GPIOH_8, 28, 36,
- 3, 0, 3, 0, 9, 0, 10, 0, 11, 0),
- BANK("BOOT", BOOT_0, BOOT_15, 37, 52,
- 0, 0, 0, 0, 0, 0, 1, 0, 2, 0),
- BANK("C", GPIOC_0, GPIOC_7, 53, 60,
- 1, 0, 1, 0, 3, 0, 4, 0, 5, 0),
- BANK("A", GPIOA_0, GPIOA_15, 61, 76,
- 5, 0, 5, 0, 16, 0, 17, 0, 18, 0),
- BANK("X", GPIOX_0, GPIOX_19, 77, 96,
- 2, 0, 2, 0, 6, 0, 7, 0, 8, 0),
+ /* name first last irq pullen pull dir out in ds */
+ BANK_DS("Z", GPIOZ_0, GPIOZ_15, 12, 27,
+ 4, 0, 4, 0, 12, 0, 13, 0, 14, 0, 5, 0),
+ BANK_DS("H", GPIOH_0, GPIOH_8, 28, 36,
+ 3, 0, 3, 0, 9, 0, 10, 0, 11, 0, 4, 0),
+ BANK_DS("BOOT", BOOT_0, BOOT_15, 37, 52,
+ 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0),
+ BANK_DS("C", GPIOC_0, GPIOC_7, 53, 60,
+ 1, 0, 1, 0, 3, 0, 4, 0, 5, 0, 1, 0),
+ BANK_DS("A", GPIOA_0, GPIOA_15, 61, 76,
+ 5, 0, 5, 0, 16, 0, 17, 0, 18, 0, 6, 0),
+ BANK_DS("X", GPIOX_0, GPIOX_19, 77, 96,
+ 2, 0, 2, 0, 6, 0, 7, 0, 8, 0, 2, 0),
};
static struct meson_bank meson_g12a_aobus_banks[] = {
- /* name first last irq pullen pull dir out in */
- BANK("AO", GPIOAO_0, GPIOAO_11, 0, 11,
- 3, 0, 2, 0, 0, 0, 4, 0, 1, 0),
+ /* name first last irq pullen pull dir out in ds */
+ BANK_DS("AO", GPIOAO_0, GPIOAO_11, 0, 11, 3, 0, 2, 0, 0, 0, 4, 0, 1, 0,
+ 0, 0),
/* GPIOE actually located in the AO bank */
- BANK("E", GPIOE_0, GPIOE_2, 97, 99,
- 3, 16, 2, 16, 0, 16, 4, 16, 1, 16),
+ BANK_DS("E", GPIOE_0, GPIOE_2, 97, 99, 3, 16, 2, 16, 0, 16, 4, 16, 1,
+ 16, 1, 0),
};
static struct meson_pmx_bank meson_g12a_periphs_pmx_banks[] = {
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 077de5925783..596786926209 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -168,68 +168,223 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
return 0;
}
-static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
- unsigned long *configs, unsigned num_configs)
+static int meson_pinconf_set_gpio_bit(struct meson_pinctrl *pc,
+ unsigned int pin,
+ unsigned int reg_type,
+ bool arg)
{
- struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
struct meson_bank *bank;
- enum pin_config_param param;
unsigned int reg, bit;
- int i, ret;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, reg_type, &reg, &bit);
+ return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
+ arg ? BIT(bit) : 0);
+}
+
+static int meson_pinconf_get_gpio_bit(struct meson_pinctrl *pc,
+ unsigned int pin,
+ unsigned int reg_type)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit, val;
+ int ret;
ret = meson_get_bank(pc, pin, &bank);
if (ret)
return ret;
+ meson_calc_reg_and_bit(bank, pin, reg_type, &reg, &bit);
+ ret = regmap_read(pc->reg_gpio, reg, &val);
+ if (ret)
+ return ret;
+
+ return BIT(bit) & val ? 1 : 0;
+}
+
+static int meson_pinconf_set_output(struct meson_pinctrl *pc,
+ unsigned int pin,
+ bool out)
+{
+ return meson_pinconf_set_gpio_bit(pc, pin, REG_DIR, !out);
+}
+
+static int meson_pinconf_get_output(struct meson_pinctrl *pc,
+ unsigned int pin)
+{
+ int ret = meson_pinconf_get_gpio_bit(pc, pin, REG_DIR);
+
+ if (ret < 0)
+ return ret;
+
+ return !ret;
+}
+
+static int meson_pinconf_set_drive(struct meson_pinctrl *pc,
+ unsigned int pin,
+ bool high)
+{
+ return meson_pinconf_set_gpio_bit(pc, pin, REG_OUT, high);
+}
+
+static int meson_pinconf_get_drive(struct meson_pinctrl *pc,
+ unsigned int pin)
+{
+ return meson_pinconf_get_gpio_bit(pc, pin, REG_OUT);
+}
+
+static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc,
+ unsigned int pin,
+ bool high)
+{
+ int ret;
+
+ ret = meson_pinconf_set_output(pc, pin, true);
+ if (ret)
+ return ret;
+
+ return meson_pinconf_set_drive(pc, pin, high);
+}
+
+static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
+ unsigned int pin)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit = 0;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit);
+ ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
+ bool pull_up)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit, val = 0;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
+ if (pull_up)
+ val = BIT(bit);
+
+ ret = regmap_update_bits(pc->reg_pull, reg, BIT(bit), val);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit);
+ ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
+ unsigned int pin,
+ u16 drive_strength_ua)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit, ds_val;
+ int ret;
+
+ if (!pc->reg_ds) {
+ dev_err(pc->dev, "drive-strength not supported\n");
+ return -ENOTSUPP;
+ }
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
+ bit = bit << 1;
+
+ if (drive_strength_ua <= 500) {
+ ds_val = MESON_PINCONF_DRV_500UA;
+ } else if (drive_strength_ua <= 2500) {
+ ds_val = MESON_PINCONF_DRV_2500UA;
+ } else if (drive_strength_ua <= 3000) {
+ ds_val = MESON_PINCONF_DRV_3000UA;
+ } else if (drive_strength_ua <= 4000) {
+ ds_val = MESON_PINCONF_DRV_4000UA;
+ } else {
+ dev_warn_once(pc->dev,
+ "pin %u: invalid drive-strength : %d , default to 4mA\n",
+ pin, drive_strength_ua);
+ ds_val = MESON_PINCONF_DRV_4000UA;
+ }
+
+ ret = regmap_update_bits(pc->reg_ds, reg, 0x3 << bit, ds_val << bit);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
+ unsigned long *configs, unsigned num_configs)
+{
+ struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
+ enum pin_config_param param;
+ unsigned int arg = 0;
+ int i, ret;
+
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
switch (param) {
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT:
+ arg = pinconf_to_config_argument(configs[i]);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg,
- &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), 0);
- if (ret)
- return ret;
+ ret = meson_pinconf_disable_bias(pc, pin);
break;
case PIN_CONFIG_BIAS_PULL_UP:
- dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
- &reg, &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
- ret = regmap_update_bits(pc->reg_pull, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
+ ret = meson_pinconf_enable_bias(pc, pin, true);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
- &reg, &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
- ret = regmap_update_bits(pc->reg_pull, reg,
- BIT(bit), 0);
- if (ret)
- return ret;
+ ret = meson_pinconf_enable_bias(pc, pin, false);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ ret = meson_pinconf_set_drive_strength(pc, pin, arg);
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ ret = meson_pinconf_set_output(pc, pin, arg);
+ break;
+ case PIN_CONFIG_OUTPUT:
+ ret = meson_pinconf_set_output_drive(pc, pin, arg);
break;
default:
- return -ENOTSUPP;
+ ret = -ENOTSUPP;
}
+
+ if (ret)
+ return ret;
}
return 0;
@@ -269,12 +424,55 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
return conf;
}
+static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
+ unsigned int pin,
+ u16 *drive_strength_ua)
+{
+ struct meson_bank *bank;
+ unsigned int reg, bit;
+ unsigned int val;
+ int ret;
+
+ if (!pc->reg_ds)
+ return -ENOTSUPP;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
+
+ ret = regmap_read(pc->reg_ds, reg, &val);
+ if (ret)
+ return ret;
+
+ switch ((val >> bit) & 0x3) {
+ case MESON_PINCONF_DRV_500UA:
+ *drive_strength_ua = 500;
+ break;
+ case MESON_PINCONF_DRV_2500UA:
+ *drive_strength_ua = 2500;
+ break;
+ case MESON_PINCONF_DRV_3000UA:
+ *drive_strength_ua = 3000;
+ break;
+ case MESON_PINCONF_DRV_4000UA:
+ *drive_strength_ua = 4000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
unsigned long *config)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
enum pin_config_param param = pinconf_to_config_param(*config);
u16 arg;
+ int ret;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
@@ -285,6 +483,29 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
else
return -EINVAL;
break;
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ ret = meson_pinconf_get_drive_strength(pc, pin, &arg);
+ if (ret)
+ return ret;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ ret = meson_pinconf_get_output(pc, pin);
+ if (ret <= 0)
+ return -EINVAL;
+ arg = 1;
+ break;
+ case PIN_CONFIG_OUTPUT:
+ ret = meson_pinconf_get_output(pc, pin);
+ if (ret <= 0)
+ return -EINVAL;
+
+ ret = meson_pinconf_get_drive(pc, pin);
+ if (ret < 0)
+ return -EINVAL;
+
+ arg = ret;
+ break;
+
default:
return -ENOTSUPP;
}
@@ -329,56 +550,19 @@ static const struct pinconf_ops meson_pinconf_ops = {
static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
- struct meson_pinctrl *pc = gpiochip_get_data(chip);
- unsigned int reg, bit;
- struct meson_bank *bank;
- int ret;
-
- ret = meson_get_bank(pc, gpio, &bank);
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, gpio, REG_DIR, &reg, &bit);
-
- return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit));
+ return meson_pinconf_set_output(gpiochip_get_data(chip), gpio, false);
}
static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
int value)
{
- struct meson_pinctrl *pc = gpiochip_get_data(chip);
- unsigned int reg, bit;
- struct meson_bank *bank;
- int ret;
-
- ret = meson_get_bank(pc, gpio, &bank);
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, gpio, REG_DIR, &reg, &bit);
- ret = regmap_update_bits(pc->reg_gpio, reg, BIT(bit), 0);
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, gpio, REG_OUT, &reg, &bit);
- return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
- value ? BIT(bit) : 0);
+ return meson_pinconf_set_output_drive(gpiochip_get_data(chip),
+ gpio, value);
}
static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
{
- struct meson_pinctrl *pc = gpiochip_get_data(chip);
- unsigned int reg, bit;
- struct meson_bank *bank;
- int ret;
-
- ret = meson_get_bank(pc, gpio, &bank);
- if (ret)
- return;
-
- meson_calc_reg_and_bit(bank, gpio, REG_OUT, &reg, &bit);
- regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
- value ? BIT(bit) : 0);
+ meson_pinconf_set_drive(gpiochip_get_data(chip), gpio, value);
}
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index adab4ea078f9..c696f3241a36 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -65,10 +65,21 @@ enum meson_reg_type {
REG_DIR,
REG_OUT,
REG_IN,
+ REG_DS,
NUM_REG,
};
/**
+ * enum meson_pinconf_drv - value of drive-strength supported
+ */
+enum meson_pinconf_drv {
+ MESON_PINCONF_DRV_500UA,
+ MESON_PINCONF_DRV_2500UA,
+ MESON_PINCONF_DRV_3000UA,
+ MESON_PINCONF_DRV_4000UA,
+};
+
+/**
* struct meson bank
*
* @name: bank name
@@ -126,7 +137,8 @@ struct meson_pinctrl {
.num_groups = ARRAY_SIZE(fn ## _groups), \
}
-#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
+#define BANK_DS(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib, \
+ dsr, dsb) \
{ \
.name = n, \
.first = f, \
@@ -139,9 +151,13 @@ struct meson_pinctrl {
[REG_DIR] = { dr, db }, \
[REG_OUT] = { or, ob }, \
[REG_IN] = { ir, ib }, \
+ [REG_DS] = { dsr, dsb }, \
}, \
}
+#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
+ BANK_DS(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib, 0, 0)
+
#define MESON_PIN(x) PINCTRL_PIN(x, #x)
/* Common pmx functions */
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 19e69701747d..d45c31f281c8 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -16,341 +16,347 @@
#include "pinctrl-mvebu.h"
-#define V(f6180, f6190, f6192, f6281, f6282, dx4122) \
+#define V(f6180, f6190, f6192, f6281, f6282, dx4122, dx1135) \
((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
- (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
+ (f6281 << 3) | (f6282 << 4) | (dx4122 << 5) | \
+ (dx1135 << 6))
enum kirkwood_variant {
- VARIANT_MV88F6180 = V(1, 0, 0, 0, 0, 0),
- VARIANT_MV88F6190 = V(0, 1, 0, 0, 0, 0),
- VARIANT_MV88F6192 = V(0, 0, 1, 0, 0, 0),
- VARIANT_MV88F6281 = V(0, 0, 0, 1, 0, 0),
- VARIANT_MV88F6282 = V(0, 0, 0, 0, 1, 0),
- VARIANT_MV98DX4122 = V(0, 0, 0, 0, 0, 1),
+ VARIANT_MV88F6180 = V(1, 0, 0, 0, 0, 0, 0),
+ VARIANT_MV88F6190 = V(0, 1, 0, 0, 0, 0, 0),
+ VARIANT_MV88F6192 = V(0, 0, 1, 0, 0, 0, 0),
+ VARIANT_MV88F6281 = V(0, 0, 0, 1, 0, 0, 0),
+ VARIANT_MV88F6282 = V(0, 0, 0, 0, 1, 0, 0),
+ VARIANT_MV98DX4122 = V(0, 0, 0, 0, 0, 1, 0),
+ VARIANT_MV98DX1135 = V(0, 0, 0, 0, 0, 0, 1),
};
static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
MPP_MODE(0,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1, 1))),
MPP_MODE(1,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1, 1))),
MPP_MODE(2,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1, 1))),
MPP_MODE(3,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1, 1))),
MPP_MODE(4,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0, 0))),
MPP_MODE(5,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(6,
- MPP_VAR_FUNCTION(0x1, "sysrst", "out", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0))),
+ MPP_VAR_FUNCTION(0x1, "sysrst", "out", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0, 0))),
MPP_MODE(7,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(8,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0, 0))),
MPP_MODE(9,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0, 0))),
MPP_MODE(10,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0, 0, 0))),
MPP_MODE(11,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0, 0))),
MPP_MODE(12,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 0)),
- MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(13,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(14,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0, 0))),
MPP_MODE(15,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(16,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0, 0))),
MPP_MODE(17,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(18,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(19,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1, 1))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1, 1, 1))),
MPP_MODE(20,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 0, 0, 0, 0, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 0, 0, 0, 0, 0, 0))),
MPP_MODE(21,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(22,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(23,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(24,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(25,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(26,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(27,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(28,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "nand", "ren", V(0, 0, 0, 0, 0, 0, 1))),
MPP_MODE(29,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "nand", "wen", V(0, 0, 0, 0, 0, 0, 1))),
MPP_MODE(30,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(31,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(32,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(33,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(34,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "nand", "ale", V(0, 0, 0, 0, 0, 0, 1))),
MPP_MODE(35,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 1, 1, 1, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "nand", "cen", V(0, 0, 0, 0, 0, 0, 1))),
MPP_MODE(36,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(37,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(38,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(39,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(40,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(41,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(42,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(43,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(44,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(45,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(46,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(47,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(48,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1, 0, 0))),
MPP_MODE(49,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 1)),
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0, 0)),
- MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1, 0))),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1, 0, 0))),
};
static const struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
@@ -440,6 +446,17 @@ static struct mvebu_pinctrl_soc_info mv98dx4122_info = {
.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
};
+static struct mvebu_pinctrl_soc_info mv98dx1135_info = {
+ .variant = VARIANT_MV98DX1135,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+
static const struct of_device_id kirkwood_pinctrl_of_match[] = {
{ .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
{ .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
@@ -447,6 +464,7 @@ static const struct of_device_id kirkwood_pinctrl_of_match[] = {
{ .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
{ .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
{ .compatible = "marvell,98dx4122-pinctrl", .data = &mv98dx4122_info },
+ { .compatible = "marvell,98dx1135-pinctrl", .data = &mv98dx1135_info },
{ }
};
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 4ccd71bbc72a..9eb86309c70b 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -38,6 +38,7 @@ static const struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA", true),
+ PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH_UA, "output drive strength", "uA", true),
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec", true),
PCONFDUMP(PIN_CONFIG_INPUT_ENABLE, "input enabled", NULL, false),
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL, false),
@@ -166,6 +167,7 @@ static const struct pinconf_generic_params dt_params[] = {
{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+ { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 },
{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
diff --git a/drivers/pinctrl/pinctrl-bm1880.c b/drivers/pinctrl/pinctrl-bm1880.c
index 446b07d8fbfc..63b130cb1ffb 100644
--- a/drivers/pinctrl/pinctrl-bm1880.c
+++ b/drivers/pinctrl/pinctrl-bm1880.c
@@ -27,6 +27,7 @@
* @ngroups: Number of @groups
* @funcs: Pinmux functions
* @nfuncs: Number of @funcs
+ * @pconf: Pinconf data
*/
struct bm1880_pinctrl {
void __iomem *base;
@@ -35,6 +36,7 @@ struct bm1880_pinctrl {
unsigned int ngroups;
const struct bm1880_pinmux_function *funcs;
unsigned int nfuncs;
+ const struct bm1880_pinconf_data *pinconf;
};
/**
@@ -55,7 +57,6 @@ struct bm1880_pctrl_group {
* @groups: List of pingroups for this function.
* @ngroups: Number of entries in @groups.
* @mux_val: Selector for this function
- * @mux_mask: Mask for function specific selector
* @mux: Offset of function specific mux
* @mux_shift: Shift for function specific selector
*/
@@ -64,11 +65,18 @@ struct bm1880_pinmux_function {
const char * const *groups;
unsigned int ngroups;
u32 mux_val;
- u32 mux_mask;
u32 mux;
u8 mux_shift;
};
+/**
+ * struct bm1880_pinconf_data - pinconf data
+ * @drv_bits: Drive strength bit width
+ */
+struct bm1880_pinconf_data {
+ u32 drv_bits;
+};
+
static const struct pinctrl_pin_desc bm1880_pins[] = {
PINCTRL_PIN(0, "MIO0"),
PINCTRL_PIN(1, "MIO1"),
@@ -636,165 +644,273 @@ static const char * const i2s1_group[] = { "i2s1_grp" };
static const char * const i2s1_mclkin_group[] = { "i2s1_mclkin_grp" };
static const char * const spi0_group[] = { "spi0_grp" };
-#define BM1880_PINMUX_FUNCTION(fname, mval, mask) \
+#define BM1880_PINMUX_FUNCTION(fname, mval) \
[F_##fname] = { \
.name = #fname, \
.groups = fname##_group, \
.ngroups = ARRAY_SIZE(fname##_group), \
.mux_val = mval, \
- .mux_mask = mask, \
}
-#define BM1880_PINMUX_FUNCTION_MUX(fname, mval, mask, offset, shift)\
- [F_##fname] = { \
- .name = #fname, \
- .groups = fname##_group, \
- .ngroups = ARRAY_SIZE(fname##_group), \
- .mux_val = mval, \
- .mux_mask = mask, \
- .mux = offset, \
- .mux_shift = shift, \
+static const struct bm1880_pinmux_function bm1880_pmux_functions[] = {
+ BM1880_PINMUX_FUNCTION(nand, 2),
+ BM1880_PINMUX_FUNCTION(spi, 0),
+ BM1880_PINMUX_FUNCTION(emmc, 1),
+ BM1880_PINMUX_FUNCTION(sdio, 0),
+ BM1880_PINMUX_FUNCTION(eth0, 0),
+ BM1880_PINMUX_FUNCTION(pwm0, 2),
+ BM1880_PINMUX_FUNCTION(pwm1, 2),
+ BM1880_PINMUX_FUNCTION(pwm2, 2),
+ BM1880_PINMUX_FUNCTION(pwm3, 2),
+ BM1880_PINMUX_FUNCTION(pwm4, 2),
+ BM1880_PINMUX_FUNCTION(pwm5, 2),
+ BM1880_PINMUX_FUNCTION(pwm6, 2),
+ BM1880_PINMUX_FUNCTION(pwm7, 2),
+ BM1880_PINMUX_FUNCTION(pwm8, 2),
+ BM1880_PINMUX_FUNCTION(pwm9, 2),
+ BM1880_PINMUX_FUNCTION(pwm10, 2),
+ BM1880_PINMUX_FUNCTION(pwm11, 2),
+ BM1880_PINMUX_FUNCTION(pwm12, 2),
+ BM1880_PINMUX_FUNCTION(pwm13, 2),
+ BM1880_PINMUX_FUNCTION(pwm14, 2),
+ BM1880_PINMUX_FUNCTION(pwm15, 2),
+ BM1880_PINMUX_FUNCTION(pwm16, 2),
+ BM1880_PINMUX_FUNCTION(pwm17, 2),
+ BM1880_PINMUX_FUNCTION(pwm18, 2),
+ BM1880_PINMUX_FUNCTION(pwm19, 2),
+ BM1880_PINMUX_FUNCTION(pwm20, 2),
+ BM1880_PINMUX_FUNCTION(pwm21, 2),
+ BM1880_PINMUX_FUNCTION(pwm22, 2),
+ BM1880_PINMUX_FUNCTION(pwm23, 2),
+ BM1880_PINMUX_FUNCTION(pwm24, 2),
+ BM1880_PINMUX_FUNCTION(pwm25, 2),
+ BM1880_PINMUX_FUNCTION(pwm26, 2),
+ BM1880_PINMUX_FUNCTION(pwm27, 2),
+ BM1880_PINMUX_FUNCTION(pwm28, 2),
+ BM1880_PINMUX_FUNCTION(pwm29, 2),
+ BM1880_PINMUX_FUNCTION(pwm30, 2),
+ BM1880_PINMUX_FUNCTION(pwm31, 2),
+ BM1880_PINMUX_FUNCTION(pwm32, 2),
+ BM1880_PINMUX_FUNCTION(pwm33, 2),
+ BM1880_PINMUX_FUNCTION(pwm34, 2),
+ BM1880_PINMUX_FUNCTION(pwm35, 2),
+ BM1880_PINMUX_FUNCTION(pwm36, 2),
+ BM1880_PINMUX_FUNCTION(pwm37, 2),
+ BM1880_PINMUX_FUNCTION(i2c0, 1),
+ BM1880_PINMUX_FUNCTION(i2c1, 1),
+ BM1880_PINMUX_FUNCTION(i2c2, 1),
+ BM1880_PINMUX_FUNCTION(i2c3, 1),
+ BM1880_PINMUX_FUNCTION(i2c4, 1),
+ BM1880_PINMUX_FUNCTION(uart0, 3),
+ BM1880_PINMUX_FUNCTION(uart1, 3),
+ BM1880_PINMUX_FUNCTION(uart2, 3),
+ BM1880_PINMUX_FUNCTION(uart3, 3),
+ BM1880_PINMUX_FUNCTION(uart4, 1),
+ BM1880_PINMUX_FUNCTION(uart5, 1),
+ BM1880_PINMUX_FUNCTION(uart6, 1),
+ BM1880_PINMUX_FUNCTION(uart7, 1),
+ BM1880_PINMUX_FUNCTION(uart8, 1),
+ BM1880_PINMUX_FUNCTION(uart9, 1),
+ BM1880_PINMUX_FUNCTION(uart10, 1),
+ BM1880_PINMUX_FUNCTION(uart11, 1),
+ BM1880_PINMUX_FUNCTION(uart12, 3),
+ BM1880_PINMUX_FUNCTION(uart13, 3),
+ BM1880_PINMUX_FUNCTION(uart14, 3),
+ BM1880_PINMUX_FUNCTION(uart15, 3),
+ BM1880_PINMUX_FUNCTION(gpio0, 0),
+ BM1880_PINMUX_FUNCTION(gpio1, 0),
+ BM1880_PINMUX_FUNCTION(gpio2, 0),
+ BM1880_PINMUX_FUNCTION(gpio3, 0),
+ BM1880_PINMUX_FUNCTION(gpio4, 0),
+ BM1880_PINMUX_FUNCTION(gpio5, 0),
+ BM1880_PINMUX_FUNCTION(gpio6, 0),
+ BM1880_PINMUX_FUNCTION(gpio7, 0),
+ BM1880_PINMUX_FUNCTION(gpio8, 0),
+ BM1880_PINMUX_FUNCTION(gpio9, 0),
+ BM1880_PINMUX_FUNCTION(gpio10, 0),
+ BM1880_PINMUX_FUNCTION(gpio11, 0),
+ BM1880_PINMUX_FUNCTION(gpio12, 1),
+ BM1880_PINMUX_FUNCTION(gpio13, 1),
+ BM1880_PINMUX_FUNCTION(gpio14, 0),
+ BM1880_PINMUX_FUNCTION(gpio15, 0),
+ BM1880_PINMUX_FUNCTION(gpio16, 0),
+ BM1880_PINMUX_FUNCTION(gpio17, 0),
+ BM1880_PINMUX_FUNCTION(gpio18, 0),
+ BM1880_PINMUX_FUNCTION(gpio19, 0),
+ BM1880_PINMUX_FUNCTION(gpio20, 0),
+ BM1880_PINMUX_FUNCTION(gpio21, 0),
+ BM1880_PINMUX_FUNCTION(gpio22, 0),
+ BM1880_PINMUX_FUNCTION(gpio23, 0),
+ BM1880_PINMUX_FUNCTION(gpio24, 0),
+ BM1880_PINMUX_FUNCTION(gpio25, 0),
+ BM1880_PINMUX_FUNCTION(gpio26, 0),
+ BM1880_PINMUX_FUNCTION(gpio27, 0),
+ BM1880_PINMUX_FUNCTION(gpio28, 0),
+ BM1880_PINMUX_FUNCTION(gpio29, 0),
+ BM1880_PINMUX_FUNCTION(gpio30, 0),
+ BM1880_PINMUX_FUNCTION(gpio31, 0),
+ BM1880_PINMUX_FUNCTION(gpio32, 0),
+ BM1880_PINMUX_FUNCTION(gpio33, 0),
+ BM1880_PINMUX_FUNCTION(gpio34, 0),
+ BM1880_PINMUX_FUNCTION(gpio35, 0),
+ BM1880_PINMUX_FUNCTION(gpio36, 0),
+ BM1880_PINMUX_FUNCTION(gpio37, 0),
+ BM1880_PINMUX_FUNCTION(gpio38, 0),
+ BM1880_PINMUX_FUNCTION(gpio39, 0),
+ BM1880_PINMUX_FUNCTION(gpio40, 0),
+ BM1880_PINMUX_FUNCTION(gpio41, 0),
+ BM1880_PINMUX_FUNCTION(gpio42, 0),
+ BM1880_PINMUX_FUNCTION(gpio43, 0),
+ BM1880_PINMUX_FUNCTION(gpio44, 0),
+ BM1880_PINMUX_FUNCTION(gpio45, 0),
+ BM1880_PINMUX_FUNCTION(gpio46, 0),
+ BM1880_PINMUX_FUNCTION(gpio47, 0),
+ BM1880_PINMUX_FUNCTION(gpio48, 0),
+ BM1880_PINMUX_FUNCTION(gpio49, 0),
+ BM1880_PINMUX_FUNCTION(gpio50, 0),
+ BM1880_PINMUX_FUNCTION(gpio51, 0),
+ BM1880_PINMUX_FUNCTION(gpio52, 0),
+ BM1880_PINMUX_FUNCTION(gpio53, 0),
+ BM1880_PINMUX_FUNCTION(gpio54, 0),
+ BM1880_PINMUX_FUNCTION(gpio55, 0),
+ BM1880_PINMUX_FUNCTION(gpio56, 0),
+ BM1880_PINMUX_FUNCTION(gpio57, 0),
+ BM1880_PINMUX_FUNCTION(gpio58, 0),
+ BM1880_PINMUX_FUNCTION(gpio59, 0),
+ BM1880_PINMUX_FUNCTION(gpio60, 0),
+ BM1880_PINMUX_FUNCTION(gpio61, 0),
+ BM1880_PINMUX_FUNCTION(gpio62, 0),
+ BM1880_PINMUX_FUNCTION(gpio63, 0),
+ BM1880_PINMUX_FUNCTION(gpio64, 0),
+ BM1880_PINMUX_FUNCTION(gpio65, 0),
+ BM1880_PINMUX_FUNCTION(gpio66, 0),
+ BM1880_PINMUX_FUNCTION(gpio67, 0),
+ BM1880_PINMUX_FUNCTION(eth1, 1),
+ BM1880_PINMUX_FUNCTION(i2s0, 2),
+ BM1880_PINMUX_FUNCTION(i2s0_mclkin, 1),
+ BM1880_PINMUX_FUNCTION(i2s1, 2),
+ BM1880_PINMUX_FUNCTION(i2s1_mclkin, 1),
+ BM1880_PINMUX_FUNCTION(spi0, 1),
+};
+
+#define BM1880_PINCONF_DAT(_width) \
+ { \
+ .drv_bits = _width, \
}
-static const struct bm1880_pinmux_function bm1880_pmux_functions[] = {
- BM1880_PINMUX_FUNCTION(nand, 2, 0x03),
- BM1880_PINMUX_FUNCTION(spi, 0, 0x03),
- BM1880_PINMUX_FUNCTION(emmc, 1, 0x03),
- BM1880_PINMUX_FUNCTION(sdio, 0, 0x03),
- BM1880_PINMUX_FUNCTION(eth0, 0, 0x03),
- BM1880_PINMUX_FUNCTION_MUX(pwm0, 2, 0x0F, 0x50, 0x00),
- BM1880_PINMUX_FUNCTION_MUX(pwm1, 2, 0x0F, 0x50, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(pwm2, 2, 0x0F, 0x50, 0x08),
- BM1880_PINMUX_FUNCTION_MUX(pwm3, 2, 0x0F, 0x50, 0x0C),
- BM1880_PINMUX_FUNCTION_MUX(pwm4, 2, 0x0F, 0x50, 0x10),
- BM1880_PINMUX_FUNCTION_MUX(pwm5, 2, 0x0F, 0x50, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(pwm6, 2, 0x0F, 0x50, 0x18),
- BM1880_PINMUX_FUNCTION_MUX(pwm7, 2, 0x0F, 0x50, 0x1C),
- BM1880_PINMUX_FUNCTION_MUX(pwm8, 2, 0x0F, 0x54, 0x00),
- BM1880_PINMUX_FUNCTION_MUX(pwm9, 2, 0x0F, 0x54, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(pwm10, 2, 0x0F, 0x54, 0x08),
- BM1880_PINMUX_FUNCTION_MUX(pwm11, 2, 0x0F, 0x54, 0x0C),
- BM1880_PINMUX_FUNCTION_MUX(pwm12, 2, 0x0F, 0x54, 0x10),
- BM1880_PINMUX_FUNCTION_MUX(pwm13, 2, 0x0F, 0x54, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(pwm14, 2, 0x0F, 0x54, 0x18),
- BM1880_PINMUX_FUNCTION_MUX(pwm15, 2, 0x0F, 0x54, 0x1C),
- BM1880_PINMUX_FUNCTION_MUX(pwm16, 2, 0x0F, 0x58, 0x00),
- BM1880_PINMUX_FUNCTION_MUX(pwm17, 2, 0x0F, 0x58, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(pwm18, 2, 0x0F, 0x58, 0x08),
- BM1880_PINMUX_FUNCTION_MUX(pwm19, 2, 0x0F, 0x58, 0x0C),
- BM1880_PINMUX_FUNCTION_MUX(pwm20, 2, 0x0F, 0x58, 0x10),
- BM1880_PINMUX_FUNCTION_MUX(pwm21, 2, 0x0F, 0x58, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(pwm22, 2, 0x0F, 0x58, 0x18),
- BM1880_PINMUX_FUNCTION_MUX(pwm23, 2, 0x0F, 0x58, 0x1C),
- BM1880_PINMUX_FUNCTION_MUX(pwm24, 2, 0x0F, 0x5C, 0x00),
- BM1880_PINMUX_FUNCTION_MUX(pwm25, 2, 0x0F, 0x5C, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(pwm26, 2, 0x0F, 0x5C, 0x08),
- BM1880_PINMUX_FUNCTION_MUX(pwm27, 2, 0x0F, 0x5C, 0x0C),
- BM1880_PINMUX_FUNCTION_MUX(pwm28, 2, 0x0F, 0x5C, 0x10),
- BM1880_PINMUX_FUNCTION_MUX(pwm29, 2, 0x0F, 0x5C, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(pwm30, 2, 0x0F, 0x5C, 0x18),
- BM1880_PINMUX_FUNCTION_MUX(pwm31, 2, 0x0F, 0x5C, 0x1C),
- BM1880_PINMUX_FUNCTION_MUX(pwm32, 2, 0x0F, 0x60, 0x00),
- BM1880_PINMUX_FUNCTION_MUX(pwm33, 2, 0x0F, 0x60, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(pwm34, 2, 0x0F, 0x60, 0x08),
- BM1880_PINMUX_FUNCTION_MUX(pwm35, 2, 0x0F, 0x60, 0x0C),
- BM1880_PINMUX_FUNCTION_MUX(pwm36, 2, 0x0F, 0x60, 0x10),
- BM1880_PINMUX_FUNCTION_MUX(pwm37, 2, 0x0F, 0x60, 0x1C),
- BM1880_PINMUX_FUNCTION(i2c0, 1, 0x03),
- BM1880_PINMUX_FUNCTION(i2c1, 1, 0x03),
- BM1880_PINMUX_FUNCTION(i2c2, 1, 0x03),
- BM1880_PINMUX_FUNCTION(i2c3, 1, 0x03),
- BM1880_PINMUX_FUNCTION(i2c4, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart0, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart1, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart2, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart3, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart4, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart5, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart6, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart7, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart8, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart9, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart10, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart11, 1, 0x03),
- BM1880_PINMUX_FUNCTION(uart12, 3, 0x03),
- BM1880_PINMUX_FUNCTION(uart13, 3, 0x03),
- BM1880_PINMUX_FUNCTION(uart14, 3, 0x03),
- BM1880_PINMUX_FUNCTION(uart15, 3, 0x03),
- BM1880_PINMUX_FUNCTION_MUX(gpio0, 0, 0x03, 0x4E0, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio1, 0, 0x03, 0x4E4, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio2, 0, 0x03, 0x4E4, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio3, 0, 0x03, 0x4E8, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio4, 0, 0x03, 0x4E8, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio5, 0, 0x03, 0x4EC, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio6, 0, 0x03, 0x4EC, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio7, 0, 0x03, 0x4F0, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio8, 0, 0x03, 0x4F0, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio9, 0, 0x03, 0x4F4, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio10, 0, 0x03, 0x4F4, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio11, 0, 0x03, 0x4F8, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio12, 1, 0x03, 0x4F8, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio13, 1, 0x03, 0x4FC, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio14, 0, 0x03, 0x474, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio15, 0, 0x03, 0x478, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio16, 0, 0x03, 0x478, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio17, 0, 0x03, 0x47C, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio18, 0, 0x03, 0x47C, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio19, 0, 0x03, 0x480, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio20, 0, 0x03, 0x480, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio21, 0, 0x03, 0x484, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio22, 0, 0x03, 0x484, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio23, 0, 0x03, 0x488, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio24, 0, 0x03, 0x488, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio25, 0, 0x03, 0x48C, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio26, 0, 0x03, 0x48C, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio27, 0, 0x03, 0x490, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio28, 0, 0x03, 0x490, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio29, 0, 0x03, 0x494, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio30, 0, 0x03, 0x494, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio31, 0, 0x03, 0x498, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio32, 0, 0x03, 0x498, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio33, 0, 0x03, 0x49C, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio34, 0, 0x03, 0x49C, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio35, 0, 0x03, 0x4A0, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio36, 0, 0x03, 0x4A0, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio37, 0, 0x03, 0x4A4, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio38, 0, 0x03, 0x4A4, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio39, 0, 0x03, 0x4A8, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio40, 0, 0x03, 0x4A8, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio41, 0, 0x03, 0x4AC, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio42, 0, 0x03, 0x4AC, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio43, 0, 0x03, 0x4B0, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio44, 0, 0x03, 0x4B0, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio45, 0, 0x03, 0x4B4, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio46, 0, 0x03, 0x4B4, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio47, 0, 0x03, 0x4B8, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio48, 0, 0x03, 0x4B8, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio49, 0, 0x03, 0x4BC, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio50, 0, 0x03, 0x4BC, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio51, 0, 0x03, 0x4C0, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio52, 0, 0x03, 0x4C0, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio53, 0, 0x03, 0x4C4, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio54, 0, 0x03, 0x4C4, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio55, 0, 0x03, 0x4C8, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio56, 0, 0x03, 0x4C8, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio57, 0, 0x03, 0x4CC, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio58, 0, 0x03, 0x4CC, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio59, 0, 0x03, 0x4D0, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio60, 0, 0x03, 0x4D0, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio61, 0, 0x03, 0x4D4, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio62, 0, 0x03, 0x4D4, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio63, 0, 0x03, 0x4D8, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio64, 0, 0x03, 0x4D8, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio65, 0, 0x03, 0x4DC, 0x04),
- BM1880_PINMUX_FUNCTION_MUX(gpio66, 0, 0x03, 0x4DC, 0x14),
- BM1880_PINMUX_FUNCTION_MUX(gpio67, 0, 0x03, 0x4E0, 0x04),
- BM1880_PINMUX_FUNCTION(eth1, 1, 0x03),
- BM1880_PINMUX_FUNCTION(i2s0, 2, 0x03),
- BM1880_PINMUX_FUNCTION(i2s0_mclkin, 1, 0x03),
- BM1880_PINMUX_FUNCTION(i2s1, 2, 0x03),
- BM1880_PINMUX_FUNCTION(i2s1_mclkin, 1, 0x03),
- BM1880_PINMUX_FUNCTION(spi0, 1, 0x03),
+static const struct bm1880_pinconf_data bm1880_pinconf[] = {
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x03),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
+ BM1880_PINCONF_DAT(0x02),
};
static int bm1880_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
@@ -870,33 +986,308 @@ static int bm1880_pinmux_set_mux(struct pinctrl_dev *pctldev,
const struct bm1880_pinmux_function *func = &pctrl->funcs[function];
int i;
- if (func->mux) {
+ for (i = 0; i < pgrp->npins; i++) {
+ unsigned int pin = pgrp->pins[i];
+ u32 offset = (pin >> 1) << 2;
+ u32 mux_offset = ((!((pin + 1) & 1) << 4) + 4);
u32 regval = readl_relaxed(pctrl->base + BM1880_REG_MUX +
- func->mux);
+ offset);
+
+ regval &= ~(0x03 << mux_offset);
+ regval |= func->mux_val << mux_offset;
+
+ writel_relaxed(regval, pctrl->base + BM1880_REG_MUX + offset);
+ }
+
+ return 0;
+}
+
+#define BM1880_PINCONF(pin, idx) ((!((pin + 1) & 1) << 4) + idx)
+#define BM1880_PINCONF_PULLCTRL(pin) BM1880_PINCONF(pin, 0)
+#define BM1880_PINCONF_PULLUP(pin) BM1880_PINCONF(pin, 1)
+#define BM1880_PINCONF_PULLDOWN(pin) BM1880_PINCONF(pin, 2)
+#define BM1880_PINCONF_DRV(pin) BM1880_PINCONF(pin, 6)
+#define BM1880_PINCONF_SCHMITT(pin) BM1880_PINCONF(pin, 9)
+#define BM1880_PINCONF_SLEW(pin) BM1880_PINCONF(pin, 10)
+
+static int bm1880_pinconf_drv_set(unsigned int mA, u32 width,
+ u32 *regval, u32 bit_offset)
+{
+ u32 _regval;
+
+ _regval = *regval;
+
+ /*
+ * There are two sets of drive strength bit width exposed by the
+ * SoC at 4mA step, hence we need to handle them separately.
+ */
+ if (width == 0x03) {
+ switch (mA) {
+ case 4:
+ _regval &= ~(width << bit_offset);
+ _regval |= (0 << bit_offset);
+ break;
+ case 8:
+ _regval &= ~(width << bit_offset);
+ _regval |= (1 << bit_offset);
+ break;
+ case 12:
+ _regval &= ~(width << bit_offset);
+ _regval |= (2 << bit_offset);
+ break;
+ case 16:
+ _regval &= ~(width << bit_offset);
+ _regval |= (3 << bit_offset);
+ break;
+ case 20:
+ _regval &= ~(width << bit_offset);
+ _regval |= (4 << bit_offset);
+ break;
+ case 24:
+ _regval &= ~(width << bit_offset);
+ _regval |= (5 << bit_offset);
+ break;
+ case 28:
+ _regval &= ~(width << bit_offset);
+ _regval |= (6 << bit_offset);
+ break;
+ case 32:
+ _regval &= ~(width << bit_offset);
+ _regval |= (7 << bit_offset);
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (mA) {
+ case 4:
+ _regval &= ~(width << bit_offset);
+ _regval |= (0 << bit_offset);
+ break;
+ case 8:
+ _regval &= ~(width << bit_offset);
+ _regval |= (1 << bit_offset);
+ break;
+ case 12:
+ _regval &= ~(width << bit_offset);
+ _regval |= (2 << bit_offset);
+ break;
+ case 16:
+ _regval &= ~(width << bit_offset);
+ _regval |= (3 << bit_offset);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ *regval = _regval;
+
+ return 0;
+}
+
+static int bm1880_pinconf_drv_get(u32 width, u32 drv)
+{
+ int ret = -ENOTSUPP;
- regval &= ~(func->mux_mask << func->mux_shift);
- regval |= func->mux_val << func->mux_shift;
- writel_relaxed(regval, pctrl->base + BM1880_REG_MUX +
- func->mux);
+ /*
+ * There are two sets of drive strength bit width exposed by the
+ * SoC at 4mA step, hence we need to handle them separately.
+ */
+ if (width == 0x03) {
+ switch (drv) {
+ case 0:
+ ret = 4;
+ break;
+ case 1:
+ ret = 8;
+ break;
+ case 2:
+ ret = 12;
+ break;
+ case 3:
+ ret = 16;
+ break;
+ case 4:
+ ret = 20;
+ break;
+ case 5:
+ ret = 24;
+ break;
+ case 6:
+ ret = 28;
+ break;
+ case 7:
+ ret = 32;
+ break;
+ default:
+ break;
+ }
} else {
- for (i = 0; i < pgrp->npins; i++) {
- unsigned int pin = pgrp->pins[i];
- u32 offset = (pin >> 1) << 2;
- u32 mux_offset = ((!((pin + 1) & 1) << 4) + 4);
- u32 regval = readl_relaxed(pctrl->base +
- BM1880_REG_MUX + offset);
-
- regval &= ~(func->mux_mask << mux_offset);
- regval |= func->mux_val << mux_offset;
-
- writel_relaxed(regval, pctrl->base +
- BM1880_REG_MUX + offset);
+ switch (drv) {
+ case 0:
+ ret = 4;
+ break;
+ case 1:
+ ret = 8;
+ break;
+ case 2:
+ ret = 12;
+ break;
+ case 3:
+ ret = 16;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *config)
+{
+ struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int param = pinconf_to_config_param(*config);
+ unsigned int arg = 0;
+ u32 regval, offset, bit_offset;
+ int ret;
+
+ offset = (pin >> 1) << 2;
+ regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ bit_offset = BM1880_PINCONF_PULLUP(pin);
+ arg = !!(regval & BIT(bit_offset));
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ bit_offset = BM1880_PINCONF_PULLDOWN(pin);
+ arg = !!(regval & BIT(bit_offset));
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ bit_offset = BM1880_PINCONF_PULLCTRL(pin);
+ arg = !!(regval & BIT(bit_offset));
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ bit_offset = BM1880_PINCONF_SCHMITT(pin);
+ arg = !!(regval & BIT(bit_offset));
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ bit_offset = BM1880_PINCONF_SLEW(pin);
+ arg = !!(regval & BIT(bit_offset));
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ bit_offset = BM1880_PINCONF_DRV(pin);
+ ret = bm1880_pinconf_drv_get(pctrl->pinconf[pin].drv_bits,
+ !!(regval & BIT(bit_offset)));
+ if (ret < 0)
+ return ret;
+
+ arg = ret;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ u32 regval, offset, bit_offset;
+ int i, ret;
+
+ offset = (pin >> 1) << 2;
+ regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset);
+
+ for (i = 0; i < num_configs; i++) {
+ unsigned int param = pinconf_to_config_param(configs[i]);
+ unsigned int arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ bit_offset = BM1880_PINCONF_PULLUP(pin);
+ regval |= BIT(bit_offset);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ bit_offset = BM1880_PINCONF_PULLDOWN(pin);
+ regval |= BIT(bit_offset);
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ bit_offset = BM1880_PINCONF_PULLCTRL(pin);
+ regval |= BIT(bit_offset);
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ bit_offset = BM1880_PINCONF_SCHMITT(pin);
+ if (arg)
+ regval |= BIT(bit_offset);
+ else
+ regval &= ~BIT(bit_offset);
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ bit_offset = BM1880_PINCONF_SLEW(pin);
+ if (arg)
+ regval |= BIT(bit_offset);
+ else
+ regval &= ~BIT(bit_offset);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ bit_offset = BM1880_PINCONF_DRV(pin);
+ ret = bm1880_pinconf_drv_set(arg,
+ pctrl->pinconf[pin].drv_bits,
+ &regval, bit_offset);
+ if (ret < 0)
+ return ret;
+
+ break;
+ default:
+ dev_warn(pctldev->dev,
+ "unsupported configuration parameter '%u'\n",
+ param);
+ continue;
}
+
+ writel_relaxed(regval, pctrl->base + BM1880_REG_MUX + offset);
}
return 0;
}
+static int bm1880_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ int i, ret;
+ struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bm1880_pctrl_group *pgrp = &pctrl->groups[selector];
+
+ for (i = 0; i < pgrp->npins; i++) {
+ ret = bm1880_pinconf_cfg_set(pctldev, pgrp->pins[i], configs,
+ num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops bm1880_pinconf_ops = {
+ .is_generic = true,
+ .pin_config_get = bm1880_pinconf_cfg_get,
+ .pin_config_set = bm1880_pinconf_cfg_set,
+ .pin_config_group_set = bm1880_pinconf_group_set,
+};
+
static const struct pinmux_ops bm1880_pinmux_ops = {
.get_functions_count = bm1880_pmux_get_functions_count,
.get_function_name = bm1880_pmux_get_function_name,
@@ -910,6 +1301,7 @@ static struct pinctrl_desc bm1880_desc = {
.npins = ARRAY_SIZE(bm1880_pins),
.pctlops = &bm1880_pctrl_ops,
.pmxops = &bm1880_pinmux_ops,
+ .confops = &bm1880_pinconf_ops,
.owner = THIS_MODULE,
};
@@ -932,6 +1324,7 @@ static int bm1880_pinctrl_probe(struct platform_device *pdev)
pctrl->ngroups = ARRAY_SIZE(bm1880_pctrl_groups);
pctrl->funcs = bm1880_pmux_functions;
pctrl->nfuncs = ARRAY_SIZE(bm1880_pmux_functions);
+ pctrl->pinconf = bm1880_pinconf;
pctrl->pctrldev = devm_pinctrl_register(&pdev->dev, &bm1880_desc,
pctrl);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 807a3263d849..62a622159006 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -3204,6 +3204,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
base,
&rockchip_regmap_config);
}
+ of_node_put(node);
}
bank->irq = irq_of_parse_and_map(bank->of_node, 0);
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index eba872ce4a7c..d3332da35637 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -622,6 +622,7 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
pctl->pctl_desc.pins = stmfx_pins;
pctl->pctl_desc.npins = ARRAY_SIZE(stmfx_pins);
pctl->pctl_desc.owner = THIS_MODULE;
+ pctl->pctl_desc.link_consumers = true;
ret = devm_pinctrl_register_and_init(pctl->dev, &pctl->pctl_desc,
pctl, &pctl->pctl_dev);
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
index 02b43f559e83..1f64e2e7efd9 100644
--- a/drivers/pinctrl/pinctrl-tb10x.c
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -471,22 +471,22 @@ struct tb10x_port {
* @base: register set base address.
* @pingroups: pointer to an array of the pin groups this driver manages.
* @pinfuncgrpcnt: number of pingroups in @pingroups.
- * @pinfuncs: pointer to an array of pin functions this driver manages.
* @pinfuncnt: number of pin functions in @pinfuncs.
* @mutex: mutex for exclusive access to a pin controller's state.
* @ports: current state of each port.
* @gpios: Indicates if a given pin is currently used as GPIO (1) or not (0).
+ * @pinfuncs: flexible array of pin functions this driver manages.
*/
struct tb10x_pinctrl {
struct pinctrl_dev *pctl;
void *base;
const struct tb10x_pinfuncgrp *pingroups;
unsigned int pinfuncgrpcnt;
- struct tb10x_of_pinfunc *pinfuncs;
unsigned int pinfuncnt;
struct mutex mutex;
struct tb10x_port ports[TB10X_PORTS];
DECLARE_BITMAP(gpios, MAX_PIN + 1);
+ struct tb10x_of_pinfunc pinfuncs[];
};
static inline void tb10x_pinctrl_set_config(struct tb10x_pinctrl *state,
@@ -759,15 +759,13 @@ static int tb10x_pinctrl_probe(struct platform_device *pdev)
return -EINVAL;
}
- state = devm_kzalloc(dev, sizeof(struct tb10x_pinctrl) +
- of_get_child_count(of_node)
- * sizeof(struct tb10x_of_pinfunc),
- GFP_KERNEL);
+ state = devm_kzalloc(dev, struct_size(state, pinfuncs,
+ of_get_child_count(of_node)),
+ GFP_KERNEL);
if (!state)
return -ENOMEM;
platform_set_drvdata(pdev, state);
- state->pinfuncs = (struct tb10x_of_pinfunc *)(state + 1);
mutex_init(&state->mutex);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 890d0a3a790b..8e14a5f2e970 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -169,11 +169,20 @@ config PINCTRL_SDM660
config PINCTRL_SDM845
tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
- depends on GPIOLIB && OF
+ depends on GPIOLIB && (OF || ACPI)
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SDM845 platform.
+config PINCTRL_SM8150
+ tristate "Qualcomm Technologies Inc SM8150 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8150 platform.
+
endif
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 344b4c6a6c6e..ebe906872272 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
+obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 6e319bcc2326..7f35c196bb3e 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -599,8 +599,23 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *chip)
int ret;
unsigned int len, i;
unsigned int max_gpios = pctrl->soc->ngpios;
+ const int *reserved = pctrl->soc->reserved_gpios;
u16 *tmp;
+ /* Driver provided reserved list overrides DT and ACPI */
+ if (reserved) {
+ bitmap_fill(chip->valid_mask, max_gpios);
+ for (i = 0; reserved[i] >= 0; i++) {
+ if (i >= max_gpios || reserved[i] >= max_gpios) {
+ dev_err(pctrl->dev, "invalid list of reserved GPIOs\n");
+ return -EINVAL;
+ }
+ clear_bit(reserved[i], chip->valid_mask);
+ }
+
+ return 0;
+ }
+
/* The number of GPIOs in the ACPI tables */
len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL,
0);
@@ -729,7 +744,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
-static void msm_gpio_irq_unmask(struct irq_data *d)
+static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
@@ -741,6 +756,17 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ if (status_clear) {
+ /*
+ * clear the interrupt status bit before unmask to avoid
+ * any erroneous interrupts that would have got latched
+ * when the interrupt is not in use.
+ */
+ val = msm_readl_intr_status(pctrl, g);
+ val &= ~BIT(g->intr_status_bit);
+ msm_writel_intr_status(val, pctrl, g);
+ }
+
val = msm_readl_intr_cfg(pctrl, g);
val |= BIT(g->intr_raw_status_bit);
val |= BIT(g->intr_enable_bit);
@@ -751,6 +777,17 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}
+static void msm_gpio_irq_enable(struct irq_data *d)
+{
+
+ msm_gpio_irq_clear_unmask(d, true);
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+ msm_gpio_irq_clear_unmask(d, false);
+}
+
static void msm_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -956,6 +993,9 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
{
+ if (pctrl->soc->reserved_gpios)
+ return true;
+
return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0;
}
@@ -978,6 +1018,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl);
pctrl->irq_chip.name = "msmgpio";
+ pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;
pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index b724581c605c..48569cda8471 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -113,6 +113,7 @@ struct msm_pinctrl_soc_data {
bool pull_no_keeper;
const char *const *tiles;
unsigned int ntiles;
+ const int *reserved_gpios;
};
extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index c97f20fca5fd..39f498c09906 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -3,6 +3,7 @@
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -420,10 +421,10 @@ 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 };
+static const unsigned int ufs_reset_pins[] = { 150 };
+static const unsigned int sdc2_clk_pins[] = { 151 };
+static const unsigned int sdc2_cmd_pins[] = { 152 };
+static const unsigned int sdc2_data_pins[] = { 153 };
enum sdm845_functions {
msm_mux_gpio,
@@ -1271,10 +1272,14 @@ static const struct msm_pingroup sdm845_groups[] = {
PINGROUP(147, NORTH, _, _, _, _, _, _, _, _, _, _),
PINGROUP(148, NORTH, _, _, _, _, _, _, _, _, _, _),
PINGROUP(149, NORTH, _, _, _, _, _, _, _, _, _, _),
+ UFS_RESET(ufs_reset, 0x99f000),
SDC_QDSD_PINGROUP(sdc2_clk, 0x99a000, 14, 6),
SDC_QDSD_PINGROUP(sdc2_cmd, 0x99a000, 11, 3),
SDC_QDSD_PINGROUP(sdc2_data, 0x99a000, 9, 0),
- UFS_RESET(ufs_reset, 0x99f000),
+};
+
+static const int sdm845_acpi_reserved_gpios[] = {
+ 0, 1, 2, 3, 81, 82, 83, 84, -1
};
static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
@@ -1284,14 +1289,42 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
.nfunctions = ARRAY_SIZE(sdm845_functions),
.groups = sdm845_groups,
.ngroups = ARRAY_SIZE(sdm845_groups),
+ .ngpios = 151,
+};
+
+static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = {
+ .pins = sdm845_pins,
+ .npins = ARRAY_SIZE(sdm845_pins),
+ .groups = sdm845_groups,
+ .ngroups = ARRAY_SIZE(sdm845_groups),
+ .reserved_gpios = sdm845_acpi_reserved_gpios,
.ngpios = 150,
};
static int sdm845_pinctrl_probe(struct platform_device *pdev)
{
- return msm_pinctrl_probe(pdev, &sdm845_pinctrl);
+ int ret;
+
+ if (pdev->dev.of_node) {
+ ret = msm_pinctrl_probe(pdev, &sdm845_pinctrl);
+ } else if (has_acpi_companion(&pdev->dev)) {
+ ret = msm_pinctrl_probe(pdev, &sdm845_acpi_pinctrl);
+ } else {
+ dev_err(&pdev->dev, "DT and ACPI disabled\n");
+ return -EINVAL;
+ }
+
+ return ret;
}
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id sdm845_pinctrl_acpi_match[] = {
+ { "QCOM0217"},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, sdm845_pinctrl_acpi_match);
+#endif
+
static const struct of_device_id sdm845_pinctrl_of_match[] = {
{ .compatible = "qcom,sdm845-pinctrl", },
{ },
@@ -1302,6 +1335,7 @@ static struct platform_driver sdm845_pinctrl_driver = {
.name = "sdm845-pinctrl",
.pm = &msm_pinctrl_dev_pm_ops,
.of_match_table = sdm845_pinctrl_of_match,
+ .acpi_match_table = ACPI_PTR(sdm845_pinctrl_acpi_match),
},
.probe = sdm845_pinctrl_probe,
.remove = msm_pinctrl_remove,
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c
new file mode 100644
index 000000000000..7359bae68c69
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c
@@ -0,0 +1,1548 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-2019, 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"
+
+static const char * const sm8150_tiles[] = {
+ "north",
+ "south",
+ "east",
+ "west"
+};
+
+enum {
+ NORTH,
+ SOUTH,
+ EAST,
+ WEST
+};
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = (unsigned int)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 = 0x1000 * id, \
+ .io_reg = 0x1000 * id + 0x4, \
+ .intr_cfg_reg = 0x1000 * id + 0x8, \
+ .intr_status_reg = 0x1000 * id + 0xc, \
+ .intr_target_reg = 0x1000 * id + 0x8, \
+ .tile = _tile, \
+ .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 = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .tile = NORTH, \
+ .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 = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .tile = SOUTH, \
+ .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 sm8150_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, "GPIO_150"),
+ PINCTRL_PIN(151, "GPIO_151"),
+ PINCTRL_PIN(152, "GPIO_152"),
+ PINCTRL_PIN(153, "GPIO_153"),
+ PINCTRL_PIN(154, "GPIO_154"),
+ PINCTRL_PIN(155, "GPIO_155"),
+ PINCTRL_PIN(156, "GPIO_156"),
+ PINCTRL_PIN(157, "GPIO_157"),
+ PINCTRL_PIN(158, "GPIO_158"),
+ PINCTRL_PIN(159, "GPIO_159"),
+ PINCTRL_PIN(160, "GPIO_160"),
+ PINCTRL_PIN(161, "GPIO_161"),
+ PINCTRL_PIN(162, "GPIO_162"),
+ PINCTRL_PIN(163, "GPIO_163"),
+ PINCTRL_PIN(164, "GPIO_164"),
+ PINCTRL_PIN(165, "GPIO_165"),
+ PINCTRL_PIN(166, "GPIO_166"),
+ PINCTRL_PIN(167, "GPIO_167"),
+ PINCTRL_PIN(168, "GPIO_168"),
+ PINCTRL_PIN(169, "GPIO_169"),
+ PINCTRL_PIN(170, "GPIO_170"),
+ PINCTRL_PIN(171, "GPIO_171"),
+ PINCTRL_PIN(172, "GPIO_172"),
+ PINCTRL_PIN(173, "GPIO_173"),
+ PINCTRL_PIN(174, "GPIO_174"),
+ PINCTRL_PIN(175, "UFS_RESET"),
+ PINCTRL_PIN(176, "SDC2_CLK"),
+ PINCTRL_PIN(177, "SDC2_CMD"),
+ PINCTRL_PIN(178, "SDC2_DATA"),
+};
+
+#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);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+DECLARE_MSM_GPIO_PINS(152);
+DECLARE_MSM_GPIO_PINS(153);
+DECLARE_MSM_GPIO_PINS(154);
+DECLARE_MSM_GPIO_PINS(155);
+DECLARE_MSM_GPIO_PINS(156);
+DECLARE_MSM_GPIO_PINS(157);
+DECLARE_MSM_GPIO_PINS(158);
+DECLARE_MSM_GPIO_PINS(159);
+DECLARE_MSM_GPIO_PINS(160);
+DECLARE_MSM_GPIO_PINS(161);
+DECLARE_MSM_GPIO_PINS(162);
+DECLARE_MSM_GPIO_PINS(163);
+DECLARE_MSM_GPIO_PINS(164);
+DECLARE_MSM_GPIO_PINS(165);
+DECLARE_MSM_GPIO_PINS(166);
+DECLARE_MSM_GPIO_PINS(167);
+DECLARE_MSM_GPIO_PINS(168);
+DECLARE_MSM_GPIO_PINS(169);
+DECLARE_MSM_GPIO_PINS(170);
+DECLARE_MSM_GPIO_PINS(171);
+DECLARE_MSM_GPIO_PINS(172);
+DECLARE_MSM_GPIO_PINS(173);
+DECLARE_MSM_GPIO_PINS(174);
+
+static const unsigned int ufs_reset_pins[] = { 175 };
+static const unsigned int sdc2_clk_pins[] = { 176 };
+static const unsigned int sdc2_cmd_pins[] = { 177 };
+static const unsigned int sdc2_data_pins[] = { 178 };
+
+enum sm8150_functions {
+ msm_mux_adsp_ext,
+ msm_mux_agera_pll,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_usb1,
+ msm_mux_atest_usb2,
+ msm_mux_atest_usb10,
+ msm_mux_atest_usb11,
+ msm_mux_atest_usb12,
+ msm_mux_atest_usb13,
+ msm_mux_atest_usb20,
+ msm_mux_atest_usb21,
+ msm_mux_atest_usb22,
+ msm_mux_atest_usb23,
+ msm_mux_audio_ref,
+ 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_ddr_pxi0,
+ msm_mux_ddr_pxi1,
+ msm_mux_ddr_pxi2,
+ msm_mux_ddr_pxi3,
+ msm_mux_edp_hot,
+ msm_mux_edp_lcd,
+ msm_mux_emac_phy,
+ msm_mux_emac_pps,
+ msm_mux_gcc_gp1,
+ msm_mux_gcc_gp2,
+ msm_mux_gcc_gp3,
+ msm_mux_gpio,
+ msm_mux_jitter_bist,
+ msm_mux_hs1_mi2s,
+ msm_mux_hs2_mi2s,
+ msm_mux_hs3_mi2s,
+ msm_mux_lpass_slimbus,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync0,
+ msm_mux_mdp_vsync1,
+ msm_mux_mdp_vsync2,
+ msm_mux_mdp_vsync3,
+ msm_mux_mss_lte,
+ msm_mux_m_voc,
+ msm_mux_nav_pps,
+ msm_mux_pa_indicator,
+ msm_mux_pci_e0,
+ msm_mux_pci_e1,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist,
+ msm_mux_pll_bypassnl,
+ msm_mux_pll_reset,
+ msm_mux_pri_mi2s,
+ msm_mux_pri_mi2s_ws,
+ msm_mux_prng_rosc,
+ msm_mux_qdss,
+ msm_mux_qdss_cti,
+ msm_mux_qlink_enable,
+ msm_mux_qlink_request,
+ msm_mux_qspi0,
+ msm_mux_qspi1,
+ msm_mux_qspi2,
+ msm_mux_qspi3,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qua_mi2s,
+ msm_mux_qup0,
+ msm_mux_qup1,
+ msm_mux_qup2,
+ msm_mux_qup3,
+ msm_mux_qup4,
+ msm_mux_qup5,
+ msm_mux_qup6,
+ msm_mux_qup7,
+ msm_mux_qup8,
+ msm_mux_qup9,
+ msm_mux_qup10,
+ msm_mux_qup11,
+ msm_mux_qup12,
+ msm_mux_qup13,
+ msm_mux_qup14,
+ msm_mux_qup15,
+ msm_mux_qup16,
+ msm_mux_qup17,
+ msm_mux_qup18,
+ msm_mux_qup19,
+ msm_mux_qup_l4,
+ msm_mux_qup_l5,
+ msm_mux_qup_l6,
+ msm_mux_rgmii,
+ msm_mux_sdc4,
+ msm_mux_sd_write,
+ msm_mux_sec_mi2s,
+ msm_mux_spkr_i2s,
+ msm_mux_sp_cmu,
+ msm_mux_ter_mi2s,
+ msm_mux_tgu_ch0,
+ msm_mux_tgu_ch2,
+ msm_mux_tgu_ch1,
+ msm_mux_tgu_ch3,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_tsif1,
+ msm_mux_tsif2,
+ msm_mux_uim1,
+ msm_mux_uim2,
+ msm_mux_uim_batt,
+ msm_mux_usb2phy_ac,
+ msm_mux_usb_phy,
+ msm_mux_vfr_1,
+ msm_mux_vsense_trigger,
+ msm_mux_wlan1_adc1,
+ msm_mux_wlan1_adc0,
+ msm_mux_wlan2_adc1,
+ msm_mux_wlan2_adc0,
+ msm_mux_wmss_reset,
+ msm_mux__,
+};
+
+static const char * const phase_flag_groups[] = {
+ "gpio18", "gpio19", "gpio20", "gpio55", "gpio56",
+ "gpio57", "gpio59", "gpio64", "gpio68", "gpio76",
+ "gpio79", "gpio80", "gpio90", "gpio91", "gpio92",
+ "gpio93", "gpio94", "gpio96", "gpio114", "gpio115",
+ "gpio116", "gpio117", "gpio118", "gpio119", "gpio120",
+ "gpio121", "gpio122", "gpio126", "gpio127", "gpio128",
+ "gpio144", "gpio145",
+};
+
+static const char * const emac_pps_groups[] = {
+ "gpio81",
+};
+
+static const char * const qup12_groups[] = {
+ "gpio83", "gpio84", "gpio85", "gpio86",
+};
+
+static const char * const qup16_groups[] = {
+ "gpio83", "gpio84", "gpio85", "gpio86",
+};
+
+static const char * const tsif1_groups[] = {
+ "gpio88", "gpio89", "gpio90", "gpio91", "gpio97",
+};
+
+static const char * const qup8_groups[] = {
+ "gpio88", "gpio89", "gpio90", "gpio91",
+};
+
+static const char * const qspi_cs_groups[] = {
+ "gpio88", "gpio94",
+};
+
+static const char * const tgu_ch3_groups[] = {
+ "gpio88",
+};
+
+static const char * const qspi0_groups[] = {
+ "gpio89",
+};
+
+static const char * const mdp_vsync0_groups[] = {
+ "gpio89",
+};
+
+static const char * const mdp_vsync1_groups[] = {
+ "gpio89",
+};
+
+static const char * const mdp_vsync2_groups[] = {
+ "gpio89",
+};
+
+static const char * const mdp_vsync3_groups[] = {
+ "gpio89",
+};
+
+static const char * const tgu_ch0_groups[] = {
+ "gpio89",
+};
+
+static const char * const qspi1_groups[] = {
+ "gpio90",
+};
+
+static const char * const sdc4_groups[] = {
+ "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+};
+
+static const char * const tgu_ch1_groups[] = {
+ "gpio90",
+};
+
+static const char * const wlan1_adc1_groups[] = {
+ "gpio90",
+};
+
+static const char * const qspi2_groups[] = {
+ "gpio91",
+};
+
+static const char * const vfr_1_groups[] = {
+ "gpio91",
+};
+
+static const char * const tgu_ch2_groups[] = {
+ "gpio91",
+};
+
+static const char * const wlan1_adc0_groups[] = {
+ "gpio91",
+};
+
+static const char * const tsif2_groups[] = {
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96",
+};
+
+static const char * const qup11_groups[] = {
+ "gpio92", "gpio93", "gpio94", "gpio95",
+};
+
+static const char * const qspi_clk_groups[] = {
+ "gpio92",
+};
+
+static const char * const wlan2_adc1_groups[] = {
+ "gpio92",
+};
+
+static const char * const qspi3_groups[] = {
+ "gpio93",
+};
+
+static const char * const wlan2_adc0_groups[] = {
+ "gpio93",
+};
+
+static const char * const sd_write_groups[] = {
+ "gpio97",
+};
+
+static const char * const qup7_groups[] = {
+ "gpio98", "gpio99", "gpio100", "gpio101",
+};
+
+static const char * const ddr_bist_groups[] = {
+ "gpio98", "gpio99", "gpio145", "gpio146",
+};
+
+static const char * const ddr_pxi3_groups[] = {
+ "gpio98", "gpio101",
+};
+
+static const char * const atest_usb13_groups[] = {
+ "gpio99",
+};
+
+static const char * const ddr_pxi1_groups[] = {
+ "gpio99", "gpio100",
+};
+
+static const char * const pll_bypassnl_groups[] = {
+ "gpio100",
+};
+
+static const char * const atest_usb12_groups[] = {
+ "gpio100",
+};
+
+static const char * const pll_reset_groups[] = {
+ "gpio101",
+};
+
+static const char * const pci_e1_groups[] = {
+ "gpio102", "gpio103",
+};
+
+static const char * const uim2_groups[] = {
+ "gpio105", "gpio106", "gpio107", "gpio108",
+};
+
+static const char * const uim1_groups[] = {
+ "gpio109", "gpio110", "gpio111", "gpio112",
+};
+
+static const char * const uim_batt_groups[] = {
+ "gpio113",
+};
+
+static const char * const usb2phy_ac_groups[] = {
+ "gpio113", "gpio123",
+};
+
+static const char * const aoss_cti_groups[] = {
+ "gpio113",
+};
+
+static const char * const qup1_groups[] = {
+ "gpio114", "gpio115", "gpio116", "gpio117",
+};
+
+static const char * const rgmii_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7", "gpio59",
+ "gpio114", "gpio115", "gpio116", "gpio117",
+ "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+};
+
+static const char * const adsp_ext_groups[] = {
+ "gpio115",
+};
+
+static const char * const qup5_groups[] = {
+ "gpio119", "gpio120", "gpio121", "gpio122",
+};
+
+static const char * const atest_usb22_groups[] = {
+ "gpio123",
+};
+
+static const char * const emac_phy_groups[] = {
+ "gpio124",
+};
+
+static const char * const hs3_mi2s_groups[] = {
+ "gpio125", "gpio165", "gpio166", "gpio167", "gpio168",
+};
+
+static const char * const sec_mi2s_groups[] = {
+ "gpio126", "gpio127", "gpio128", "gpio129", "gpio130",
+};
+
+static const char * const qup2_groups[] = {
+ "gpio126", "gpio127", "gpio128", "gpio129",
+};
+
+static const char * const jitter_bist_groups[] = {
+ "gpio129",
+};
+
+static const char * const atest_usb21_groups[] = {
+ "gpio129",
+};
+
+static const char * const pll_bist_groups[] = {
+ "gpio130",
+};
+
+static const char * const atest_usb20_groups[] = {
+ "gpio130",
+};
+
+static const char * const atest_char0_groups[] = {
+ "gpio130",
+};
+
+static const char * const ter_mi2s_groups[] = {
+ "gpio131", "gpio132", "gpio133", "gpio134", "gpio135",
+};
+
+static const char * const gcc_gp1_groups[] = {
+ "gpio131", "gpio136",
+};
+
+static const char * const atest_char1_groups[] = {
+ "gpio133",
+};
+
+static const char * const atest_char2_groups[] = {
+ "gpio134",
+};
+
+static const char * const atest_char3_groups[] = {
+ "gpio135",
+};
+
+static const char * const qua_mi2s_groups[] = {
+ "gpio136", "gpio137", "gpio138", "gpio139", "gpio140", "gpio141",
+ "gpio142",
+};
+
+static const char * const pri_mi2s_groups[] = {
+ "gpio143", "gpio144", "gpio146", "gpio147",
+};
+
+static const char * const qup3_groups[] = {
+ "gpio144", "gpio145", "gpio146", "gpio147",
+};
+
+static const char * const ddr_pxi0_groups[] = {
+ "gpio144", "gpio145",
+};
+
+static const char * const pri_mi2s_ws_groups[] = {
+ "gpio145",
+};
+
+static const char * const vsense_trigger_groups[] = {
+ "gpio145",
+};
+
+static const char * const atest_usb1_groups[] = {
+ "gpio145",
+};
+
+static const char * const atest_usb11_groups[] = {
+ "gpio146",
+};
+
+static const char * const ddr_pxi2_groups[] = {
+ "gpio146", "gpio147",
+};
+
+static const char * const dbg_out_groups[] = {
+ "gpio147",
+};
+
+static const char * const atest_usb10_groups[] = {
+ "gpio147",
+};
+
+static const char * const spkr_i2s_groups[] = {
+ "gpio148", "gpio149", "gpio150", "gpio151", "gpio152",
+};
+
+static const char * const audio_ref_groups[] = {
+ "gpio148",
+};
+
+static const char * const lpass_slimbus_groups[] = {
+ "gpio149", "gpio150", "gpio151", "gpio152",
+};
+
+static const char * const tsense_pwm1_groups[] = {
+ "gpio150",
+};
+
+static const char * const tsense_pwm2_groups[] = {
+ "gpio150",
+};
+
+static const char * const btfm_slimbus_groups[] = {
+ "gpio153", "gpio154",
+};
+
+static const char * const hs1_mi2s_groups[] = {
+ "gpio155", "gpio156", "gpio157", "gpio158", "gpio159",
+};
+
+static const char * const cri_trng0_groups[] = {
+ "gpio159",
+};
+
+static const char * const hs2_mi2s_groups[] = {
+ "gpio160", "gpio161", "gpio162", "gpio163", "gpio164",
+};
+
+static const char * const cri_trng1_groups[] = {
+ "gpio160",
+};
+
+static const char * const cri_trng_groups[] = {
+ "gpio161",
+};
+
+static const char * const sp_cmu_groups[] = {
+ "gpio162",
+};
+
+static const char * const prng_rosc_groups[] = {
+ "gpio163",
+};
+
+static const char * const qup0_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+
+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", "gpio150", "gpio151", "gpio152",
+ "gpio153", "gpio154", "gpio155", "gpio156", "gpio157", "gpio158",
+ "gpio159", "gpio160", "gpio161", "gpio162", "gpio163", "gpio164",
+ "gpio165", "gpio166", "gpio167", "gpio168", "gpio169", "gpio170",
+ "gpio171", "gpio172", "gpio173", "gpio174",
+};
+
+static const char * const qup6_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+
+static const char * const qup_l6_groups[] = {
+ "gpio6", "gpio34", "gpio97", "gpio123",
+};
+
+static const char * const qup_l5_groups[] = {
+ "gpio7", "gpio33", "gpio82", "gpio96",
+};
+
+static const char * const mdp_vsync_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio81", "gpio82",
+};
+
+static const char * const edp_lcd_groups[] = {
+ "gpio9",
+};
+
+static const char * const qup10_groups[] = {
+ "gpio9", "gpio10", "gpio11", "gpio12",
+};
+
+static const char * const m_voc_groups[] = {
+ "gpio10",
+};
+
+static const char * const edp_hot_groups[] = {
+ "gpio10",
+};
+
+static const char * const cam_mclk_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16",
+};
+
+static const char * const qdss_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
+ "gpio23", "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
+ "gpio33", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio47", "gpio48", "gpio83", "gpio117", "gpio118",
+ "gpio119", "gpio120", "gpio121", "gpio132",
+ "gpio133", "gpio134",
+};
+
+static const char * const cci_i2c_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20", "gpio31", "gpio32", "gpio33",
+ "gpio34",
+};
+
+static const char * const cci_timer0_groups[] = {
+ "gpio21",
+};
+
+static const char * const gcc_gp2_groups[] = {
+ "gpio21", "gpio137",
+};
+
+static const char * const cci_timer1_groups[] = {
+ "gpio22",
+};
+
+static const char * const gcc_gp3_groups[] = {
+ "gpio22", "gpio138",
+};
+
+static const char * const cci_timer2_groups[] = {
+ "gpio23",
+};
+
+static const char * const qup18_groups[] = {
+ "gpio23", "gpio24", "gpio25", "gpio26",
+};
+
+static const char * const cci_timer3_groups[] = {
+ "gpio24",
+};
+
+static const char * const cci_async_groups[] = {
+ "gpio24", "gpio25", "gpio26",
+};
+
+static const char * const cci_timer4_groups[] = {
+ "gpio25",
+};
+
+static const char * const qup15_groups[] = {
+ "gpio27", "gpio28", "gpio29", "gpio30",
+};
+
+static const char * const pci_e0_groups[] = {
+ "gpio35", "gpio36",
+};
+
+static const char * const qup_l4_groups[] = {
+ "gpio37", "gpio59", "gpio81", "gpio95",
+};
+
+static const char * const agera_pll_groups[] = {
+ "gpio37",
+};
+
+static const char * const usb_phy_groups[] = {
+ "gpio38",
+};
+
+static const char * const qup9_groups[] = {
+ "gpio39", "gpio40", "gpio41", "gpio42",
+};
+
+static const char * const qup13_groups[] = {
+ "gpio43", "gpio44", "gpio45", "gpio46",
+};
+
+static const char * const qdss_cti_groups[] = {
+ "gpio45", "gpio46", "gpio49", "gpio50", "gpio56", "gpio57", "gpio58",
+ "gpio58",
+};
+
+static const char * const qup14_groups[] = {
+ "gpio47", "gpio48", "gpio49", "gpio50",
+};
+
+static const char * const qup4_groups[] = {
+ "gpio51", "gpio52", "gpio53", "gpio54",
+};
+
+static const char * const qup17_groups[] = {
+ "gpio55", "gpio56", "gpio57", "gpio58",
+};
+
+static const char * const qup19_groups[] = {
+ "gpio55", "gpio56", "gpio57", "gpio58",
+};
+
+static const char * const atest_char_groups[] = {
+ "gpio59",
+};
+
+static const char * const nav_pps_groups[] = {
+ "gpio60", "gpio60", "gpio76", "gpio76", "gpio77", "gpio77", "gpio81",
+ "gpio81", "gpio82", "gpio82",
+};
+
+static const char * const atest_usb2_groups[] = {
+ "gpio60",
+};
+
+static const char * const qlink_request_groups[] = {
+ "gpio61",
+};
+
+static const char * const qlink_enable_groups[] = {
+ "gpio62",
+};
+
+static const char * const wmss_reset_groups[] = {
+ "gpio63",
+};
+
+static const char * const atest_usb23_groups[] = {
+ "gpio63",
+};
+
+static const char * const pa_indicator_groups[] = {
+ "gpio68",
+};
+
+static const char * const mss_lte_groups[] = {
+ "gpio69", "gpio70",
+};
+
+static const struct msm_function sm8150_functions[] = {
+ FUNCTION(adsp_ext),
+ FUNCTION(agera_pll),
+ FUNCTION(aoss_cti),
+ FUNCTION(ddr_pxi2),
+ FUNCTION(atest_char),
+ FUNCTION(atest_char0),
+ FUNCTION(atest_char1),
+ FUNCTION(atest_char2),
+ FUNCTION(atest_char3),
+ FUNCTION(audio_ref),
+ FUNCTION(atest_usb1),
+ FUNCTION(atest_usb2),
+ FUNCTION(atest_usb10),
+ FUNCTION(atest_usb11),
+ FUNCTION(atest_usb12),
+ FUNCTION(atest_usb13),
+ FUNCTION(atest_usb20),
+ FUNCTION(atest_usb21),
+ FUNCTION(atest_usb22),
+ FUNCTION(atest_usb23),
+ 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(ddr_pxi0),
+ FUNCTION(ddr_pxi1),
+ FUNCTION(ddr_pxi3),
+ FUNCTION(edp_hot),
+ FUNCTION(edp_lcd),
+ FUNCTION(emac_phy),
+ FUNCTION(emac_pps),
+ FUNCTION(gcc_gp1),
+ FUNCTION(gcc_gp2),
+ FUNCTION(gcc_gp3),
+ FUNCTION(gpio),
+ FUNCTION(hs1_mi2s),
+ FUNCTION(hs2_mi2s),
+ FUNCTION(hs3_mi2s),
+ FUNCTION(jitter_bist),
+ FUNCTION(lpass_slimbus),
+ FUNCTION(mdp_vsync),
+ FUNCTION(mdp_vsync0),
+ FUNCTION(mdp_vsync1),
+ FUNCTION(mdp_vsync2),
+ FUNCTION(mdp_vsync3),
+ FUNCTION(mss_lte),
+ FUNCTION(m_voc),
+ FUNCTION(nav_pps),
+ FUNCTION(pa_indicator),
+ FUNCTION(pci_e0),
+ FUNCTION(phase_flag),
+ FUNCTION(pll_bypassnl),
+ FUNCTION(pll_bist),
+ FUNCTION(pci_e1),
+ FUNCTION(pll_reset),
+ FUNCTION(pri_mi2s),
+ FUNCTION(pri_mi2s_ws),
+ FUNCTION(prng_rosc),
+ FUNCTION(qdss),
+ FUNCTION(qdss_cti),
+ FUNCTION(qlink_request),
+ FUNCTION(qlink_enable),
+ FUNCTION(qspi0),
+ FUNCTION(qspi1),
+ FUNCTION(qspi2),
+ FUNCTION(qspi3),
+ FUNCTION(qspi_clk),
+ FUNCTION(qspi_cs),
+ FUNCTION(qua_mi2s),
+ FUNCTION(qup0),
+ FUNCTION(qup1),
+ FUNCTION(qup2),
+ FUNCTION(qup3),
+ FUNCTION(qup4),
+ FUNCTION(qup5),
+ FUNCTION(qup6),
+ FUNCTION(qup7),
+ FUNCTION(qup8),
+ FUNCTION(qup9),
+ FUNCTION(qup10),
+ FUNCTION(qup11),
+ FUNCTION(qup12),
+ FUNCTION(qup13),
+ FUNCTION(qup14),
+ FUNCTION(qup15),
+ FUNCTION(qup16),
+ FUNCTION(qup17),
+ FUNCTION(qup18),
+ FUNCTION(qup19),
+ FUNCTION(qup_l4),
+ FUNCTION(qup_l5),
+ FUNCTION(qup_l6),
+ FUNCTION(rgmii),
+ FUNCTION(sdc4),
+ FUNCTION(sd_write),
+ FUNCTION(sec_mi2s),
+ FUNCTION(spkr_i2s),
+ FUNCTION(sp_cmu),
+ FUNCTION(ter_mi2s),
+ FUNCTION(tgu_ch0),
+ FUNCTION(tgu_ch1),
+ FUNCTION(tgu_ch2),
+ FUNCTION(tgu_ch3),
+ FUNCTION(tsense_pwm1),
+ FUNCTION(tsense_pwm2),
+ FUNCTION(tsif1),
+ FUNCTION(tsif2),
+ FUNCTION(uim1),
+ FUNCTION(uim2),
+ FUNCTION(uim_batt),
+ FUNCTION(usb2phy_ac),
+ FUNCTION(usb_phy),
+ FUNCTION(vfr_1),
+ FUNCTION(vsense_trigger),
+ FUNCTION(wlan1_adc0),
+ FUNCTION(wlan1_adc1),
+ FUNCTION(wlan2_adc0),
+ FUNCTION(wlan2_adc1),
+ FUNCTION(wmss_reset),
+};
+
+/*
+ * Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup sm8150_groups[] = {
+ [0] = PINGROUP(0, SOUTH, qup0, _, _, _, _, _, _, _, _),
+ [1] = PINGROUP(1, SOUTH, qup0, _, _, _, _, _, _, _, _),
+ [2] = PINGROUP(2, SOUTH, qup0, _, _, _, _, _, _, _, _),
+ [3] = PINGROUP(3, SOUTH, qup0, _, _, _, _, _, _, _, _),
+ [4] = PINGROUP(4, SOUTH, qup6, rgmii, _, _, _, _, _, _, _),
+ [5] = PINGROUP(5, SOUTH, qup6, rgmii, _, _, _, _, _, _, _),
+ [6] = PINGROUP(6, SOUTH, qup6, rgmii, qup_l6, _, _, _, _, _, _),
+ [7] = PINGROUP(7, SOUTH, qup6, rgmii, qup_l5, _, _, _, _, _, _),
+ [8] = PINGROUP(8, NORTH, mdp_vsync, _, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, NORTH, mdp_vsync, edp_lcd, qup10, _, _, _, _, _, _),
+ [10] = PINGROUP(10, NORTH, mdp_vsync, m_voc, edp_hot, qup10, _, _, _, _, _),
+ [11] = PINGROUP(11, NORTH, qup10, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, NORTH, qup10, _, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, NORTH, cam_mclk, qdss, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, NORTH, cam_mclk, qdss, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, NORTH, cam_mclk, qdss, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, NORTH, cam_mclk, qdss, _, _, _, _, _, _, _),
+ [17] = PINGROUP(17, NORTH, cci_i2c, qdss, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, NORTH, cci_i2c, phase_flag, _, qdss, _, _, _, _, _),
+ [19] = PINGROUP(19, NORTH, cci_i2c, phase_flag, _, qdss, _, _, _, _, _),
+ [20] = PINGROUP(20, NORTH, cci_i2c, phase_flag, _, qdss, _, _, _, _, _),
+ [21] = PINGROUP(21, EAST, cci_timer0, gcc_gp2, qdss, _, _, _, _, _, _),
+ [22] = PINGROUP(22, EAST, cci_timer1, gcc_gp3, qdss, _, _, _, _, _, _),
+ [23] = PINGROUP(23, EAST, cci_timer2, qup18, qdss, _, _, _, _, _, _),
+ [24] = PINGROUP(24, EAST, cci_timer3, cci_async, qup18, qdss, _, _, _, _, _),
+ [25] = PINGROUP(25, EAST, cci_timer4, cci_async, qup18, qdss, _, _, _, _, _),
+ [26] = PINGROUP(26, EAST, cci_async, qup18, qdss, _, _, _, _, _, _),
+ [27] = PINGROUP(27, EAST, qup15, _, qdss, _, _, _, _, _, _),
+ [28] = PINGROUP(28, EAST, qup15, qdss, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, EAST, qup15, qdss, _, _, _, _, _, _, _),
+ [30] = PINGROUP(30, EAST, qup15, qdss, _, _, _, _, _, _, _),
+ [31] = PINGROUP(31, NORTH, cci_i2c, qdss, _, _, _, _, _, _, _),
+ [32] = PINGROUP(32, NORTH, cci_i2c, qdss, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, NORTH, cci_i2c, qup_l5, qdss, _, _, _, _, _, _),
+ [34] = PINGROUP(34, NORTH, cci_i2c, qup_l6, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, NORTH, pci_e0, _, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, NORTH, pci_e0, _, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, NORTH, qup_l4, agera_pll, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, SOUTH, usb_phy, _, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, NORTH, qup9, qdss, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, NORTH, qup9, qdss, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, NORTH, qup9, qdss, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, NORTH, qup9, qdss, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, EAST, qup13, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, EAST, qup13, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, EAST, qup13, qdss_cti, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, EAST, qup13, qdss_cti, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, EAST, qup14, qdss, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, EAST, qup14, qdss, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, EAST, qup14, _, qdss_cti, _, _, _, _, _, _),
+ [50] = PINGROUP(50, EAST, qup14, qdss_cti, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, SOUTH, qup4, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, SOUTH, qup4, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, SOUTH, qup4, _, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, SOUTH, qup4, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, SOUTH, qup17, qup19, phase_flag, _, _, _, _, _, _),
+ [56] = PINGROUP(56, SOUTH, qup17, qup19, qdss_cti, phase_flag, _, _, _, _, _),
+ [57] = PINGROUP(57, SOUTH, qup17, qup19, qdss_cti, phase_flag, _, _, _, _, _),
+ [58] = PINGROUP(58, SOUTH, qup17, qup19, qdss_cti, phase_flag, _, _, _, _, _),
+ [59] = PINGROUP(59, SOUTH, rgmii, qup_l4, phase_flag, _, atest_char, _, _, _, _),
+ [60] = PINGROUP(60, SOUTH, _, nav_pps, nav_pps, atest_usb2, _, _, _, _, _),
+ [61] = PINGROUP(61, SOUTH, qlink_request, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, SOUTH, qlink_enable, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, SOUTH, wmss_reset, atest_usb23, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, SOUTH, _, phase_flag, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, SOUTH, _, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, SOUTH, _, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, SOUTH, _, _, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, SOUTH, _, pa_indicator, phase_flag, _, _, _, _, _, _),
+ [69] = PINGROUP(69, SOUTH, mss_lte, _, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, SOUTH, mss_lte, _, _, _, _, _, _, _, _),
+ [71] = PINGROUP(71, SOUTH, _, _, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, SOUTH, _, _, _, _, _, _, _, _, _),
+ [73] = PINGROUP(73, SOUTH, _, _, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, SOUTH, _, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, SOUTH, _, _, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, SOUTH, _, _, _, nav_pps, nav_pps, phase_flag, _, _, _),
+ [77] = PINGROUP(77, SOUTH, _, _, _, nav_pps, nav_pps, _, _, _, _),
+ [78] = PINGROUP(78, SOUTH, _, _, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, SOUTH, _, _, phase_flag, _, _, _, _, _, _),
+ [80] = PINGROUP(80, SOUTH, _, _, phase_flag, _, _, _, _, _, _),
+ [81] = PINGROUP(81, SOUTH, _, _, _, nav_pps, nav_pps, qup_l4, mdp_vsync, emac_pps, _),
+ [82] = PINGROUP(82, SOUTH, _, _, _, nav_pps, nav_pps, qup_l5, mdp_vsync, _, _),
+ [83] = PINGROUP(83, NORTH, qup12, qup16, _, qdss, _, _, _, _, _),
+ [84] = PINGROUP(84, NORTH, qup12, qup16, _, _, _, _, _, _, _),
+ [85] = PINGROUP(85, NORTH, qup12, qup16, _, _, _, _, _, _, _),
+ [86] = PINGROUP(86, NORTH, qup12, qup16, _, _, _, _, _, _, _),
+ [87] = PINGROUP(87, EAST, _, _, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, NORTH, tsif1, qup8, qspi_cs, tgu_ch3, _, _, _, _, _),
+ [89] = PINGROUP(89, NORTH, tsif1, qup8, qspi0, mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3, tgu_ch0, _),
+ [90] = PINGROUP(90, NORTH, tsif1, qup8, qspi1, sdc4, phase_flag, tgu_ch1, _, _, wlan1_adc1),
+ [91] = PINGROUP(91, NORTH, tsif1, qup8, qspi2, sdc4, vfr_1, phase_flag, tgu_ch2, _, _),
+ [92] = PINGROUP(92, NORTH, tsif2, qup11, qspi_clk, sdc4, phase_flag, _, wlan2_adc1, _, _),
+ [93] = PINGROUP(93, NORTH, tsif2, qup11, qspi3, sdc4, phase_flag, _, wlan2_adc0, _, _),
+ [94] = PINGROUP(94, NORTH, tsif2, qup11, qspi_cs, sdc4, phase_flag, _, _, _, _),
+ [95] = PINGROUP(95, NORTH, tsif2, qup11, sdc4, qup_l4, _, _, _, _, _),
+ [96] = PINGROUP(96, NORTH, tsif2, qup_l5, phase_flag, _, _, _, _, _, _),
+ [97] = PINGROUP(97, NORTH, sd_write, tsif1, qup_l6, _, _, _, _, _, _),
+ [98] = PINGROUP(98, SOUTH, qup7, ddr_bist, ddr_pxi3, _, _, _, _, _, _),
+ [99] = PINGROUP(99, SOUTH, qup7, ddr_bist, atest_usb13, ddr_pxi1, _, _, _, _, _),
+ [100] = PINGROUP(100, SOUTH, qup7, pll_bypassnl, atest_usb12, ddr_pxi1, _, _, _, _, _),
+ [101] = PINGROUP(101, SOUTH, qup7, pll_reset, ddr_pxi3, _, _, _, _, _, _),
+ [102] = PINGROUP(102, NORTH, pci_e1, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, NORTH, pci_e1, _, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, NORTH, _, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, WEST, uim2, _, _, _, _, _, _, _, _),
+ [106] = PINGROUP(106, WEST, uim2, _, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, WEST, uim2, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, WEST, uim2, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, WEST, uim1, _, _, _, _, _, _, _, _),
+ [110] = PINGROUP(110, WEST, uim1, _, _, _, _, _, _, _, _),
+ [111] = PINGROUP(111, WEST, uim1, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, WEST, uim1, _, _, _, _, _, _, _, _),
+ [113] = PINGROUP(113, WEST, uim_batt, usb2phy_ac, aoss_cti, _, _, _, _, _, _),
+ [114] = PINGROUP(114, SOUTH, qup1, rgmii, phase_flag, _, _, _, _, _, _),
+ [115] = PINGROUP(115, SOUTH, qup1, rgmii, phase_flag, adsp_ext, _, _, _, _, _),
+ [116] = PINGROUP(116, SOUTH, qup1, rgmii, phase_flag, _, _, _, _, _, _),
+ [117] = PINGROUP(117, SOUTH, qup1, rgmii, phase_flag, _, qdss, _, _, _, _),
+ [118] = PINGROUP(118, SOUTH, rgmii, phase_flag, _, qdss, _, _, _, _, _),
+ [119] = PINGROUP(119, SOUTH, qup5, rgmii, phase_flag, _, qdss, _, _, _, _),
+ [120] = PINGROUP(120, SOUTH, qup5, rgmii, phase_flag, _, qdss, _, _, _, _),
+ [121] = PINGROUP(121, SOUTH, qup5, rgmii, phase_flag, _, qdss, _, _, _, _),
+ [122] = PINGROUP(122, SOUTH, qup5, rgmii, phase_flag, _, _, _, _, _, _),
+ [123] = PINGROUP(123, SOUTH, usb2phy_ac, qup_l6, atest_usb22, _, _, _, _, _, _),
+ [124] = PINGROUP(124, SOUTH, emac_phy, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, WEST, hs3_mi2s, _, _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, SOUTH, sec_mi2s, qup2, phase_flag, _, _, _, _, _, _),
+ [127] = PINGROUP(127, SOUTH, sec_mi2s, qup2, phase_flag, _, _, _, _, _, _),
+ [128] = PINGROUP(128, SOUTH, sec_mi2s, qup2, phase_flag, _, _, _, _, _, _),
+ [129] = PINGROUP(129, SOUTH, sec_mi2s, qup2, jitter_bist, atest_usb21, _, _, _, _, _),
+ [130] = PINGROUP(130, SOUTH, sec_mi2s, pll_bist, atest_usb20, atest_char0, _, _, _, _, _),
+ [131] = PINGROUP(131, SOUTH, ter_mi2s, gcc_gp1, _, _, _, _, _, _, _),
+ [132] = PINGROUP(132, SOUTH, ter_mi2s, _, qdss, _, _, _, _, _, _),
+ [133] = PINGROUP(133, SOUTH, ter_mi2s, qdss, atest_char1, _, _, _, _, _, _),
+ [134] = PINGROUP(134, SOUTH, ter_mi2s, qdss, atest_char2, _, _, _, _, _, _),
+ [135] = PINGROUP(135, SOUTH, ter_mi2s, atest_char3, _, _, _, _, _, _, _),
+ [136] = PINGROUP(136, SOUTH, qua_mi2s, gcc_gp1, _, _, _, _, _, _, _),
+ [137] = PINGROUP(137, SOUTH, qua_mi2s, gcc_gp2, _, _, _, _, _, _, _),
+ [138] = PINGROUP(138, SOUTH, qua_mi2s, gcc_gp3, _, _, _, _, _, _, _),
+ [139] = PINGROUP(139, SOUTH, qua_mi2s, _, _, _, _, _, _, _, _),
+ [140] = PINGROUP(140, SOUTH, qua_mi2s, _, _, _, _, _, _, _, _),
+ [141] = PINGROUP(141, SOUTH, qua_mi2s, _, _, _, _, _, _, _, _),
+ [142] = PINGROUP(142, SOUTH, qua_mi2s, _, _, _, _, _, _, _, _),
+ [143] = PINGROUP(143, SOUTH, pri_mi2s, _, _, _, _, _, _, _, _),
+ [144] = PINGROUP(144, SOUTH, pri_mi2s, qup3, phase_flag, _, ddr_pxi0, _, _, _, _),
+ [145] = PINGROUP(145, SOUTH, pri_mi2s_ws, qup3, phase_flag, ddr_bist, _, vsense_trigger, atest_usb1, ddr_pxi0, _),
+ [146] = PINGROUP(146, SOUTH, pri_mi2s, qup3, ddr_bist, atest_usb11, ddr_pxi2, _, _, _, _),
+ [147] = PINGROUP(147, SOUTH, pri_mi2s, qup3, dbg_out, atest_usb10, ddr_pxi2, _, _, _, _),
+ [148] = PINGROUP(148, SOUTH, spkr_i2s, audio_ref, _, _, _, _, _, _, _),
+ [149] = PINGROUP(149, SOUTH, lpass_slimbus, spkr_i2s, _, _, _, _, _, _, _),
+ [150] = PINGROUP(150, SOUTH, lpass_slimbus, spkr_i2s, tsense_pwm1, tsense_pwm2, _, _, _, _, _),
+ [151] = PINGROUP(151, SOUTH, lpass_slimbus, spkr_i2s, _, _, _, _, _, _, _),
+ [152] = PINGROUP(152, SOUTH, lpass_slimbus, spkr_i2s, _, _, _, _, _, _, _),
+ [153] = PINGROUP(153, SOUTH, btfm_slimbus, _, _, _, _, _, _, _, _),
+ [154] = PINGROUP(154, SOUTH, btfm_slimbus, _, _, _, _, _, _, _, _),
+ [155] = PINGROUP(155, WEST, hs1_mi2s, _, _, _, _, _, _, _, _),
+ [156] = PINGROUP(156, WEST, hs1_mi2s, _, _, _, _, _, _, _, _),
+ [157] = PINGROUP(157, WEST, hs1_mi2s, _, _, _, _, _, _, _, _),
+ [158] = PINGROUP(158, WEST, hs1_mi2s, _, _, _, _, _, _, _, _),
+ [159] = PINGROUP(159, WEST, hs1_mi2s, cri_trng0, _, _, _, _, _, _, _),
+ [160] = PINGROUP(160, WEST, hs2_mi2s, cri_trng1, _, _, _, _, _, _, _),
+ [161] = PINGROUP(161, WEST, hs2_mi2s, cri_trng, _, _, _, _, _, _, _),
+ [162] = PINGROUP(162, WEST, hs2_mi2s, sp_cmu, _, _, _, _, _, _, _),
+ [163] = PINGROUP(163, WEST, hs2_mi2s, prng_rosc, _, _, _, _, _, _, _),
+ [164] = PINGROUP(164, WEST, hs2_mi2s, _, _, _, _, _, _, _, _),
+ [165] = PINGROUP(165, WEST, hs3_mi2s, _, _, _, _, _, _, _, _),
+ [166] = PINGROUP(166, WEST, hs3_mi2s, _, _, _, _, _, _, _, _),
+ [167] = PINGROUP(167, WEST, hs3_mi2s, _, _, _, _, _, _, _, _),
+ [168] = PINGROUP(168, WEST, hs3_mi2s, _, _, _, _, _, _, _, _),
+ [169] = PINGROUP(169, NORTH, _, _, _, _, _, _, _, _, _),
+ [170] = PINGROUP(170, NORTH, _, _, _, _, _, _, _, _, _),
+ [171] = PINGROUP(171, NORTH, _, _, _, _, _, _, _, _, _),
+ [172] = PINGROUP(172, NORTH, _, _, _, _, _, _, _, _, _),
+ [173] = PINGROUP(173, NORTH, _, _, _, _, _, _, _, _, _),
+ [174] = PINGROUP(174, NORTH, _, _, _, _, _, _, _, _, _),
+ [175] = UFS_RESET(ufs_reset, 0xB6000),
+ [176] = SDC_QDSD_PINGROUP(sdc2_clk, 0xB2000, 14, 6),
+ [177] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xB2000, 11, 3),
+ [178] = SDC_QDSD_PINGROUP(sdc2_data, 0xB2000, 9, 0),
+};
+
+static const struct msm_pinctrl_soc_data sm8150_pinctrl = {
+ .pins = sm8150_pins,
+ .npins = ARRAY_SIZE(sm8150_pins),
+ .functions = sm8150_functions,
+ .nfunctions = ARRAY_SIZE(sm8150_functions),
+ .groups = sm8150_groups,
+ .ngroups = ARRAY_SIZE(sm8150_groups),
+ .ngpios = 176,
+ .tiles = sm8150_tiles,
+ .ntiles = ARRAY_SIZE(sm8150_tiles),
+};
+
+static int sm8150_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &sm8150_pinctrl);
+}
+
+static const struct of_device_id sm8150_pinctrl_of_match[] = {
+ { .compatible = "qcom,sm8150-pinctrl", },
+ { },
+};
+
+static struct platform_driver sm8150_pinctrl_driver = {
+ .driver = {
+ .name = "sm8150-pinctrl",
+ .of_match_table = sm8150_pinctrl_of_match,
+ },
+ .probe = sm8150_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init sm8150_pinctrl_init(void)
+{
+ return platform_driver_register(&sm8150_pinctrl_driver);
+}
+arch_initcall(sm8150_pinctrl_init);
+
+static void __exit sm8150_pinctrl_exit(void)
+{
+ platform_driver_unregister(&sm8150_pinctrl_driver);
+}
+module_exit(sm8150_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI sm8150 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, sm8150_pinctrl_of_match);
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 3f989f5cb021..b8640ad41bef 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -717,7 +717,7 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
#ifdef DEBUG
-static bool is0s(const u16 *enum_ids, unsigned int n)
+static bool __init is0s(const u16 *enum_ids, unsigned int n)
{
unsigned int i;
@@ -728,11 +728,11 @@ static bool is0s(const u16 *enum_ids, unsigned int n)
return true;
}
-static unsigned int sh_pfc_errors;
-static unsigned int sh_pfc_warnings;
+static unsigned int sh_pfc_errors __initdata = 0;
+static unsigned int sh_pfc_warnings __initdata = 0;
-static void sh_pfc_check_cfg_reg(const char *drvname,
- const struct pinmux_cfg_reg *cfg_reg)
+static void __init sh_pfc_check_cfg_reg(const char *drvname,
+ const struct pinmux_cfg_reg *cfg_reg)
{
unsigned int i, n, rw, fw;
@@ -764,7 +764,7 @@ static void sh_pfc_check_cfg_reg(const char *drvname,
}
}
-static void sh_pfc_check_info(const struct sh_pfc_soc_info *info)
+static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info)
{
const struct sh_pfc_function *func;
const char *drvname = info->name;
@@ -773,6 +773,35 @@ static void sh_pfc_check_info(const struct sh_pfc_soc_info *info)
pr_info("Checking %s\n", drvname);
+ /* Check pins */
+ for (i = 0; i < info->nr_pins; i++) {
+ for (j = 0; j < i; j++) {
+ if (!strcmp(info->pins[i].name, info->pins[j].name)) {
+ pr_err("%s: pin %s/%s: name conflict\n",
+ drvname, info->pins[i].name,
+ info->pins[j].name);
+ sh_pfc_errors++;
+ }
+
+ if (info->pins[i].pin != (u16)-1 &&
+ info->pins[i].pin == info->pins[j].pin) {
+ pr_err("%s: pin %s/%s: pin %u conflict\n",
+ drvname, info->pins[i].name,
+ info->pins[j].name, info->pins[i].pin);
+ sh_pfc_errors++;
+ }
+
+ if (info->pins[i].enum_id &&
+ info->pins[i].enum_id == info->pins[j].enum_id) {
+ pr_err("%s: pin %s/%s: enum_id %u conflict\n",
+ drvname, info->pins[i].name,
+ info->pins[j].name,
+ info->pins[i].enum_id);
+ sh_pfc_errors++;
+ }
+ }
+ }
+
/* Check groups and functions */
refcnts = kcalloc(info->nr_groups, sizeof(*refcnts), GFP_KERNEL);
if (!refcnts)
@@ -780,9 +809,15 @@ static void sh_pfc_check_info(const struct sh_pfc_soc_info *info)
for (i = 0; i < info->nr_functions; i++) {
func = &info->functions[i];
+ if (!func->name) {
+ pr_err("%s: empty function %u\n", drvname, i);
+ sh_pfc_errors++;
+ continue;
+ }
for (j = 0; j < func->nr_groups; j++) {
for (k = 0; k < info->nr_groups; k++) {
- if (!strcmp(func->groups[j],
+ if (info->groups[k].name &&
+ !strcmp(func->groups[j],
info->groups[k].name)) {
refcnts[k]++;
break;
@@ -798,13 +833,18 @@ static void sh_pfc_check_info(const struct sh_pfc_soc_info *info)
}
for (i = 0; i < info->nr_groups; i++) {
+ if (!info->groups[i].name) {
+ pr_err("%s: empty group %u\n", drvname, i);
+ sh_pfc_errors++;
+ continue;
+ }
if (!refcnts[i]) {
pr_err("%s: orphan group %s\n", drvname,
info->groups[i].name);
sh_pfc_errors++;
} else if (refcnts[i] > 1) {
- pr_err("%s: group %s referred by %u functions\n",
- drvname, info->groups[i].name, refcnts[i]);
+ pr_warn("%s: group %s referenced by %u functions\n",
+ drvname, info->groups[i].name, refcnts[i]);
sh_pfc_warnings++;
}
}
@@ -816,7 +856,7 @@ static void sh_pfc_check_info(const struct sh_pfc_soc_info *info)
sh_pfc_check_cfg_reg(drvname, &info->cfg_regs[i]);
}
-static void sh_pfc_check_driver(const struct platform_driver *pdrv)
+static void __init sh_pfc_check_driver(const struct platform_driver *pdrv)
{
unsigned int i;
diff --git a/drivers/pinctrl/sh-pfc/pfc-emev2.c b/drivers/pinctrl/sh-pfc/pfc-emev2.c
index 0af1ef82a1a8..6c66fc335d2f 100644
--- a/drivers/pinctrl/sh-pfc/pfc-emev2.c
+++ b/drivers/pinctrl/sh-pfc/pfc-emev2.c
@@ -19,6 +19,20 @@
PORT_1(155, fn, pfx##155, sfx), PORT_1(156, fn, pfx##156, sfx), \
PORT_1(157, fn, pfx##157, sfx), PORT_1(158, fn, pfx##158, sfx)
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP(LCD3_B2, "B15", fn), \
+ PIN_NOGP(LCD3_B3, "C15", fn), \
+ PIN_NOGP(LCD3_B4, "D15", fn), \
+ PIN_NOGP(LCD3_B5, "B14", fn), \
+ PIN_NOGP(LCD3_B6, "C14", fn), \
+ PIN_NOGP(LCD3_B7, "D14", fn), \
+ PIN_NOGP(LCD3_G2, "B17", fn), \
+ PIN_NOGP(LCD3_G3, "C17", fn), \
+ PIN_NOGP(LCD3_G4, "D17", fn), \
+ PIN_NOGP(LCD3_G5, "B16", fn), \
+ PIN_NOGP(LCD3_G6, "C16", fn), \
+ PIN_NOGP(LCD3_G7, "D16", fn)
+
enum {
PINMUX_RESERVED = 0,
@@ -218,10 +232,13 @@ enum {
PINMUX_MARK_END,
};
-/* Pin numbers for pins without a corresponding GPIO port number are computed
- * from the row and column numbers with a 1000 offset to avoid collisions with
- * GPIO port numbers. */
-#define PIN_NUMBER(row, col) (1000+((row)-1)*23+(col)-1)
+/*
+ * Pins not associated with a GPIO port.
+ */
+enum {
+ PORT_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
/* Expand to a list of sh_pfc_pin entries (named PORT#).
* NOTE: No config are recorded since the driver do not handle pinconf. */
@@ -230,20 +247,7 @@ enum {
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_EMEV_GPIO_ALL(),
-
- /* Pins not associated with a GPIO port */
- SH_PFC_PIN_NAMED(2, 14, B14),
- SH_PFC_PIN_NAMED(2, 15, B15),
- SH_PFC_PIN_NAMED(2, 16, B16),
- SH_PFC_PIN_NAMED(2, 17, B17),
- SH_PFC_PIN_NAMED(3, 14, C14),
- SH_PFC_PIN_NAMED(3, 15, C15),
- SH_PFC_PIN_NAMED(3, 16, C16),
- SH_PFC_PIN_NAMED(3, 17, C17),
- SH_PFC_PIN_NAMED(4, 14, D14),
- SH_PFC_PIN_NAMED(4, 15, D15),
- SH_PFC_PIN_NAMED(4, 16, D16),
- SH_PFC_PIN_NAMED(4, 17, D17),
+ PINMUX_NOGP_ALL(),
};
/* Expand to a list of name_DATA, name_FN marks */
@@ -829,12 +833,10 @@ static const unsigned int lcd3_rgb888_pins[] = {
/* R[0:7], G[0:7], B[0:7] */
32, 33, 34, 35,
36, 37, 38, 39,
- 40, 41, PIN_NUMBER(2, 17), PIN_NUMBER(3, 17),
- PIN_NUMBER(4, 17), PIN_NUMBER(2, 16), PIN_NUMBER(3, 16),
- PIN_NUMBER(4, 16),
- 42, 43, PIN_NUMBER(2, 15), PIN_NUMBER(3, 15),
- PIN_NUMBER(4, 15), PIN_NUMBER(2, 14), PIN_NUMBER(3, 14),
- PIN_NUMBER(4, 14)
+ 40, 41, PIN_LCD3_G2, PIN_LCD3_G3,
+ PIN_LCD3_G4, PIN_LCD3_G5, PIN_LCD3_G6, PIN_LCD3_G7,
+ 42, 43, PIN_LCD3_B2, PIN_LCD3_B3,
+ PIN_LCD3_B4, PIN_LCD3_B5, PIN_LCD3_B6, PIN_LCD3_B7
};
static const unsigned int lcd3_rgb888_mux[] = {
LCD3_R0_MARK, LCD3_R1_MARK, LCD3_R2_MARK, LCD3_R3_MARK,
@@ -850,12 +852,10 @@ static const unsigned int yuv3_pins[] = {
/* CLK_O, HS, VS, DE */
18, 21, 22, 23,
/* YUV3_D[0:15] */
- 40, 41, PIN_NUMBER(2, 17), PIN_NUMBER(3, 17),
- PIN_NUMBER(4, 17), PIN_NUMBER(2, 16), PIN_NUMBER(3, 16),
- PIN_NUMBER(4, 16),
- 42, 43, PIN_NUMBER(2, 15), PIN_NUMBER(3, 15),
- PIN_NUMBER(4, 15), PIN_NUMBER(2, 14), PIN_NUMBER(3, 14),
- PIN_NUMBER(4, 14),
+ 40, 41, PIN_LCD3_G2, PIN_LCD3_G3,
+ PIN_LCD3_G4, PIN_LCD3_G5, PIN_LCD3_G6, PIN_LCD3_G7,
+ 42, 43, PIN_LCD3_B2, PIN_LCD3_B3,
+ PIN_LCD3_B4, PIN_LCD3_B5, PIN_LCD3_B6, PIN_LCD3_B7,
};
static const unsigned int yuv3_mux[] = {
YUV3_CLK_O_MARK, YUV3_HS_MARK, YUV3_VS_MARK, YUV3_DE_MARK,
@@ -972,12 +972,10 @@ static const unsigned int tp33_pins[] = {
/* CLK, CTRL */
38, 39,
/* TP33_DATA[0:15] */
- 40, 41, PIN_NUMBER(2, 17), PIN_NUMBER(3, 17),
- PIN_NUMBER(4, 17), PIN_NUMBER(2, 16), PIN_NUMBER(3, 16),
- PIN_NUMBER(4, 16),
- 42, 43, PIN_NUMBER(2, 15), PIN_NUMBER(3, 15),
- PIN_NUMBER(4, 15), PIN_NUMBER(2, 14), PIN_NUMBER(3, 14),
- PIN_NUMBER(4, 14),
+ 40, 41, PIN_LCD3_G2, PIN_LCD3_G3,
+ PIN_LCD3_G4, PIN_LCD3_G5, PIN_LCD3_G6, PIN_LCD3_G7,
+ 42, 43, PIN_LCD3_B2, PIN_LCD3_B3,
+ PIN_LCD3_B4, PIN_LCD3_B5, PIN_LCD3_B6, PIN_LCD3_B7,
};
static const unsigned int tp33_mux[] = {
TP33_CLK_MARK, TP33_CTRL_MARK,
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
index bf12849defdb..b21f5afe610f 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
@@ -1252,7 +1252,7 @@ static const u16 pinmux_data[] = {
#define __O (SH_PFC_PIN_CFG_OUTPUT)
#define __IO (SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
-#define __PUD (SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
+#define __PUD (SH_PFC_PIN_CFG_PULL_UP_DOWN)
#define R8A73A4_PIN_IO_PU_PD(pin) SH_PFC_PIN_CFG(pin, __IO | __PUD)
#define R8A73A4_PIN_O(pin) SH_PFC_PIN_CFG(pin, __O)
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
index 696a0f6fc1da..fdf1b0f09f57 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
@@ -1515,7 +1515,7 @@ static const u16 pinmux_data[] = {
#define __IO (SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
#define __PD (SH_PFC_PIN_CFG_PULL_DOWN)
#define __PU (SH_PFC_PIN_CFG_PULL_UP)
-#define __PUD (SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
+#define __PUD (SH_PFC_PIN_CFG_PULL_UP_DOWN)
#define R8A7740_PIN_I_PD(pin) SH_PFC_PIN_CFG(pin, __I | __PD)
#define R8A7740_PIN_I_PU(pin) SH_PFC_PIN_CFG(pin, __I | __PU)
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77470.c b/drivers/pinctrl/sh-pfc/pfc-r8a77470.c
index c05dc1490486..b3b116da1bb0 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77470.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77470.c
@@ -10,7 +10,7 @@
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_4(0, fn, sfx), \
PORT_GP_1(0, 4, fn, sfx), \
PORT_GP_CFG_1(0, 5, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
index 49fe52d35f30..24866a5958ae 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -22,28 +22,17 @@
#define PORT_GP_PUP_1(bank, pin, fn, sfx) \
PORT_GP_CFG_1(bank, pin, fn, sfx, SH_PFC_PIN_CFG_PULL_UP)
-#define PORT_GP_PUP_27(bank, fn, sfx) \
- PORT_GP_PUP_1(bank, 0, fn, sfx), PORT_GP_PUP_1(bank, 1, fn, sfx), \
- PORT_GP_PUP_1(bank, 2, fn, sfx), PORT_GP_PUP_1(bank, 3, fn, sfx), \
- PORT_GP_PUP_1(bank, 4, fn, sfx), PORT_GP_PUP_1(bank, 5, fn, sfx), \
- PORT_GP_PUP_1(bank, 6, fn, sfx), PORT_GP_PUP_1(bank, 7, fn, sfx), \
- PORT_GP_PUP_1(bank, 8, fn, sfx), PORT_GP_PUP_1(bank, 9, fn, sfx), \
- PORT_GP_PUP_1(bank, 10, fn, sfx), PORT_GP_PUP_1(bank, 11, fn, sfx), \
- PORT_GP_PUP_1(bank, 12, fn, sfx), PORT_GP_PUP_1(bank, 13, fn, sfx), \
- PORT_GP_PUP_1(bank, 14, fn, sfx), PORT_GP_PUP_1(bank, 15, fn, sfx), \
- PORT_GP_PUP_1(bank, 16, fn, sfx), PORT_GP_PUP_1(bank, 17, fn, sfx), \
- PORT_GP_PUP_1(bank, 18, fn, sfx), PORT_GP_PUP_1(bank, 19, fn, sfx), \
- PORT_GP_PUP_1(bank, 20, fn, sfx), PORT_GP_PUP_1(bank, 21, fn, sfx), \
- PORT_GP_PUP_1(bank, 22, fn, sfx), PORT_GP_PUP_1(bank, 23, fn, sfx), \
- PORT_GP_PUP_1(bank, 24, fn, sfx), PORT_GP_PUP_1(bank, 25, fn, sfx), \
- PORT_GP_PUP_1(bank, 26, fn, sfx)
-
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_32(0, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
PORT_GP_CFG_32(1, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
PORT_GP_CFG_32(2, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
PORT_GP_CFG_32(3, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \
- PORT_GP_PUP_27(4, fn, sfx)
+ PORT_GP_CFG_27(4, fn, sfx, SH_PFC_PIN_CFG_PULL_UP)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP(CLKOUT, "B25", fn), \
+ PIN_NOGP(CS0, "A20", fn), \
+ PIN_NOGP(CS1_A26, "C20", fn)
enum {
PINMUX_RESERVED = 0,
@@ -1253,19 +1242,17 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_MSEL(IP10_24_22, CAN_CLK_C, SEL_CANCLK_C),
};
-/* Pin numbers for pins without a corresponding GPIO port number are computed
- * from the row and column numbers with a 1000 offset to avoid collisions with
- * GPIO port numbers.
+/*
+ * Pins not associated with a GPIO port.
*/
-#define PIN_NUMBER(row, col) (1000+((row)-1)*25+(col)-1)
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /* Pins not associated with a GPIO port */
- SH_PFC_PIN_NAMED(3, 20, C20),
- SH_PFC_PIN_NAMED(1, 20, A20),
- SH_PFC_PIN_NAMED(2, 25, B25),
+ PINMUX_NOGP_ALL(),
};
/* - macro */
@@ -1400,7 +1387,7 @@ HSPI_PFC_DAT(hspi1_a, HSPI_CLK1_A, HSPI_CS1_A,
HSPI_RX1_A, HSPI_TX1_A);
HSPI_PFC_PIN(hspi1_b, RCAR_GP_PIN(0, 27), RCAR_GP_PIN(0, 26),
- PIN_NUMBER(1, 20), PIN_NUMBER(2, 25));
+ PIN_CS0, PIN_CLKOUT);
HSPI_PFC_DAT(hspi1_b, HSPI_CLK1_B, HSPI_CS1_B,
HSPI_RX1_B, HSPI_TX1_B);
@@ -1426,7 +1413,7 @@ I2C_PFC_PIN(i2c1_b, RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 18));
I2C_PFC_MUX(i2c1_b, SDA1_B, SCL1_B);
/* - I2C2 ------------------------------------------------------------------ */
-I2C_PFC_PIN(i2c2_a, PIN_NUMBER(3, 20), RCAR_GP_PIN(1, 3));
+I2C_PFC_PIN(i2c2_a, PIN_CS1_A26, RCAR_GP_PIN(1, 3));
I2C_PFC_MUX(i2c2_a, SDA2_A, SCL2_A);
I2C_PFC_PIN(i2c2_b, RCAR_GP_PIN(0, 3), RCAR_GP_PIN(0, 4));
I2C_PFC_MUX(i2c2_b, SDA2_B, SCL2_B);
@@ -1516,7 +1503,7 @@ SCIF_PFC_PIN(scif2_data_e, RCAR_GP_PIN(0, 3), RCAR_GP_PIN(0, 4));
SCIF_PFC_DAT(scif2_data_e, TX2_E, RX2_E);
SCIF_PFC_PIN(scif2_clk_a, RCAR_GP_PIN(3, 9));
SCIF_PFC_CLK(scif2_clk_a, SCK2_A);
-SCIF_PFC_PIN(scif2_clk_b, PIN_NUMBER(3, 20));
+SCIF_PFC_PIN(scif2_clk_b, PIN_CS1_A26);
SCIF_PFC_CLK(scif2_clk_b, SCK2_B);
SCIF_PFC_PIN(scif2_clk_c, RCAR_GP_PIN(4, 12));
SCIF_PFC_CLK(scif2_clk_c, SCK2_C);
@@ -1631,7 +1618,7 @@ SSI_PFC_PINS(ssi0_data, RCAR_GP_PIN(3, 10));
SSI_PFC_DATA(ssi0_data, SSI_SDATA0);
SSI_PFC_PINS(ssi1_a_ctrl, RCAR_GP_PIN(2, 20), RCAR_GP_PIN(2, 21));
SSI_PFC_CTRL(ssi1_a_ctrl, SSI_SCK1_A, SSI_WS1_A);
-SSI_PFC_PINS(ssi1_b_ctrl, PIN_NUMBER(3, 20), RCAR_GP_PIN(1, 3));
+SSI_PFC_PINS(ssi1_b_ctrl, PIN_CS1_A26, RCAR_GP_PIN(1, 3));
SSI_PFC_CTRL(ssi1_b_ctrl, SSI_SCK1_B, SSI_WS1_B);
SSI_PFC_PINS(ssi1_data, RCAR_GP_PIN(3, 9));
SSI_PFC_DATA(ssi1_data, SSI_SDATA1);
@@ -2921,8 +2908,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
{ },
};
-#define PIN_NONE U16_MAX
-
static const struct pinmux_bias_reg pinmux_bias_regs[] = {
{ PINMUX_BIAS_REG("PUPR0", 0x100, "N/A", 0) {
[ 0] = RCAR_GP_PIN(0, 6), /* A0 */
@@ -2969,28 +2954,28 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 7] = RCAR_GP_PIN(1, 10), /* DACK0 */
[ 8] = RCAR_GP_PIN(1, 12), /* IRQ0 */
[ 9] = RCAR_GP_PIN(1, 13), /* IRQ1 */
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NONE,
- [16] = PIN_NONE,
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
- [30] = PIN_NONE,
- [31] = PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
} },
{ PINMUX_BIAS_REG("PUPR2", 0x108, "N/A", 0) {
[ 0] = RCAR_GP_PIN(1, 22), /* DU0_DR0 */
@@ -3112,21 +3097,21 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[14] = RCAR_GP_PIN(4, 20), /* ETH_MAGIC */
[15] = RCAR_GP_PIN(4, 25), /* AVS1 */
[16] = RCAR_GP_PIN(4, 26), /* AVS2 */
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
- [30] = PIN_NONE,
- [31] = PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
} },
{ /* sentinel */ },
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
index 0c121b28ec3f..3e47cdc1411d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
@@ -11,7 +11,7 @@
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index c41a6761cf9d..3366ed561cce 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -20,7 +20,7 @@
* All pins assigned to GPIO bank 3 can be used for SD interfaces in
* which case they support both 3.3V and 1.8V signalling.
*/
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_30(1, fn, sfx), \
PORT_GP_30(2, fn, sfx), \
@@ -28,6 +28,12 @@
PORT_GP_32(4, fn, sfx), \
PORT_GP_32(5, fn, sfx)
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP(IIC0_SDA, "AF15", fn), \
+ PIN_NOGP(IIC0_SCL, "AG15", fn), \
+ PIN_NOGP(IIC3_SDA, "AH15", fn), \
+ PIN_NOGP(IIC3_SCL, "AJ15", fn)
+
enum {
PINMUX_RESERVED = 0,
@@ -1727,19 +1733,17 @@ static const u16 pinmux_data[] = {
PINMUX_DATA(I2C3_SDA_MARK, FN_SEL_IICDVFS_1),
};
-/* R8A7790 has 6 banks with 32 GPIOs in each = 192 GPIOs */
-#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
-#define PIN_NUMBER(r, c) (((r) - 'A') * 31 + (c) + 200)
-#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
+/*
+ * Pins not associated with a GPIO port.
+ */
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /* Pins not associated with a GPIO port */
- SH_PFC_PIN_NAMED(ROW_GROUP_A('F'), 15, AF15),
- SH_PFC_PIN_NAMED(ROW_GROUP_A('G'), 15, AG15),
- SH_PFC_PIN_NAMED(ROW_GROUP_A('H'), 15, AH15),
- SH_PFC_PIN_NAMED(ROW_GROUP_A('J'), 15, AJ15),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -2135,7 +2139,7 @@ static const unsigned int hscif1_ctrl_b_mux[] = {
/* - I2C0 ------------------------------------------------------------------- */
static const unsigned int i2c0_pins[] = {
/* SCL, SDA */
- PIN_A_NUMBER('G', 15), PIN_A_NUMBER('F', 15),
+ PIN_IIC0_SCL, PIN_IIC0_SDA,
};
static const unsigned int i2c0_mux[] = {
I2C0_SCL_MARK, I2C0_SDA_MARK,
@@ -2201,7 +2205,7 @@ static const unsigned int i2c2_e_mux[] = {
/* - I2C3 ------------------------------------------------------------------- */
static const unsigned int i2c3_pins[] = {
/* SCL, SDA */
- PIN_A_NUMBER('J', 15), PIN_A_NUMBER('H', 15),
+ PIN_IIC3_SCL, PIN_IIC3_SDA,
};
static const unsigned int i2c3_mux[] = {
I2C3_SCL_MARK, I2C3_SDA_MARK,
@@ -2209,7 +2213,7 @@ static const unsigned int i2c3_mux[] = {
/* - IIC0 (I2C4) ------------------------------------------------------------ */
static const unsigned int iic0_pins[] = {
/* SCL, SDA */
- PIN_A_NUMBER('G', 15), PIN_A_NUMBER('F', 15),
+ PIN_IIC0_SCL, PIN_IIC0_SDA,
};
static const unsigned int iic0_mux[] = {
IIC0_SCL_MARK, IIC0_SDA_MARK,
@@ -2274,8 +2278,8 @@ static const unsigned int iic2_e_mux[] = {
};
/* - IIC3 (I2C7) ------------------------------------------------------------ */
static const unsigned int iic3_pins[] = {
-/* SCL, SDA */
- PIN_A_NUMBER('J', 15), PIN_A_NUMBER('H', 15),
+ /* SCL, SDA */
+ PIN_IIC3_SCL, PIN_IIC3_SDA,
};
static const unsigned int iic3_mux[] = {
IIC3_SCL_MARK, IIC3_SDA_MARK,
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 1292ec8d268f..bc9caf812fc1 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -15,7 +15,7 @@
* Pins 0-23 assigned to GPIO bank 6 can be used for SD interfaces in
* which case they support both 3.3V and 1.8V signalling.
*/
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_26(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7792.c b/drivers/pinctrl/sh-pfc/pfc-r8a7792.c
index bbace1478613..258f82fb31c0 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7792.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7792.c
@@ -11,7 +11,7 @@
#include "core.h"
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_29(0, fn, sfx), \
PORT_GP_23(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
index 1ff4969d8381..34481b6c4328 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
@@ -14,7 +14,7 @@
#include "core.h"
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_26(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c
index f16dfbad3f17..95f9aae3bfba 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c
@@ -11,11 +11,9 @@
#include "core.h"
#include "sh_pfc.h"
-#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | \
- SH_PFC_PIN_CFG_PULL_UP | \
- SH_PFC_PIN_CFG_PULL_DOWN)
+#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_16(0, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_28(1, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_15(2, fn, sfx, CFG_FLAGS), \
@@ -28,6 +26,53 @@
PORT_GP_CFG_26(5, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_32(6, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_4(7, fn, sfx, CFG_FLAGS)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(ASEBRK, "ASEBRK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_MDIO, "AVB_MDIO", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD0, "AVB_RD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD1, "AVB_RD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD2, "AVB_RD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD3, "AVB_RD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RXC, "AVB_RXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RX_CTL, "AVB_RX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD0, "AVB_TD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD1, "AVB_TD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD2, "AVB_TD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD3, "AVB_TD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXC, "AVB_TXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXCREFCLK, "AVB_TXCREFCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TX_CTL, "AVB_TX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(CLKOUT, "CLKOUT", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN0, "DU_DOTCLKIN0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN1, "DU_DOTCLKIN1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN2, "DU_DOTCLKIN2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN3, "DU_DOTCLKIN3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(EXTALR, "EXTALR", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN),\
+ PIN_NOGP_CFG(FSCLKST_N, "FSCLKST#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO2, "QSPI0_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO3, "QSPI0_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MISO_IO1, "QSPI0_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MOSI_IO0, "QSPI0_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SPCLK, "QSPI0_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SSL, "QSPI0_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO2, "QSPI1_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO3, "QSPI1_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MISO_IO1, "QSPI1_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDO, "TDO", fn, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TRST_N, "TRST#", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
/*
* F_() : just information
* FM() : macro for FN_xxx / xxx_MARK
@@ -1447,69 +1492,16 @@ static const u16 pinmux_data[] = {
};
/*
- * R8A7795 has 8 banks with 32 GPIOs in each => 256 GPIOs.
- * Physical layout rows: A - AW, cols: 1 - 39.
+ * Pins not associated with a GPIO port.
*/
-#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
-#define PIN_NUMBER(r, c) (((r) - 'A') * 39 + (c) + 300)
-#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
-#define PIN_NONE U16_MAX
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /*
- * Pins not associated with a GPIO port.
- *
- * The pin positions are different between different r8a7795
- * packages, all that is needed for the pfc driver is a unique
- * number for each pin. To this end use the pin layout from
- * R-Car H3SiP to calculate a unique number for each pin.
- */
- SH_PFC_PIN_NAMED_CFG('A', 8, AVB_TX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 9, AVB_MDIO, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 12, AVB_TXCREFCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 13, AVB_RD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 14, AVB_RD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 16, AVB_RX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 17, AVB_TD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 18, AVB_TD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 19, AVB_TXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 13, AVB_RD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 14, AVB_RD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 17, AVB_TD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 18, AVB_TD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 19, AVB_RXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('C', 1, PRESETOUT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('F', 1, CLKOUT, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('H', 37, MLB_REF, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 3, QSPI1_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 5, QSPI1_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 6, RPC_WP#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 7, RPC_RESET#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('W', 3, QSPI0_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 3, QSPI0_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 6, QSPI0_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 7, RPC_INT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 4, QSPI0_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 6, QSPI0_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 3, QSPI1_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 5, QSPI0_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 7, QSPI1_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 38, FSCLKST#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 39, EXTALR, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 4, QSPI1_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 5, QSPI1_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 7, DU_DOTCLKIN0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 8, DU_DOTCLKIN1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 7, DU_DOTCLKIN2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 8, DU_DOTCLKIN3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 26, TRST#, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 29, TDI, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 30, TMS, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 27, TCK, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 28, TDO, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 30, ASEBRK, CFG_FLAGS),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -1658,7 +1650,7 @@ static const unsigned int avb_phy_int_mux[] = {
};
static const unsigned int avb_mdio_pins[] = {
/* AVB_MDC, AVB_MDIO */
- RCAR_GP_PIN(2, 9), PIN_NUMBER('A', 9),
+ RCAR_GP_PIN(2, 9), PIN_AVB_MDIO,
};
static const unsigned int avb_mdio_mux[] = {
AVB_MDC_MARK, AVB_MDIO_MARK,
@@ -1671,11 +1663,11 @@ static const unsigned int avb_mii_pins[] = {
* AVB_RD1, AVB_RD2, AVB_RD3,
* AVB_TXCREFCLK
*/
- PIN_NUMBER('A', 8), PIN_NUMBER('A', 19), PIN_NUMBER('A', 18),
- PIN_NUMBER('B', 18), PIN_NUMBER('A', 17), PIN_NUMBER('B', 17),
- PIN_NUMBER('A', 16), PIN_NUMBER('B', 19), PIN_NUMBER('A', 13),
- PIN_NUMBER('B', 13), PIN_NUMBER('A', 14), PIN_NUMBER('B', 14),
- PIN_NUMBER('A', 12),
+ PIN_AVB_TX_CTL, PIN_AVB_TXC, PIN_AVB_TD0,
+ PIN_AVB_TD1, PIN_AVB_TD2, PIN_AVB_TD3,
+ PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
+ PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
+ PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
@@ -3137,22 +3129,21 @@ static const unsigned int pwm6_b_mux[] = {
/* - QSPI0 ------------------------------------------------------------------ */
static const unsigned int qspi0_ctrl_pins[] = {
/* QSPI0_SPCLK, QSPI0_SSL */
- PIN_NUMBER('W', 3), PIN_NUMBER('Y', 3),
+ PIN_QSPI0_SPCLK, PIN_QSPI0_SSL,
};
static const unsigned int qspi0_ctrl_mux[] = {
QSPI0_SPCLK_MARK, QSPI0_SSL_MARK,
};
static const unsigned int qspi0_data2_pins[] = {
/* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */
- PIN_A_NUMBER('C', 5), PIN_A_NUMBER('B', 4),
+ PIN_QSPI0_MOSI_IO0, PIN_QSPI0_MISO_IO1,
};
static const unsigned int qspi0_data2_mux[] = {
QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
};
static const unsigned int qspi0_data4_pins[] = {
/* QSPI0_MOSI_IO0, QSPI0_MISO_IO1, QSPI0_IO2, QSPI0_IO3 */
- PIN_A_NUMBER('C', 5), PIN_A_NUMBER('B', 4),
- PIN_NUMBER('Y', 6), PIN_A_NUMBER('B', 6),
+ PIN_QSPI0_MOSI_IO0, PIN_QSPI0_MISO_IO1, PIN_QSPI0_IO2, PIN_QSPI0_IO3,
};
static const unsigned int qspi0_data4_mux[] = {
QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
@@ -3161,22 +3152,21 @@ static const unsigned int qspi0_data4_mux[] = {
/* - QSPI1 ------------------------------------------------------------------ */
static const unsigned int qspi1_ctrl_pins[] = {
/* QSPI1_SPCLK, QSPI1_SSL */
- PIN_NUMBER('V', 3), PIN_NUMBER('V', 5),
+ PIN_QSPI1_SPCLK, PIN_QSPI1_SSL,
};
static const unsigned int qspi1_ctrl_mux[] = {
QSPI1_SPCLK_MARK, QSPI1_SSL_MARK,
};
static const unsigned int qspi1_data2_pins[] = {
/* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */
- PIN_A_NUMBER('C', 7), PIN_A_NUMBER('E', 5),
+ PIN_QSPI1_MOSI_IO0, PIN_QSPI1_MISO_IO1,
};
static const unsigned int qspi1_data2_mux[] = {
QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
};
static const unsigned int qspi1_data4_pins[] = {
/* QSPI1_MOSI_IO0, QSPI1_MISO_IO1, QSPI1_IO2, QSPI1_IO3 */
- PIN_A_NUMBER('C', 7), PIN_A_NUMBER('E', 5),
- PIN_A_NUMBER('E', 4), PIN_A_NUMBER('C', 3),
+ PIN_QSPI1_MOSI_IO0, PIN_QSPI1_MISO_IO1, PIN_QSPI1_IO2, PIN_QSPI1_IO3,
};
static const unsigned int qspi1_data4_mux[] = {
QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
@@ -3812,6 +3802,36 @@ static const unsigned int tmu_tclk2_b_mux[] = {
TCLK2_B_MARK,
};
+/* - TPU ------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ /* TPU0TO0 */
+ RCAR_GP_PIN(6, 28),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPU0TO0_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ /* TPU0TO1 */
+ RCAR_GP_PIN(6, 29),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPU0TO1_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ /* TPU0TO2 */
+ RCAR_GP_PIN(6, 30),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPU0TO2_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ /* TPU0TO3 */
+ RCAR_GP_PIN(6, 31),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPU0TO3_MARK,
+};
+
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
/* PWEN, OVC */
@@ -4165,6 +4185,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
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(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),
SH_PFC_PIN_GROUP(usb2),
@@ -4635,6 +4659,13 @@ static const char * const tmu_groups[] = {
"tmu_tclk2_b",
};
+static const char * const tpu_groups[] = {
+ "tpu_to0",
+ "tpu_to1",
+ "tpu_to2",
+ "tpu_to3",
+};
+
static const char * const usb0_groups[] = {
"usb0",
};
@@ -4707,6 +4738,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(sdhi3),
SH_PFC_FUNCTION(ssi),
SH_PFC_FUNCTION(tmu),
+ SH_PFC_FUNCTION(tpu),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb2),
@@ -5272,44 +5304,44 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ PINMUX_DRIVE_REG("DRVCTRL0", 0xe6060300) {
- { PIN_NUMBER('W', 3), 28, 2 }, /* QSPI0_SPCLK */
- { PIN_A_NUMBER('C', 5), 24, 2 }, /* QSPI0_MOSI_IO0 */
- { PIN_A_NUMBER('B', 4), 20, 2 }, /* QSPI0_MISO_IO1 */
- { PIN_NUMBER('Y', 6), 16, 2 }, /* QSPI0_IO2 */
- { PIN_A_NUMBER('B', 6), 12, 2 }, /* QSPI0_IO3 */
- { PIN_NUMBER('Y', 3), 8, 2 }, /* QSPI0_SSL */
- { PIN_NUMBER('V', 3), 4, 2 }, /* QSPI1_SPCLK */
- { PIN_A_NUMBER('C', 7), 0, 2 }, /* QSPI1_MOSI_IO0 */
+ { PIN_QSPI0_SPCLK, 28, 2 }, /* QSPI0_SPCLK */
+ { PIN_QSPI0_MOSI_IO0, 24, 2 }, /* QSPI0_MOSI_IO0 */
+ { PIN_QSPI0_MISO_IO1, 20, 2 }, /* QSPI0_MISO_IO1 */
+ { PIN_QSPI0_IO2, 16, 2 }, /* QSPI0_IO2 */
+ { PIN_QSPI0_IO3, 12, 2 }, /* QSPI0_IO3 */
+ { PIN_QSPI0_SSL, 8, 2 }, /* QSPI0_SSL */
+ { PIN_QSPI1_SPCLK, 4, 2 }, /* QSPI1_SPCLK */
+ { PIN_QSPI1_MOSI_IO0, 0, 2 }, /* QSPI1_MOSI_IO0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL1", 0xe6060304) {
- { PIN_A_NUMBER('E', 5), 28, 2 }, /* QSPI1_MISO_IO1 */
- { PIN_A_NUMBER('E', 4), 24, 2 }, /* QSPI1_IO2 */
- { PIN_A_NUMBER('C', 3), 20, 2 }, /* QSPI1_IO3 */
- { PIN_NUMBER('V', 5), 16, 2 }, /* QSPI1_SSL */
- { PIN_NUMBER('Y', 7), 12, 2 }, /* RPC_INT# */
- { PIN_NUMBER('V', 6), 8, 2 }, /* RPC_WP# */
- { PIN_NUMBER('V', 7), 4, 2 }, /* RPC_RESET# */
- { PIN_NUMBER('A', 16), 0, 3 }, /* AVB_RX_CTL */
+ { PIN_QSPI1_MISO_IO1, 28, 2 }, /* QSPI1_MISO_IO1 */
+ { PIN_QSPI1_IO2, 24, 2 }, /* QSPI1_IO2 */
+ { PIN_QSPI1_IO3, 20, 2 }, /* QSPI1_IO3 */
+ { PIN_QSPI1_SSL, 16, 2 }, /* QSPI1_SSL */
+ { PIN_RPC_INT_N, 12, 2 }, /* RPC_INT# */
+ { PIN_RPC_WP_N, 8, 2 }, /* RPC_WP# */
+ { PIN_RPC_RESET_N, 4, 2 }, /* RPC_RESET# */
+ { PIN_AVB_RX_CTL, 0, 3 }, /* AVB_RX_CTL */
} },
{ PINMUX_DRIVE_REG("DRVCTRL2", 0xe6060308) {
- { PIN_NUMBER('B', 19), 28, 3 }, /* AVB_RXC */
- { PIN_NUMBER('A', 13), 24, 3 }, /* AVB_RD0 */
- { PIN_NUMBER('B', 13), 20, 3 }, /* AVB_RD1 */
- { PIN_NUMBER('A', 14), 16, 3 }, /* AVB_RD2 */
- { PIN_NUMBER('B', 14), 12, 3 }, /* AVB_RD3 */
- { PIN_NUMBER('A', 8), 8, 3 }, /* AVB_TX_CTL */
- { PIN_NUMBER('A', 19), 4, 3 }, /* AVB_TXC */
- { PIN_NUMBER('A', 18), 0, 3 }, /* AVB_TD0 */
+ { PIN_AVB_RXC, 28, 3 }, /* AVB_RXC */
+ { PIN_AVB_RD0, 24, 3 }, /* AVB_RD0 */
+ { PIN_AVB_RD1, 20, 3 }, /* AVB_RD1 */
+ { PIN_AVB_RD2, 16, 3 }, /* AVB_RD2 */
+ { PIN_AVB_RD3, 12, 3 }, /* AVB_RD3 */
+ { PIN_AVB_TX_CTL, 8, 3 }, /* AVB_TX_CTL */
+ { PIN_AVB_TXC, 4, 3 }, /* AVB_TXC */
+ { PIN_AVB_TD0, 0, 3 }, /* AVB_TD0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) {
- { PIN_NUMBER('B', 18), 28, 3 }, /* AVB_TD1 */
- { PIN_NUMBER('A', 17), 24, 3 }, /* AVB_TD2 */
- { PIN_NUMBER('B', 17), 20, 3 }, /* AVB_TD3 */
- { PIN_NUMBER('A', 12), 16, 3 }, /* AVB_TXCREFCLK */
- { PIN_NUMBER('A', 9), 12, 3 }, /* AVB_MDIO */
- { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
- { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
- { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
+ { PIN_AVB_TD1, 28, 3 }, /* AVB_TD1 */
+ { PIN_AVB_TD2, 24, 3 }, /* AVB_TD2 */
+ { PIN_AVB_TD3, 20, 3 }, /* AVB_TD3 */
+ { PIN_AVB_TXCREFCLK, 16, 3 }, /* AVB_TXCREFCLK */
+ { PIN_AVB_MDIO, 12, 3 }, /* AVB_MDIO */
+ { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
+ { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
+ { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
} },
{ PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) {
{ RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */
@@ -5352,7 +5384,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 */
+ { PIN_CLKOUT, 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 */
@@ -5363,7 +5395,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
} },
{ PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) {
{ RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */
- { PIN_NUMBER('C', 1), 24, 3 }, /* PRESETOUT# */
+ { PIN_PRESETOUT_N, 24, 3 }, /* PRESETOUT# */
{ RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */
{ RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */
{ RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */
@@ -5382,30 +5414,30 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) {
- { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
- { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
- { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
- { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
- { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
- { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
- { PIN_A_NUMBER('P', 7), 4, 2 }, /* DU_DOTCLKIN0 */
- { PIN_A_NUMBER('P', 8), 0, 2 }, /* DU_DOTCLKIN1 */
+ { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
+ { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
+ { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
+ { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
+ { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
+ { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
+ { PIN_DU_DOTCLKIN0, 4, 2 }, /* DU_DOTCLKIN0 */
+ { PIN_DU_DOTCLKIN1, 0, 2 }, /* DU_DOTCLKIN1 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) {
- { PIN_A_NUMBER('R', 7), 28, 2 }, /* DU_DOTCLKIN2 */
- { PIN_A_NUMBER('R', 8), 24, 2 }, /* DU_DOTCLKIN3 */
- { PIN_A_NUMBER('D', 38), 20, 2 }, /* FSCLKST# */
- { PIN_A_NUMBER('R', 30), 4, 2 }, /* TMS */
+ { PIN_DU_DOTCLKIN2, 28, 2 }, /* DU_DOTCLKIN2 */
+ { PIN_DU_DOTCLKIN3, 24, 2 }, /* DU_DOTCLKIN3 */
+ { PIN_FSCLKST_N, 20, 2 }, /* FSCLKST# */
+ { PIN_TMS, 4, 2 }, /* TMS */
} },
{ PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) {
- { PIN_A_NUMBER('T', 28), 28, 2 }, /* TDO */
- { PIN_A_NUMBER('T', 30), 24, 2 }, /* ASEBRK */
- { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
- { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
- { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
- { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
- { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
- { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
+ { PIN_TDO, 28, 2 }, /* TDO */
+ { PIN_ASEBRK, 24, 2 }, /* ASEBRK */
+ { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
+ { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
+ { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
+ { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
+ { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
+ { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) {
{ RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */
@@ -5474,7 +5506,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */
{ RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */
{ RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */
- { PIN_NUMBER('H', 37), 4, 3 }, /* MLB_REF */
+ { PIN_MLB_REF, 4, 3 }, /* MLB_REF */
{ RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) {
@@ -5548,35 +5580,35 @@ static int r8a7795es1_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin,
static const struct pinmux_bias_reg pinmux_bias_regs[] = {
{ PINMUX_BIAS_REG("PUEN0", 0xe6060400, "PUD0", 0xe6060440) {
- [ 0] = PIN_NUMBER('W', 3), /* QSPI0_SPCLK */
- [ 1] = PIN_A_NUMBER('C', 5), /* QSPI0_MOSI_IO0 */
- [ 2] = PIN_A_NUMBER('B', 4), /* QSPI0_MISO_IO1 */
- [ 3] = PIN_NUMBER('Y', 6), /* QSPI0_IO2 */
- [ 4] = PIN_A_NUMBER('B', 6), /* QSPI0_IO3 */
- [ 5] = PIN_NUMBER('Y', 3), /* QSPI0_SSL */
- [ 6] = PIN_NUMBER('V', 3), /* QSPI1_SPCLK */
- [ 7] = PIN_A_NUMBER('C', 7), /* QSPI1_MOSI_IO0 */
- [ 8] = PIN_A_NUMBER('E', 5), /* QSPI1_MISO_IO1 */
- [ 9] = PIN_A_NUMBER('E', 4), /* QSPI1_IO2 */
- [10] = PIN_A_NUMBER('C', 3), /* QSPI1_IO3 */
- [11] = PIN_NUMBER('V', 5), /* QSPI1_SSL */
- [12] = PIN_NUMBER('Y', 7), /* RPC_INT# */
- [13] = PIN_NUMBER('V', 6), /* RPC_WP# */
- [14] = PIN_NUMBER('V', 7), /* RPC_RESET# */
- [15] = PIN_NUMBER('A', 16), /* AVB_RX_CTL */
- [16] = PIN_NUMBER('B', 19), /* AVB_RXC */
- [17] = PIN_NUMBER('A', 13), /* AVB_RD0 */
- [18] = PIN_NUMBER('B', 13), /* AVB_RD1 */
- [19] = PIN_NUMBER('A', 14), /* AVB_RD2 */
- [20] = PIN_NUMBER('B', 14), /* AVB_RD3 */
- [21] = PIN_NUMBER('A', 8), /* AVB_TX_CTL */
- [22] = PIN_NUMBER('A', 19), /* AVB_TXC */
- [23] = PIN_NUMBER('A', 18), /* AVB_TD0 */
- [24] = PIN_NUMBER('B', 18), /* AVB_TD1 */
- [25] = PIN_NUMBER('A', 17), /* AVB_TD2 */
- [26] = PIN_NUMBER('B', 17), /* AVB_TD3 */
- [27] = PIN_NUMBER('A', 12), /* AVB_TXCREFCLK */
- [28] = PIN_NUMBER('A', 9), /* AVB_MDIO */
+ [ 0] = PIN_QSPI0_SPCLK, /* QSPI0_SPCLK */
+ [ 1] = PIN_QSPI0_MOSI_IO0, /* QSPI0_MOSI_IO0 */
+ [ 2] = PIN_QSPI0_MISO_IO1, /* QSPI0_MISO_IO1 */
+ [ 3] = PIN_QSPI0_IO2, /* QSPI0_IO2 */
+ [ 4] = PIN_QSPI0_IO3, /* QSPI0_IO3 */
+ [ 5] = PIN_QSPI0_SSL, /* QSPI0_SSL */
+ [ 6] = PIN_QSPI1_SPCLK, /* QSPI1_SPCLK */
+ [ 7] = PIN_QSPI1_MOSI_IO0, /* QSPI1_MOSI_IO0 */
+ [ 8] = PIN_QSPI1_MISO_IO1, /* QSPI1_MISO_IO1 */
+ [ 9] = PIN_QSPI1_IO2, /* QSPI1_IO2 */
+ [10] = PIN_QSPI1_IO3, /* QSPI1_IO3 */
+ [11] = PIN_QSPI1_SSL, /* QSPI1_SSL */
+ [12] = PIN_RPC_INT_N, /* RPC_INT# */
+ [13] = PIN_RPC_WP_N, /* RPC_WP# */
+ [14] = PIN_RPC_RESET_N, /* RPC_RESET# */
+ [15] = PIN_AVB_RX_CTL, /* AVB_RX_CTL */
+ [16] = PIN_AVB_RXC, /* AVB_RXC */
+ [17] = PIN_AVB_RD0, /* AVB_RD0 */
+ [18] = PIN_AVB_RD1, /* AVB_RD1 */
+ [19] = PIN_AVB_RD2, /* AVB_RD2 */
+ [20] = PIN_AVB_RD3, /* AVB_RD3 */
+ [21] = PIN_AVB_TX_CTL, /* AVB_TX_CTL */
+ [22] = PIN_AVB_TXC, /* AVB_TXC */
+ [23] = PIN_AVB_TD0, /* AVB_TD0 */
+ [24] = PIN_AVB_TD1, /* AVB_TD1 */
+ [25] = PIN_AVB_TD2, /* AVB_TD2 */
+ [26] = PIN_AVB_TD3, /* AVB_TD3 */
+ [27] = PIN_AVB_TXCREFCLK, /* AVB_TXCREFCLK */
+ [28] = PIN_AVB_MDIO, /* AVB_MDIO */
[29] = RCAR_GP_PIN(2, 9), /* AVB_MDC */
[30] = RCAR_GP_PIN(2, 10), /* AVB_MAGIC */
[31] = RCAR_GP_PIN(2, 11), /* AVB_PHY_INT */
@@ -5616,7 +5648,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] = PIN_CLKOUT, /* CLKOUT */
[ 1] = RCAR_GP_PIN(1, 20), /* CS0_N */
[ 2] = RCAR_GP_PIN(1, 21), /* CS1_N_A26 */
[ 3] = RCAR_GP_PIN(1, 22), /* BS_N */
@@ -5625,7 +5657,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 6] = RCAR_GP_PIN(1, 25), /* WE0_N */
[ 7] = RCAR_GP_PIN(1, 26), /* WE1_N */
[ 8] = RCAR_GP_PIN(1, 27), /* EX_WAIT0_A */
- [ 9] = PIN_NUMBER('C', 1), /* PRESETOUT# */
+ [ 9] = PIN_PRESETOUT_N, /* PRESETOUT# */
[10] = RCAR_GP_PIN(0, 0), /* D0 */
[11] = RCAR_GP_PIN(0, 1), /* D1 */
[12] = RCAR_GP_PIN(0, 2), /* D2 */
@@ -5646,20 +5678,20 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[27] = RCAR_GP_PIN(7, 1), /* AVS2 */
[28] = RCAR_GP_PIN(7, 2), /* GP7_02 */
[29] = RCAR_GP_PIN(7, 3), /* GP7_03 */
- [30] = PIN_A_NUMBER('P', 7), /* DU_DOTCLKIN0 */
- [31] = PIN_A_NUMBER('P', 8), /* DU_DOTCLKIN1 */
+ [30] = PIN_DU_DOTCLKIN0, /* DU_DOTCLKIN0 */
+ [31] = PIN_DU_DOTCLKIN1, /* DU_DOTCLKIN1 */
} },
{ PINMUX_BIAS_REG("PUEN3", 0xe606040c, "PUD3", 0xe606044c) {
- [ 0] = PIN_A_NUMBER('R', 7), /* DU_DOTCLKIN2 */
- [ 1] = PIN_A_NUMBER('R', 8), /* DU_DOTCLKIN3 */
- [ 2] = PIN_A_NUMBER('D', 38), /* FSCLKST# */
- [ 3] = PIN_A_NUMBER('D', 39), /* EXTALR*/
- [ 4] = PIN_A_NUMBER('R', 26), /* TRST# */
- [ 5] = PIN_A_NUMBER('T', 27), /* TCK */
- [ 6] = PIN_A_NUMBER('R', 30), /* TMS */
- [ 7] = PIN_A_NUMBER('R', 29), /* TDI */
- [ 8] = PIN_NONE,
- [ 9] = PIN_A_NUMBER('T', 30), /* ASEBRK */
+ [ 0] = PIN_DU_DOTCLKIN2, /* DU_DOTCLKIN2 */
+ [ 1] = PIN_DU_DOTCLKIN3, /* DU_DOTCLKIN3 */
+ [ 2] = PIN_FSCLKST_N, /* FSCLKST# */
+ [ 3] = PIN_EXTALR, /* EXTALR*/
+ [ 4] = PIN_TRST_N, /* TRST# */
+ [ 5] = PIN_TCK, /* TCK */
+ [ 6] = PIN_TMS, /* TMS */
+ [ 7] = PIN_TDI, /* TDI */
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = PIN_ASEBRK, /* ASEBRK */
[10] = RCAR_GP_PIN(3, 0), /* SD0_CLK */
[11] = RCAR_GP_PIN(3, 1), /* SD0_CMD */
[12] = RCAR_GP_PIN(3, 2), /* SD0_DAT0 */
@@ -5724,7 +5756,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 3] = RCAR_GP_PIN(5, 23), /* MLB_CLK */
[ 4] = RCAR_GP_PIN(5, 24), /* MLB_SIG */
[ 5] = RCAR_GP_PIN(5, 25), /* MLB_DAT */
- [ 6] = PIN_NUMBER('H', 37), /* MLB_REF */
+ [ 6] = PIN_MLB_REF, /* MLB_REF */
[ 7] = RCAR_GP_PIN(6, 0), /* SSI_SCK01239 */
[ 8] = RCAR_GP_PIN(6, 1), /* SSI_WS01239 */
[ 9] = RCAR_GP_PIN(6, 2), /* SSI_SDATA0 */
@@ -5759,31 +5791,31 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 4] = RCAR_GP_PIN(6, 29), /* USB30_OVC */
[ 5] = RCAR_GP_PIN(6, 30), /* USB31_PWEN */
[ 6] = RCAR_GP_PIN(6, 31), /* USB31_OVC */
- [ 7] = PIN_NONE,
- [ 8] = PIN_NONE,
- [ 9] = PIN_NONE,
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NONE,
- [16] = PIN_NONE,
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
- [30] = PIN_NONE,
- [31] = PIN_NONE,
+ [ 7] = SH_PFC_PIN_NONE,
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
} },
{ /* sentinel */ },
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
index 68bcb8980b16..7df010f757b1 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
@@ -12,11 +12,9 @@
#include "core.h"
#include "sh_pfc.h"
-#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | \
- SH_PFC_PIN_CFG_PULL_UP | \
- SH_PFC_PIN_CFG_PULL_DOWN)
+#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_16(0, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_29(1, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_15(2, fn, sfx, CFG_FLAGS), \
@@ -29,6 +27,52 @@
PORT_GP_CFG_26(5, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_32(6, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_4(7, fn, sfx, CFG_FLAGS)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(ASEBRK, "ASEBRK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_MDIO, "AVB_MDIO", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD0, "AVB_RD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD1, "AVB_RD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD2, "AVB_RD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD3, "AVB_RD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RXC, "AVB_RXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RX_CTL, "AVB_RX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD0, "AVB_TD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD1, "AVB_TD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD2, "AVB_TD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD3, "AVB_TD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXC, "AVB_TXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXCREFCLK, "AVB_TXCREFCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TX_CTL, "AVB_TX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN0, "DU_DOTCLKIN0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN1, "DU_DOTCLKIN1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN2, "DU_DOTCLKIN2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN3, "DU_DOTCLKIN3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(EXTALR, "EXTALR", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN),\
+ PIN_NOGP_CFG(FSCLKST_N, "FSCLKST#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO2, "QSPI0_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO3, "QSPI0_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MISO_IO1, "QSPI0_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MOSI_IO0, "QSPI0_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SPCLK, "QSPI0_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SSL, "QSPI0_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO2, "QSPI1_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO3, "QSPI1_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MISO_IO1, "QSPI1_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDO, "TDO", fn, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TRST_N, "TRST#", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
/*
* F_() : just information
* FM() : macro for FN_xxx / xxx_MARK
@@ -1508,68 +1552,16 @@ static const u16 pinmux_data[] = {
};
/*
- * R8A7795 has 8 banks with 32 GPIOs in each => 256 GPIOs.
- * Physical layout rows: A - AW, cols: 1 - 39.
+ * Pins not associated with a GPIO port.
*/
-#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
-#define PIN_NUMBER(r, c) (((r) - 'A') * 39 + (c) + 300)
-#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
-#define PIN_NONE U16_MAX
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /*
- * Pins not associated with a GPIO port.
- *
- * The pin positions are different between different r8a7795
- * packages, all that is needed for the pfc driver is a unique
- * number for each pin. To this end use the pin layout from
- * R-Car H3SiP to calculate a unique number for each pin.
- */
- SH_PFC_PIN_NAMED_CFG('A', 8, AVB_TX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 9, AVB_MDIO, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 12, AVB_TXCREFCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 13, AVB_RD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 14, AVB_RD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 16, AVB_RX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 17, AVB_TD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 18, AVB_TD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 19, AVB_TXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 13, AVB_RD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 14, AVB_RD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 17, AVB_TD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 18, AVB_TD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 19, AVB_RXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('C', 1, PRESETOUT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('H', 37, MLB_REF, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 3, QSPI1_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 5, QSPI1_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 6, RPC_WP#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 7, RPC_RESET#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('W', 3, QSPI0_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 3, QSPI0_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 6, QSPI0_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 7, RPC_INT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 4, QSPI0_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 6, QSPI0_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 3, QSPI1_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 5, QSPI0_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 7, QSPI1_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 38, FSCLKST#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 39, EXTALR, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 4, QSPI1_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 5, QSPI1_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 7, DU_DOTCLKIN0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 8, DU_DOTCLKIN1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 7, DU_DOTCLKIN2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 8, DU_DOTCLKIN3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 26, TRST#, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 29, TDI, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 30, TMS, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 27, TCK, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 28, TDO, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 30, ASEBRK, CFG_FLAGS),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -1717,7 +1709,7 @@ static const unsigned int avb_phy_int_mux[] = {
};
static const unsigned int avb_mdio_pins[] = {
/* AVB_MDC, AVB_MDIO */
- RCAR_GP_PIN(2, 9), PIN_NUMBER('A', 9),
+ RCAR_GP_PIN(2, 9), PIN_AVB_MDIO,
};
static const unsigned int avb_mdio_mux[] = {
AVB_MDC_MARK, AVB_MDIO_MARK,
@@ -1730,11 +1722,11 @@ static const unsigned int avb_mii_pins[] = {
* AVB_RD1, AVB_RD2, AVB_RD3,
* AVB_TXCREFCLK
*/
- PIN_NUMBER('A', 8), PIN_NUMBER('A', 19), PIN_NUMBER('A', 18),
- PIN_NUMBER('B', 18), PIN_NUMBER('A', 17), PIN_NUMBER('B', 17),
- PIN_NUMBER('A', 16), PIN_NUMBER('B', 19), PIN_NUMBER('A', 13),
- PIN_NUMBER('B', 13), PIN_NUMBER('A', 14), PIN_NUMBER('B', 14),
- PIN_NUMBER('A', 12),
+ PIN_AVB_TX_CTL, PIN_AVB_TXC, PIN_AVB_TD0,
+ PIN_AVB_TD1, PIN_AVB_TD2, PIN_AVB_TD3,
+ PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
+ PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
+ PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
@@ -3901,6 +3893,36 @@ static const unsigned int tmu_tclk2_b_mux[] = {
TCLK2_B_MARK,
};
+/* - TPU ------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ /* TPU0TO0 */
+ RCAR_GP_PIN(6, 28),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPU0TO0_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ /* TPU0TO1 */
+ RCAR_GP_PIN(6, 29),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPU0TO1_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ /* TPU0TO2 */
+ RCAR_GP_PIN(6, 30),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPU0TO2_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ /* TPU0TO3 */
+ RCAR_GP_PIN(6, 31),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPU0TO3_MARK,
+};
+
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
/* PWEN, OVC */
@@ -4451,6 +4473,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
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(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),
SH_PFC_PIN_GROUP(usb2),
@@ -4946,6 +4972,13 @@ static const char * const tmu_groups[] = {
"tmu_tclk2_b",
};
+static const char * const tpu_groups[] = {
+ "tpu_to0",
+ "tpu_to1",
+ "tpu_to2",
+ "tpu_to3",
+};
+
static const char * const usb0_groups[] = {
"usb0",
};
@@ -5048,6 +5081,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(sdhi3),
SH_PFC_FUNCTION(ssi),
SH_PFC_FUNCTION(tmu),
+ SH_PFC_FUNCTION(tpu),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb2),
@@ -5623,44 +5657,44 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ PINMUX_DRIVE_REG("DRVCTRL0", 0xe6060300) {
- { PIN_NUMBER('W', 3), 28, 2 }, /* QSPI0_SPCLK */
- { PIN_A_NUMBER('C', 5), 24, 2 }, /* QSPI0_MOSI_IO0 */
- { PIN_A_NUMBER('B', 4), 20, 2 }, /* QSPI0_MISO_IO1 */
- { PIN_NUMBER('Y', 6), 16, 2 }, /* QSPI0_IO2 */
- { PIN_A_NUMBER('B', 6), 12, 2 }, /* QSPI0_IO3 */
- { PIN_NUMBER('Y', 3), 8, 2 }, /* QSPI0_SSL */
- { PIN_NUMBER('V', 3), 4, 2 }, /* QSPI1_SPCLK */
- { PIN_A_NUMBER('C', 7), 0, 2 }, /* QSPI1_MOSI_IO0 */
+ { PIN_QSPI0_SPCLK, 28, 2 }, /* QSPI0_SPCLK */
+ { PIN_QSPI0_MOSI_IO0, 24, 2 }, /* QSPI0_MOSI_IO0 */
+ { PIN_QSPI0_MISO_IO1, 20, 2 }, /* QSPI0_MISO_IO1 */
+ { PIN_QSPI0_IO2, 16, 2 }, /* QSPI0_IO2 */
+ { PIN_QSPI0_IO3, 12, 2 }, /* QSPI0_IO3 */
+ { PIN_QSPI0_SSL, 8, 2 }, /* QSPI0_SSL */
+ { PIN_QSPI1_SPCLK, 4, 2 }, /* QSPI1_SPCLK */
+ { PIN_QSPI1_MOSI_IO0, 0, 2 }, /* QSPI1_MOSI_IO0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL1", 0xe6060304) {
- { PIN_A_NUMBER('E', 5), 28, 2 }, /* QSPI1_MISO_IO1 */
- { PIN_A_NUMBER('E', 4), 24, 2 }, /* QSPI1_IO2 */
- { PIN_A_NUMBER('C', 3), 20, 2 }, /* QSPI1_IO3 */
- { PIN_NUMBER('V', 5), 16, 2 }, /* QSPI1_SSL */
- { PIN_NUMBER('Y', 7), 12, 2 }, /* RPC_INT# */
- { PIN_NUMBER('V', 6), 8, 2 }, /* RPC_WP# */
- { PIN_NUMBER('V', 7), 4, 2 }, /* RPC_RESET# */
- { PIN_NUMBER('A', 16), 0, 3 }, /* AVB_RX_CTL */
+ { PIN_QSPI1_MISO_IO1, 28, 2 }, /* QSPI1_MISO_IO1 */
+ { PIN_QSPI1_IO2, 24, 2 }, /* QSPI1_IO2 */
+ { PIN_QSPI1_IO3, 20, 2 }, /* QSPI1_IO3 */
+ { PIN_QSPI1_SSL, 16, 2 }, /* QSPI1_SSL */
+ { PIN_RPC_INT_N, 12, 2 }, /* RPC_INT# */
+ { PIN_RPC_WP_N, 8, 2 }, /* RPC_WP# */
+ { PIN_RPC_RESET_N, 4, 2 }, /* RPC_RESET# */
+ { PIN_AVB_RX_CTL, 0, 3 }, /* AVB_RX_CTL */
} },
{ PINMUX_DRIVE_REG("DRVCTRL2", 0xe6060308) {
- { PIN_NUMBER('B', 19), 28, 3 }, /* AVB_RXC */
- { PIN_NUMBER('A', 13), 24, 3 }, /* AVB_RD0 */
- { PIN_NUMBER('B', 13), 20, 3 }, /* AVB_RD1 */
- { PIN_NUMBER('A', 14), 16, 3 }, /* AVB_RD2 */
- { PIN_NUMBER('B', 14), 12, 3 }, /* AVB_RD3 */
- { PIN_NUMBER('A', 8), 8, 3 }, /* AVB_TX_CTL */
- { PIN_NUMBER('A', 19), 4, 3 }, /* AVB_TXC */
- { PIN_NUMBER('A', 18), 0, 3 }, /* AVB_TD0 */
+ { PIN_AVB_RXC, 28, 3 }, /* AVB_RXC */
+ { PIN_AVB_RD0, 24, 3 }, /* AVB_RD0 */
+ { PIN_AVB_RD1, 20, 3 }, /* AVB_RD1 */
+ { PIN_AVB_RD2, 16, 3 }, /* AVB_RD2 */
+ { PIN_AVB_RD3, 12, 3 }, /* AVB_RD3 */
+ { PIN_AVB_TX_CTL, 8, 3 }, /* AVB_TX_CTL */
+ { PIN_AVB_TXC, 4, 3 }, /* AVB_TXC */
+ { PIN_AVB_TD0, 0, 3 }, /* AVB_TD0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) {
- { PIN_NUMBER('B', 18), 28, 3 }, /* AVB_TD1 */
- { PIN_NUMBER('A', 17), 24, 3 }, /* AVB_TD2 */
- { PIN_NUMBER('B', 17), 20, 3 }, /* AVB_TD3 */
- { PIN_NUMBER('A', 12), 16, 3 }, /* AVB_TXCREFCLK */
- { PIN_NUMBER('A', 9), 12, 3 }, /* AVB_MDIO */
- { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
- { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
- { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
+ { PIN_AVB_TD1, 28, 3 }, /* AVB_TD1 */
+ { PIN_AVB_TD2, 24, 3 }, /* AVB_TD2 */
+ { PIN_AVB_TD3, 20, 3 }, /* AVB_TD3 */
+ { PIN_AVB_TXCREFCLK, 16, 3 }, /* AVB_TXCREFCLK */
+ { PIN_AVB_MDIO, 12, 3 }, /* AVB_MDIO */
+ { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
+ { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
+ { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
} },
{ PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) {
{ RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */
@@ -5714,7 +5748,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
} },
{ PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) {
{ RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */
- { PIN_NUMBER('C', 1), 24, 3 }, /* PRESETOUT# */
+ { PIN_PRESETOUT_N, 24, 3 }, /* PRESETOUT# */
{ RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */
{ RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */
{ RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */
@@ -5733,30 +5767,30 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) {
- { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
- { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
- { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
- { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
- { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
- { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
- { PIN_A_NUMBER('P', 7), 4, 2 }, /* DU_DOTCLKIN0 */
- { PIN_A_NUMBER('P', 8), 0, 2 }, /* DU_DOTCLKIN1 */
+ { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
+ { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
+ { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
+ { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
+ { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
+ { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
+ { PIN_DU_DOTCLKIN0, 4, 2 }, /* DU_DOTCLKIN0 */
+ { PIN_DU_DOTCLKIN1, 0, 2 }, /* DU_DOTCLKIN1 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) {
- { PIN_A_NUMBER('R', 7), 28, 2 }, /* DU_DOTCLKIN2 */
- { PIN_A_NUMBER('R', 8), 24, 2 }, /* DU_DOTCLKIN3 */
- { PIN_A_NUMBER('D', 38), 20, 2 }, /* FSCLKST# */
- { PIN_A_NUMBER('R', 30), 4, 2 }, /* TMS */
+ { PIN_DU_DOTCLKIN2, 28, 2 }, /* DU_DOTCLKIN2 */
+ { PIN_DU_DOTCLKIN3, 24, 2 }, /* DU_DOTCLKIN3 */
+ { PIN_FSCLKST_N, 20, 2 }, /* FSCLKST# */
+ { PIN_TMS, 4, 2 }, /* TMS */
} },
{ PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) {
- { PIN_A_NUMBER('T', 28), 28, 2 }, /* TDO */
- { PIN_A_NUMBER('T', 30), 24, 2 }, /* ASEBRK */
- { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
- { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
- { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
- { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
- { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
- { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
+ { PIN_TDO, 28, 2 }, /* TDO */
+ { PIN_ASEBRK, 24, 2 }, /* ASEBRK */
+ { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
+ { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
+ { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
+ { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
+ { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
+ { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) {
{ RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */
@@ -5825,7 +5859,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */
{ RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */
{ RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */
- { PIN_NUMBER('H', 37), 4, 3 }, /* MLB_REF */
+ { PIN_MLB_REF, 4, 3 }, /* MLB_REF */
{ RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) {
@@ -5898,35 +5932,35 @@ static int r8a7795_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *poc
static const struct pinmux_bias_reg pinmux_bias_regs[] = {
{ PINMUX_BIAS_REG("PUEN0", 0xe6060400, "PUD0", 0xe6060440) {
- [ 0] = PIN_NUMBER('W', 3), /* QSPI0_SPCLK */
- [ 1] = PIN_A_NUMBER('C', 5), /* QSPI0_MOSI_IO0 */
- [ 2] = PIN_A_NUMBER('B', 4), /* QSPI0_MISO_IO1 */
- [ 3] = PIN_NUMBER('Y', 6), /* QSPI0_IO2 */
- [ 4] = PIN_A_NUMBER('B', 6), /* QSPI0_IO3 */
- [ 5] = PIN_NUMBER('Y', 3), /* QSPI0_SSL */
- [ 6] = PIN_NUMBER('V', 3), /* QSPI1_SPCLK */
- [ 7] = PIN_A_NUMBER('C', 7), /* QSPI1_MOSI_IO0 */
- [ 8] = PIN_A_NUMBER('E', 5), /* QSPI1_MISO_IO1 */
- [ 9] = PIN_A_NUMBER('E', 4), /* QSPI1_IO2 */
- [10] = PIN_A_NUMBER('C', 3), /* QSPI1_IO3 */
- [11] = PIN_NUMBER('V', 5), /* QSPI1_SSL */
- [12] = PIN_NUMBER('Y', 7), /* RPC_INT# */
- [13] = PIN_NUMBER('V', 6), /* RPC_WP# */
- [14] = PIN_NUMBER('V', 7), /* RPC_RESET# */
- [15] = PIN_NUMBER('A', 16), /* AVB_RX_CTL */
- [16] = PIN_NUMBER('B', 19), /* AVB_RXC */
- [17] = PIN_NUMBER('A', 13), /* AVB_RD0 */
- [18] = PIN_NUMBER('B', 13), /* AVB_RD1 */
- [19] = PIN_NUMBER('A', 14), /* AVB_RD2 */
- [20] = PIN_NUMBER('B', 14), /* AVB_RD3 */
- [21] = PIN_NUMBER('A', 8), /* AVB_TX_CTL */
- [22] = PIN_NUMBER('A', 19), /* AVB_TXC */
- [23] = PIN_NUMBER('A', 18), /* AVB_TD0 */
- [24] = PIN_NUMBER('B', 18), /* AVB_TD1 */
- [25] = PIN_NUMBER('A', 17), /* AVB_TD2 */
- [26] = PIN_NUMBER('B', 17), /* AVB_TD3 */
- [27] = PIN_NUMBER('A', 12), /* AVB_TXCREFCLK */
- [28] = PIN_NUMBER('A', 9), /* AVB_MDIO */
+ [ 0] = PIN_QSPI0_SPCLK, /* QSPI0_SPCLK */
+ [ 1] = PIN_QSPI0_MOSI_IO0, /* QSPI0_MOSI_IO0 */
+ [ 2] = PIN_QSPI0_MISO_IO1, /* QSPI0_MISO_IO1 */
+ [ 3] = PIN_QSPI0_IO2, /* QSPI0_IO2 */
+ [ 4] = PIN_QSPI0_IO3, /* QSPI0_IO3 */
+ [ 5] = PIN_QSPI0_SSL, /* QSPI0_SSL */
+ [ 6] = PIN_QSPI1_SPCLK, /* QSPI1_SPCLK */
+ [ 7] = PIN_QSPI1_MOSI_IO0, /* QSPI1_MOSI_IO0 */
+ [ 8] = PIN_QSPI1_MISO_IO1, /* QSPI1_MISO_IO1 */
+ [ 9] = PIN_QSPI1_IO2, /* QSPI1_IO2 */
+ [10] = PIN_QSPI1_IO3, /* QSPI1_IO3 */
+ [11] = PIN_QSPI1_SSL, /* QSPI1_SSL */
+ [12] = PIN_RPC_INT_N, /* RPC_INT# */
+ [13] = PIN_RPC_WP_N, /* RPC_WP# */
+ [14] = PIN_RPC_RESET_N, /* RPC_RESET# */
+ [15] = PIN_AVB_RX_CTL, /* AVB_RX_CTL */
+ [16] = PIN_AVB_RXC, /* AVB_RXC */
+ [17] = PIN_AVB_RD0, /* AVB_RD0 */
+ [18] = PIN_AVB_RD1, /* AVB_RD1 */
+ [19] = PIN_AVB_RD2, /* AVB_RD2 */
+ [20] = PIN_AVB_RD3, /* AVB_RD3 */
+ [21] = PIN_AVB_TX_CTL, /* AVB_TX_CTL */
+ [22] = PIN_AVB_TXC, /* AVB_TXC */
+ [23] = PIN_AVB_TD0, /* AVB_TD0 */
+ [24] = PIN_AVB_TD1, /* AVB_TD1 */
+ [25] = PIN_AVB_TD2, /* AVB_TD2 */
+ [26] = PIN_AVB_TD3, /* AVB_TD3 */
+ [27] = PIN_AVB_TXCREFCLK, /* AVB_TXCREFCLK */
+ [28] = PIN_AVB_MDIO, /* AVB_MDIO */
[29] = RCAR_GP_PIN(2, 9), /* AVB_MDC */
[30] = RCAR_GP_PIN(2, 10), /* AVB_MAGIC */
[31] = RCAR_GP_PIN(2, 11), /* AVB_PHY_INT */
@@ -5975,7 +6009,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 6] = RCAR_GP_PIN(1, 25), /* WE0_N */
[ 7] = RCAR_GP_PIN(1, 26), /* WE1_N */
[ 8] = RCAR_GP_PIN(1, 27), /* EX_WAIT0_A */
- [ 9] = PIN_NUMBER('C', 1), /* PRESETOUT# */
+ [ 9] = PIN_PRESETOUT_N, /* PRESETOUT# */
[10] = RCAR_GP_PIN(0, 0), /* D0 */
[11] = RCAR_GP_PIN(0, 1), /* D1 */
[12] = RCAR_GP_PIN(0, 2), /* D2 */
@@ -5996,20 +6030,20 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[27] = RCAR_GP_PIN(7, 1), /* AVS2 */
[28] = RCAR_GP_PIN(7, 2), /* GP7_02 */
[29] = RCAR_GP_PIN(7, 3), /* GP7_03 */
- [30] = PIN_A_NUMBER('P', 7), /* DU_DOTCLKIN0 */
- [31] = PIN_A_NUMBER('P', 8), /* DU_DOTCLKIN1 */
+ [30] = PIN_DU_DOTCLKIN0, /* DU_DOTCLKIN0 */
+ [31] = PIN_DU_DOTCLKIN1, /* DU_DOTCLKIN1 */
} },
{ PINMUX_BIAS_REG("PUEN3", 0xe606040c, "PUD3", 0xe606044c) {
- [ 0] = PIN_A_NUMBER('R', 7), /* DU_DOTCLKIN2 */
- [ 1] = PIN_A_NUMBER('R', 8), /* DU_DOTCLKIN3 */
- [ 2] = PIN_A_NUMBER('D', 38), /* FSCLKST# */
- [ 3] = PIN_A_NUMBER('D', 39), /* EXTALR*/
- [ 4] = PIN_A_NUMBER('R', 26), /* TRST# */
- [ 5] = PIN_A_NUMBER('T', 27), /* TCK */
- [ 6] = PIN_A_NUMBER('R', 30), /* TMS */
- [ 7] = PIN_A_NUMBER('R', 29), /* TDI */
- [ 8] = PIN_NONE,
- [ 9] = PIN_A_NUMBER('T', 30), /* ASEBRK */
+ [ 0] = PIN_DU_DOTCLKIN2, /* DU_DOTCLKIN2 */
+ [ 1] = PIN_DU_DOTCLKIN3, /* DU_DOTCLKIN3 */
+ [ 2] = PIN_FSCLKST_N, /* FSCLKST# */
+ [ 3] = PIN_EXTALR, /* EXTALR*/
+ [ 4] = PIN_TRST_N, /* TRST# */
+ [ 5] = PIN_TCK, /* TCK */
+ [ 6] = PIN_TMS, /* TMS */
+ [ 7] = PIN_TDI, /* TDI */
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = PIN_ASEBRK, /* ASEBRK */
[10] = RCAR_GP_PIN(3, 0), /* SD0_CLK */
[11] = RCAR_GP_PIN(3, 1), /* SD0_CMD */
[12] = RCAR_GP_PIN(3, 2), /* SD0_DAT0 */
@@ -6074,7 +6108,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 3] = RCAR_GP_PIN(5, 23), /* MLB_CLK */
[ 4] = RCAR_GP_PIN(5, 24), /* MLB_SIG */
[ 5] = RCAR_GP_PIN(5, 25), /* MLB_DAT */
- [ 6] = PIN_NUMBER('H', 37), /* MLB_REF */
+ [ 6] = PIN_MLB_REF, /* MLB_REF */
[ 7] = RCAR_GP_PIN(6, 0), /* SSI_SCK01239 */
[ 8] = RCAR_GP_PIN(6, 1), /* SSI_WS01239 */
[ 9] = RCAR_GP_PIN(6, 2), /* SSI_SDATA0 */
@@ -6109,31 +6143,31 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 4] = RCAR_GP_PIN(6, 29), /* USB30_OVC */
[ 5] = RCAR_GP_PIN(6, 30), /* USB2_CH3_PWEN */
[ 6] = RCAR_GP_PIN(6, 31), /* USB2_CH3_OVC */
- [ 7] = PIN_NONE,
- [ 8] = PIN_NONE,
- [ 9] = PIN_NONE,
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NONE,
- [16] = PIN_NONE,
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
- [30] = PIN_NONE,
- [31] = PIN_NONE,
+ [ 7] = SH_PFC_PIN_NONE,
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
} },
{ /* sentinel */ },
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
index 38cce690db70..61db7c7a35ec 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
@@ -17,11 +17,9 @@
#include "core.h"
#include "sh_pfc.h"
-#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | \
- SH_PFC_PIN_CFG_PULL_UP | \
- SH_PFC_PIN_CFG_PULL_DOWN)
+#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_16(0, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_29(1, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_15(2, fn, sfx, CFG_FLAGS), \
@@ -34,6 +32,51 @@
PORT_GP_CFG_26(5, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_32(6, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_4(7, fn, sfx, CFG_FLAGS)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(ASEBRK, "ASEBRK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_MDIO, "AVB_MDIO", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD0, "AVB_RD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD1, "AVB_RD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD2, "AVB_RD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD3, "AVB_RD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RXC, "AVB_RXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RX_CTL, "AVB_RX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD0, "AVB_TD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD1, "AVB_TD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD2, "AVB_TD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD3, "AVB_TD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXC, "AVB_TXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXCREFCLK, "AVB_TXCREFCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TX_CTL, "AVB_TX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN0, "DU_DOTCLKIN0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN1, "DU_DOTCLKIN1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN2, "DU_DOTCLKIN2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(EXTALR, "EXTALR", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN),\
+ PIN_NOGP_CFG(FSCLKST, "FSCLKST", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO2, "QSPI0_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO3, "QSPI0_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MISO_IO1, "QSPI0_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MOSI_IO0, "QSPI0_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SPCLK, "QSPI0_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SSL, "QSPI0_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO2, "QSPI1_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO3, "QSPI1_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MISO_IO1, "QSPI1_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDO, "TDO", fn, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TRST_N, "TRST#", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
/*
* F_() : just information
* FM() : macro for FN_xxx / xxx_MARK
@@ -1512,67 +1555,16 @@ static const u16 pinmux_data[] = {
};
/*
- * R8A7796 has 8 banks with 32 GPIOs in each => 256 GPIOs.
- * Physical layout rows: A - AW, cols: 1 - 39.
+ * Pins not associated with a GPIO port.
*/
-#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
-#define PIN_NUMBER(r, c) (((r) - 'A') * 39 + (c) + 300)
-#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
-#define PIN_NONE U16_MAX
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /*
- * Pins not associated with a GPIO port.
- *
- * The pin positions are different between different r8a7796
- * packages, all that is needed for the pfc driver is a unique
- * number for each pin. To this end use the pin layout from
- * R-Car M3SiP to calculate a unique number for each pin.
- */
- SH_PFC_PIN_NAMED_CFG('A', 8, AVB_TX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 9, AVB_MDIO, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 12, AVB_TXCREFCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 13, AVB_RD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 14, AVB_RD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 16, AVB_RX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 17, AVB_TD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 18, AVB_TD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 19, AVB_TXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 13, AVB_RD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 14, AVB_RD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 17, AVB_TD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 18, AVB_TD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 19, AVB_RXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('C', 1, PRESETOUT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('H', 37, MLB_REF, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 3, QSPI1_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 5, QSPI1_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 6, RPC_WP#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 7, RPC_RESET#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('W', 3, QSPI0_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 3, QSPI0_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 6, QSPI0_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 7, RPC_INT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 4, QSPI0_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 6, QSPI0_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 3, QSPI1_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 5, QSPI0_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 7, QSPI1_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 38, FSCLKST, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 39, EXTALR, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 4, QSPI1_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 5, QSPI1_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 7, DU_DOTCLKIN0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 8, DU_DOTCLKIN1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 8, DU_DOTCLKIN2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 26, TRST#, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 29, TDI, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 30, TMS, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 27, TCK, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 28, TDO, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 30, ASEBRK, CFG_FLAGS),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -1721,7 +1713,7 @@ static const unsigned int avb_phy_int_mux[] = {
};
static const unsigned int avb_mdio_pins[] = {
/* AVB_MDC, AVB_MDIO */
- RCAR_GP_PIN(2, 9), PIN_NUMBER('A', 9),
+ RCAR_GP_PIN(2, 9), PIN_AVB_MDIO,
};
static const unsigned int avb_mdio_mux[] = {
AVB_MDC_MARK, AVB_MDIO_MARK,
@@ -1734,11 +1726,11 @@ static const unsigned int avb_mii_pins[] = {
* AVB_RD1, AVB_RD2, AVB_RD3,
* AVB_TXCREFCLK
*/
- PIN_NUMBER('A', 8), PIN_NUMBER('A', 19), PIN_NUMBER('A', 18),
- PIN_NUMBER('B', 18), PIN_NUMBER('A', 17), PIN_NUMBER('B', 17),
- PIN_NUMBER('A', 16), PIN_NUMBER('B', 19), PIN_NUMBER('A', 13),
- PIN_NUMBER('B', 13), PIN_NUMBER('A', 14), PIN_NUMBER('B', 14),
- PIN_NUMBER('A', 12),
+ PIN_AVB_TX_CTL, PIN_AVB_TXC, PIN_AVB_TD0,
+ PIN_AVB_TD1, PIN_AVB_TD2, PIN_AVB_TD3,
+ PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
+ PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
+ PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
@@ -3891,6 +3883,36 @@ static const unsigned int tmu_tclk2_b_mux[] = {
TCLK2_B_MARK,
};
+/* - TPU ------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ /* TPU0TO0 */
+ RCAR_GP_PIN(6, 28),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPU0TO0_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ /* TPU0TO1 */
+ RCAR_GP_PIN(6, 29),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPU0TO1_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ /* TPU0TO2 */
+ RCAR_GP_PIN(6, 30),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPU0TO2_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ /* TPU0TO3 */
+ RCAR_GP_PIN(6, 31),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPU0TO3_MARK,
+};
+
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
/* PWEN, OVC */
@@ -4110,7 +4132,7 @@ static const unsigned int vin5_clk_mux[] = {
};
static const struct {
- struct sh_pfc_pin_group common[312];
+ struct sh_pfc_pin_group common[316];
struct sh_pfc_pin_group automotive[30];
} pinmux_groups = {
.common = {
@@ -4397,6 +4419,10 @@ static const struct {
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(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),
SH_PFC_PIN_GROUP(usb30),
@@ -4918,6 +4944,13 @@ static const char * const tmu_groups[] = {
"tmu_tclk2_b",
};
+static const char * const tpu_groups[] = {
+ "tpu_to0",
+ "tpu_to1",
+ "tpu_to2",
+ "tpu_to3",
+};
+
static const char * const usb0_groups[] = {
"usb0",
};
@@ -4963,7 +4996,7 @@ static const char * const vin5_groups[] = {
};
static const struct {
- struct sh_pfc_function common[49];
+ struct sh_pfc_function common[50];
struct sh_pfc_function automotive[4];
} pinmux_functions = {
.common = {
@@ -5011,6 +5044,7 @@ static const struct {
SH_PFC_FUNCTION(sdhi3),
SH_PFC_FUNCTION(ssi),
SH_PFC_FUNCTION(tmu),
+ SH_PFC_FUNCTION(tpu),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb30),
@@ -5590,44 +5624,44 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ PINMUX_DRIVE_REG("DRVCTRL0", 0xe6060300) {
- { PIN_NUMBER('W', 3), 28, 2 }, /* QSPI0_SPCLK */
- { PIN_A_NUMBER('C', 5), 24, 2 }, /* QSPI0_MOSI_IO0 */
- { PIN_A_NUMBER('B', 4), 20, 2 }, /* QSPI0_MISO_IO1 */
- { PIN_NUMBER('Y', 6), 16, 2 }, /* QSPI0_IO2 */
- { PIN_A_NUMBER('B', 6), 12, 2 }, /* QSPI0_IO3 */
- { PIN_NUMBER('Y', 3), 8, 2 }, /* QSPI0_SSL */
- { PIN_NUMBER('V', 3), 4, 2 }, /* QSPI1_SPCLK */
- { PIN_A_NUMBER('C', 7), 0, 2 }, /* QSPI1_MOSI_IO0 */
+ { PIN_QSPI0_SPCLK, 28, 2 }, /* QSPI0_SPCLK */
+ { PIN_QSPI0_MOSI_IO0, 24, 2 }, /* QSPI0_MOSI_IO0 */
+ { PIN_QSPI0_MISO_IO1, 20, 2 }, /* QSPI0_MISO_IO1 */
+ { PIN_QSPI0_IO2, 16, 2 }, /* QSPI0_IO2 */
+ { PIN_QSPI0_IO3, 12, 2 }, /* QSPI0_IO3 */
+ { PIN_QSPI0_SSL, 8, 2 }, /* QSPI0_SSL */
+ { PIN_QSPI1_SPCLK, 4, 2 }, /* QSPI1_SPCLK */
+ { PIN_QSPI1_MOSI_IO0, 0, 2 }, /* QSPI1_MOSI_IO0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL1", 0xe6060304) {
- { PIN_A_NUMBER('E', 5), 28, 2 }, /* QSPI1_MISO_IO1 */
- { PIN_A_NUMBER('E', 4), 24, 2 }, /* QSPI1_IO2 */
- { PIN_A_NUMBER('C', 3), 20, 2 }, /* QSPI1_IO3 */
- { PIN_NUMBER('V', 5), 16, 2 }, /* QSPI1_SSL */
- { PIN_NUMBER('Y', 7), 12, 2 }, /* RPC_INT# */
- { PIN_NUMBER('V', 6), 8, 2 }, /* RPC_WP# */
- { PIN_NUMBER('V', 7), 4, 2 }, /* RPC_RESET# */
- { PIN_NUMBER('A', 16), 0, 3 }, /* AVB_RX_CTL */
+ { PIN_QSPI1_MISO_IO1, 28, 2 }, /* QSPI1_MISO_IO1 */
+ { PIN_QSPI1_IO2, 24, 2 }, /* QSPI1_IO2 */
+ { PIN_QSPI1_IO3, 20, 2 }, /* QSPI1_IO3 */
+ { PIN_QSPI1_SSL, 16, 2 }, /* QSPI1_SSL */
+ { PIN_RPC_INT_N, 12, 2 }, /* RPC_INT# */
+ { PIN_RPC_WP_N, 8, 2 }, /* RPC_WP# */
+ { PIN_RPC_RESET_N, 4, 2 }, /* RPC_RESET# */
+ { PIN_AVB_RX_CTL, 0, 3 }, /* AVB_RX_CTL */
} },
{ PINMUX_DRIVE_REG("DRVCTRL2", 0xe6060308) {
- { PIN_NUMBER('B', 19), 28, 3 }, /* AVB_RXC */
- { PIN_NUMBER('A', 13), 24, 3 }, /* AVB_RD0 */
- { PIN_NUMBER('B', 13), 20, 3 }, /* AVB_RD1 */
- { PIN_NUMBER('A', 14), 16, 3 }, /* AVB_RD2 */
- { PIN_NUMBER('B', 14), 12, 3 }, /* AVB_RD3 */
- { PIN_NUMBER('A', 8), 8, 3 }, /* AVB_TX_CTL */
- { PIN_NUMBER('A', 19), 4, 3 }, /* AVB_TXC */
- { PIN_NUMBER('A', 18), 0, 3 }, /* AVB_TD0 */
+ { PIN_AVB_RXC, 28, 3 }, /* AVB_RXC */
+ { PIN_AVB_RD0, 24, 3 }, /* AVB_RD0 */
+ { PIN_AVB_RD1, 20, 3 }, /* AVB_RD1 */
+ { PIN_AVB_RD2, 16, 3 }, /* AVB_RD2 */
+ { PIN_AVB_RD3, 12, 3 }, /* AVB_RD3 */
+ { PIN_AVB_TX_CTL, 8, 3 }, /* AVB_TX_CTL */
+ { PIN_AVB_TXC, 4, 3 }, /* AVB_TXC */
+ { PIN_AVB_TD0, 0, 3 }, /* AVB_TD0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) {
- { PIN_NUMBER('B', 18), 28, 3 }, /* AVB_TD1 */
- { PIN_NUMBER('A', 17), 24, 3 }, /* AVB_TD2 */
- { PIN_NUMBER('B', 17), 20, 3 }, /* AVB_TD3 */
- { PIN_NUMBER('A', 12), 16, 3 }, /* AVB_TXCREFCLK */
- { PIN_NUMBER('A', 9), 12, 3 }, /* AVB_MDIO */
- { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
- { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
- { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
+ { PIN_AVB_TD1, 28, 3 }, /* AVB_TD1 */
+ { PIN_AVB_TD2, 24, 3 }, /* AVB_TD2 */
+ { PIN_AVB_TD3, 20, 3 }, /* AVB_TD3 */
+ { PIN_AVB_TXCREFCLK, 16, 3 }, /* AVB_TXCREFCLK */
+ { PIN_AVB_MDIO, 12, 3 }, /* AVB_MDIO */
+ { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
+ { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
+ { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
} },
{ PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) {
{ RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */
@@ -5681,7 +5715,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
} },
{ PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) {
{ RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */
- { PIN_NUMBER('C', 1), 24, 3 }, /* PRESETOUT# */
+ { PIN_PRESETOUT_N, 24, 3 }, /* PRESETOUT# */
{ RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */
{ RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */
{ RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */
@@ -5700,29 +5734,29 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) {
- { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
- { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
- { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
- { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
- { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
- { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
- { PIN_A_NUMBER('P', 7), 4, 2 }, /* DU_DOTCLKIN0 */
- { PIN_A_NUMBER('P', 8), 0, 2 }, /* DU_DOTCLKIN1 */
+ { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
+ { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
+ { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
+ { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
+ { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
+ { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
+ { PIN_DU_DOTCLKIN0, 4, 2 }, /* DU_DOTCLKIN0 */
+ { PIN_DU_DOTCLKIN1, 0, 2 }, /* DU_DOTCLKIN1 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) {
- { PIN_A_NUMBER('R', 8), 28, 2 }, /* DU_DOTCLKIN2 */
- { PIN_A_NUMBER('D', 38), 20, 2 }, /* FSCLKST */
- { PIN_A_NUMBER('R', 30), 4, 2 }, /* TMS */
+ { PIN_DU_DOTCLKIN2, 28, 2 }, /* DU_DOTCLKIN2 */
+ { PIN_FSCLKST, 20, 2 }, /* FSCLKST */
+ { PIN_TMS, 4, 2 }, /* TMS */
} },
{ PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) {
- { PIN_A_NUMBER('T', 28), 28, 2 }, /* TDO */
- { PIN_A_NUMBER('T', 30), 24, 2 }, /* ASEBRK */
- { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
- { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
- { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
- { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
- { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
- { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
+ { PIN_TDO, 28, 2 }, /* TDO */
+ { PIN_ASEBRK, 24, 2 }, /* ASEBRK */
+ { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
+ { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
+ { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
+ { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
+ { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
+ { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) {
{ RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */
@@ -5791,7 +5825,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */
{ RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */
{ RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */
- { PIN_NUMBER('H', 37), 4, 3 }, /* MLB_REF */
+ { PIN_MLB_REF, 4, 3 }, /* MLB_REF */
{ RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) {
@@ -5864,35 +5898,35 @@ static int r8a7796_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *poc
static const struct pinmux_bias_reg pinmux_bias_regs[] = {
{ PINMUX_BIAS_REG("PUEN0", 0xe6060400, "PUD0", 0xe6060440) {
- [ 0] = PIN_NUMBER('W', 3), /* QSPI0_SPCLK */
- [ 1] = PIN_A_NUMBER('C', 5), /* QSPI0_MOSI_IO0 */
- [ 2] = PIN_A_NUMBER('B', 4), /* QSPI0_MISO_IO1 */
- [ 3] = PIN_NUMBER('Y', 6), /* QSPI0_IO2 */
- [ 4] = PIN_A_NUMBER('B', 6), /* QSPI0_IO3 */
- [ 5] = PIN_NUMBER('Y', 3), /* QSPI0_SSL */
- [ 6] = PIN_NUMBER('V', 3), /* QSPI1_SPCLK */
- [ 7] = PIN_A_NUMBER('C', 7), /* QSPI1_MOSI_IO0 */
- [ 8] = PIN_A_NUMBER('E', 5), /* QSPI1_MISO_IO1 */
- [ 9] = PIN_A_NUMBER('E', 4), /* QSPI1_IO2 */
- [10] = PIN_A_NUMBER('C', 3), /* QSPI1_IO3 */
- [11] = PIN_NUMBER('V', 5), /* QSPI1_SSL */
- [12] = PIN_NUMBER('Y', 7), /* RPC_INT# */
- [13] = PIN_NUMBER('V', 6), /* RPC_WP# */
- [14] = PIN_NUMBER('V', 7), /* RPC_RESET# */
- [15] = PIN_NUMBER('A', 16), /* AVB_RX_CTL */
- [16] = PIN_NUMBER('B', 19), /* AVB_RXC */
- [17] = PIN_NUMBER('A', 13), /* AVB_RD0 */
- [18] = PIN_NUMBER('B', 13), /* AVB_RD1 */
- [19] = PIN_NUMBER('A', 14), /* AVB_RD2 */
- [20] = PIN_NUMBER('B', 14), /* AVB_RD3 */
- [21] = PIN_NUMBER('A', 8), /* AVB_TX_CTL */
- [22] = PIN_NUMBER('A', 19), /* AVB_TXC */
- [23] = PIN_NUMBER('A', 18), /* AVB_TD0 */
- [24] = PIN_NUMBER('B', 18), /* AVB_TD1 */
- [25] = PIN_NUMBER('A', 17), /* AVB_TD2 */
- [26] = PIN_NUMBER('B', 17), /* AVB_TD3 */
- [27] = PIN_NUMBER('A', 12), /* AVB_TXCREFCLK */
- [28] = PIN_NUMBER('A', 9), /* AVB_MDIO */
+ [ 0] = PIN_QSPI0_SPCLK, /* QSPI0_SPCLK */
+ [ 1] = PIN_QSPI0_MOSI_IO0, /* QSPI0_MOSI_IO0 */
+ [ 2] = PIN_QSPI0_MISO_IO1, /* QSPI0_MISO_IO1 */
+ [ 3] = PIN_QSPI0_IO2, /* QSPI0_IO2 */
+ [ 4] = PIN_QSPI0_IO3, /* QSPI0_IO3 */
+ [ 5] = PIN_QSPI0_SSL, /* QSPI0_SSL */
+ [ 6] = PIN_QSPI1_SPCLK, /* QSPI1_SPCLK */
+ [ 7] = PIN_QSPI1_MOSI_IO0, /* QSPI1_MOSI_IO0 */
+ [ 8] = PIN_QSPI1_MISO_IO1, /* QSPI1_MISO_IO1 */
+ [ 9] = PIN_QSPI1_IO2, /* QSPI1_IO2 */
+ [10] = PIN_QSPI1_IO3, /* QSPI1_IO3 */
+ [11] = PIN_QSPI1_SSL, /* QSPI1_SSL */
+ [12] = PIN_RPC_INT_N, /* RPC_INT# */
+ [13] = PIN_RPC_WP_N, /* RPC_WP# */
+ [14] = PIN_RPC_RESET_N, /* RPC_RESET# */
+ [15] = PIN_AVB_RX_CTL, /* AVB_RX_CTL */
+ [16] = PIN_AVB_RXC, /* AVB_RXC */
+ [17] = PIN_AVB_RD0, /* AVB_RD0 */
+ [18] = PIN_AVB_RD1, /* AVB_RD1 */
+ [19] = PIN_AVB_RD2, /* AVB_RD2 */
+ [20] = PIN_AVB_RD3, /* AVB_RD3 */
+ [21] = PIN_AVB_TX_CTL, /* AVB_TX_CTL */
+ [22] = PIN_AVB_TXC, /* AVB_TXC */
+ [23] = PIN_AVB_TD0, /* AVB_TD0 */
+ [24] = PIN_AVB_TD1, /* AVB_TD1 */
+ [25] = PIN_AVB_TD2, /* AVB_TD2 */
+ [26] = PIN_AVB_TD3, /* AVB_TD3 */
+ [27] = PIN_AVB_TXCREFCLK, /* AVB_TXCREFCLK */
+ [28] = PIN_AVB_MDIO, /* AVB_MDIO */
[29] = RCAR_GP_PIN(2, 9), /* AVB_MDC */
[30] = RCAR_GP_PIN(2, 10), /* AVB_MAGIC */
[31] = RCAR_GP_PIN(2, 11), /* AVB_PHY_INT */
@@ -5941,7 +5975,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 6] = RCAR_GP_PIN(1, 25), /* WE0_N */
[ 7] = RCAR_GP_PIN(1, 26), /* WE1_N */
[ 8] = RCAR_GP_PIN(1, 27), /* EX_WAIT0_A */
- [ 9] = PIN_NUMBER('C', 1), /* PRESETOUT# */
+ [ 9] = PIN_PRESETOUT_N, /* PRESETOUT# */
[10] = RCAR_GP_PIN(0, 0), /* D0 */
[11] = RCAR_GP_PIN(0, 1), /* D1 */
[12] = RCAR_GP_PIN(0, 2), /* D2 */
@@ -5962,20 +5996,20 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[27] = RCAR_GP_PIN(7, 1), /* AVS2 */
[28] = RCAR_GP_PIN(7, 2), /* GP7_02 */
[29] = RCAR_GP_PIN(7, 3), /* GP7_03 */
- [30] = PIN_A_NUMBER('P', 7), /* DU_DOTCLKIN0 */
- [31] = PIN_A_NUMBER('P', 8), /* DU_DOTCLKIN1 */
+ [30] = PIN_DU_DOTCLKIN0, /* DU_DOTCLKIN0 */
+ [31] = PIN_DU_DOTCLKIN1, /* DU_DOTCLKIN1 */
} },
{ PINMUX_BIAS_REG("PUEN3", 0xe606040c, "PUD3", 0xe606044c) {
- [ 0] = PIN_A_NUMBER('R', 8), /* DU_DOTCLKIN2 */
- [ 1] = PIN_NONE,
- [ 2] = PIN_A_NUMBER('D', 38), /* FSCLKST */
- [ 3] = PIN_A_NUMBER('D', 39), /* EXTALR*/
- [ 4] = PIN_A_NUMBER('R', 26), /* TRST# */
- [ 5] = PIN_A_NUMBER('T', 27), /* TCK */
- [ 6] = PIN_A_NUMBER('R', 30), /* TMS */
- [ 7] = PIN_A_NUMBER('R', 29), /* TDI */
- [ 8] = PIN_NONE,
- [ 9] = PIN_A_NUMBER('T', 30), /* ASEBRK */
+ [ 0] = PIN_DU_DOTCLKIN2, /* DU_DOTCLKIN2 */
+ [ 1] = SH_PFC_PIN_NONE,
+ [ 2] = PIN_FSCLKST, /* FSCLKST */
+ [ 3] = PIN_EXTALR, /* EXTALR*/
+ [ 4] = PIN_TRST_N, /* TRST# */
+ [ 5] = PIN_TCK, /* TCK */
+ [ 6] = PIN_TMS, /* TMS */
+ [ 7] = PIN_TDI, /* TDI */
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = PIN_ASEBRK, /* ASEBRK */
[10] = RCAR_GP_PIN(3, 0), /* SD0_CLK */
[11] = RCAR_GP_PIN(3, 1), /* SD0_CMD */
[12] = RCAR_GP_PIN(3, 2), /* SD0_DAT0 */
@@ -6040,7 +6074,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 3] = RCAR_GP_PIN(5, 23), /* MLB_CLK */
[ 4] = RCAR_GP_PIN(5, 24), /* MLB_SIG */
[ 5] = RCAR_GP_PIN(5, 25), /* MLB_DAT */
- [ 6] = PIN_NUMBER('H', 37), /* MLB_REF */
+ [ 6] = PIN_MLB_REF, /* MLB_REF */
[ 7] = RCAR_GP_PIN(6, 0), /* SSI_SCK01239 */
[ 8] = RCAR_GP_PIN(6, 1), /* SSI_WS01239 */
[ 9] = RCAR_GP_PIN(6, 2), /* SSI_SDATA0 */
@@ -6075,31 +6109,31 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 4] = RCAR_GP_PIN(6, 29), /* USB30_OVC */
[ 5] = RCAR_GP_PIN(6, 30), /* GP6_30 */
[ 6] = RCAR_GP_PIN(6, 31), /* GP6_31 */
- [ 7] = PIN_NONE,
- [ 8] = PIN_NONE,
- [ 9] = PIN_NONE,
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NONE,
- [16] = PIN_NONE,
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
- [30] = PIN_NONE,
- [31] = PIN_NONE,
+ [ 7] = SH_PFC_PIN_NONE,
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
} },
{ /* sentinel */ },
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77965.c b/drivers/pinctrl/sh-pfc/pfc-r8a77965.c
index 090024355eba..697c77a4ea95 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77965.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77965.c
@@ -18,11 +18,9 @@
#include "core.h"
#include "sh_pfc.h"
-#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | \
- SH_PFC_PIN_CFG_PULL_UP | \
- SH_PFC_PIN_CFG_PULL_DOWN)
+#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_16(0, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_29(1, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_15(2, fn, sfx, CFG_FLAGS), \
@@ -35,6 +33,51 @@
PORT_GP_CFG_26(5, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_32(6, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_4(7, fn, sfx, CFG_FLAGS)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(ASEBRK, "ASEBRK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_MDIO, "AVB_MDIO", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD0, "AVB_RD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD1, "AVB_RD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD2, "AVB_RD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RD3, "AVB_RD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RXC, "AVB_RXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_RX_CTL, "AVB_RX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD0, "AVB_TD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD1, "AVB_TD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD2, "AVB_TD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD3, "AVB_TD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXC, "AVB_TXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXCREFCLK, "AVB_TXCREFCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TX_CTL, "AVB_TX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN0, "DU_DOTCLKIN0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN1, "DU_DOTCLKIN1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(DU_DOTCLKIN3, "DU_DOTCLKIN3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(EXTALR, "EXTALR", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN),\
+ PIN_NOGP_CFG(FSCLKST, "FSCLKST", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO2, "QSPI0_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_IO3, "QSPI0_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MISO_IO1, "QSPI0_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_MOSI_IO0, "QSPI0_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SPCLK, "QSPI0_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI0_SSL, "QSPI0_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO2, "QSPI1_IO2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_IO3, "QSPI1_IO3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MISO_IO1, "QSPI1_MISO_IO1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TDO, "TDO", fn, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
+ PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TRST_N, "TRST#", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
/*
* F_() : just information
* FM() : macro for FN_xxx / xxx_MARK
@@ -1517,67 +1560,16 @@ static const u16 pinmux_data[] = {
};
/*
- * R8A77965 has 8 banks with 32 GPIOs in each => 256 GPIOs.
- * Physical layout rows: A - AW, cols: 1 - 39.
+ * Pins not associated with a GPIO port.
*/
-#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
-#define PIN_NUMBER(r, c) (((r) - 'A') * 39 + (c) + 300)
-#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
-#define PIN_NONE U16_MAX
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /*
- * Pins not associated with a GPIO port.
- *
- * The pin positions are different between different r8a77965
- * packages, all that is needed for the pfc driver is a unique
- * number for each pin. To this end use the pin layout from
- * R-Car M3SiP to calculate a unique number for each pin.
- */
- SH_PFC_PIN_NAMED_CFG('A', 8, AVB_TX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 9, AVB_MDIO, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 12, AVB_TXCREFCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 13, AVB_RD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 14, AVB_RD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 16, AVB_RX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 17, AVB_TD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 18, AVB_TD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('A', 19, AVB_TXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 13, AVB_RD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 14, AVB_RD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 17, AVB_TD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 18, AVB_TD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('B', 19, AVB_RXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('C', 1, PRESETOUT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('H', 37, MLB_REF, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 3, QSPI1_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 5, QSPI1_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 6, RPC_WP#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('V', 7, RPC_RESET#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('W', 3, QSPI0_SPCLK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 3, QSPI0_SSL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 6, QSPI0_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('Y', 7, RPC_INT#, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 4, QSPI0_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 6, QSPI0_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 3, QSPI1_IO3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 5, QSPI0_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 7, QSPI1_MOSI_IO0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 38, FSCLKST, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 39, EXTALR, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 4, QSPI1_IO2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 5, QSPI1_MISO_IO1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 7, DU_DOTCLKIN0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 8, DU_DOTCLKIN1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 8, DU_DOTCLKIN3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 26, TRST#, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 29, TDI, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 30, TMS, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 27, TCK, SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 28, TDO, SH_PFC_PIN_CFG_DRIVE_STRENGTH),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 30, ASEBRK, CFG_FLAGS),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -1726,7 +1718,7 @@ static const unsigned int avb_phy_int_mux[] = {
};
static const unsigned int avb_mdio_pins[] = {
/* AVB_MDC, AVB_MDIO */
- RCAR_GP_PIN(2, 9), PIN_NUMBER('A', 9),
+ RCAR_GP_PIN(2, 9), PIN_AVB_MDIO,
};
static const unsigned int avb_mdio_mux[] = {
AVB_MDC_MARK, AVB_MDIO_MARK,
@@ -1739,11 +1731,11 @@ static const unsigned int avb_mii_pins[] = {
* AVB_RD1, AVB_RD2, AVB_RD3,
* AVB_TXCREFCLK
*/
- PIN_NUMBER('A', 8), PIN_NUMBER('A', 19), PIN_NUMBER('A', 18),
- PIN_NUMBER('B', 18), PIN_NUMBER('A', 17), PIN_NUMBER('B', 17),
- PIN_NUMBER('A', 16), PIN_NUMBER('B', 19), PIN_NUMBER('A', 13),
- PIN_NUMBER('B', 13), PIN_NUMBER('A', 14), PIN_NUMBER('B', 14),
- PIN_NUMBER('A', 12),
+ PIN_AVB_TX_CTL, PIN_AVB_TXC, PIN_AVB_TD0,
+ PIN_AVB_TD1, PIN_AVB_TD2, PIN_AVB_TD3,
+ PIN_AVB_RX_CTL, PIN_AVB_RXC, PIN_AVB_RD0,
+ PIN_AVB_RD1, PIN_AVB_RD2, PIN_AVB_RD3,
+ PIN_AVB_TXCREFCLK,
};
static const unsigned int avb_mii_mux[] = {
@@ -4116,6 +4108,36 @@ static const unsigned int tmu_tclk2_b_mux[] = {
TCLK2_B_MARK,
};
+/* - TPU ------------------------------------------------------------------- */
+static const unsigned int tpu_to0_pins[] = {
+ /* TPU0TO0 */
+ RCAR_GP_PIN(6, 28),
+};
+static const unsigned int tpu_to0_mux[] = {
+ TPU0TO0_MARK,
+};
+static const unsigned int tpu_to1_pins[] = {
+ /* TPU0TO1 */
+ RCAR_GP_PIN(6, 29),
+};
+static const unsigned int tpu_to1_mux[] = {
+ TPU0TO1_MARK,
+};
+static const unsigned int tpu_to2_pins[] = {
+ /* TPU0TO2 */
+ RCAR_GP_PIN(6, 30),
+};
+static const unsigned int tpu_to2_mux[] = {
+ TPU0TO2_MARK,
+};
+static const unsigned int tpu_to3_pins[] = {
+ /* TPU0TO3 */
+ RCAR_GP_PIN(6, 31),
+};
+static const unsigned int tpu_to3_mux[] = {
+ TPU0TO3_MARK,
+};
+
/* - USB0 ------------------------------------------------------------------- */
static const unsigned int usb0_pins[] = {
/* PWEN, OVC */
@@ -4672,6 +4694,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
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(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),
SH_PFC_PIN_GROUP(usb30),
@@ -5164,6 +5190,13 @@ static const char * const tmu_groups[] = {
"tmu_tclk2_b",
};
+static const char * const tpu_groups[] = {
+ "tpu_to0",
+ "tpu_to1",
+ "tpu_to2",
+ "tpu_to3",
+};
+
static const char * const usb0_groups[] = {
"usb0",
};
@@ -5258,6 +5291,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(sdhi3),
SH_PFC_FUNCTION(ssi),
SH_PFC_FUNCTION(tmu),
+ SH_PFC_FUNCTION(tpu),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb30),
@@ -5830,44 +5864,44 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ PINMUX_DRIVE_REG("DRVCTRL0", 0xe6060300) {
- { PIN_NUMBER('W', 3), 28, 2 }, /* QSPI0_SPCLK */
- { PIN_A_NUMBER('C', 5), 24, 2 }, /* QSPI0_MOSI_IO0 */
- { PIN_A_NUMBER('B', 4), 20, 2 }, /* QSPI0_MISO_IO1 */
- { PIN_NUMBER('Y', 6), 16, 2 }, /* QSPI0_IO2 */
- { PIN_A_NUMBER('B', 6), 12, 2 }, /* QSPI0_IO3 */
- { PIN_NUMBER('Y', 3), 8, 2 }, /* QSPI0_SSL */
- { PIN_NUMBER('V', 3), 4, 2 }, /* QSPI1_SPCLK */
- { PIN_A_NUMBER('C', 7), 0, 2 }, /* QSPI1_MOSI_IO0 */
+ { PIN_QSPI0_SPCLK, 28, 2 }, /* QSPI0_SPCLK */
+ { PIN_QSPI0_MOSI_IO0, 24, 2 }, /* QSPI0_MOSI_IO0 */
+ { PIN_QSPI0_MISO_IO1, 20, 2 }, /* QSPI0_MISO_IO1 */
+ { PIN_QSPI0_IO2, 16, 2 }, /* QSPI0_IO2 */
+ { PIN_QSPI0_IO3, 12, 2 }, /* QSPI0_IO3 */
+ { PIN_QSPI0_SSL, 8, 2 }, /* QSPI0_SSL */
+ { PIN_QSPI1_SPCLK, 4, 2 }, /* QSPI1_SPCLK */
+ { PIN_QSPI1_MOSI_IO0, 0, 2 }, /* QSPI1_MOSI_IO0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL1", 0xe6060304) {
- { PIN_A_NUMBER('E', 5), 28, 2 }, /* QSPI1_MISO_IO1 */
- { PIN_A_NUMBER('E', 4), 24, 2 }, /* QSPI1_IO2 */
- { PIN_A_NUMBER('C', 3), 20, 2 }, /* QSPI1_IO3 */
- { PIN_NUMBER('V', 5), 16, 2 }, /* QSPI1_SSL */
- { PIN_NUMBER('Y', 7), 12, 2 }, /* RPC_INT# */
- { PIN_NUMBER('V', 6), 8, 2 }, /* RPC_WP# */
- { PIN_NUMBER('V', 7), 4, 2 }, /* RPC_RESET# */
- { PIN_NUMBER('A', 16), 0, 3 }, /* AVB_RX_CTL */
+ { PIN_QSPI1_MISO_IO1, 28, 2 }, /* QSPI1_MISO_IO1 */
+ { PIN_QSPI1_IO2, 24, 2 }, /* QSPI1_IO2 */
+ { PIN_QSPI1_IO3, 20, 2 }, /* QSPI1_IO3 */
+ { PIN_QSPI1_SSL, 16, 2 }, /* QSPI1_SSL */
+ { PIN_RPC_INT_N, 12, 2 }, /* RPC_INT# */
+ { PIN_RPC_WP_N, 8, 2 }, /* RPC_WP# */
+ { PIN_RPC_RESET_N, 4, 2 }, /* RPC_RESET# */
+ { PIN_AVB_RX_CTL, 0, 3 }, /* AVB_RX_CTL */
} },
{ PINMUX_DRIVE_REG("DRVCTRL2", 0xe6060308) {
- { PIN_NUMBER('B', 19), 28, 3 }, /* AVB_RXC */
- { PIN_NUMBER('A', 13), 24, 3 }, /* AVB_RD0 */
- { PIN_NUMBER('B', 13), 20, 3 }, /* AVB_RD1 */
- { PIN_NUMBER('A', 14), 16, 3 }, /* AVB_RD2 */
- { PIN_NUMBER('B', 14), 12, 3 }, /* AVB_RD3 */
- { PIN_NUMBER('A', 8), 8, 3 }, /* AVB_TX_CTL */
- { PIN_NUMBER('A', 19), 4, 3 }, /* AVB_TXC */
- { PIN_NUMBER('A', 18), 0, 3 }, /* AVB_TD0 */
+ { PIN_AVB_RXC, 28, 3 }, /* AVB_RXC */
+ { PIN_AVB_RD0, 24, 3 }, /* AVB_RD0 */
+ { PIN_AVB_RD1, 20, 3 }, /* AVB_RD1 */
+ { PIN_AVB_RD2, 16, 3 }, /* AVB_RD2 */
+ { PIN_AVB_RD3, 12, 3 }, /* AVB_RD3 */
+ { PIN_AVB_TX_CTL, 8, 3 }, /* AVB_TX_CTL */
+ { PIN_AVB_TXC, 4, 3 }, /* AVB_TXC */
+ { PIN_AVB_TD0, 0, 3 }, /* AVB_TD0 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) {
- { PIN_NUMBER('B', 18), 28, 3 }, /* AVB_TD1 */
- { PIN_NUMBER('A', 17), 24, 3 }, /* AVB_TD2 */
- { PIN_NUMBER('B', 17), 20, 3 }, /* AVB_TD3 */
- { PIN_NUMBER('A', 12), 16, 3 }, /* AVB_TXCREFCLK */
- { PIN_NUMBER('A', 9), 12, 3 }, /* AVB_MDIO */
- { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
- { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
- { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
+ { PIN_AVB_TD1, 28, 3 }, /* AVB_TD1 */
+ { PIN_AVB_TD2, 24, 3 }, /* AVB_TD2 */
+ { PIN_AVB_TD3, 20, 3 }, /* AVB_TD3 */
+ { PIN_AVB_TXCREFCLK, 16, 3 }, /* AVB_TXCREFCLK */
+ { PIN_AVB_MDIO, 12, 3 }, /* AVB_MDIO */
+ { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */
+ { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */
+ { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */
} },
{ PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) {
{ RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */
@@ -5921,7 +5955,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
} },
{ PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) {
{ RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */
- { PIN_NUMBER('C', 1), 24, 3 }, /* PRESETOUT# */
+ { PIN_PRESETOUT_N, 24, 3 }, /* PRESETOUT# */
{ RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */
{ RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */
{ RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */
@@ -5940,29 +5974,29 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) {
- { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
- { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
- { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
- { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
- { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
- { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
- { PIN_A_NUMBER('P', 7), 4, 2 }, /* DU_DOTCLKIN0 */
- { PIN_A_NUMBER('P', 8), 0, 2 }, /* DU_DOTCLKIN1 */
+ { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */
+ { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */
+ { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */
+ { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */
+ { RCAR_GP_PIN(7, 2), 12, 3 }, /* GP7_02 */
+ { RCAR_GP_PIN(7, 3), 8, 3 }, /* GP7_03 */
+ { PIN_DU_DOTCLKIN0, 4, 2 }, /* DU_DOTCLKIN0 */
+ { PIN_DU_DOTCLKIN1, 0, 2 }, /* DU_DOTCLKIN1 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) {
- { PIN_A_NUMBER('R', 8), 28, 2 }, /* DU_DOTCLKIN3 */
- { PIN_A_NUMBER('D', 38), 20, 2 }, /* FSCLKST */
- { PIN_A_NUMBER('R', 30), 4, 2 }, /* TMS */
+ { PIN_DU_DOTCLKIN3, 28, 2 }, /* DU_DOTCLKIN3 */
+ { PIN_FSCLKST, 20, 2 }, /* FSCLKST */
+ { PIN_TMS, 4, 2 }, /* TMS */
} },
{ PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) {
- { PIN_A_NUMBER('T', 28), 28, 2 }, /* TDO */
- { PIN_A_NUMBER('T', 30), 24, 2 }, /* ASEBRK */
- { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
- { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
- { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
- { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
- { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
- { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
+ { PIN_TDO, 28, 2 }, /* TDO */
+ { PIN_ASEBRK, 24, 2 }, /* ASEBRK */
+ { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */
+ { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */
+ { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */
+ { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */
+ { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */
+ { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) {
{ RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */
@@ -6031,7 +6065,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = {
{ RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */
{ RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */
{ RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */
- { PIN_NUMBER('H', 37), 4, 3 }, /* MLB_REF */
+ { PIN_MLB_REF, 4, 3 }, /* MLB_REF */
{ RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */
} },
{ PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) {
@@ -6104,35 +6138,35 @@ static int r8a77965_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *po
static const struct pinmux_bias_reg pinmux_bias_regs[] = {
{ PINMUX_BIAS_REG("PUEN0", 0xe6060400, "PUD0", 0xe6060440) {
- [ 0] = PIN_NUMBER('W', 3), /* QSPI0_SPCLK */
- [ 1] = PIN_A_NUMBER('C', 5), /* QSPI0_MOSI_IO0 */
- [ 2] = PIN_A_NUMBER('B', 4), /* QSPI0_MISO_IO1 */
- [ 3] = PIN_NUMBER('Y', 6), /* QSPI0_IO2 */
- [ 4] = PIN_A_NUMBER('B', 6), /* QSPI0_IO3 */
- [ 5] = PIN_NUMBER('Y', 3), /* QSPI0_SSL */
- [ 6] = PIN_NUMBER('V', 3), /* QSPI1_SPCLK */
- [ 7] = PIN_A_NUMBER('C', 7), /* QSPI1_MOSI_IO0 */
- [ 8] = PIN_A_NUMBER('E', 5), /* QSPI1_MISO_IO1 */
- [ 9] = PIN_A_NUMBER('E', 4), /* QSPI1_IO2 */
- [10] = PIN_A_NUMBER('C', 3), /* QSPI1_IO3 */
- [11] = PIN_NUMBER('V', 5), /* QSPI1_SSL */
- [12] = PIN_NUMBER('Y', 7), /* RPC_INT# */
- [13] = PIN_NUMBER('V', 6), /* RPC_WP# */
- [14] = PIN_NUMBER('V', 7), /* RPC_RESET# */
- [15] = PIN_NUMBER('A', 16), /* AVB_RX_CTL */
- [16] = PIN_NUMBER('B', 19), /* AVB_RXC */
- [17] = PIN_NUMBER('A', 13), /* AVB_RD0 */
- [18] = PIN_NUMBER('B', 13), /* AVB_RD1 */
- [19] = PIN_NUMBER('A', 14), /* AVB_RD2 */
- [20] = PIN_NUMBER('B', 14), /* AVB_RD3 */
- [21] = PIN_NUMBER('A', 8), /* AVB_TX_CTL */
- [22] = PIN_NUMBER('A', 19), /* AVB_TXC */
- [23] = PIN_NUMBER('A', 18), /* AVB_TD0 */
- [24] = PIN_NUMBER('B', 18), /* AVB_TD1 */
- [25] = PIN_NUMBER('A', 17), /* AVB_TD2 */
- [26] = PIN_NUMBER('B', 17), /* AVB_TD3 */
- [27] = PIN_NUMBER('A', 12), /* AVB_TXCREFCLK */
- [28] = PIN_NUMBER('A', 9), /* AVB_MDIO */
+ [ 0] = PIN_QSPI0_SPCLK, /* QSPI0_SPCLK */
+ [ 1] = PIN_QSPI0_MOSI_IO0, /* QSPI0_MOSI_IO0 */
+ [ 2] = PIN_QSPI0_MISO_IO1, /* QSPI0_MISO_IO1 */
+ [ 3] = PIN_QSPI0_IO2, /* QSPI0_IO2 */
+ [ 4] = PIN_QSPI0_IO3, /* QSPI0_IO3 */
+ [ 5] = PIN_QSPI0_SSL, /* QSPI0_SSL */
+ [ 6] = PIN_QSPI1_SPCLK, /* QSPI1_SPCLK */
+ [ 7] = PIN_QSPI1_MOSI_IO0, /* QSPI1_MOSI_IO0 */
+ [ 8] = PIN_QSPI1_MISO_IO1, /* QSPI1_MISO_IO1 */
+ [ 9] = PIN_QSPI1_IO2, /* QSPI1_IO2 */
+ [10] = PIN_QSPI1_IO3, /* QSPI1_IO3 */
+ [11] = PIN_QSPI1_SSL, /* QSPI1_SSL */
+ [12] = PIN_RPC_INT_N, /* RPC_INT# */
+ [13] = PIN_RPC_WP_N, /* RPC_WP# */
+ [14] = PIN_RPC_RESET_N, /* RPC_RESET# */
+ [15] = PIN_AVB_RX_CTL, /* AVB_RX_CTL */
+ [16] = PIN_AVB_RXC, /* AVB_RXC */
+ [17] = PIN_AVB_RD0, /* AVB_RD0 */
+ [18] = PIN_AVB_RD1, /* AVB_RD1 */
+ [19] = PIN_AVB_RD2, /* AVB_RD2 */
+ [20] = PIN_AVB_RD3, /* AVB_RD3 */
+ [21] = PIN_AVB_TX_CTL, /* AVB_TX_CTL */
+ [22] = PIN_AVB_TXC, /* AVB_TXC */
+ [23] = PIN_AVB_TD0, /* AVB_TD0 */
+ [24] = PIN_AVB_TD1, /* AVB_TD1 */
+ [25] = PIN_AVB_TD2, /* AVB_TD2 */
+ [26] = PIN_AVB_TD3, /* AVB_TD3 */
+ [27] = PIN_AVB_TXCREFCLK, /* AVB_TXCREFCLK */
+ [28] = PIN_AVB_MDIO, /* AVB_MDIO */
[29] = RCAR_GP_PIN(2, 9), /* AVB_MDC */
[30] = RCAR_GP_PIN(2, 10), /* AVB_MAGIC */
[31] = RCAR_GP_PIN(2, 11), /* AVB_PHY_INT */
@@ -6181,7 +6215,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 6] = RCAR_GP_PIN(1, 25), /* WE0_N */
[ 7] = RCAR_GP_PIN(1, 26), /* WE1_N */
[ 8] = RCAR_GP_PIN(1, 27), /* EX_WAIT0_A */
- [ 9] = PIN_NUMBER('C', 1), /* PRESETOUT# */
+ [ 9] = PIN_PRESETOUT_N, /* PRESETOUT# */
[10] = RCAR_GP_PIN(0, 0), /* D0 */
[11] = RCAR_GP_PIN(0, 1), /* D1 */
[12] = RCAR_GP_PIN(0, 2), /* D2 */
@@ -6202,20 +6236,20 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[27] = RCAR_GP_PIN(7, 1), /* AVS2 */
[28] = RCAR_GP_PIN(7, 2), /* GP7_02 */
[29] = RCAR_GP_PIN(7, 3), /* GP7_03 */
- [30] = PIN_A_NUMBER('P', 7), /* DU_DOTCLKIN0 */
- [31] = PIN_A_NUMBER('P', 8), /* DU_DOTCLKIN1 */
+ [30] = PIN_DU_DOTCLKIN0, /* DU_DOTCLKIN0 */
+ [31] = PIN_DU_DOTCLKIN1, /* DU_DOTCLKIN1 */
} },
{ PINMUX_BIAS_REG("PUEN3", 0xe606040c, "PUD3", 0xe606044c) {
- [ 0] = PIN_A_NUMBER('R', 8), /* DU_DOTCLKIN3 */
- [ 1] = PIN_NONE,
- [ 2] = PIN_A_NUMBER('D', 38), /* FSCLKST */
- [ 3] = PIN_A_NUMBER('D', 39), /* EXTALR*/
- [ 4] = PIN_A_NUMBER('R', 26), /* TRST# */
- [ 5] = PIN_A_NUMBER('T', 27), /* TCK */
- [ 6] = PIN_A_NUMBER('R', 30), /* TMS */
- [ 7] = PIN_A_NUMBER('R', 29), /* TDI */
- [ 8] = PIN_NONE,
- [ 9] = PIN_A_NUMBER('T', 30), /* ASEBRK */
+ [ 0] = PIN_DU_DOTCLKIN3, /* DU_DOTCLKIN3 */
+ [ 1] = SH_PFC_PIN_NONE,
+ [ 2] = PIN_FSCLKST, /* FSCLKST */
+ [ 3] = PIN_EXTALR, /* EXTALR*/
+ [ 4] = PIN_TRST_N, /* TRST# */
+ [ 5] = PIN_TCK, /* TCK */
+ [ 6] = PIN_TMS, /* TMS */
+ [ 7] = PIN_TDI, /* TDI */
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = PIN_ASEBRK, /* ASEBRK */
[10] = RCAR_GP_PIN(3, 0), /* SD0_CLK */
[11] = RCAR_GP_PIN(3, 1), /* SD0_CMD */
[12] = RCAR_GP_PIN(3, 2), /* SD0_DAT0 */
@@ -6280,7 +6314,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 3] = RCAR_GP_PIN(5, 23), /* MLB_CLK */
[ 4] = RCAR_GP_PIN(5, 24), /* MLB_SIG */
[ 5] = RCAR_GP_PIN(5, 25), /* MLB_DAT */
- [ 6] = PIN_NUMBER('H', 37), /* MLB_REF */
+ [ 6] = PIN_MLB_REF, /* MLB_REF */
[ 7] = RCAR_GP_PIN(6, 0), /* SSI_SCK01239 */
[ 8] = RCAR_GP_PIN(6, 1), /* SSI_WS01239 */
[ 9] = RCAR_GP_PIN(6, 2), /* SSI_SDATA0 */
@@ -6315,31 +6349,31 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[ 4] = RCAR_GP_PIN(6, 29), /* USB30_OVC */
[ 5] = RCAR_GP_PIN(6, 30), /* GP6_30 */
[ 6] = RCAR_GP_PIN(6, 31), /* GP6_31 */
- [ 7] = PIN_NONE,
- [ 8] = PIN_NONE,
- [ 9] = PIN_NONE,
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NONE,
- [16] = PIN_NONE,
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
- [30] = PIN_NONE,
- [31] = PIN_NONE,
+ [ 7] = SH_PFC_PIN_NONE,
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
+ [30] = SH_PFC_PIN_NONE,
+ [31] = SH_PFC_PIN_NONE,
} },
{ /* sentinel */ },
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c
index 2d76b548b942..25e27b6bee89 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c
@@ -19,7 +19,7 @@
#include "core.h"
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
PORT_GP_28(1, fn, sfx), \
PORT_GP_CFG_17(2, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
@@ -205,8 +205,8 @@
#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) 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 IP6_31_28 FM(VI1_DATA11) FM(SCL4) FM(IRQ4) FM(D14) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(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)
@@ -631,14 +631,12 @@ static const u16 pinmux_data[] = {
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),
@@ -1121,20 +1119,6 @@ static const unsigned int mmc_ctrl_pins[] = {
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[] = {
@@ -1726,8 +1710,6 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
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),
@@ -1897,8 +1879,6 @@ static const char * const mmc_groups[] = {
"mmc_data4",
"mmc_data8",
"mmc_ctrl",
- "mmc_cd",
- "mmc_wp",
};
static const char * const msiof0_groups[] = {
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c
index 9ed4ead2dafb..14fe4032a52d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c
@@ -19,7 +19,7 @@
#include "core.h"
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
PORT_GP_28(1, fn, sfx), \
PORT_GP_CFG_30(2, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77990.c b/drivers/pinctrl/sh-pfc/pfc-r8a77990.c
index 91a837b02a36..2dfb8d9cfda1 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77990.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77990.c
@@ -17,10 +17,9 @@
#include "core.h"
#include "sh_pfc.h"
-#define CFG_FLAGS (SH_PFC_PIN_CFG_PULL_UP | \
- SH_PFC_PIN_CFG_PULL_DOWN)
+#define CFG_FLAGS (SH_PFC_PIN_CFG_PULL_UP_DOWN)
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_CFG_18(0, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_23(1, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_26(2, fn, sfx, CFG_FLAGS), \
@@ -41,6 +40,25 @@
PORT_GP_CFG_1(6, 15, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_1(6, 16, fn, sfx, CFG_FLAGS), \
PORT_GP_CFG_1(6, 17, fn, sfx, CFG_FLAGS)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(ASEBRK, "ASEBRK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_MDC, "AVB_MDC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_MDIO, "AVB_MDIO", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD0, "AVB_TD0", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD1, "AVB_TD1", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD2, "AVB_TD2", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TD3, "AVB_TD3", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TXC, "AVB_TXC", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(AVB_TX_CTL, "AVB_TX_CTL", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(FSCLKST_N, "FSCLKST_N", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT_N", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TCK, "TCK", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TDI, "TDI", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \
+ PIN_NOGP_CFG(TRST_N, "TRST_N", fn, CFG_FLAGS)
+
/*
* F_() : just information
* FM() : macro for FN_xxx / xxx_MARK
@@ -1277,41 +1295,16 @@ static const u16 pinmux_data[] = {
};
/*
- * R8A77990 has 7 banks with 32 GPIOs in each => 224 GPIOs.
- * Physical layout rows: A - AE, cols: 1 - 25.
+ * Pins not associated with a GPIO port.
*/
-#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
-#define PIN_NUMBER(r, c) (((r) - 'A') * 25 + (c) + 300)
-#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
-#define PIN_NONE U16_MAX
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
-
- /*
- * Pins not associated with a GPIO port.
- *
- * The pin positions are different between different R8A77990
- * packages, all that is needed for the pfc driver is a unique
- * number for each pin. To this end use the pin layout from
- * R8A77990 to calculate a unique number for each pin.
- */
- SH_PFC_PIN_NAMED_CFG('F', 1, TRST_N, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('F', 3, TMS, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('F', 4, TCK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('G', 2, TDI, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('G', 3, FSCLKST_N, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('H', 1, ASEBRK, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('N', 1, AVB_TXC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('N', 2, AVB_TD0, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('N', 3, AVB_TD1, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('N', 5, AVB_TD2, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('N', 6, AVB_TD3, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('P', 3, AVB_TX_CTL, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('P', 4, AVB_MDIO, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('P', 5, AVB_MDC, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG('T', 21, MLB_REF, CFG_FLAGS),
- SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 3, PRESETOUT_N, CFG_FLAGS),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------ */
@@ -5026,15 +5019,15 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[0] = RCAR_GP_PIN(2, 23), /* RD# */
[1] = RCAR_GP_PIN(2, 22), /* BS# */
[2] = RCAR_GP_PIN(2, 21), /* AVB_PHY_INT */
- [3] = PIN_NUMBER('P', 5), /* AVB_MDC */
- [4] = PIN_NUMBER('P', 4), /* AVB_MDIO */
+ [3] = PIN_AVB_MDC, /* AVB_MDC */
+ [4] = PIN_AVB_MDIO, /* AVB_MDIO */
[5] = RCAR_GP_PIN(2, 20), /* AVB_TXCREFCLK */
- [6] = PIN_NUMBER('N', 6), /* AVB_TD3 */
- [7] = PIN_NUMBER('N', 5), /* AVB_TD2 */
- [8] = PIN_NUMBER('N', 3), /* AVB_TD1 */
- [9] = PIN_NUMBER('N', 2), /* AVB_TD0 */
- [10] = PIN_NUMBER('N', 1), /* AVB_TXC */
- [11] = PIN_NUMBER('P', 3), /* AVB_TX_CTL */
+ [6] = PIN_AVB_TD3, /* AVB_TD3 */
+ [7] = PIN_AVB_TD2, /* AVB_TD2 */
+ [8] = PIN_AVB_TD1, /* AVB_TD1 */
+ [9] = PIN_AVB_TD0, /* AVB_TD0 */
+ [10] = PIN_AVB_TXC, /* AVB_TXC */
+ [11] = PIN_AVB_TX_CTL, /* AVB_TX_CTL */
[12] = RCAR_GP_PIN(2, 19), /* AVB_RD3 */
[13] = RCAR_GP_PIN(2, 18), /* AVB_RD2 */
[14] = RCAR_GP_PIN(2, 17), /* AVB_RD1 */
@@ -5085,33 +5078,33 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[25] = RCAR_GP_PIN(1, 2), /* A2 */
[26] = RCAR_GP_PIN(1, 1), /* A1 */
[27] = RCAR_GP_PIN(1, 0), /* A0 */
- [28] = PIN_NONE,
- [29] = PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
[30] = RCAR_GP_PIN(2, 25), /* PUEN_EX_WAIT0 */
[31] = RCAR_GP_PIN(2, 24), /* PUEN_RD/WR# */
} },
{ PINMUX_BIAS_REG("PUEN2", 0xe6060408, "PUD2", 0xe6060448) {
[0] = RCAR_GP_PIN(3, 1), /* SD0_CMD */
[1] = RCAR_GP_PIN(3, 0), /* SD0_CLK */
- [2] = PIN_NUMBER('H', 1), /* ASEBRK */
- [3] = PIN_NONE,
- [4] = PIN_NUMBER('G', 2), /* TDI */
- [5] = PIN_NUMBER('F', 3), /* TMS */
- [6] = PIN_NUMBER('F', 4), /* TCK */
- [7] = PIN_NUMBER('F', 1), /* TRST# */
- [8] = PIN_NONE,
- [9] = PIN_NONE,
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NUMBER('G', 3), /* FSCLKST# */
+ [2] = PIN_ASEBRK, /* ASEBRK */
+ [3] = SH_PFC_PIN_NONE,
+ [4] = PIN_TDI, /* TDI */
+ [5] = PIN_TMS, /* TMS */
+ [6] = PIN_TCK, /* TCK */
+ [7] = PIN_TRST_N, /* TRST# */
+ [8] = SH_PFC_PIN_NONE,
+ [9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = PIN_FSCLKST_N, /* FSCLKST# */
[16] = RCAR_GP_PIN(0, 17), /* SDA4 */
[17] = RCAR_GP_PIN(0, 16), /* SCL4 */
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_A_NUMBER('D', 3), /* PRESETOUT# */
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = PIN_PRESETOUT_N, /* PRESETOUT# */
[21] = RCAR_GP_PIN(0, 15), /* D15 */
[22] = RCAR_GP_PIN(0, 14), /* D14 */
[23] = RCAR_GP_PIN(0, 13), /* D13 */
@@ -5130,8 +5123,8 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[2] = RCAR_GP_PIN(5, 3), /* CTS0#_A */
[3] = RCAR_GP_PIN(5, 2), /* TX0_A */
[4] = RCAR_GP_PIN(5, 1), /* RX0_A */
- [5] = PIN_NONE,
- [6] = PIN_NONE,
+ [5] = SH_PFC_PIN_NONE,
+ [6] = SH_PFC_PIN_NONE,
[7] = RCAR_GP_PIN(3, 15), /* SD1_WP */
[8] = RCAR_GP_PIN(3, 14), /* SD1_CD */
[9] = RCAR_GP_PIN(3, 13), /* SD0_WP */
@@ -5175,7 +5168,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[13] = RCAR_GP_PIN(6, 2), /* SSI_SDATA0 */
[14] = RCAR_GP_PIN(6, 1), /* SSI_WS01239 */
[15] = RCAR_GP_PIN(6, 0), /* SSI_SCK01239 */
- [16] = PIN_NUMBER('T', 21), /* MLB_REF */
+ [16] = PIN_MLB_REF, /* MLB_REF */
[17] = RCAR_GP_PIN(5, 19), /* MLB_DAT */
[18] = RCAR_GP_PIN(5, 18), /* MLB_SIG */
[19] = RCAR_GP_PIN(5, 17), /* MLB_CLK */
@@ -5193,36 +5186,36 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
[31] = RCAR_GP_PIN(5, 5), /* RX1 */
} },
{ PINMUX_BIAS_REG("PUEN5", 0xe6060414, "PUD5", 0xe6060454) {
- [0] = PIN_NONE,
- [1] = PIN_NONE,
- [2] = PIN_NONE,
- [3] = PIN_NONE,
- [4] = PIN_NONE,
- [5] = PIN_NONE,
- [6] = PIN_NONE,
- [7] = PIN_NONE,
- [8] = PIN_NONE,
- [9] = PIN_NONE,
- [10] = PIN_NONE,
- [11] = PIN_NONE,
- [12] = PIN_NONE,
- [13] = PIN_NONE,
- [14] = PIN_NONE,
- [15] = PIN_NONE,
- [16] = PIN_NONE,
- [17] = PIN_NONE,
- [18] = PIN_NONE,
- [19] = PIN_NONE,
- [20] = PIN_NONE,
- [21] = PIN_NONE,
- [22] = PIN_NONE,
- [23] = PIN_NONE,
- [24] = PIN_NONE,
- [25] = PIN_NONE,
- [26] = PIN_NONE,
- [27] = PIN_NONE,
- [28] = PIN_NONE,
- [29] = PIN_NONE,
+ [0] = SH_PFC_PIN_NONE,
+ [1] = SH_PFC_PIN_NONE,
+ [2] = SH_PFC_PIN_NONE,
+ [3] = SH_PFC_PIN_NONE,
+ [4] = SH_PFC_PIN_NONE,
+ [5] = SH_PFC_PIN_NONE,
+ [6] = SH_PFC_PIN_NONE,
+ [7] = SH_PFC_PIN_NONE,
+ [8] = SH_PFC_PIN_NONE,
+ [9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = SH_PFC_PIN_NONE,
[30] = RCAR_GP_PIN(6, 9), /* PUEN_USB30_OVC */
[31] = RCAR_GP_PIN(6, 17), /* PUEN_USB30_PWEN */
} },
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77995.c b/drivers/pinctrl/sh-pfc/pfc-r8a77995.c
index dd87085d48cb..c10b756476b1 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a77995.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a77995.c
@@ -17,7 +17,7 @@
#include "core.h"
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_9(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index e1276d143117..afabd95105d5 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -43,6 +43,9 @@
PORT_1(288, fn, pfx##288, sfx), PORT_1(289, fn, pfx##289, sfx), \
PORT_10(290, fn, pfx##29, sfx), PORT_10(300, fn, pfx##30, sfx)
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP(A11, "F26", fn)
+
enum {
PINMUX_RESERVED = 0,
@@ -1147,7 +1150,7 @@ static const u16 pinmux_data[] = {
#define __IO (SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
#define __PD (SH_PFC_PIN_CFG_PULL_DOWN)
#define __PU (SH_PFC_PIN_CFG_PULL_UP)
-#define __PUD (SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
+#define __PUD (SH_PFC_PIN_CFG_PULL_UP_DOWN)
#define SH73A0_PIN_I_PD(pin) SH_PFC_PIN_CFG(pin, __I | __PD)
#define SH73A0_PIN_I_PU(pin) SH_PFC_PIN_CFG(pin, __I | __PU)
@@ -1158,11 +1161,13 @@ static const u16 pinmux_data[] = {
#define SH73A0_PIN_IO_PU_PD(pin) SH_PFC_PIN_CFG(pin, __IO | __PUD)
#define SH73A0_PIN_O(pin) SH_PFC_PIN_CFG(pin, __O)
-/* Pin numbers for pins without a corresponding GPIO port number are computed
- * from the row and column numbers with a 1000 offset to avoid collisions with
- * GPIO port numbers.
+/*
+ * Pins not associated with a GPIO port.
*/
-#define PIN_NUMBER(row, col) (1000+((row)-1)*34+(col)-1)
+enum {
+ PORT_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
static const struct sh_pfc_pin pinmux_pins[] = {
/* Table 25-1 (I/O and Pull U/D) */
@@ -1437,7 +1442,7 @@ static const struct sh_pfc_pin pinmux_pins[] = {
SH73A0_PIN_O(309),
/* Pins not associated with a GPIO port */
- SH_PFC_PIN_NAMED(6, 26, F26),
+ PINMUX_NOGP_ALL(),
};
/* - BSC -------------------------------------------------------------------- */
@@ -1863,7 +1868,7 @@ static const unsigned int keysc_out7_2_mux[] = {
};
static const unsigned int keysc_out8_0_pins[] = {
/* KEYOUT8 */
- PIN_NUMBER(6, 26),
+ PIN_A11,
};
static const unsigned int keysc_out8_0_mux[] = {
KEYOUT8_MARK,
@@ -3073,7 +3078,7 @@ static const unsigned int tpu4_to2_mux[] = {
};
static const unsigned int tpu4_to3_pins[] = {
/* TO */
- PIN_NUMBER(6, 26),
+ PIN_A11,
};
static const unsigned int tpu4_to3_mux[] = {
TPU4TO3_MARK,
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7734.c b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
index fac7b4699121..5dfd991ffdaa 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7734.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
@@ -11,7 +11,7 @@
#include "sh_pfc.h"
-#define CPU_ALL_PORT(fn, sfx) \
+#define CPU_ALL_GP(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \
PORT_GP_32(2, fn, sfx), \
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index c97d2ba7677c..2824be4eb887 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -569,8 +569,7 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- return pin->configs &
- (SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN);
+ return pin->configs & SH_PFC_PIN_CFG_PULL_UP_DOWN;
case PIN_CONFIG_BIAS_PULL_UP:
return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 7db5819eea7e..835148fc0f28 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -21,10 +21,14 @@ enum {
PINMUX_TYPE_INPUT,
};
+#define SH_PFC_PIN_NONE U16_MAX
+
#define SH_PFC_PIN_CFG_INPUT (1 << 0)
#define SH_PFC_PIN_CFG_OUTPUT (1 << 1)
#define SH_PFC_PIN_CFG_PULL_UP (1 << 2)
#define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3)
+#define SH_PFC_PIN_CFG_PULL_UP_DOWN (SH_PFC_PIN_CFG_PULL_UP | \
+ SH_PFC_PIN_CFG_PULL_DOWN)
#define SH_PFC_PIN_CFG_IO_VOLTAGE (1 << 4)
#define SH_PFC_PIN_CFG_DRIVE_STRENGTH (1 << 5)
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
@@ -542,9 +546,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
PORT_GP_CFG_1(bank, 25, fn, sfx, cfg)
#define PORT_GP_26(bank, fn, sfx) PORT_GP_CFG_26(bank, fn, sfx, 0)
-#define PORT_GP_CFG_28(bank, fn, sfx, cfg) \
+#define PORT_GP_CFG_27(bank, fn, sfx, cfg) \
PORT_GP_CFG_26(bank, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 26, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 26, fn, sfx, cfg)
+#define PORT_GP_27(bank, fn, sfx) PORT_GP_CFG_27(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_28(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_27(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 27, fn, sfx, cfg)
#define PORT_GP_28(bank, fn, sfx) PORT_GP_CFG_28(bank, fn, sfx, 0)
@@ -584,7 +592,7 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
/* GP_ALL(suffix) - Expand to a list of GP_#_#_suffix */
#define _GP_ALL(bank, pin, name, sfx, cfg) name##_##sfx
-#define GP_ALL(str) CPU_ALL_PORT(_GP_ALL, str)
+#define GP_ALL(str) CPU_ALL_GP(_GP_ALL, str)
/* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */
#define _GP_GPIO(bank, _pin, _name, sfx, cfg) \
@@ -594,11 +602,29 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
.enum_id = _name##_DATA, \
.configs = cfg, \
}
-#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, unused)
+#define PINMUX_GPIO_GP_ALL() CPU_ALL_GP(_GP_GPIO, unused)
/* PINMUX_DATA_GP_ALL - Expand to a list of name_DATA, name_FN marks */
#define _GP_DATA(bank, pin, name, sfx, cfg) PINMUX_DATA(name##_DATA, name##_FN)
-#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, unused)
+#define PINMUX_DATA_GP_ALL() CPU_ALL_GP(_GP_DATA, unused)
+
+/*
+ * GP_ASSIGN_LAST() - Expand to an enum definition for the last GP pin
+ *
+ * The largest GP pin index is obtained by taking the size of a union,
+ * containing one array per GP pin, sized by the corresponding pin index.
+ * As the fields in the CPU_ALL_GP() macro definition are separated by commas,
+ * while the members of a union must be terminated by semicolons, the commas
+ * are absorbed by wrapping them inside dummy attributes.
+ */
+#define _GP_ENTRY(bank, pin, name, sfx, cfg) \
+ deprecated)); char name[(bank * 32) + pin] __attribute__((deprecated
+#define GP_ASSIGN_LAST() \
+ GP_LAST = sizeof(union { \
+ char dummy[0] __attribute__((deprecated, \
+ CPU_ALL_GP(_GP_ENTRY, unused), \
+ deprecated)); \
+ })
/*
* PORT style (linear pin space)
@@ -641,22 +667,6 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
.configs = cfgs, \
}
-/* SH_PFC_PIN_NAMED - Expand to a sh_pfc_pin entry with the given name */
-#define SH_PFC_PIN_NAMED(row, col, _name) \
- { \
- .pin = PIN_NUMBER(row, col), \
- .name = __stringify(PIN_##_name), \
- .configs = SH_PFC_PIN_CFG_NO_GPIO, \
- }
-
-/* SH_PFC_PIN_NAMED_CFG - Expand to a sh_pfc_pin entry with the given name */
-#define SH_PFC_PIN_NAMED_CFG(row, col, _name, cfgs) \
- { \
- .pin = PIN_NUMBER(row, col), \
- .name = __stringify(PIN_##_name), \
- .configs = SH_PFC_PIN_CFG_NO_GPIO | cfgs, \
- }
-
/* PINMUX_DATA_ALL - Expand to a list of PORT_name_DATA, PORT_name_FN0,
* PORT_name_OUT, PORT_name_IN marks
*/
@@ -665,6 +675,24 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
PORT##pfx##_OUT, PORT##pfx##_IN)
#define PINMUX_DATA_ALL() CPU_ALL_PORT(_PORT_DATA, , unused)
+/*
+ * PORT_ASSIGN_LAST() - Expand to an enum definition for the last PORT pin
+ *
+ * The largest PORT pin index is obtained by taking the size of a union,
+ * containing one array per PORT pin, sized by the corresponding pin index.
+ * As the fields in the CPU_ALL_PORT() macro definition are separated by
+ * commas, while the members of a union must be terminated by semicolons, the
+ * commas are absorbed by wrapping them inside dummy attributes.
+ */
+#define _PORT_ENTRY(pn, pfx, sfx) \
+ deprecated)); char pfx[pn] __attribute__((deprecated
+#define PORT_ASSIGN_LAST() \
+ PORT_LAST = sizeof(union { \
+ char dummy[0] __attribute__((deprecated, \
+ CPU_ALL_PORT(_PORT_ENTRY, PORT, unused), \
+ deprecated)); \
+ })
+
/* GPIO_FN(name) - Expand to a sh_pfc_pin entry for a function GPIO */
#define PINMUX_GPIO_FN(gpio, base, data_or_mark) \
[gpio - (base)] = { \
@@ -675,6 +703,26 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
/*
+ * Pins not associated with a GPIO port
+ */
+
+#define PIN_NOGP_CFG(pin, name, fn, cfg) fn(pin, name, cfg)
+#define PIN_NOGP(pin, name, fn) fn(pin, name, 0)
+
+/* NOGP_ALL - Expand to a list of PIN_id */
+#define _NOGP_ALL(pin, name, cfg) PIN_##pin
+#define NOGP_ALL() CPU_ALL_NOGP(_NOGP_ALL)
+
+/* PINMUX_NOGP_ALL - Expand to a list of sh_pfc_pin entries */
+#define _NOGP_PINMUX(_pin, _name, cfg) \
+ { \
+ .pin = PIN_##_pin, \
+ .name = "PIN_" _name, \
+ .configs = SH_PFC_PIN_CFG_NO_GPIO | cfg, \
+ }
+#define PINMUX_NOGP_ALL() CPU_ALL_NOGP(_NOGP_PINMUX)
+
+/*
* PORTnCR helper macro for SH-Mobile/R-Mobile
*/
#define PORTCR(nr, reg) \
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 2317ccf63321..b453aed1bbeb 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -44,6 +44,18 @@
#define STM32_GPIO_AFRL 0x20
#define STM32_GPIO_AFRH 0x24
+/* custom bitfield to backup pin status */
+#define STM32_GPIO_BKP_MODE_SHIFT 0
+#define STM32_GPIO_BKP_MODE_MASK GENMASK(1, 0)
+#define STM32_GPIO_BKP_ALT_SHIFT 2
+#define STM32_GPIO_BKP_ALT_MASK GENMASK(5, 2)
+#define STM32_GPIO_BKP_SPEED_SHIFT 6
+#define STM32_GPIO_BKP_SPEED_MASK GENMASK(7, 6)
+#define STM32_GPIO_BKP_PUPD_SHIFT 8
+#define STM32_GPIO_BKP_PUPD_MASK GENMASK(9, 8)
+#define STM32_GPIO_BKP_TYPE 10
+#define STM32_GPIO_BKP_VAL 11
+
#define STM32_GPIO_PINS_PER_BANK 16
#define STM32_GPIO_IRQ_LINE 16
@@ -79,6 +91,7 @@ struct stm32_gpio_bank {
struct irq_domain *domain;
u32 bank_nr;
u32 bank_ioport_nr;
+ u32 pin_backup[STM32_GPIO_PINS_PER_BANK];
};
struct stm32_pinctrl {
@@ -98,6 +111,8 @@ struct stm32_pinctrl {
struct stm32_desc_pin *pins;
u32 npins;
u32 pkg;
+ u16 irqmux_map;
+ spinlock_t irqmux_lock;
};
static inline int stm32_gpio_pin(int gpio)
@@ -133,11 +148,50 @@ static inline u32 stm32_gpio_get_alt(u32 function)
return 0;
}
+static void stm32_gpio_backup_value(struct stm32_gpio_bank *bank,
+ u32 offset, u32 value)
+{
+ bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_VAL);
+ bank->pin_backup[offset] |= value << STM32_GPIO_BKP_VAL;
+}
+
+static void stm32_gpio_backup_mode(struct stm32_gpio_bank *bank, u32 offset,
+ u32 mode, u32 alt)
+{
+ bank->pin_backup[offset] &= ~(STM32_GPIO_BKP_MODE_MASK |
+ STM32_GPIO_BKP_ALT_MASK);
+ bank->pin_backup[offset] |= mode << STM32_GPIO_BKP_MODE_SHIFT;
+ bank->pin_backup[offset] |= alt << STM32_GPIO_BKP_ALT_SHIFT;
+}
+
+static void stm32_gpio_backup_driving(struct stm32_gpio_bank *bank, u32 offset,
+ u32 drive)
+{
+ bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_TYPE);
+ bank->pin_backup[offset] |= drive << STM32_GPIO_BKP_TYPE;
+}
+
+static void stm32_gpio_backup_speed(struct stm32_gpio_bank *bank, u32 offset,
+ u32 speed)
+{
+ bank->pin_backup[offset] &= ~STM32_GPIO_BKP_SPEED_MASK;
+ bank->pin_backup[offset] |= speed << STM32_GPIO_BKP_SPEED_SHIFT;
+}
+
+static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset,
+ u32 bias)
+{
+ bank->pin_backup[offset] &= ~STM32_GPIO_BKP_PUPD_MASK;
+ bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT;
+}
+
/* GPIO functions */
static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
unsigned offset, int value)
{
+ stm32_gpio_backup_value(bank, offset, value);
+
if (!value)
offset += STM32_GPIO_PINS_PER_BANK;
@@ -307,9 +361,53 @@ static int stm32_gpio_domain_activate(struct irq_domain *d,
{
struct stm32_gpio_bank *bank = d->host_data;
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
+ unsigned long flags;
+ int ret = 0;
+
+ /*
+ * gpio irq mux is shared between several banks, a lock has to be done
+ * to avoid overriding.
+ */
+ spin_lock_irqsave(&pctl->irqmux_lock, flags);
+ if (pctl->hwlock)
+ ret = hwspin_lock_timeout(pctl->hwlock, HWSPINLOCK_TIMEOUT);
+
+ if (ret) {
+ dev_err(pctl->dev, "Can't get hwspinlock\n");
+ goto unlock;
+ }
+
+ if (pctl->irqmux_map & BIT(irq_data->hwirq)) {
+ dev_err(pctl->dev, "irq line %ld already requested.\n",
+ irq_data->hwirq);
+ ret = -EBUSY;
+ if (pctl->hwlock)
+ hwspin_unlock(pctl->hwlock);
+ goto unlock;
+ } else {
+ pctl->irqmux_map |= BIT(irq_data->hwirq);
+ }
regmap_field_write(pctl->irqmux[irq_data->hwirq], bank->bank_ioport_nr);
- return 0;
+
+ if (pctl->hwlock)
+ hwspin_unlock(pctl->hwlock);
+
+unlock:
+ spin_unlock_irqrestore(&pctl->irqmux_lock, flags);
+ return ret;
+}
+
+static void stm32_gpio_domain_deactivate(struct irq_domain *d,
+ struct irq_data *irq_data)
+{
+ struct stm32_gpio_bank *bank = d->host_data;
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pctl->irqmux_lock, flags);
+ pctl->irqmux_map &= ~BIT(irq_data->hwirq);
+ spin_unlock_irqrestore(&pctl->irqmux_lock, flags);
}
static int stm32_gpio_domain_alloc(struct irq_domain *d,
@@ -338,6 +436,7 @@ static const struct irq_domain_ops stm32_gpio_domain_ops = {
.alloc = stm32_gpio_domain_alloc,
.free = irq_domain_free_irqs_common,
.activate = stm32_gpio_domain_activate,
+ .deactivate = stm32_gpio_domain_deactivate,
};
/* Pinctrl functions */
@@ -620,6 +719,8 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
if (pctl->hwlock)
hwspin_unlock(pctl->hwlock);
+ stm32_gpio_backup_mode(bank, pin, mode, alt);
+
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
clk_disable(bank->clk);
@@ -732,6 +833,8 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
if (pctl->hwlock)
hwspin_unlock(pctl->hwlock);
+ stm32_gpio_backup_driving(bank, offset, drive);
+
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
clk_disable(bank->clk);
@@ -784,6 +887,8 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
if (pctl->hwlock)
hwspin_unlock(pctl->hwlock);
+ stm32_gpio_backup_speed(bank, offset, speed);
+
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
clk_disable(bank->clk);
@@ -836,6 +941,8 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
if (pctl->hwlock)
hwspin_unlock(pctl->hwlock);
+ stm32_gpio_backup_bias(bank, offset, bias);
+
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
clk_disable(bank->clk);
@@ -1290,6 +1397,8 @@ int stm32_pctl_probe(struct platform_device *pdev)
pctl->hwlock = hwspin_lock_request_specific(hwlock_id);
}
+ spin_lock_init(&pctl->irqmux_lock);
+
pctl->dev = dev;
pctl->match_data = match->data;
@@ -1329,6 +1438,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
pctl->pctl_desc.owner = THIS_MODULE;
pctl->pctl_desc.pins = pins;
pctl->pctl_desc.npins = pctl->npins;
+ pctl->pctl_desc.link_consumers = true;
pctl->pctl_desc.confops = &stm32_pconf_ops;
pctl->pctl_desc.pctlops = &stm32_pctrl_ops;
pctl->pctl_desc.pmxops = &stm32_pmx_ops;
@@ -1369,3 +1479,75 @@ int stm32_pctl_probe(struct platform_device *pdev)
return 0;
}
+
+static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
+ struct stm32_pinctrl *pctl, u32 pin)
+{
+ const struct pin_desc *desc = pin_desc_get(pctl->pctl_dev, pin);
+ u32 val, alt, mode, offset = stm32_gpio_pin(pin);
+ struct pinctrl_gpio_range *range;
+ struct stm32_gpio_bank *bank;
+ bool pin_is_irq;
+ int ret;
+
+ range = pinctrl_find_gpio_range_from_pin(pctl->pctl_dev, pin);
+ if (!range)
+ return 0;
+
+ pin_is_irq = gpiochip_line_is_irq(range->gc, offset);
+
+ if (!desc || (!pin_is_irq && !desc->gpio_owner))
+ return 0;
+
+ bank = gpiochip_get_data(range->gc);
+
+ alt = bank->pin_backup[offset] & STM32_GPIO_BKP_ALT_MASK;
+ alt >>= STM32_GPIO_BKP_ALT_SHIFT;
+ mode = bank->pin_backup[offset] & STM32_GPIO_BKP_MODE_MASK;
+ mode >>= STM32_GPIO_BKP_MODE_SHIFT;
+
+ ret = stm32_pmx_set_mode(bank, offset, mode, alt);
+ if (ret)
+ return ret;
+
+ if (mode == 1) {
+ val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_VAL);
+ val = val >> STM32_GPIO_BKP_VAL;
+ __stm32_gpio_set(bank, offset, val);
+ }
+
+ val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_TYPE);
+ val >>= STM32_GPIO_BKP_TYPE;
+ ret = stm32_pconf_set_driving(bank, offset, val);
+ if (ret)
+ return ret;
+
+ val = bank->pin_backup[offset] & STM32_GPIO_BKP_SPEED_MASK;
+ val >>= STM32_GPIO_BKP_SPEED_SHIFT;
+ ret = stm32_pconf_set_speed(bank, offset, val);
+ if (ret)
+ return ret;
+
+ val = bank->pin_backup[offset] & STM32_GPIO_BKP_PUPD_MASK;
+ val >>= STM32_GPIO_BKP_PUPD_SHIFT;
+ ret = stm32_pconf_set_bias(bank, offset, val);
+ if (ret)
+ return ret;
+
+ if (pin_is_irq)
+ regmap_field_write(pctl->irqmux[offset], bank->bank_ioport_nr);
+
+ return 0;
+}
+
+int __maybe_unused stm32_pinctrl_resume(struct device *dev)
+{
+ struct stm32_pinctrl *pctl = dev_get_drvdata(dev);
+ struct stm32_pinctrl_group *g = pctl->groups;
+ int i;
+
+ for (i = g->pin; i < g->pin + pctl->ngroups; i++)
+ stm32_pinctrl_restore_gpio_regs(pctl, i);
+
+ return 0;
+}
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h
index de5e7012ca03..ec0d34c33903 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.h
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h
@@ -65,5 +65,7 @@ struct stm32_gpio_bank;
int stm32_pctl_probe(struct platform_device *pdev);
void stm32_pmx_get_mode(struct stm32_gpio_bank *bank,
int pin, u32 *mode, u32 *alt);
+int stm32_pinctrl_resume(struct device *dev);
+
#endif /* __PINCTRL_STM32_H */
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c
index 320544f69e57..2ccb99d64df8 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c
@@ -2342,11 +2342,16 @@ static const struct of_device_id stm32mp157_pctrl_match[] = {
{ }
};
+static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume)
+};
+
static struct platform_driver stm32mp157_pinctrl_driver = {
.probe = stm32_pctl_probe,
.driver = {
.name = "stm32mp157-pinctrl",
.of_match_table = stm32mp157_pctrl_match,
+ .pm = &stm32_pinctrl_dev_pm_ops,
},
};
diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig
index 5906a856be38..a67d0d9ae8cd 100644
--- a/drivers/pinctrl/tegra/Kconfig
+++ b/drivers/pinctrl/tegra/Kconfig
@@ -24,6 +24,10 @@ config PINCTRL_TEGRA210
bool
select PINCTRL_TEGRA
+config PINCTRL_TEGRA194
+ bool
+ select PINCTRL_TEGRA
+
config PINCTRL_TEGRA_XUSB
def_bool y if ARCH_TEGRA
select GENERIC_PHY
diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile
index bbcb043c34a2..ead4e10097d0 100644
--- a/drivers/pinctrl/tegra/Makefile
+++ b/drivers/pinctrl/tegra/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o
+obj-$(CONFIG_PINCTRL_TEGRA194) += pinctrl-tegra194.o
obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index abcfbad94f00..186ef98e7b2b 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -284,7 +284,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
const struct tegra_pingroup *g,
enum tegra_pinconf_param param,
bool report_err,
- s8 *bank, s16 *reg, s8 *bit, s8 *width)
+ s8 *bank, s32 *reg, s8 *bit, s8 *width)
{
switch (param) {
case TEGRA_PINCONF_PARAM_PULL:
@@ -443,7 +443,7 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
const struct tegra_pingroup *g;
int ret;
s8 bank, bit, width;
- s16 reg;
+ s32 reg;
u32 val, mask;
g = &pmx->soc->groups[group];
@@ -472,7 +472,7 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
const struct tegra_pingroup *g;
int ret, i;
s8 bank, bit, width;
- s16 reg;
+ s32 reg;
u32 val, mask;
g = &pmx->soc->groups[group];
@@ -540,7 +540,7 @@ static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
const struct tegra_pingroup *g;
int i, ret;
s8 bank, bit, width;
- s16 reg;
+ s32 reg;
u32 val;
g = &pmx->soc->groups[group];
@@ -613,10 +613,20 @@ static void tegra_pinctrl_clear_parked_bits(struct tegra_pmx *pmx)
for (i = 0; i < pmx->soc->ngroups; ++i) {
g = &pmx->soc->groups[i];
- if (g->parked_bit >= 0) {
- val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
- val &= ~(1 << g->parked_bit);
- pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
+ if (g->parked_bitmask > 0) {
+ unsigned int bank, reg;
+
+ if (g->mux_reg != -1) {
+ bank = g->mux_bank;
+ reg = g->mux_reg;
+ } else {
+ bank = g->drv_bank;
+ reg = g->drv_reg;
+ }
+
+ val = pmx_readl(pmx, bank, reg);
+ val &= ~g->parked_bitmask;
+ pmx_writel(pmx, val, bank, reg);
}
}
}
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
index 9b5a71624fd0..105309774079 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.h
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.h
@@ -96,7 +96,6 @@ struct tegra_function {
* @tri_reg: Tri-state register offset.
* @tri_bank: Tri-state register bank.
* @tri_bit: Tri-state register bit.
- * @parked_bit: Parked register bit. -1 if unsupported.
* @einput_bit: Enable-input register bit.
* @odrain_bit: Open-drain register bit.
* @lock_bit: Lock register bit.
@@ -118,6 +117,7 @@ struct tegra_function {
* @slwf_bit: Slew Falling register bit.
* @slwf_width: Slew Falling field width.
* @drvtype_bit: Drive type register bit.
+ * @parked_bitmask: Parked register mask. 0 if unsupported.
*
* -1 in a *_reg field means that feature is unsupported for this group.
* *_bank and *_reg values are irrelevant when *_reg is -1.
@@ -135,10 +135,10 @@ struct tegra_pingroup {
const unsigned *pins;
u8 npins;
u8 funcs[4];
- s16 mux_reg;
- s16 pupd_reg;
- s16 tri_reg;
- s16 drv_reg;
+ s32 mux_reg;
+ s32 pupd_reg;
+ s32 tri_reg;
+ s32 drv_reg;
u32 mux_bank:2;
u32 pupd_bank:2;
u32 tri_bank:2;
@@ -146,7 +146,6 @@ struct tegra_pingroup {
s32 mux_bit:6;
s32 pupd_bit:6;
s32 tri_bit:6;
- s32 parked_bit:6;
s32 einput_bit:6;
s32 odrain_bit:6;
s32 lock_bit:6;
@@ -164,6 +163,7 @@ struct tegra_pingroup {
s32 drvup_width:6;
s32 slwr_width:6;
s32 slwf_width:6;
+ u32 parked_bitmask;
};
/**
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c
index 762151f17a88..e72ab1eb2398 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra114.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c
@@ -1572,8 +1572,8 @@ static struct tegra_function tegra114_functions[] = {
.lock_bit = 7, \
.ioreset_bit = PINGROUP_BIT_##ior(8), \
.rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \
- .parked_bit = -1, \
.drv_reg = -1, \
+ .parked_bitmask = 0, \
}
#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \
@@ -1593,7 +1593,6 @@ static struct tegra_function tegra114_functions[] = {
.rcv_sel_bit = -1, \
.drv_reg = DRV_PINGROUP_REG(r), \
.drv_bank = 0, \
- .parked_bit = -1, \
.hsm_bit = hsm_b, \
.schmitt_bit = schmitt_b, \
.lpmd_bit = lpmd_b, \
@@ -1606,6 +1605,7 @@ static struct tegra_function tegra114_functions[] = {
.slwf_bit = slwf_b, \
.slwf_width = slwf_w, \
.drvtype_bit = PINGROUP_BIT_##drvtype(6), \
+ .parked_bitmask = 0, \
}
static const struct tegra_pingroup tegra114_groups[] = {
@@ -1831,7 +1831,7 @@ static const struct tegra_pingroup tegra114_groups[] = {
static const struct tegra_pinctrl_soc_data tegra114_pinctrl = {
.ngpios = NUM_GPIOS,
- .gpio_compatible = "nvidia,tegra30-gpio",
+ .gpio_compatible = "nvidia,tegra114-gpio",
.pins = tegra114_pins,
.npins = ARRAY_SIZE(tegra114_pins),
.functions = tegra114_functions,
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c
index 930c43758c92..26096c6b967e 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra124.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c
@@ -1741,8 +1741,8 @@ static struct tegra_function tegra124_functions[] = {
.lock_bit = 7, \
.ioreset_bit = PINGROUP_BIT_##ior(8), \
.rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \
- .parked_bit = -1, \
.drv_reg = -1, \
+ .parked_bitmask = 0, \
}
#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \
@@ -1762,7 +1762,6 @@ static struct tegra_function tegra124_functions[] = {
.rcv_sel_bit = -1, \
.drv_reg = DRV_PINGROUP_REG(r), \
.drv_bank = 0, \
- .parked_bit = -1, \
.hsm_bit = hsm_b, \
.schmitt_bit = schmitt_b, \
.lpmd_bit = lpmd_b, \
@@ -1775,6 +1774,7 @@ static struct tegra_function tegra124_functions[] = {
.slwf_bit = slwf_b, \
.slwf_width = slwf_w, \
.drvtype_bit = PINGROUP_BIT_##drvtype(6), \
+ .parked_bitmask = 0, \
}
#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1) \
@@ -2043,7 +2043,7 @@ static const struct tegra_pingroup tegra124_groups[] = {
static const struct tegra_pinctrl_soc_data tegra124_pinctrl = {
.ngpios = NUM_GPIOS,
- .gpio_compatible = "nvidia,tegra30-gpio",
+ .gpio_compatible = "nvidia,tegra124-gpio",
.pins = tegra124_pins,
.npins = ARRAY_SIZE(tegra124_pins),
.functions = tegra124_functions,
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra194.c b/drivers/pinctrl/tegra/pinctrl-tegra194.c
new file mode 100644
index 000000000000..daf44cf240c9
--- /dev/null
+++ b/drivers/pinctrl/tegra/pinctrl-tegra194.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Pinctrl data for the NVIDIA Tegra194 pinmux
+ *
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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/init.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/* Define unique ID for each pins */
+enum pin_id {
+ TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0 = 256,
+ TEGRA_PIN_PEX_L5_RST_N_PGG1 = 257,
+ TEGRA_PIN_NUM_GPIOS = 258,
+};
+
+/* Table for pin descriptor */
+static const struct pinctrl_pin_desc tegra194_pins[] = {
+ PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0,
+ "TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PGG1,
+ "TEGRA_PIN_PEX_L5_RST_N_PGG1"),
+};
+
+static const unsigned int pex_l5_clkreq_n_pgg0_pins[] = {
+ TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0,
+};
+
+static const unsigned int pex_l5_rst_n_pgg1_pins[] = {
+ TEGRA_PIN_PEX_L5_RST_N_PGG1,
+};
+
+/* Define unique ID for each function */
+enum tegra_mux_dt {
+ TEGRA_MUX_RSVD0,
+ TEGRA_MUX_RSVD1,
+ TEGRA_MUX_RSVD2,
+ TEGRA_MUX_RSVD3,
+ TEGRA_MUX_PE5,
+};
+
+/* Make list of each function name */
+#define TEGRA_PIN_FUNCTION(lid) \
+ { \
+ .name = #lid, \
+ }
+static struct tegra_function tegra194_functions[] = {
+ TEGRA_PIN_FUNCTION(rsvd0),
+ TEGRA_PIN_FUNCTION(rsvd1),
+ TEGRA_PIN_FUNCTION(rsvd2),
+ TEGRA_PIN_FUNCTION(rsvd3),
+ TEGRA_PIN_FUNCTION(pe5),
+};
+
+#define DRV_PINGROUP_ENTRY_Y(r, drvdn_b, drvdn_w, drvup_b, \
+ drvup_w, slwr_b, slwr_w, slwf_b, \
+ slwf_w, bank) \
+ .drv_reg = ((r)), \
+ .drv_bank = bank, \
+ .drvdn_bit = drvdn_b, \
+ .drvdn_width = drvdn_w, \
+ .drvup_bit = drvup_b, \
+ .drvup_width = drvup_w, \
+ .slwr_bit = slwr_b, \
+ .slwr_width = slwr_w, \
+ .slwf_bit = slwf_b, \
+ .slwf_width = slwf_w
+
+#define PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_lpbk, e_input, \
+ e_od, schmitt_b, drvtype) \
+ .mux_reg = ((r)), \
+ .lpmd_bit = -1, \
+ .lock_bit = -1, \
+ .hsm_bit = -1, \
+ .mux_bank = bank, \
+ .mux_bit = 0, \
+ .pupd_reg = ((r)), \
+ .pupd_bank = bank, \
+ .pupd_bit = 2, \
+ .tri_reg = ((r)), \
+ .tri_bank = bank, \
+ .tri_bit = 4, \
+ .einput_bit = e_input, \
+ .odrain_bit = e_od, \
+ .schmitt_bit = schmitt_b, \
+ .drvtype_bit = 13, \
+ .drv_reg = -1, \
+ .parked_bitmask = 0
+
+#define drive_pex_l5_clkreq_n_pgg0 \
+ DRV_PINGROUP_ENTRY_Y(0x14004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l5_rst_n_pgg1 \
+ DRV_PINGROUP_ENTRY_Y(0x1400c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, bank, pupd, e_lpbk, \
+ e_input, e_lpdr, e_od, schmitt_b, drvtype, io_rail) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .funcs = { \
+ TEGRA_MUX_##f0, \
+ TEGRA_MUX_##f1, \
+ TEGRA_MUX_##f2, \
+ TEGRA_MUX_##f3, \
+ }, \
+ PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_lpbk, \
+ e_input, e_od, \
+ schmitt_b, drvtype), \
+ drive_##pg_name, \
+ }
+
+static const struct tegra_pingroup tegra194_groups[] = {
+ PINGROUP(pex_l5_clkreq_n_pgg0, PE5, RSVD1, RSVD2, RSVD3, 0x14000, 0,
+ Y, -1, 6, 8, 11, 12, N, "vddio_pex_ctl_2"),
+ PINGROUP(pex_l5_rst_n_pgg1, PE5, RSVD1, RSVD2, RSVD3, 0x14008, 0,
+ Y, -1, 6, 8, 11, 12, N, "vddio_pex_ctl_2"),
+};
+
+static const struct tegra_pinctrl_soc_data tegra194_pinctrl = {
+ .ngpios = TEGRA_PIN_NUM_GPIOS,
+ .pins = tegra194_pins,
+ .npins = ARRAY_SIZE(tegra194_pins),
+ .functions = tegra194_functions,
+ .nfunctions = ARRAY_SIZE(tegra194_functions),
+ .groups = tegra194_groups,
+ .ngroups = ARRAY_SIZE(tegra194_groups),
+ .hsm_in_mux = true,
+ .schmitt_in_mux = true,
+ .drvtype_in_mux = true,
+};
+
+static int tegra194_pinctrl_probe(struct platform_device *pdev)
+{
+ return tegra_pinctrl_probe(pdev, &tegra194_pinctrl);
+}
+
+static const struct of_device_id tegra194_pinctrl_of_match[] = {
+ { .compatible = "nvidia,tegra194-pinmux", },
+ { },
+};
+
+static struct platform_driver tegra194_pinctrl_driver = {
+ .driver = {
+ .name = "tegra194-pinctrl",
+ .of_match_table = tegra194_pinctrl_of_match,
+ },
+ .probe = tegra194_pinctrl_probe,
+};
+
+static int __init tegra194_pinctrl_init(void)
+{
+ return platform_driver_register(&tegra194_pinctrl_driver);
+}
+arch_initcall(tegra194_pinctrl_init);
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c
index 4b7837e38fb5..0dc2cf0d05b1 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra20.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c
@@ -1989,13 +1989,13 @@ static struct tegra_function tegra20_functions[] = {
.tri_reg = ((tri_r) - TRISTATE_REG_A), \
.tri_bank = 0, \
.tri_bit = tri_b, \
- .parked_bit = -1, \
.einput_bit = -1, \
.odrain_bit = -1, \
.lock_bit = -1, \
.ioreset_bit = -1, \
.rcv_sel_bit = -1, \
.drv_reg = -1, \
+ .parked_bitmask = 0, \
}
/* Pin groups with only pull up and pull down control */
@@ -2009,7 +2009,7 @@ static struct tegra_function tegra20_functions[] = {
.pupd_bank = 2, \
.pupd_bit = pupd_b, \
.drv_reg = -1, \
- .parked_bit = -1, \
+ .parked_bitmask = 0, \
}
/* Pin groups for drive strength registers (configurable version) */
@@ -2025,7 +2025,7 @@ static struct tegra_function tegra20_functions[] = {
.tri_reg = -1, \
.drv_reg = ((r) - PINGROUP_REG_A), \
.drv_bank = 3, \
- .parked_bit = -1, \
+ .parked_bitmask = 0, \
.hsm_bit = hsm_b, \
.schmitt_bit = schmitt_b, \
.lpmd_bit = lpmd_b, \
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c
index 0b56ad5c9c1c..39ab6480a941 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra210.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c
@@ -1302,7 +1302,6 @@ static struct tegra_function tegra210_functions[] = {
.lock_bit = 7, \
.ioreset_bit = -1, \
.rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10), \
- .parked_bit = 5, \
.hsm_bit = PINGROUP_BIT_##hsm(9), \
.schmitt_bit = 12, \
.drvtype_bit = PINGROUP_BIT_##drvtype(13), \
@@ -1317,10 +1316,11 @@ static struct tegra_function tegra210_functions[] = {
.slwr_width = slwr_w, \
.slwf_bit = slwf_b, \
.slwf_width = slwf_w, \
+ .parked_bitmask = BIT(5), \
}
-#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, \
- slwr_b, slwr_w, slwf_b, slwf_w) \
+#define DRV_PINGROUP(pg_name, r, prk_mask, drvdn_b, drvdn_w, drvup_b, \
+ drvup_w, slwr_b, slwr_w, slwf_b, slwf_w) \
{ \
.name = "drive_" #pg_name, \
.pins = drive_##pg_name##_pins, \
@@ -1335,7 +1335,6 @@ static struct tegra_function tegra210_functions[] = {
.rcv_sel_bit = -1, \
.drv_reg = DRV_PINGROUP_REG(r), \
.drv_bank = 0, \
- .parked_bit = -1, \
.hsm_bit = -1, \
.schmitt_bit = -1, \
.lpmd_bit = -1, \
@@ -1348,6 +1347,7 @@ static struct tegra_function tegra210_functions[] = {
.slwf_bit = slwf_b, \
.slwf_width = slwf_w, \
.drvtype_bit = -1, \
+ .parked_bitmask = prk_mask, \
}
static const struct tegra_pingroup tegra210_groups[] = {
@@ -1515,37 +1515,37 @@ static const struct tegra_pingroup tegra210_groups[] = {
PINGROUP(pz4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x328c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(pz5, SOC, RSVD1, RSVD2, RSVD3, 0x3290, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
- /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
- DRV_PINGROUP(pa6, 0x9c0, 12, 5, 20, 5, -1, -1, -1, -1),
- DRV_PINGROUP(pcc7, 0x9c4, 12, 5, 20, 5, -1, -1, -1, -1),
- DRV_PINGROUP(pe6, 0x9c8, 12, 5, 20, 5, -1, -1, -1, -1),
- DRV_PINGROUP(pe7, 0x9cc, 12, 5, 20, 5, -1, -1, -1, -1),
- DRV_PINGROUP(ph6, 0x9d0, 12, 5, 20, 5, -1, -1, -1, -1),
- DRV_PINGROUP(pk0, 0x9d4, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk1, 0x9d8, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk2, 0x9dc, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk3, 0x9e0, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk4, 0x9e4, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk5, 0x9e8, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk6, 0x9ec, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pk7, 0x9f0, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pl0, 0x9f4, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pl1, 0x9f8, -1, -1, -1, -1, 28, 2, 30, 2),
- DRV_PINGROUP(pz0, 0x9fc, 12, 7, 20, 7, -1, -1, -1, -1),
- DRV_PINGROUP(pz1, 0xa00, 12, 7, 20, 7, -1, -1, -1, -1),
- DRV_PINGROUP(pz2, 0xa04, 12, 7, 20, 7, -1, -1, -1, -1),
- DRV_PINGROUP(pz3, 0xa08, 12, 7, 20, 7, -1, -1, -1, -1),
- DRV_PINGROUP(pz4, 0xa0c, 12, 7, 20, 7, -1, -1, -1, -1),
- DRV_PINGROUP(pz5, 0xa10, 12, 7, 20, 7, -1, -1, -1, -1),
- DRV_PINGROUP(sdmmc1, 0xa98, 12, 7, 20, 7, 28, 2, 30, 2),
- DRV_PINGROUP(sdmmc2, 0xa9c, 2, 6, 8, 6, 28, 2, 30, 2),
- DRV_PINGROUP(sdmmc3, 0xab0, 12, 7, 20, 7, 28, 2, 30, 2),
- DRV_PINGROUP(sdmmc4, 0xab4, 2, 6, 8, 6, 28, 2, 30, 2),
+ /* pg_name, r, prk_mask, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
+ DRV_PINGROUP(pa6, 0x9c0, 0x0, 12, 5, 20, 5, -1, -1, -1, -1),
+ DRV_PINGROUP(pcc7, 0x9c4, 0x0, 12, 5, 20, 5, -1, -1, -1, -1),
+ DRV_PINGROUP(pe6, 0x9c8, 0x0, 12, 5, 20, 5, -1, -1, -1, -1),
+ DRV_PINGROUP(pe7, 0x9cc, 0x0, 12, 5, 20, 5, -1, -1, -1, -1),
+ DRV_PINGROUP(ph6, 0x9d0, 0x0, 12, 5, 20, 5, -1, -1, -1, -1),
+ DRV_PINGROUP(pk0, 0x9d4, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk1, 0x9d8, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk2, 0x9dc, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk3, 0x9e0, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk4, 0x9e4, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk5, 0x9e8, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk6, 0x9ec, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pk7, 0x9f0, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pl0, 0x9f4, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pl1, 0x9f8, 0x0, -1, -1, -1, -1, 28, 2, 30, 2),
+ DRV_PINGROUP(pz0, 0x9fc, 0x0, 12, 7, 20, 7, -1, -1, -1, -1),
+ DRV_PINGROUP(pz1, 0xa00, 0x0, 12, 7, 20, 7, -1, -1, -1, -1),
+ DRV_PINGROUP(pz2, 0xa04, 0x0, 12, 7, 20, 7, -1, -1, -1, -1),
+ DRV_PINGROUP(pz3, 0xa08, 0x0, 12, 7, 20, 7, -1, -1, -1, -1),
+ DRV_PINGROUP(pz4, 0xa0c, 0x0, 12, 7, 20, 7, -1, -1, -1, -1),
+ DRV_PINGROUP(pz5, 0xa10, 0x0, 12, 7, 20, 7, -1, -1, -1, -1),
+ DRV_PINGROUP(sdmmc1, 0xa98, 0x0, 12, 7, 20, 7, 28, 2, 30, 2),
+ DRV_PINGROUP(sdmmc2, 0xa9c, 0x7ffc000, 2, 6, 8, 6, 28, 2, 30, 2),
+ DRV_PINGROUP(sdmmc3, 0xab0, 0x0, 12, 7, 20, 7, 28, 2, 30, 2),
+ DRV_PINGROUP(sdmmc4, 0xab4, 0x7ffc000, 2, 6, 8, 6, 28, 2, 30, 2),
};
static const struct tegra_pinctrl_soc_data tegra210_pinctrl = {
.ngpios = NUM_GPIOS,
- .gpio_compatible = "nvidia,tegra30-gpio",
+ .gpio_compatible = "nvidia,tegra210-gpio",
.pins = tegra210_pins,
.npins = ARRAY_SIZE(tegra210_pins),
.functions = tegra210_functions,
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c
index 610124c3d192..7299a371827f 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra30.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c
@@ -2133,8 +2133,8 @@ static struct tegra_function tegra30_functions[] = {
.lock_bit = 7, \
.ioreset_bit = PINGROUP_BIT_##ior(8), \
.rcv_sel_bit = -1, \
- .parked_bit = -1, \
.drv_reg = -1, \
+ .parked_bitmask = 0, \
}
#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \
@@ -2154,7 +2154,6 @@ static struct tegra_function tegra30_functions[] = {
.rcv_sel_bit = -1, \
.drv_reg = DRV_PINGROUP_REG(r), \
.drv_bank = 0, \
- .parked_bit = -1, \
.hsm_bit = hsm_b, \
.schmitt_bit = schmitt_b, \
.lpmd_bit = lpmd_b, \
@@ -2167,6 +2166,7 @@ static struct tegra_function tegra30_functions[] = {
.slwf_bit = slwf_b, \
.slwf_width = slwf_w, \
.drvtype_bit = -1, \
+ .parked_bitmask = 0, \
}
static const struct tegra_pingroup tegra30_groups[] = {
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index e03304fe25bb..6cca72782af6 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -70,7 +70,6 @@ MODULE_LICENSE("GPL");
* SECTION: prototypes for static functions of dasd.c
*/
static int dasd_alloc_queue(struct dasd_block *);
-static void dasd_setup_queue(struct dasd_block *);
static void dasd_free_queue(struct dasd_block *);
static int dasd_flush_block_queue(struct dasd_block *);
static void dasd_device_tasklet(unsigned long);
@@ -120,9 +119,18 @@ struct dasd_device *dasd_alloc_device(void)
kfree(device);
return ERR_PTR(-ENOMEM);
}
+ /* Get two pages for ese format. */
+ device->ese_mem = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA, 1);
+ if (!device->ese_mem) {
+ free_page((unsigned long) device->erp_mem);
+ free_pages((unsigned long) device->ccw_mem, 1);
+ kfree(device);
+ return ERR_PTR(-ENOMEM);
+ }
dasd_init_chunklist(&device->ccw_chunks, device->ccw_mem, PAGE_SIZE*2);
dasd_init_chunklist(&device->erp_chunks, device->erp_mem, PAGE_SIZE);
+ dasd_init_chunklist(&device->ese_chunks, device->ese_mem, PAGE_SIZE * 2);
spin_lock_init(&device->mem_lock);
atomic_set(&device->tasklet_scheduled, 0);
tasklet_init(&device->tasklet, dasd_device_tasklet,
@@ -146,6 +154,7 @@ struct dasd_device *dasd_alloc_device(void)
void dasd_free_device(struct dasd_device *device)
{
kfree(device->private);
+ free_pages((unsigned long) device->ese_mem, 1);
free_page((unsigned long) device->erp_mem);
free_pages((unsigned long) device->ccw_mem, 1);
kfree(device);
@@ -348,7 +357,8 @@ static int dasd_state_basic_to_ready(struct dasd_device *device)
}
return rc;
}
- dasd_setup_queue(block);
+ if (device->discipline->setup_blk_queue)
+ device->discipline->setup_blk_queue(block);
set_capacity(block->gdp,
block->blocks << block->s2b_shift);
device->state = DASD_STATE_READY;
@@ -1258,6 +1268,49 @@ struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength, int datasize,
}
EXPORT_SYMBOL(dasd_smalloc_request);
+struct dasd_ccw_req *dasd_fmalloc_request(int magic, int cplength,
+ int datasize,
+ struct dasd_device *device)
+{
+ struct dasd_ccw_req *cqr;
+ unsigned long flags;
+ int size, cqr_size;
+ char *data;
+
+ cqr_size = (sizeof(*cqr) + 7L) & -8L;
+ size = cqr_size;
+ if (cplength > 0)
+ size += cplength * sizeof(struct ccw1);
+ if (datasize > 0)
+ size += datasize;
+
+ spin_lock_irqsave(&device->mem_lock, flags);
+ cqr = dasd_alloc_chunk(&device->ese_chunks, size);
+ spin_unlock_irqrestore(&device->mem_lock, flags);
+ if (!cqr)
+ return ERR_PTR(-ENOMEM);
+ memset(cqr, 0, sizeof(*cqr));
+ data = (char *)cqr + cqr_size;
+ cqr->cpaddr = NULL;
+ if (cplength > 0) {
+ cqr->cpaddr = data;
+ data += cplength * sizeof(struct ccw1);
+ memset(cqr->cpaddr, 0, cplength * sizeof(struct ccw1));
+ }
+ cqr->data = NULL;
+ if (datasize > 0) {
+ cqr->data = data;
+ memset(cqr->data, 0, datasize);
+ }
+
+ cqr->magic = magic;
+ set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ dasd_get_device(device);
+
+ return cqr;
+}
+EXPORT_SYMBOL(dasd_fmalloc_request);
+
void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
{
unsigned long flags;
@@ -1269,6 +1322,17 @@ void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
}
EXPORT_SYMBOL(dasd_sfree_request);
+void dasd_ffree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&device->mem_lock, flags);
+ dasd_free_chunk(&device->ese_chunks, cqr);
+ spin_unlock_irqrestore(&device->mem_lock, flags);
+ dasd_put_device(device);
+}
+EXPORT_SYMBOL(dasd_ffree_request);
+
/*
* Check discipline magic in cqr.
*/
@@ -1573,13 +1637,43 @@ static int dasd_check_hpf_error(struct irb *irb)
irb->scsw.tm.sesq == SCSW_SESQ_PATH_NOFCX));
}
+static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb)
+{
+ struct dasd_device *device = NULL;
+ u8 *sense = NULL;
+
+ if (!block)
+ return 0;
+ device = block->base;
+ if (!device || !device->discipline->is_ese)
+ return 0;
+ if (!device->discipline->is_ese(device))
+ return 0;
+
+ sense = dasd_get_sense(irb);
+ if (!sense)
+ return 0;
+
+ return !!(sense[1] & SNS1_NO_REC_FOUND) ||
+ !!(sense[1] & SNS1_FILE_PROTECTED) ||
+ scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
+}
+
+static int dasd_ese_oos_cond(u8 *sense)
+{
+ return sense[0] & SNS0_EQUIPMENT_CHECK &&
+ sense[1] & SNS1_PERM_ERR &&
+ sense[1] & SNS1_WRITE_INHIBITED &&
+ sense[25] == 0x01;
+}
+
/*
* Interrupt handler for "normal" ssch-io based dasd devices.
*/
void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
struct irb *irb)
{
- struct dasd_ccw_req *cqr, *next;
+ struct dasd_ccw_req *cqr, *next, *fcqr;
struct dasd_device *device;
unsigned long now;
int nrf_suppressed = 0;
@@ -1641,6 +1735,17 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+
+ /*
+ * Extent pool probably out-of-space.
+ * Stop device and check exhaust level.
+ */
+ if (dasd_ese_oos_cond(sense)) {
+ dasd_generic_space_exhaust(device, cqr);
+ device->discipline->ext_pool_exhaust(device, cqr);
+ dasd_put_device(device);
+ return;
+ }
}
if (!(fp_suppressed || nrf_suppressed))
device->discipline->dump_sense_dbf(device, irb, "int");
@@ -1672,6 +1777,31 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
return;
}
+ if (dasd_ese_needs_format(cqr->block, irb)) {
+ if (rq_data_dir((struct request *)cqr->callback_data) == READ) {
+ device->discipline->ese_read(cqr);
+ cqr->status = DASD_CQR_SUCCESS;
+ cqr->stopclk = now;
+ dasd_device_clear_timer(device);
+ dasd_schedule_device_bh(device);
+ return;
+ }
+ fcqr = device->discipline->ese_format(device, cqr);
+ if (IS_ERR(fcqr)) {
+ /*
+ * If we can't format now, let the request go
+ * one extra round. Maybe we can format later.
+ */
+ cqr->status = DASD_CQR_QUEUED;
+ } else {
+ fcqr->status = DASD_CQR_QUEUED;
+ cqr->status = DASD_CQR_QUEUED;
+ list_add(&fcqr->devlist, &device->ccw_queue);
+ dasd_schedule_device_bh(device);
+ return;
+ }
+ }
+
/* Check for clear pending */
if (cqr->status == DASD_CQR_CLEAR_PENDING &&
scsw_fctl(&irb->scsw) & SCSW_FCTL_CLEAR_FUNC) {
@@ -1910,7 +2040,7 @@ static void __dasd_device_check_expire(struct dasd_device *device)
static int __dasd_device_is_unusable(struct dasd_device *device,
struct dasd_ccw_req *cqr)
{
- int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM);
+ int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM | DASD_STOPPED_NOSPC);
if (test_bit(DASD_FLAG_OFFLINE, &device->flags) &&
!test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
@@ -2412,6 +2542,15 @@ int dasd_sleep_on_queue(struct list_head *ccw_queue)
EXPORT_SYMBOL(dasd_sleep_on_queue);
/*
+ * Start requests from a ccw_queue and wait interruptible for their completion.
+ */
+int dasd_sleep_on_queue_interruptible(struct list_head *ccw_queue)
+{
+ return _dasd_sleep_on_queue(ccw_queue, 1);
+}
+EXPORT_SYMBOL(dasd_sleep_on_queue_interruptible);
+
+/*
* Queue a request to the tail of the device ccw_queue and wait
* interruptible for it's completion.
*/
@@ -3130,55 +3269,6 @@ static int dasd_alloc_queue(struct dasd_block *block)
}
/*
- * Allocate and initialize request queue.
- */
-static void dasd_setup_queue(struct dasd_block *block)
-{
- unsigned int logical_block_size = block->bp_block;
- struct request_queue *q = block->request_queue;
- unsigned int max_bytes, max_discard_sectors;
- int max;
-
- if (block->base->features & DASD_FEATURE_USERAW) {
- /*
- * the max_blocks value for raw_track access is 256
- * it is higher than the native ECKD value because we
- * only need one ccw per track
- * so the max_hw_sectors are
- * 2048 x 512B = 1024kB = 16 tracks
- */
- max = 2048;
- } else {
- max = block->base->discipline->max_blocks << block->s2b_shift;
- }
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
- q->limits.max_dev_sectors = max;
- blk_queue_logical_block_size(q, logical_block_size);
- blk_queue_max_hw_sectors(q, max);
- blk_queue_max_segments(q, USHRT_MAX);
- /* with page sized segments we can translate each segement into
- * one idaw/tidaw
- */
- blk_queue_max_segment_size(q, PAGE_SIZE);
- blk_queue_segment_boundary(q, PAGE_SIZE - 1);
-
- /* Only activate blocklayer discard support for devices that support it */
- if (block->base->features & DASD_FEATURE_DISCARD) {
- q->limits.discard_granularity = logical_block_size;
- q->limits.discard_alignment = PAGE_SIZE;
-
- /* Calculate max_discard_sectors and make it PAGE aligned */
- max_bytes = USHRT_MAX * logical_block_size;
- max_bytes = ALIGN(max_bytes, PAGE_SIZE) - PAGE_SIZE;
- max_discard_sectors = max_bytes / logical_block_size;
-
- blk_queue_max_discard_sectors(q, max_discard_sectors);
- blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
- blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
- }
-}
-
-/*
* Deactivate and free request queue.
*/
static void dasd_free_queue(struct dasd_block *block)
@@ -3806,6 +3896,43 @@ int dasd_generic_verify_path(struct dasd_device *device, __u8 lpm)
}
EXPORT_SYMBOL_GPL(dasd_generic_verify_path);
+void dasd_generic_space_exhaust(struct dasd_device *device,
+ struct dasd_ccw_req *cqr)
+{
+ dasd_eer_write(device, NULL, DASD_EER_NOSPC);
+
+ if (device->state < DASD_STATE_BASIC)
+ return;
+
+ if (cqr->status == DASD_CQR_IN_IO ||
+ cqr->status == DASD_CQR_CLEAR_PENDING) {
+ cqr->status = DASD_CQR_QUEUED;
+ cqr->retries++;
+ }
+ dasd_device_set_stop_bits(device, DASD_STOPPED_NOSPC);
+ dasd_device_clear_timer(device);
+ dasd_schedule_device_bh(device);
+}
+EXPORT_SYMBOL_GPL(dasd_generic_space_exhaust);
+
+void dasd_generic_space_avail(struct dasd_device *device)
+{
+ dev_info(&device->cdev->dev, "Extent pool space is available\n");
+ DBF_DEV_EVENT(DBF_WARNING, device, "%s", "space available");
+
+ dasd_device_remove_stop_bits(device, DASD_STOPPED_NOSPC);
+ dasd_schedule_device_bh(device);
+
+ if (device->block) {
+ dasd_schedule_block_bh(device->block);
+ if (device->block->request_queue)
+ blk_mq_run_hw_queues(device->block->request_queue, true);
+ }
+ if (!device->stopped)
+ wake_up(&generic_waitq);
+}
+EXPORT_SYMBOL_GPL(dasd_generic_space_avail);
+
/*
* clear active requests and requeue them to block layer if possible
*/
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 245f33c2f71e..32fc51341d99 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1642,6 +1642,35 @@ static DEVICE_ATTR(path_interval, 0644, dasd_path_interval_show,
dasd_path_interval_store);
+#define DASD_DEFINE_ATTR(_name, _func) \
+static ssize_t dasd_##_name##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct ccw_device *cdev = to_ccwdev(dev); \
+ struct dasd_device *device = dasd_device_from_cdev(cdev); \
+ int val = 0; \
+ \
+ if (IS_ERR(device)) \
+ return -ENODEV; \
+ if (device->discipline && _func) \
+ val = _func(device); \
+ dasd_put_device(device); \
+ \
+ return snprintf(buf, PAGE_SIZE, "%d\n", val); \
+} \
+static DEVICE_ATTR(_name, 0444, dasd_##_name##_show, NULL); \
+
+DASD_DEFINE_ATTR(ese, device->discipline->is_ese);
+DASD_DEFINE_ATTR(extent_size, device->discipline->ext_size);
+DASD_DEFINE_ATTR(pool_id, device->discipline->ext_pool_id);
+DASD_DEFINE_ATTR(space_configured, device->discipline->space_configured);
+DASD_DEFINE_ATTR(space_allocated, device->discipline->space_allocated);
+DASD_DEFINE_ATTR(logical_capacity, device->discipline->logical_capacity);
+DASD_DEFINE_ATTR(warn_threshold, device->discipline->ext_pool_warn_thrshld);
+DASD_DEFINE_ATTR(cap_at_warnlevel, device->discipline->ext_pool_cap_at_warnlevel);
+DASD_DEFINE_ATTR(pool_oos, device->discipline->ext_pool_oos);
+
static struct attribute * dasd_attrs[] = {
&dev_attr_readonly.attr,
&dev_attr_discipline.attr,
@@ -1667,6 +1696,7 @@ static struct attribute * dasd_attrs[] = {
&dev_attr_path_interval.attr,
&dev_attr_path_reset.attr,
&dev_attr_hpf.attr,
+ &dev_attr_ese.attr,
NULL,
};
@@ -1674,6 +1704,39 @@ static const struct attribute_group dasd_attr_group = {
.attrs = dasd_attrs,
};
+static struct attribute *capacity_attrs[] = {
+ &dev_attr_space_configured.attr,
+ &dev_attr_space_allocated.attr,
+ &dev_attr_logical_capacity.attr,
+ NULL,
+};
+
+static const struct attribute_group capacity_attr_group = {
+ .name = "capacity",
+ .attrs = capacity_attrs,
+};
+
+static struct attribute *ext_pool_attrs[] = {
+ &dev_attr_pool_id.attr,
+ &dev_attr_extent_size.attr,
+ &dev_attr_warn_threshold.attr,
+ &dev_attr_cap_at_warnlevel.attr,
+ &dev_attr_pool_oos.attr,
+ NULL,
+};
+
+static const struct attribute_group ext_pool_attr_group = {
+ .name = "extent_pool",
+ .attrs = ext_pool_attrs,
+};
+
+static const struct attribute_group *dasd_attr_groups[] = {
+ &dasd_attr_group,
+ &capacity_attr_group,
+ &ext_pool_attr_group,
+ NULL,
+};
+
/*
* Return value of the specified feature.
*/
@@ -1715,16 +1778,15 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
EXPORT_SYMBOL(dasd_set_feature);
-int
-dasd_add_sysfs_files(struct ccw_device *cdev)
+int dasd_add_sysfs_files(struct ccw_device *cdev)
{
- return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
+ return sysfs_create_groups(&cdev->dev.kobj, dasd_attr_groups);
}
void
dasd_remove_sysfs_files(struct ccw_device *cdev)
{
- sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
+ sysfs_remove_groups(&cdev->dev.kobj, dasd_attr_groups);
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index e1fe02477ea8..8d4971645cf1 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -615,14 +615,34 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
"dump sense not available for DIAG data");
}
+/*
+ * Initialize block layer request queue.
+ */
+static void dasd_diag_setup_blk_queue(struct dasd_block *block)
+{
+ unsigned int logical_block_size = block->bp_block;
+ struct request_queue *q = block->request_queue;
+ int max;
+
+ max = DIAG_MAX_BLOCKS << block->s2b_shift;
+ blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
+ q->limits.max_dev_sectors = max;
+ blk_queue_logical_block_size(q, logical_block_size);
+ blk_queue_max_hw_sectors(q, max);
+ blk_queue_max_segments(q, USHRT_MAX);
+ /* With page sized segments each segment can be translated into one idaw/tidaw */
+ blk_queue_max_segment_size(q, PAGE_SIZE);
+ blk_queue_segment_boundary(q, PAGE_SIZE - 1);
+}
+
static struct dasd_discipline dasd_diag_discipline = {
.owner = THIS_MODULE,
.name = "DIAG",
.ebcname = "DIAG",
- .max_blocks = DIAG_MAX_BLOCKS,
.check_device = dasd_diag_check_device,
.verify_path = dasd_generic_verify_path,
.fill_geometry = dasd_diag_fill_geometry,
+ .setup_blk_queue = dasd_diag_setup_blk_queue,
.start_IO = dasd_start_diag,
.term_IO = dasd_diag_term_IO,
.handle_terminated_request = dasd_diag_handle_terminated_request,
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index c09039eea707..fc53e1e221f0 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -42,20 +42,6 @@
#endif /* PRINTK_HEADER */
#define PRINTK_HEADER "dasd(eckd):"
-#define ECKD_C0(i) (i->home_bytes)
-#define ECKD_F(i) (i->formula)
-#define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):\
- (i->factors.f_0x02.f1))
-#define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):\
- (i->factors.f_0x02.f2))
-#define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):\
- (i->factors.f_0x02.f3))
-#define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0)
-#define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0)
-#define ECKD_F6(i) (i->factor6)
-#define ECKD_F7(i) (i->factor7)
-#define ECKD_F8(i) (i->factor8)
-
/*
* raw track access always map to 64k in memory
* so it maps to 16 blocks of 4k per track
@@ -103,6 +89,19 @@ static struct {
} *dasd_reserve_req;
static DEFINE_MUTEX(dasd_reserve_mutex);
+static struct {
+ struct dasd_ccw_req cqr;
+ struct ccw1 ccw[2];
+ char data[40];
+} *dasd_vol_info_req;
+static DEFINE_MUTEX(dasd_vol_info_mutex);
+
+struct ext_pool_exhaust_work_data {
+ struct work_struct worker;
+ struct dasd_device *device;
+ struct dasd_device *base;
+};
+
/* definitions for the path verification worker */
struct path_verification_work_data {
struct work_struct worker;
@@ -122,6 +121,7 @@ struct check_attention_work_data {
__u8 lpum;
};
+static int dasd_eckd_ext_pool_id(struct dasd_device *);
static int prepare_itcw(struct itcw *, unsigned int, unsigned int, int,
struct dasd_device *, struct dasd_device *,
unsigned int, int, unsigned int, unsigned int,
@@ -157,17 +157,10 @@ static const int sizes_trk0[] = { 28, 148, 84 };
#define LABEL_SIZE 140
/* head and record addresses of count_area read in analysis ccw */
-static const int count_area_head[] = { 0, 0, 0, 0, 2 };
+static const int count_area_head[] = { 0, 0, 0, 0, 1 };
static const int count_area_rec[] = { 1, 2, 3, 4, 1 };
static inline unsigned int
-round_up_multiple(unsigned int no, unsigned int mult)
-{
- int rem = no % mult;
- return (rem ? no - rem + mult : no);
-}
-
-static inline unsigned int
ceil_quot(unsigned int d1, unsigned int d2)
{
return (d1 + (d2 - 1)) / d2;
@@ -1491,6 +1484,311 @@ static int dasd_eckd_read_features(struct dasd_device *device)
return rc;
}
+/* Read Volume Information - Volume Storage Query */
+static int dasd_eckd_read_vol_info(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+ struct dasd_psf_prssd_data *prssdp;
+ struct dasd_rssd_vsq *vsq;
+ struct dasd_ccw_req *cqr;
+ struct ccw1 *ccw;
+ int useglobal;
+ int rc;
+
+ /* This command cannot be executed on an alias device */
+ if (private->uid.type == UA_BASE_PAV_ALIAS ||
+ private->uid.type == UA_HYPER_PAV_ALIAS)
+ return 0;
+
+ useglobal = 0;
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 /* PSF + RSSD */,
+ sizeof(*prssdp) + sizeof(*vsq), device, NULL);
+ if (IS_ERR(cqr)) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+ "Could not allocate initialization request");
+ mutex_lock(&dasd_vol_info_mutex);
+ useglobal = 1;
+ cqr = &dasd_vol_info_req->cqr;
+ memset(cqr, 0, sizeof(*cqr));
+ memset(dasd_vol_info_req, 0, sizeof(*dasd_vol_info_req));
+ cqr->cpaddr = &dasd_vol_info_req->ccw;
+ cqr->data = &dasd_vol_info_req->data;
+ cqr->magic = DASD_ECKD_MAGIC;
+ }
+
+ /* Prepare for Read Subsystem Data */
+ prssdp = cqr->data;
+ prssdp->order = PSF_ORDER_PRSSD;
+ prssdp->suborder = PSF_SUBORDER_VSQ; /* Volume Storage Query */
+ prssdp->lss = private->ned->ID;
+ prssdp->volume = private->ned->unit_addr;
+
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = DASD_ECKD_CCW_PSF;
+ ccw->count = sizeof(*prssdp);
+ ccw->flags |= CCW_FLAG_CC;
+ ccw->cda = (__u32)(addr_t)prssdp;
+
+ /* Read Subsystem Data - Volume Storage Query */
+ vsq = (struct dasd_rssd_vsq *)(prssdp + 1);
+ memset(vsq, 0, sizeof(*vsq));
+
+ ccw++;
+ ccw->cmd_code = DASD_ECKD_CCW_RSSD;
+ ccw->count = sizeof(*vsq);
+ ccw->flags |= CCW_FLAG_SLI;
+ ccw->cda = (__u32)(addr_t)vsq;
+
+ cqr->buildclk = get_tod_clock();
+ cqr->status = DASD_CQR_FILLED;
+ cqr->startdev = device;
+ cqr->memdev = device;
+ cqr->block = NULL;
+ cqr->retries = 256;
+ cqr->expires = device->default_expires * HZ;
+ /* The command might not be supported. Suppress the error output */
+ __set_bit(DASD_CQR_SUPPRESS_CR, &cqr->flags);
+
+ rc = dasd_sleep_on_interruptible(cqr);
+ if (rc == 0) {
+ memcpy(&private->vsq, vsq, sizeof(*vsq));
+ } else {
+ dev_warn(&device->cdev->dev,
+ "Reading the volume storage information failed with rc=%d\n", rc);
+ }
+
+ if (useglobal)
+ mutex_unlock(&dasd_vol_info_mutex);
+ else
+ dasd_sfree_request(cqr, cqr->memdev);
+
+ return rc;
+}
+
+static int dasd_eckd_is_ese(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->vsq.vol_info.ese;
+}
+
+static int dasd_eckd_ext_pool_id(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->vsq.extent_pool_id;
+}
+
+/*
+ * This value represents the total amount of available space. As more space is
+ * allocated by ESE volumes, this value will decrease.
+ * The data for this value is therefore updated on any call.
+ */
+static int dasd_eckd_space_configured(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+ int rc;
+
+ rc = dasd_eckd_read_vol_info(device);
+
+ return rc ? : private->vsq.space_configured;
+}
+
+/*
+ * The value of space allocated by an ESE volume may have changed and is
+ * therefore updated on any call.
+ */
+static int dasd_eckd_space_allocated(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+ int rc;
+
+ rc = dasd_eckd_read_vol_info(device);
+
+ return rc ? : private->vsq.space_allocated;
+}
+
+static int dasd_eckd_logical_capacity(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->vsq.logical_capacity;
+}
+
+static void dasd_eckd_ext_pool_exhaust_work(struct work_struct *work)
+{
+ struct ext_pool_exhaust_work_data *data;
+ struct dasd_device *device;
+ struct dasd_device *base;
+
+ data = container_of(work, struct ext_pool_exhaust_work_data, worker);
+ device = data->device;
+ base = data->base;
+
+ if (!base)
+ base = device;
+ if (dasd_eckd_space_configured(base) != 0) {
+ dasd_generic_space_avail(device);
+ } else {
+ dev_warn(&device->cdev->dev, "No space left in the extent pool\n");
+ DBF_DEV_EVENT(DBF_WARNING, device, "%s", "out of space");
+ }
+
+ dasd_put_device(device);
+ kfree(data);
+}
+
+static int dasd_eckd_ext_pool_exhaust(struct dasd_device *device,
+ struct dasd_ccw_req *cqr)
+{
+ struct ext_pool_exhaust_work_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_ATOMIC);
+ if (!data)
+ return -ENOMEM;
+ INIT_WORK(&data->worker, dasd_eckd_ext_pool_exhaust_work);
+ dasd_get_device(device);
+ data->device = device;
+
+ if (cqr->block)
+ data->base = cqr->block->base;
+ else if (cqr->basedev)
+ data->base = cqr->basedev;
+ else
+ data->base = NULL;
+
+ schedule_work(&data->worker);
+
+ return 0;
+}
+
+static void dasd_eckd_cpy_ext_pool_data(struct dasd_device *device,
+ struct dasd_rssd_lcq *lcq)
+{
+ struct dasd_eckd_private *private = device->private;
+ int pool_id = dasd_eckd_ext_pool_id(device);
+ struct dasd_ext_pool_sum eps;
+ int i;
+
+ for (i = 0; i < lcq->pool_count; i++) {
+ eps = lcq->ext_pool_sum[i];
+ if (eps.pool_id == pool_id) {
+ memcpy(&private->eps, &eps,
+ sizeof(struct dasd_ext_pool_sum));
+ }
+ }
+}
+
+/* Read Extent Pool Information - Logical Configuration Query */
+static int dasd_eckd_read_ext_pool_info(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+ struct dasd_psf_prssd_data *prssdp;
+ struct dasd_rssd_lcq *lcq;
+ struct dasd_ccw_req *cqr;
+ struct ccw1 *ccw;
+ int rc;
+
+ /* This command cannot be executed on an alias device */
+ if (private->uid.type == UA_BASE_PAV_ALIAS ||
+ private->uid.type == UA_HYPER_PAV_ALIAS)
+ return 0;
+
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 /* PSF + RSSD */,
+ sizeof(*prssdp) + sizeof(*lcq), device, NULL);
+ if (IS_ERR(cqr)) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+ "Could not allocate initialization request");
+ return PTR_ERR(cqr);
+ }
+
+ /* Prepare for Read Subsystem Data */
+ prssdp = cqr->data;
+ memset(prssdp, 0, sizeof(*prssdp));
+ prssdp->order = PSF_ORDER_PRSSD;
+ prssdp->suborder = PSF_SUBORDER_LCQ; /* Logical Configuration Query */
+
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = DASD_ECKD_CCW_PSF;
+ ccw->count = sizeof(*prssdp);
+ ccw->flags |= CCW_FLAG_CC;
+ ccw->cda = (__u32)(addr_t)prssdp;
+
+ lcq = (struct dasd_rssd_lcq *)(prssdp + 1);
+ memset(lcq, 0, sizeof(*lcq));
+
+ ccw++;
+ ccw->cmd_code = DASD_ECKD_CCW_RSSD;
+ ccw->count = sizeof(*lcq);
+ ccw->flags |= CCW_FLAG_SLI;
+ ccw->cda = (__u32)(addr_t)lcq;
+
+ cqr->buildclk = get_tod_clock();
+ cqr->status = DASD_CQR_FILLED;
+ cqr->startdev = device;
+ cqr->memdev = device;
+ cqr->block = NULL;
+ cqr->retries = 256;
+ cqr->expires = device->default_expires * HZ;
+ /* The command might not be supported. Suppress the error output */
+ __set_bit(DASD_CQR_SUPPRESS_CR, &cqr->flags);
+
+ rc = dasd_sleep_on_interruptible(cqr);
+ if (rc == 0) {
+ dasd_eckd_cpy_ext_pool_data(device, lcq);
+ } else {
+ dev_warn(&device->cdev->dev,
+ "Reading the logical configuration failed with rc=%d\n", rc);
+ }
+
+ dasd_sfree_request(cqr, cqr->memdev);
+
+ return rc;
+}
+
+/*
+ * Depending on the device type, the extent size is specified either as
+ * cylinders per extent (CKD) or size per extent (FBA)
+ * A 1GB size corresponds to 1113cyl, and 16MB to 21cyl.
+ */
+static int dasd_eckd_ext_size(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+ struct dasd_ext_pool_sum eps = private->eps;
+
+ if (!eps.flags.extent_size_valid)
+ return 0;
+ if (eps.extent_size.size_1G)
+ return 1113;
+ if (eps.extent_size.size_16M)
+ return 21;
+
+ return 0;
+}
+
+static int dasd_eckd_ext_pool_warn_thrshld(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->eps.warn_thrshld;
+}
+
+static int dasd_eckd_ext_pool_cap_at_warnlevel(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->eps.flags.capacity_at_warnlevel;
+}
+
+/*
+ * Extent Pool out of space
+ */
+static int dasd_eckd_ext_pool_oos(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->eps.flags.pool_oos;
+}
/*
* Build CP for Perform Subsystem Function - SSC.
@@ -1721,6 +2019,16 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Feature Codes */
dasd_eckd_read_features(device);
+ /* Read Volume Information */
+ rc = dasd_eckd_read_vol_info(device);
+ if (rc)
+ goto out_err3;
+
+ /* Read Extent Pool Information */
+ rc = dasd_eckd_read_ext_pool_info(device);
+ if (rc)
+ goto out_err3;
+
/* Read Device Characteristics */
rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
&private->rdc_data, 64);
@@ -1751,6 +2059,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
if (readonly)
set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+ if (dasd_eckd_is_ese(device))
+ dasd_set_feature(device->cdev, DASD_FEATURE_DISCARD, 1);
+
dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) "
"with %d cylinders, %d heads, %d sectors%s\n",
private->rdc_data.dev_type,
@@ -1823,8 +2134,8 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
- /* Define extent for the first 3 tracks. */
- define_extent(ccw++, cqr->data, 0, 2,
+ /* Define extent for the first 2 tracks. */
+ define_extent(ccw++, cqr->data, 0, 1,
DASD_ECKD_CCW_READ_COUNT, device, 0);
LO_data = cqr->data + sizeof(struct DE_eckd_data);
/* Locate record for the first 4 records on track 0. */
@@ -1843,9 +2154,9 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
count_data++;
}
- /* Locate record for the first record on track 2. */
+ /* Locate record for the first record on track 1. */
ccw[-1].flags |= CCW_FLAG_CC;
- locate_record(ccw++, LO_data++, 2, 0, 1,
+ locate_record(ccw++, LO_data++, 1, 0, 1,
DASD_ECKD_CCW_READ_COUNT, device, 0);
/* Read count ccw. */
ccw[-1].flags |= CCW_FLAG_CC;
@@ -1860,6 +2171,9 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
cqr->retries = 255;
cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
+ /* Set flags to suppress output for expected errors */
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+
return cqr;
}
@@ -1967,7 +2281,7 @@ static int dasd_eckd_end_analysis(struct dasd_block *block)
}
}
if (i == 3)
- count_area = &private->count_area[4];
+ count_area = &private->count_area[3];
if (private->uses_cdl == 0) {
for (i = 0; i < 5; i++) {
@@ -2099,8 +2413,7 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata,
*/
itcw_size = itcw_calc_size(0, count, 0);
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev,
- NULL);
+ cqr = dasd_fmalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev);
if (IS_ERR(cqr))
return cqr;
@@ -2193,8 +2506,7 @@ dasd_eckd_build_check(struct dasd_device *base, struct format_data_t *fdata,
}
cplength += count;
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize,
- startdev, NULL);
+ cqr = dasd_fmalloc_request(DASD_ECKD_MAGIC, cplength, datasize, startdev);
if (IS_ERR(cqr))
return cqr;
@@ -2241,13 +2553,11 @@ dasd_eckd_build_check(struct dasd_device *base, struct format_data_t *fdata,
}
static struct dasd_ccw_req *
-dasd_eckd_build_format(struct dasd_device *base,
- struct format_data_t *fdata,
- int enable_pav)
+dasd_eckd_build_format(struct dasd_device *base, struct dasd_device *startdev,
+ struct format_data_t *fdata, int enable_pav)
{
struct dasd_eckd_private *base_priv;
struct dasd_eckd_private *start_priv;
- struct dasd_device *startdev = NULL;
struct dasd_ccw_req *fcp;
struct eckd_count *ect;
struct ch_t address;
@@ -2338,9 +2648,8 @@ dasd_eckd_build_format(struct dasd_device *base,
fdata->intensity);
return ERR_PTR(-EINVAL);
}
- /* Allocate the format ccw request. */
- fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
- datasize, startdev, NULL);
+
+ fcp = dasd_fmalloc_request(DASD_ECKD_MAGIC, cplength, datasize, startdev);
if (IS_ERR(fcp))
return fcp;
@@ -2513,7 +2822,7 @@ dasd_eckd_format_build_ccw_req(struct dasd_device *base,
struct dasd_ccw_req *ccw_req;
if (!fmt_buffer) {
- ccw_req = dasd_eckd_build_format(base, fdata, enable_pav);
+ ccw_req = dasd_eckd_build_format(base, NULL, fdata, enable_pav);
} else {
if (tpm)
ccw_req = dasd_eckd_build_check_tcw(base, fdata,
@@ -2659,7 +2968,7 @@ out_err:
rc = -EIO;
}
list_del_init(&cqr->blocklist);
- dasd_sfree_request(cqr, device);
+ dasd_ffree_request(cqr, device);
private->count--;
}
@@ -2699,6 +3008,96 @@ static int dasd_eckd_format_device(struct dasd_device *base,
}
/*
+ * Callback function to free ESE format requests.
+ */
+static void dasd_eckd_ese_format_cb(struct dasd_ccw_req *cqr, void *data)
+{
+ struct dasd_device *device = cqr->startdev;
+ struct dasd_eckd_private *private = device->private;
+
+ private->count--;
+ dasd_ffree_request(cqr, device);
+}
+
+static struct dasd_ccw_req *
+dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr)
+{
+ struct dasd_eckd_private *private;
+ struct format_data_t fdata;
+ unsigned int recs_per_trk;
+ struct dasd_ccw_req *fcqr;
+ struct dasd_device *base;
+ struct dasd_block *block;
+ unsigned int blksize;
+ struct request *req;
+ sector_t first_trk;
+ sector_t last_trk;
+ int rc;
+
+ req = cqr->callback_data;
+ base = cqr->block->base;
+ private = base->private;
+ block = base->block;
+ blksize = block->bp_block;
+ recs_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
+
+ first_trk = blk_rq_pos(req) >> block->s2b_shift;
+ sector_div(first_trk, recs_per_trk);
+ last_trk =
+ (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift;
+ sector_div(last_trk, recs_per_trk);
+
+ fdata.start_unit = first_trk;
+ fdata.stop_unit = last_trk;
+ fdata.blksize = blksize;
+ fdata.intensity = private->uses_cdl ? DASD_FMT_INT_COMPAT : 0;
+
+ rc = dasd_eckd_format_sanity_checks(base, &fdata);
+ if (rc)
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * We're building the request with PAV disabled as we're reusing
+ * the former startdev.
+ */
+ fcqr = dasd_eckd_build_format(base, startdev, &fdata, 0);
+ if (IS_ERR(fcqr))
+ return fcqr;
+
+ fcqr->callback = dasd_eckd_ese_format_cb;
+
+ return fcqr;
+}
+
+/*
+ * When data is read from an unformatted area of an ESE volume, this function
+ * returns zeroed data and thereby mimics a read of zero data.
+ */
+static void dasd_eckd_ese_read(struct dasd_ccw_req *cqr)
+{
+ unsigned int blksize, off;
+ struct dasd_device *base;
+ struct req_iterator iter;
+ struct request *req;
+ struct bio_vec bv;
+ char *dst;
+
+ req = (struct request *) cqr->callback_data;
+ base = cqr->block->base;
+ blksize = base->block->bp_block;
+
+ rq_for_each_segment(bv, req, iter) {
+ dst = page_address(bv.bv_page) + bv.bv_offset;
+ for (off = 0; off < bv.bv_len; off += blksize) {
+ if (dst && rq_data_dir(req) == READ) {
+ dst += off;
+ memset(dst, 0, blksize);
+ }
+ }
+ }
+}
+
+/*
* Helper function to count consecutive records of a single track.
*/
static int dasd_eckd_count_records(struct eckd_count *fmt_buffer, int start,
@@ -3033,6 +3432,277 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
}
}
+static int dasd_eckd_ras_sanity_checks(struct dasd_device *device,
+ unsigned int first_trk,
+ unsigned int last_trk)
+{
+ struct dasd_eckd_private *private = device->private;
+ unsigned int trks_per_vol;
+ int rc = 0;
+
+ trks_per_vol = private->real_cyl * private->rdc_data.trk_per_cyl;
+
+ if (first_trk >= trks_per_vol) {
+ dev_warn(&device->cdev->dev,
+ "Start track number %u used in the space release command is too big\n",
+ first_trk);
+ rc = -EINVAL;
+ } else if (last_trk >= trks_per_vol) {
+ dev_warn(&device->cdev->dev,
+ "Stop track number %u used in the space release command is too big\n",
+ last_trk);
+ rc = -EINVAL;
+ } else if (first_trk > last_trk) {
+ dev_warn(&device->cdev->dev,
+ "Start track %u used in the space release command exceeds the end track\n",
+ first_trk);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+/*
+ * Helper function to count the amount of involved extents within a given range
+ * with extent alignment in mind.
+ */
+static int count_exts(unsigned int from, unsigned int to, int trks_per_ext)
+{
+ int cur_pos = 0;
+ int count = 0;
+ int tmp;
+
+ if (from == to)
+ return 1;
+
+ /* Count first partial extent */
+ if (from % trks_per_ext != 0) {
+ tmp = from + trks_per_ext - (from % trks_per_ext) - 1;
+ if (tmp > to)
+ tmp = to;
+ cur_pos = tmp - from + 1;
+ count++;
+ }
+ /* Count full extents */
+ if (to - (from + cur_pos) + 1 >= trks_per_ext) {
+ tmp = to - ((to - trks_per_ext + 1) % trks_per_ext);
+ count += (tmp - (from + cur_pos) + 1) / trks_per_ext;
+ cur_pos = tmp;
+ }
+ /* Count last partial extent */
+ if (cur_pos < to)
+ count++;
+
+ return count;
+}
+
+/*
+ * Release allocated space for a given range or an entire volume.
+ */
+static struct dasd_ccw_req *
+dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
+ struct request *req, unsigned int first_trk,
+ unsigned int last_trk, int by_extent)
+{
+ struct dasd_eckd_private *private = device->private;
+ struct dasd_dso_ras_ext_range *ras_range;
+ struct dasd_rssd_features *features;
+ struct dasd_dso_ras_data *ras_data;
+ u16 heads, beg_head, end_head;
+ int cur_to_trk, cur_from_trk;
+ struct dasd_ccw_req *cqr;
+ u32 beg_cyl, end_cyl;
+ struct ccw1 *ccw;
+ int trks_per_ext;
+ size_t ras_size;
+ size_t size;
+ int nr_exts;
+ void *rq;
+ int i;
+
+ if (dasd_eckd_ras_sanity_checks(device, first_trk, last_trk))
+ return ERR_PTR(-EINVAL);
+
+ rq = req ? blk_mq_rq_to_pdu(req) : NULL;
+
+ features = &private->features;
+
+ trks_per_ext = dasd_eckd_ext_size(device) * private->rdc_data.trk_per_cyl;
+ nr_exts = 0;
+ if (by_extent)
+ nr_exts = count_exts(first_trk, last_trk, trks_per_ext);
+ ras_size = sizeof(*ras_data);
+ size = ras_size + (nr_exts * sizeof(*ras_range));
+
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, size, device, rq);
+ if (IS_ERR(cqr)) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+ "Could not allocate RAS request");
+ return cqr;
+ }
+
+ ras_data = cqr->data;
+ memset(ras_data, 0, size);
+
+ ras_data->order = DSO_ORDER_RAS;
+ ras_data->flags.vol_type = 0; /* CKD volume */
+ /* Release specified extents or entire volume */
+ ras_data->op_flags.by_extent = by_extent;
+ /*
+ * This bit guarantees initialisation of tracks within an extent that is
+ * not fully specified, but is only supported with a certain feature
+ * subset.
+ */
+ ras_data->op_flags.guarantee_init = !!(features->feature[56] & 0x01);
+ ras_data->lss = private->ned->ID;
+ ras_data->dev_addr = private->ned->unit_addr;
+ ras_data->nr_exts = nr_exts;
+
+ if (by_extent) {
+ heads = private->rdc_data.trk_per_cyl;
+ cur_from_trk = first_trk;
+ cur_to_trk = first_trk + trks_per_ext -
+ (first_trk % trks_per_ext) - 1;
+ if (cur_to_trk > last_trk)
+ cur_to_trk = last_trk;
+ ras_range = (struct dasd_dso_ras_ext_range *)(cqr->data + ras_size);
+
+ for (i = 0; i < nr_exts; i++) {
+ beg_cyl = cur_from_trk / heads;
+ beg_head = cur_from_trk % heads;
+ end_cyl = cur_to_trk / heads;
+ end_head = cur_to_trk % heads;
+
+ set_ch_t(&ras_range->beg_ext, beg_cyl, beg_head);
+ set_ch_t(&ras_range->end_ext, end_cyl, end_head);
+
+ cur_from_trk = cur_to_trk + 1;
+ cur_to_trk = cur_from_trk + trks_per_ext - 1;
+ if (cur_to_trk > last_trk)
+ cur_to_trk = last_trk;
+ ras_range++;
+ }
+ }
+
+ ccw = cqr->cpaddr;
+ ccw->cda = (__u32)(addr_t)cqr->data;
+ ccw->cmd_code = DASD_ECKD_CCW_DSO;
+ ccw->count = size;
+
+ cqr->startdev = device;
+ cqr->memdev = device;
+ cqr->block = block;
+ cqr->retries = 256;
+ cqr->expires = device->default_expires * HZ;
+ cqr->buildclk = get_tod_clock();
+ cqr->status = DASD_CQR_FILLED;
+
+ return cqr;
+}
+
+static int dasd_eckd_release_space_full(struct dasd_device *device)
+{
+ struct dasd_ccw_req *cqr;
+ int rc;
+
+ cqr = dasd_eckd_dso_ras(device, NULL, NULL, 0, 0, 0);
+ if (IS_ERR(cqr))
+ return PTR_ERR(cqr);
+
+ rc = dasd_sleep_on_interruptible(cqr);
+
+ dasd_sfree_request(cqr, cqr->memdev);
+
+ return rc;
+}
+
+static int dasd_eckd_release_space_trks(struct dasd_device *device,
+ unsigned int from, unsigned int to)
+{
+ struct dasd_eckd_private *private = device->private;
+ struct dasd_block *block = device->block;
+ struct dasd_ccw_req *cqr, *n;
+ struct list_head ras_queue;
+ unsigned int device_exts;
+ int trks_per_ext;
+ int stop, step;
+ int cur_pos;
+ int rc = 0;
+ int retry;
+
+ INIT_LIST_HEAD(&ras_queue);
+
+ device_exts = private->real_cyl / dasd_eckd_ext_size(device);
+ trks_per_ext = dasd_eckd_ext_size(device) * private->rdc_data.trk_per_cyl;
+
+ /* Make sure device limits are not exceeded */
+ step = trks_per_ext * min(device_exts, DASD_ECKD_RAS_EXTS_MAX);
+ cur_pos = from;
+
+ do {
+ retry = 0;
+ while (cur_pos < to) {
+ stop = cur_pos + step -
+ ((cur_pos + step) % trks_per_ext) - 1;
+ if (stop > to)
+ stop = to;
+
+ cqr = dasd_eckd_dso_ras(device, NULL, NULL, cur_pos, stop, 1);
+ if (IS_ERR(cqr)) {
+ rc = PTR_ERR(cqr);
+ if (rc == -ENOMEM) {
+ if (list_empty(&ras_queue))
+ goto out;
+ retry = 1;
+ break;
+ }
+ goto err_out;
+ }
+
+ spin_lock_irq(&block->queue_lock);
+ list_add_tail(&cqr->blocklist, &ras_queue);
+ spin_unlock_irq(&block->queue_lock);
+ cur_pos = stop + 1;
+ }
+
+ rc = dasd_sleep_on_queue_interruptible(&ras_queue);
+
+err_out:
+ list_for_each_entry_safe(cqr, n, &ras_queue, blocklist) {
+ device = cqr->startdev;
+ private = device->private;
+
+ spin_lock_irq(&block->queue_lock);
+ list_del_init(&cqr->blocklist);
+ spin_unlock_irq(&block->queue_lock);
+ dasd_sfree_request(cqr, device);
+ private->count--;
+ }
+ } while (retry);
+
+out:
+ return rc;
+}
+
+static int dasd_eckd_release_space(struct dasd_device *device,
+ struct format_data_t *rdata)
+{
+ if (rdata->intensity & DASD_FMT_INT_ESE_FULL)
+ return dasd_eckd_release_space_full(device);
+ else if (rdata->intensity == 0)
+ return dasd_eckd_release_space_trks(device, rdata->start_unit,
+ rdata->stop_unit);
+ else
+ return -EINVAL;
+}
+
+static struct dasd_ccw_req *
+dasd_eckd_build_cp_discard(struct dasd_device *device, struct dasd_block *block,
+ struct request *req, sector_t first_trk,
+ sector_t last_trk)
+{
+ return dasd_eckd_dso_ras(device, block, req, first_trk, last_trk, 1);
+}
+
static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
struct dasd_device *startdev,
struct dasd_block *block,
@@ -3214,6 +3884,14 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
cqr->retries = startdev->default_retries;
cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
+
+ /* Set flags to suppress output for expected errors */
+ if (dasd_eckd_is_ese(basedev)) {
+ set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+ }
+
return cqr;
}
@@ -3385,6 +4063,11 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
cqr->retries = startdev->default_retries;
cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
+
+ /* Set flags to suppress output for expected errors */
+ if (dasd_eckd_is_ese(basedev))
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+
return cqr;
}
@@ -3704,6 +4387,14 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
cqr->retries = startdev->default_retries;
cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
+
+ /* Set flags to suppress output for expected errors */
+ if (dasd_eckd_is_ese(basedev)) {
+ set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+ }
+
return cqr;
out_error:
dasd_sfree_request(cqr, startdev);
@@ -3756,6 +4447,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
cmdwtd = private->features.feature[12] & 0x40;
use_prefix = private->features.feature[8] & 0x01;
+ if (req_op(req) == REQ_OP_DISCARD)
+ return dasd_eckd_build_cp_discard(startdev, block, req,
+ first_trk, last_trk);
+
cqr = NULL;
if (cdlspecial || dasd_page_cache) {
/* do nothing, just fall through to the cmd mode single case */
@@ -4034,12 +4729,14 @@ static struct dasd_ccw_req *dasd_eckd_build_alias_cp(struct dasd_device *base,
struct dasd_block *block,
struct request *req)
{
+ struct dasd_device *startdev = NULL;
struct dasd_eckd_private *private;
- struct dasd_device *startdev;
- unsigned long flags;
struct dasd_ccw_req *cqr;
+ unsigned long flags;
- startdev = dasd_alias_get_start_dev(base);
+ /* Discard requests can only be processed on base devices */
+ if (req_op(req) != REQ_OP_DISCARD)
+ startdev = dasd_alias_get_start_dev(base);
if (!startdev)
startdev = base;
private = startdev->private;
@@ -4965,6 +5662,16 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
/* Read Feature Codes */
dasd_eckd_read_features(device);
+ /* Read Volume Information */
+ rc = dasd_eckd_read_vol_info(device);
+ if (rc)
+ goto out_err2;
+
+ /* Read Extent Pool Information */
+ rc = dasd_eckd_read_ext_pool_info(device);
+ if (rc)
+ goto out_err2;
+
/* Read Device Characteristics */
rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
&temp_rdc_data, 64);
@@ -5635,6 +6342,73 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
device->discipline->check_attention(device, lpum);
}
+static void dasd_eckd_oos_resume(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+ struct alias_pav_group *pavgroup, *tempgroup;
+ struct dasd_device *dev, *n;
+ unsigned long flags;
+
+ spin_lock_irqsave(&private->lcu->lock, flags);
+ list_for_each_entry_safe(dev, n, &private->lcu->active_devices,
+ alias_list) {
+ if (dev->stopped & DASD_STOPPED_NOSPC)
+ dasd_generic_space_avail(dev);
+ }
+ list_for_each_entry_safe(dev, n, &private->lcu->inactive_devices,
+ alias_list) {
+ if (dev->stopped & DASD_STOPPED_NOSPC)
+ dasd_generic_space_avail(dev);
+ }
+ /* devices in PAV groups */
+ list_for_each_entry_safe(pavgroup, tempgroup,
+ &private->lcu->grouplist,
+ group) {
+ list_for_each_entry_safe(dev, n, &pavgroup->baselist,
+ alias_list) {
+ if (dev->stopped & DASD_STOPPED_NOSPC)
+ dasd_generic_space_avail(dev);
+ }
+ list_for_each_entry_safe(dev, n, &pavgroup->aliaslist,
+ alias_list) {
+ if (dev->stopped & DASD_STOPPED_NOSPC)
+ dasd_generic_space_avail(dev);
+ }
+ }
+ spin_unlock_irqrestore(&private->lcu->lock, flags);
+}
+
+static void dasd_eckd_handle_oos(struct dasd_device *device, void *messages,
+ __u8 lpum)
+{
+ struct dasd_oos_message *oos = messages;
+
+ switch (oos->code) {
+ case REPO_WARN:
+ case POOL_WARN:
+ dev_warn(&device->cdev->dev,
+ "Extent pool usage has reached a critical value\n");
+ dasd_eckd_oos_resume(device);
+ break;
+ case REPO_EXHAUST:
+ case POOL_EXHAUST:
+ dev_warn(&device->cdev->dev,
+ "Extent pool is exhausted\n");
+ break;
+ case REPO_RELIEVE:
+ case POOL_RELIEVE:
+ dev_info(&device->cdev->dev,
+ "Extent pool physical space constraint has been relieved\n");
+ break;
+ }
+
+ /* In any case, update related data */
+ dasd_eckd_read_ext_pool_info(device);
+
+ /* to make sure there is no attention left schedule work again */
+ device->discipline->check_attention(device, lpum);
+}
+
static void dasd_eckd_check_attention_work(struct work_struct *work)
{
struct check_attention_work_data *data;
@@ -5653,9 +6427,14 @@ static void dasd_eckd_check_attention_work(struct work_struct *work)
rc = dasd_eckd_read_message_buffer(device, messages, data->lpum);
if (rc)
goto out;
+
if (messages->length == ATTENTION_LENGTH_CUIR &&
messages->format == ATTENTION_FORMAT_CUIR)
dasd_eckd_handle_cuir(device, messages, data->lpum);
+ if (messages->length == ATTENTION_LENGTH_OOS &&
+ messages->format == ATTENTION_FORMAT_OOS)
+ dasd_eckd_handle_oos(device, messages, data->lpum);
+
out:
dasd_put_device(device);
kfree(messages);
@@ -5734,6 +6513,72 @@ static void dasd_eckd_handle_hpf_error(struct dasd_device *device,
dasd_schedule_requeue(device);
}
+/*
+ * Initialize block layer request queue.
+ */
+static void dasd_eckd_setup_blk_queue(struct dasd_block *block)
+{
+ unsigned int logical_block_size = block->bp_block;
+ struct request_queue *q = block->request_queue;
+ struct dasd_device *device = block->base;
+ struct dasd_eckd_private *private;
+ unsigned int max_discard_sectors;
+ unsigned int max_bytes;
+ unsigned int ext_bytes; /* Extent Size in Bytes */
+ int recs_per_trk;
+ int trks_per_cyl;
+ int ext_limit;
+ int ext_size; /* Extent Size in Cylinders */
+ int max;
+
+ private = device->private;
+ trks_per_cyl = private->rdc_data.trk_per_cyl;
+ recs_per_trk = recs_per_track(&private->rdc_data, 0, logical_block_size);
+
+ if (device->features & DASD_FEATURE_USERAW) {
+ /*
+ * the max_blocks value for raw_track access is 256
+ * it is higher than the native ECKD value because we
+ * only need one ccw per track
+ * so the max_hw_sectors are
+ * 2048 x 512B = 1024kB = 16 tracks
+ */
+ max = DASD_ECKD_MAX_BLOCKS_RAW << block->s2b_shift;
+ } else {
+ max = DASD_ECKD_MAX_BLOCKS << block->s2b_shift;
+ }
+ blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
+ q->limits.max_dev_sectors = max;
+ blk_queue_logical_block_size(q, logical_block_size);
+ blk_queue_max_hw_sectors(q, max);
+ blk_queue_max_segments(q, USHRT_MAX);
+ /* With page sized segments each segment can be translated into one idaw/tidaw */
+ blk_queue_max_segment_size(q, PAGE_SIZE);
+ blk_queue_segment_boundary(q, PAGE_SIZE - 1);
+
+ if (dasd_eckd_is_ese(device)) {
+ /*
+ * Depending on the extent size, up to UINT_MAX bytes can be
+ * accepted. However, neither DASD_ECKD_RAS_EXTS_MAX nor the
+ * device limits should be exceeded.
+ */
+ ext_size = dasd_eckd_ext_size(device);
+ ext_limit = min(private->real_cyl / ext_size, DASD_ECKD_RAS_EXTS_MAX);
+ ext_bytes = ext_size * trks_per_cyl * recs_per_trk *
+ logical_block_size;
+ max_bytes = UINT_MAX - (UINT_MAX % ext_bytes);
+ if (max_bytes / ext_bytes > ext_limit)
+ max_bytes = ext_bytes * ext_limit;
+
+ max_discard_sectors = max_bytes / 512;
+
+ blk_queue_max_discard_sectors(q, max_discard_sectors);
+ blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
+ q->limits.discard_granularity = ext_bytes;
+ q->limits.discard_alignment = ext_bytes;
+ }
+}
+
static struct ccw_driver dasd_eckd_driver = {
.driver = {
.name = "dasd-eckd",
@@ -5754,24 +6599,10 @@ static struct ccw_driver dasd_eckd_driver = {
.int_class = IRQIO_DAS,
};
-/*
- * max_blocks is dependent on the amount of storage that is available
- * in the static io buffer for each device. Currently each device has
- * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
- * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
- * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
- * addition we have one define extent ccw + 16 bytes of data and one
- * locate record ccw + 16 bytes of data. That makes:
- * (8192 - 24 - 136 - 8 - 16 - 8 - 16) / 16 = 499 blocks at maximum.
- * We want to fit two into the available memory so that we can immediately
- * start the next request if one finishes off. That makes 249.5 blocks
- * for one request. Give a little safety and the result is 240.
- */
static struct dasd_discipline dasd_eckd_discipline = {
.owner = THIS_MODULE,
.name = "ECKD",
.ebcname = "ECKD",
- .max_blocks = 190,
.check_device = dasd_eckd_check_characteristics,
.uncheck_device = dasd_eckd_uncheck_device,
.do_analysis = dasd_eckd_do_analysis,
@@ -5779,6 +6610,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.basic_to_ready = dasd_eckd_basic_to_ready,
.online_to_ready = dasd_eckd_online_to_ready,
.basic_to_known = dasd_eckd_basic_to_known,
+ .setup_blk_queue = dasd_eckd_setup_blk_queue,
.fill_geometry = dasd_eckd_fill_geometry,
.start_IO = dasd_start_IO,
.term_IO = dasd_term_IO,
@@ -5806,6 +6638,19 @@ static struct dasd_discipline dasd_eckd_discipline = {
.disable_hpf = dasd_eckd_disable_hpf_device,
.hpf_enabled = dasd_eckd_hpf_enabled,
.reset_path = dasd_eckd_reset_path,
+ .is_ese = dasd_eckd_is_ese,
+ .space_allocated = dasd_eckd_space_allocated,
+ .space_configured = dasd_eckd_space_configured,
+ .logical_capacity = dasd_eckd_logical_capacity,
+ .release_space = dasd_eckd_release_space,
+ .ext_pool_id = dasd_eckd_ext_pool_id,
+ .ext_size = dasd_eckd_ext_size,
+ .ext_pool_cap_at_warnlevel = dasd_eckd_ext_pool_cap_at_warnlevel,
+ .ext_pool_warn_thrshld = dasd_eckd_ext_pool_warn_thrshld,
+ .ext_pool_oos = dasd_eckd_ext_pool_oos,
+ .ext_pool_exhaust = dasd_eckd_ext_pool_exhaust,
+ .ese_format = dasd_eckd_ese_format,
+ .ese_read = dasd_eckd_ese_read,
};
static int __init
@@ -5818,16 +6663,22 @@ dasd_eckd_init(void)
GFP_KERNEL | GFP_DMA);
if (!dasd_reserve_req)
return -ENOMEM;
+ dasd_vol_info_req = kmalloc(sizeof(*dasd_vol_info_req),
+ GFP_KERNEL | GFP_DMA);
+ if (!dasd_vol_info_req)
+ return -ENOMEM;
path_verification_worker = kmalloc(sizeof(*path_verification_worker),
GFP_KERNEL | GFP_DMA);
if (!path_verification_worker) {
kfree(dasd_reserve_req);
+ kfree(dasd_vol_info_req);
return -ENOMEM;
}
rawpadpage = (void *)__get_free_page(GFP_KERNEL);
if (!rawpadpage) {
kfree(path_verification_worker);
kfree(dasd_reserve_req);
+ kfree(dasd_vol_info_req);
return -ENOMEM;
}
ret = ccw_driver_register(&dasd_eckd_driver);
@@ -5836,6 +6687,7 @@ dasd_eckd_init(void)
else {
kfree(path_verification_worker);
kfree(dasd_reserve_req);
+ kfree(dasd_vol_info_req);
free_page((unsigned long)rawpadpage);
}
return ret;
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index 5869d2fede35..6943508d0f1d 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -50,16 +50,26 @@
#define DASD_ECKD_CCW_PFX_READ 0xEA
#define DASD_ECKD_CCW_RSCK 0xF9
#define DASD_ECKD_CCW_RCD 0xFA
+#define DASD_ECKD_CCW_DSO 0xF7
+
+/* Define Subssystem Function / Orders */
+#define DSO_ORDER_RAS 0x81
/*
- * Perform Subsystem Function / Sub-Orders
+ * Perform Subsystem Function / Orders
*/
#define PSF_ORDER_PRSSD 0x18
#define PSF_ORDER_CUIR_RESPONSE 0x1A
-#define PSF_SUBORDER_QHA 0x1C
#define PSF_ORDER_SSC 0x1D
/*
+ * Perform Subsystem Function / Sub-Orders
+ */
+#define PSF_SUBORDER_QHA 0x1C /* Query Host Access */
+#define PSF_SUBORDER_VSQ 0x52 /* Volume Storage Query */
+#define PSF_SUBORDER_LCQ 0x53 /* Logical Configuration Query */
+
+/*
* CUIR response condition codes
*/
#define PSF_CUIR_INVALID 0x00
@@ -80,10 +90,22 @@
#define CUIR_RESUME 0x02
/*
+ * Out-of-space (OOS) Codes
+ */
+#define REPO_WARN 0x01
+#define REPO_EXHAUST 0x02
+#define POOL_WARN 0x03
+#define POOL_EXHAUST 0x04
+#define REPO_RELIEVE 0x05
+#define POOL_RELIEVE 0x06
+
+/*
* attention message definitions
*/
#define ATTENTION_LENGTH_CUIR 0x0e
#define ATTENTION_FORMAT_CUIR 0x01
+#define ATTENTION_LENGTH_OOS 0x10
+#define ATTENTION_FORMAT_OOS 0x06
#define DASD_ECKD_PG_GROUPED 0x10
@@ -99,6 +121,12 @@
#define DASD_ECKD_PATH_THRHLD 256
#define DASD_ECKD_PATH_INTERVAL 300
+/*
+ * Maximum number of blocks to be chained
+ */
+#define DASD_ECKD_MAX_BLOCKS 190
+#define DASD_ECKD_MAX_BLOCKS_RAW 256
+
/*****************************************************************************
* SECTION: Type Definitions
****************************************************************************/
@@ -116,35 +144,12 @@ struct ch_t {
__u16 head;
} __attribute__ ((packed));
-struct chs_t {
- __u16 cyl;
- __u16 head;
- __u32 sector;
-} __attribute__ ((packed));
-
struct chr_t {
__u16 cyl;
__u16 head;
__u8 record;
} __attribute__ ((packed));
-struct geom_t {
- __u16 cyl;
- __u16 head;
- __u32 sector;
-} __attribute__ ((packed));
-
-struct eckd_home {
- __u8 skip_control[14];
- __u16 cell_number;
- __u8 physical_addr[3];
- __u8 flag;
- struct ch_t track_addr;
- __u8 reserved;
- __u8 key_length;
- __u8 reserved2[2];
-} __attribute__ ((packed));
-
struct DE_eckd_data {
struct {
unsigned char perm:2; /* Permissions on this extent */
@@ -387,6 +392,86 @@ struct dasd_rssd_messages {
char messages[4087];
} __packed;
+/*
+ * Read Subsystem Data - Volume Storage Query
+ */
+struct dasd_rssd_vsq {
+ struct {
+ __u8 tse:1;
+ __u8 space_not_available:1;
+ __u8 ese:1;
+ __u8 unused:5;
+ } __packed vol_info;
+ __u8 unused1;
+ __u16 extent_pool_id;
+ __u8 warn_cap_limit;
+ __u8 warn_cap_guaranteed;
+ __u16 unused2;
+ __u32 limit_capacity;
+ __u32 guaranteed_capacity;
+ __u32 space_allocated;
+ __u32 space_configured;
+ __u32 logical_capacity;
+} __packed;
+
+/*
+ * Extent Pool Summary
+ */
+struct dasd_ext_pool_sum {
+ __u16 pool_id;
+ __u8 repo_warn_thrshld;
+ __u8 warn_thrshld;
+ struct {
+ __u8 type:1; /* 0 - CKD / 1 - FB */
+ __u8 track_space_efficient:1;
+ __u8 extent_space_efficient:1;
+ __u8 standard_volume:1;
+ __u8 extent_size_valid:1;
+ __u8 capacity_at_warnlevel:1;
+ __u8 pool_oos:1;
+ __u8 unused0:1;
+ __u8 unused1;
+ } __packed flags;
+ struct {
+ __u8 reserved0:1;
+ __u8 size_1G:1;
+ __u8 reserved1:5;
+ __u8 size_16M:1;
+ } __packed extent_size;
+ __u8 unused;
+} __packed;
+
+/*
+ * Read Subsystem Data-Response - Logical Configuration Query - Header
+ */
+struct dasd_rssd_lcq {
+ __u16 data_length; /* Length of data returned */
+ __u16 pool_count; /* Count of extent pools returned - Max: 448 */
+ struct {
+ __u8 pool_info_valid:1; /* Detailed Information valid */
+ __u8 pool_id_volume:1;
+ __u8 pool_id_cec:1;
+ __u8 unused0:5;
+ __u8 unused1;
+ } __packed header_flags;
+ char sfi_type[6]; /* Storage Facility Image Type (EBCDIC) */
+ char sfi_model[3]; /* Storage Facility Image Model (EBCDIC) */
+ __u8 sfi_seq_num[10]; /* Storage Facility Image Sequence Number */
+ __u8 reserved[7];
+ struct dasd_ext_pool_sum ext_pool_sum[448];
+} __packed;
+
+struct dasd_oos_message {
+ __u16 length;
+ __u8 format;
+ __u8 code;
+ __u8 percentage_empty;
+ __u8 reserved;
+ __u16 ext_pool_id;
+ __u16 token;
+ __u8 unused[6];
+} __packed;
+
struct dasd_cuir_message {
__u16 length;
__u8 format;
@@ -461,6 +546,42 @@ struct dasd_psf_ssc_data {
unsigned char reserved[59];
} __attribute__((packed));
+/* Maximum number of extents for a single Release Allocated Space command */
+#define DASD_ECKD_RAS_EXTS_MAX 110U
+
+struct dasd_dso_ras_ext_range {
+ struct ch_t beg_ext;
+ struct ch_t end_ext;
+} __packed;
+
+/*
+ * Define Subsytem Operation - Release Allocated Space
+ */
+struct dasd_dso_ras_data {
+ __u8 order;
+ struct {
+ __u8 message:1; /* Must be zero */
+ __u8 reserved1:2;
+ __u8 vol_type:1; /* 0 - CKD/FBA, 1 - FB */
+ __u8 reserved2:4;
+ } __packed flags;
+ /* Operation Flags to specify scope */
+ struct {
+ __u8 reserved1:2;
+ /* Release Space by Extent */
+ __u8 by_extent:1; /* 0 - entire volume, 1 - specified extents */
+ __u8 guarantee_init:1;
+ __u8 force_release:1; /* Internal - will be ignored */
+ __u16 reserved2:11;
+ } __packed op_flags;
+ __u8 lss;
+ __u8 dev_addr;
+ __u32 reserved1;
+ __u8 reserved2[10];
+ __u16 nr_exts; /* Defines number of ext_scope - max 110 */
+ __u16 reserved3;
+} __packed;
+
/*
* some structures and definitions for alias handling
@@ -551,6 +672,8 @@ struct dasd_eckd_private {
int uses_cdl;
struct attrib_data_t attrib; /* e.g. cache operations */
struct dasd_rssd_features features;
+ struct dasd_rssd_vsq vsq;
+ struct dasd_ext_pool_sum eps;
u32 real_cyl;
/* alias managemnet */
@@ -572,7 +695,5 @@ int dasd_alias_remove_device(struct dasd_device *);
struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *);
void dasd_alias_handle_summary_unit_check(struct work_struct *);
void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *);
-void dasd_alias_lcu_setup_complete(struct dasd_device *);
-void dasd_alias_wait_for_lcu_setup(struct dasd_device *);
int dasd_alias_update_add_device(struct dasd_device *);
#endif /* DASD_ECKD_H */
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 93bb09da7fdc..5ae64af9ccea 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -386,6 +386,7 @@ void dasd_eer_write(struct dasd_device *device, struct dasd_ccw_req *cqr,
dasd_eer_write_standard_trigger(device, cqr, id);
break;
case DASD_EER_NOPATH:
+ case DASD_EER_NOSPC:
dasd_eer_write_standard_trigger(device, NULL, id);
break;
case DASD_EER_STATECHANGE:
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 56007a3e7f11..cbb770824226 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -770,27 +770,46 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
}
/*
- * max_blocks is dependent on the amount of storage that is available
- * in the static io buffer for each device. Currently each device has
- * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
- * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
- * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
- * addition we have one define extent ccw + 16 bytes of data and a
- * locate record ccw for each block (stupid devices!) + 16 bytes of data.
- * That makes:
- * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum.
- * We want to fit two into the available memory so that we can immediately
- * start the next request if one finishes off. That makes 100.1 blocks
- * for one request. Give a little safety and the result is 96.
+ * Initialize block layer request queue.
*/
+static void dasd_fba_setup_blk_queue(struct dasd_block *block)
+{
+ unsigned int logical_block_size = block->bp_block;
+ struct request_queue *q = block->request_queue;
+ unsigned int max_bytes, max_discard_sectors;
+ int max;
+
+ max = DASD_FBA_MAX_BLOCKS << block->s2b_shift;
+ blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
+ q->limits.max_dev_sectors = max;
+ blk_queue_logical_block_size(q, logical_block_size);
+ blk_queue_max_hw_sectors(q, max);
+ blk_queue_max_segments(q, USHRT_MAX);
+ /* With page sized segments each segment can be translated into one idaw/tidaw */
+ blk_queue_max_segment_size(q, PAGE_SIZE);
+ blk_queue_segment_boundary(q, PAGE_SIZE - 1);
+
+ q->limits.discard_granularity = logical_block_size;
+ q->limits.discard_alignment = PAGE_SIZE;
+
+ /* Calculate max_discard_sectors and make it PAGE aligned */
+ max_bytes = USHRT_MAX * logical_block_size;
+ max_bytes = ALIGN_DOWN(max_bytes, PAGE_SIZE);
+ max_discard_sectors = max_bytes / logical_block_size;
+
+ blk_queue_max_discard_sectors(q, max_discard_sectors);
+ blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
+ blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
+}
+
static struct dasd_discipline dasd_fba_discipline = {
.owner = THIS_MODULE,
.name = "FBA ",
.ebcname = "FBA ",
- .max_blocks = 96,
.check_device = dasd_fba_check_characteristics,
.do_analysis = dasd_fba_do_analysis,
.verify_path = dasd_generic_verify_path,
+ .setup_blk_queue = dasd_fba_setup_blk_queue,
.fill_geometry = dasd_fba_fill_geometry,
.start_IO = dasd_start_IO,
.term_IO = dasd_term_IO,
diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h
index b14bf1b2c691..8f75df06e893 100644
--- a/drivers/s390/block/dasd_fba.h
+++ b/drivers/s390/block/dasd_fba.h
@@ -9,6 +9,11 @@
#ifndef DASD_FBA_H
#define DASD_FBA_H
+/*
+ * Maximum number of blocks to be chained
+ */
+#define DASD_FBA_MAX_BLOCKS 96
+
struct DE_fba_data {
struct {
unsigned char perm:2; /* Permissions on this extent */
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index de6b96036aa4..91c9f9586e0f 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -268,7 +268,6 @@ struct dasd_discipline {
struct module *owner;
char ebcname[8]; /* a name used for tagging and printks */
char name[8]; /* a name used for tagging and printks */
- int max_blocks; /* maximum number of blocks to be chained */
struct list_head list; /* used for list of disciplines */
@@ -307,6 +306,10 @@ struct dasd_discipline {
int (*online_to_ready) (struct dasd_device *);
int (*basic_to_known)(struct dasd_device *);
+ /*
+ * Initialize block layer request queue.
+ */
+ void (*setup_blk_queue)(struct dasd_block *);
/* (struct dasd_device *);
* Device operation functions. build_cp creates a ccw chain for
* a block device request, start_io starts the request and
@@ -367,6 +370,25 @@ struct dasd_discipline {
void (*disable_hpf)(struct dasd_device *);
int (*hpf_enabled)(struct dasd_device *);
void (*reset_path)(struct dasd_device *, __u8);
+
+ /*
+ * Extent Space Efficient (ESE) relevant functions
+ */
+ int (*is_ese)(struct dasd_device *);
+ /* Capacity */
+ int (*space_allocated)(struct dasd_device *);
+ int (*space_configured)(struct dasd_device *);
+ int (*logical_capacity)(struct dasd_device *);
+ int (*release_space)(struct dasd_device *, struct format_data_t *);
+ /* Extent Pool */
+ int (*ext_pool_id)(struct dasd_device *);
+ int (*ext_size)(struct dasd_device *);
+ int (*ext_pool_cap_at_warnlevel)(struct dasd_device *);
+ int (*ext_pool_warn_thrshld)(struct dasd_device *);
+ int (*ext_pool_oos)(struct dasd_device *);
+ int (*ext_pool_exhaust)(struct dasd_device *, struct dasd_ccw_req *);
+ struct dasd_ccw_req *(*ese_format)(struct dasd_device *, struct dasd_ccw_req *);
+ void (*ese_read)(struct dasd_ccw_req *);
};
extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -386,6 +408,7 @@ extern struct dasd_discipline *dasd_diag_discipline_pointer;
#define DASD_EER_NOPATH 2
#define DASD_EER_STATECHANGE 3
#define DASD_EER_PPRCSUSPEND 4
+#define DASD_EER_NOSPC 5
/* DASD path handling */
@@ -482,8 +505,10 @@ struct dasd_device {
spinlock_t mem_lock;
void *ccw_mem;
void *erp_mem;
+ void *ese_mem;
struct list_head ccw_chunks;
struct list_head erp_chunks;
+ struct list_head ese_chunks;
atomic_t tasklet_scheduled;
struct tasklet_struct tasklet;
@@ -558,6 +583,7 @@ struct dasd_queue {
#define DASD_STOPPED_SU 16 /* summary unit check handling */
#define DASD_STOPPED_PM 32 /* pm state transition */
#define DASD_UNRESUMED_PM 64 /* pm resume failed state */
+#define DASD_STOPPED_NOSPC 128 /* no space left */
/* per device flags */
#define DASD_FLAG_OFFLINE 3 /* device is in offline processing */
@@ -700,7 +726,9 @@ extern struct kmem_cache *dasd_page_cache;
struct dasd_ccw_req *
dasd_smalloc_request(int, int, int, struct dasd_device *, struct dasd_ccw_req *);
+struct dasd_ccw_req *dasd_fmalloc_request(int, int, int, struct dasd_device *);
void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
+void dasd_ffree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
struct dasd_device *dasd_alloc_device(void);
@@ -727,6 +755,7 @@ void dasd_schedule_block_bh(struct dasd_block *);
int dasd_sleep_on(struct dasd_ccw_req *);
int dasd_sleep_on_queue(struct list_head *);
int dasd_sleep_on_immediatly(struct dasd_ccw_req *);
+int dasd_sleep_on_queue_interruptible(struct list_head *);
int dasd_sleep_on_interruptible(struct dasd_ccw_req *);
void dasd_device_set_timer(struct dasd_device *, int);
void dasd_device_clear_timer(struct dasd_device *);
@@ -750,6 +779,8 @@ int dasd_generic_restore_device(struct ccw_device *);
enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *);
void dasd_generic_path_event(struct ccw_device *, int *);
int dasd_generic_verify_path(struct dasd_device *, __u8);
+void dasd_generic_space_exhaust(struct dasd_device *, struct dasd_ccw_req *);
+void dasd_generic_space_avail(struct dasd_device *);
int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
char *dasd_get_sense(struct irb *);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 8e26001dc11c..9a5f3add325f 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -333,6 +333,59 @@ out_err:
return rc;
}
+static int dasd_release_space(struct dasd_device *device,
+ struct format_data_t *rdata)
+{
+ if (!device->discipline->is_ese && !device->discipline->is_ese(device))
+ return -ENOTSUPP;
+ if (!device->discipline->release_space)
+ return -ENOTSUPP;
+
+ return device->discipline->release_space(device, rdata);
+}
+
+/*
+ * Release allocated space
+ */
+static int dasd_ioctl_release_space(struct block_device *bdev, void __user *argp)
+{
+ struct format_data_t rdata;
+ struct dasd_device *base;
+ int rc = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (!argp)
+ return -EINVAL;
+
+ base = dasd_device_from_gendisk(bdev->bd_disk);
+ if (!base)
+ return -ENODEV;
+ if (base->features & DASD_FEATURE_READONLY ||
+ test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+ rc = -EROFS;
+ goto out_err;
+ }
+ if (bdev != bdev->bd_contains) {
+ pr_warn("%s: The specified DASD is a partition and tracks cannot be released\n",
+ dev_name(&base->cdev->dev));
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ if (copy_from_user(&rdata, argp, sizeof(rdata))) {
+ rc = -EFAULT;
+ goto out_err;
+ }
+
+ rc = dasd_release_space(base, &rdata);
+
+out_err:
+ dasd_put_device(base);
+
+ return rc;
+}
+
#ifdef CONFIG_DASD_PROFILE
/*
* Reset device profile information
@@ -595,6 +648,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode,
case BIODASDREADALLCMB:
rc = dasd_ioctl_readall_cmb(block, cmd, argp);
break;
+ case BIODASDRAS:
+ rc = dasd_ioctl_release_space(bdev, argp);
+ break;
default:
/* if the discipline has an ioctl method try it. */
rc = -ENOTTY;
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index 6c90aa725f23..e71992a3c55f 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -41,7 +41,6 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
sclp.has_hvs = !!(sccb->fac119 & 0x80);
sclp.has_kss = !!(sccb->fac98 & 0x01);
sclp.has_sipl = !!(sccb->cbl & 0x02);
- sclp.has_sipl_g2 = !!(sccb->cbl & 0x04);
if (sccb->fac85 & 0x02)
S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
if (sccb->fac91 & 0x40)
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 4ebf6d4fc66c..c522e9313c50 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -581,7 +581,7 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
}
EXPORT_SYMBOL(ccwgroup_driver_register);
-static int __ccwgroup_match_all(struct device *dev, void *data)
+static int __ccwgroup_match_all(struct device *dev, const void *data)
{
return 1;
}
@@ -608,9 +608,9 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver)
}
EXPORT_SYMBOL(ccwgroup_driver_unregister);
-static int __ccwgroupdev_check_busid(struct device *dev, void *id)
+static int __ccwgroupdev_check_busid(struct device *dev, const void *id)
{
- char *bus_id = id;
+ const char *bus_id = id;
return (strcmp(bus_id, dev_name(dev)) == 0);
}
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 8d9f36625ba5..8f080d3fd380 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -203,7 +203,7 @@ static void chsc_cleanup_sch_driver(void)
static DEFINE_SPINLOCK(chsc_lock);
-static int chsc_subchannel_match_next_free(struct device *dev, void *data)
+static int chsc_subchannel_match_next_free(struct device *dev, const void *data)
{
struct subchannel *sch = to_subchannel(dev);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index e1f2d0eed544..22c55816100b 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -491,10 +491,10 @@ static int css_probe_device(struct subchannel_id schid, struct schib *schib)
}
static int
-check_subchannel(struct device * dev, void * data)
+check_subchannel(struct device *dev, const void *data)
{
struct subchannel *sch;
- struct subchannel_id *schid = data;
+ struct subchannel_id *schid = (void *)data;
sch = to_subchannel(dev);
return schid_equal(&sch->schid, schid);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 9985b7484a6b..c421899be20f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -643,10 +643,10 @@ static int ccw_device_add(struct ccw_device *cdev)
return device_add(dev);
}
-static int match_dev_id(struct device *dev, void *data)
+static int match_dev_id(struct device *dev, const void *data)
{
struct ccw_device *cdev = to_ccwdev(dev);
- struct ccw_dev_id *dev_id = data;
+ struct ccw_dev_id *dev_id = (void *)data;
return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
}
@@ -1699,11 +1699,9 @@ EXPORT_SYMBOL_GPL(ccw_device_force_console);
* get ccw_device matching the busid, but only if owned by cdrv
*/
static int
-__ccwdev_check_busid(struct device *dev, void *id)
+__ccwdev_check_busid(struct device *dev, const void *id)
{
- char *bus_id;
-
- bus_id = id;
+ const char *bus_id = id;
return (strcmp(bus_id, dev_name(dev)) == 0);
}
diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c
index 6bca1d5455d4..9f26d4310bb3 100644
--- a/drivers/s390/cio/scm.c
+++ b/drivers/s390/cio/scm.c
@@ -174,10 +174,10 @@ out:
kobject_uevent(&scmdev->dev.kobj, KOBJ_CHANGE);
}
-static int check_address(struct device *dev, void *data)
+static int check_address(struct device *dev, const void *data)
{
struct scm_device *scmdev = to_scm_dev(dev);
- struct sale *sale = data;
+ const struct sale *sale = data;
return scmdev->address == sale->sa;
}
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index b9fc502c58c2..a76b8a8bcbbb 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -208,7 +208,6 @@ static inline int ap_query_configuration(struct ap_config_info *info)
return -EINVAL;
return ap_qci(info);
}
-EXPORT_SYMBOL(ap_query_configuration);
/**
* ap_init_configuration(): Allocate and query configuration array.
@@ -1356,16 +1355,16 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
* Helper function to be used with bus_find_dev
* matches for the card device with the given id
*/
-static int __match_card_device_with_id(struct device *dev, void *data)
+static int __match_card_device_with_id(struct device *dev, const void *data)
{
- return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long) data;
+ return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long)(void *) data;
}
/*
* Helper function to be used with bus_find_dev
* matches for the queue device with a given qid
*/
-static int __match_queue_device_with_qid(struct device *dev, void *data)
+static int __match_queue_device_with_qid(struct device *dev, const void *data)
{
return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data;
}
@@ -1374,7 +1373,7 @@ static int __match_queue_device_with_qid(struct device *dev, void *data)
* Helper function to be used with bus_find_dev
* matches any queue device with given queue id
*/
-static int __match_queue_device_with_queue_id(struct device *dev, void *data)
+static int __match_queue_device_with_queue_id(struct device *dev, const void *data)
{
return is_queue_dev(dev)
&& AP_QID_QUEUE(to_ap_queue(dev)->qid) == (int)(long) data;
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 2c9fb1423a39..0604b49a4d32 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -26,7 +26,7 @@
static int vfio_ap_mdev_reset_queues(struct mdev_device *mdev);
-static int match_apqn(struct device *dev, void *data)
+static int match_apqn(struct device *dev, const void *data)
{
struct vfio_ap_queue *q = dev_get_drvdata(dev);
@@ -115,7 +115,6 @@ static void vfio_ap_wait_for_irqclear(int apqn)
* Unregisters the ISC in the GIB when the saved ISC not invalid.
* Unpin the guest's page holding the NIB when it exist.
* Reset the saved_pfn and saved_isc to invalid values.
- * Clear the pointer to the matrix mediated device.
*
*/
static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
@@ -127,7 +126,6 @@ static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
&q->saved_pfn, 1);
q->saved_pfn = 0;
q->saved_isc = VFIO_AP_ISC_INVALID;
- q->matrix_mdev = NULL;
}
/**
@@ -179,6 +177,7 @@ struct ap_queue_status vfio_ap_irq_disable(struct vfio_ap_queue *q)
status.response_code);
end_free:
vfio_ap_free_aqic_resources(q);
+ q->matrix_mdev = NULL;
return status;
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 6d6b14295734..faf43b1d3dbe 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2965,7 +2965,7 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba)
del_timer_sync(&phba->fcp_poll_timer);
break;
case LPFC_PCI_DEV_OC:
- /* Stop any OneConnect device sepcific driver timers */
+ /* Stop any OneConnect device specific driver timers */
lpfc_sli4_stop_fcf_redisc_wait_timer(phba);
break;
default:
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 7f0ceb65c3f3..c074631086a4 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -372,7 +372,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
return err;
}
-static int always_match(struct device *dev, void *data)
+static int always_match(struct device *dev, const void *data)
{
return 1;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 91673351bcf3..75ac046cae52 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3652,7 +3652,7 @@ EXPORT_SYMBOL_GPL(spi_write_then_read);
/*-------------------------------------------------------------------------*/
#if IS_ENABLED(CONFIG_OF)
-static int __spi_of_device_match(struct device *dev, void *data)
+static int __spi_of_device_match(struct device *dev, const void *data)
{
return dev->of_node == data;
}
@@ -3753,7 +3753,7 @@ static int spi_acpi_controller_match(struct device *dev, const void *data)
return ACPI_COMPANION(dev->parent) == data;
}
-static int spi_acpi_device_match(struct device *dev, void *data)
+static int spi_acpi_device_match(struct device *dev, const void *data)
{
return ACPI_COMPANION(dev) == data;
}
diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 86a8545c8d97..b9841adb7181 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -561,13 +561,6 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d)
return 0;
}
-static int match_bus_dev(struct device *dev, void *data)
-{
- char *mdev_name = data;
-
- return !strcmp(dev_name(dev), mdev_name);
-}
-
/**
* get_channel - get pointer to channel
* @mdev: name of the device interface
@@ -579,7 +572,7 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch)
struct most_interface *iface;
struct most_channel *c, *tmp;
- dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev);
+ dev = bus_find_device_by_name(&mc.bus, NULL, mdev);
if (!dev)
return NULL;
iface = to_most_interface(dev);
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
index d26bdfd11266..25c75b977666 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -45,7 +45,7 @@ static u32 phy_CalculateBitShift(u32 BitMask)
/**
* Function: PHY_QueryBBReg
*
-* OverView: Read "sepcific bits" from BB register
+* OverView: Read "specific bits" from BB register
*
* Input:
* struct adapter * Adapter,
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
index ba39647a690c..3199977f1e73 100644
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -123,8 +123,6 @@ static void bcm2835_thermal_debugfs(struct platform_device *pdev)
struct debugfs_regset32 *regset;
data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
- if (!data->debugfsdir)
- return;
regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
if (!regset)
diff --git a/drivers/thermal/intel/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c
index 79d214b7291c..5149a817456b 100644
--- a/drivers/thermal/intel/intel_powerclamp.c
+++ b/drivers/thermal/intel/intel_powerclamp.c
@@ -698,17 +698,9 @@ DEFINE_SHOW_ATTRIBUTE(powerclamp_debug);
static inline void powerclamp_create_debug_files(void)
{
debug_dir = debugfs_create_dir("intel_powerclamp", NULL);
- if (!debug_dir)
- return;
-
- if (!debugfs_create_file("powerclamp_calib", S_IRUGO, debug_dir,
- cal_data, &powerclamp_debug_fops))
- goto file_error;
- return;
-
-file_error:
- debugfs_remove_recursive(debug_dir);
+ debugfs_create_file("powerclamp_calib", S_IRUGO, debug_dir, cal_data,
+ &powerclamp_debug_fops);
}
static enum cpuhp_state hp_state;
diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index e85d54d1cdf3..ddb4a973c698 100644
--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
@@ -75,29 +75,14 @@ static struct dentry *debugfs;
static unsigned int pkg_interrupt_cnt;
static unsigned int pkg_work_cnt;
-static int pkg_temp_debugfs_init(void)
+static void pkg_temp_debugfs_init(void)
{
- struct dentry *d;
-
debugfs = debugfs_create_dir("pkg_temp_thermal", NULL);
- if (!debugfs)
- return -ENOENT;
-
- d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs,
- &pkg_interrupt_cnt);
- if (!d)
- goto err_out;
-
- d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs,
- &pkg_work_cnt);
- if (!d)
- goto err_out;
- return 0;
-
-err_out:
- debugfs_remove_recursive(debugfs);
- return -ENOENT;
+ debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs,
+ &pkg_interrupt_cnt);
+ debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs,
+ &pkg_work_cnt);
}
/*
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c
index fcf70a3728b6..43941eb734eb 100644
--- a/drivers/thermal/tegra/soctherm.c
+++ b/drivers/thermal/tegra/soctherm.c
@@ -1485,23 +1485,13 @@ DEFINE_SHOW_ATTRIBUTE(regs);
static void soctherm_debug_init(struct platform_device *pdev)
{
struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
- struct dentry *root, *file;
+ struct dentry *root;
root = debugfs_create_dir("soctherm", NULL);
- if (!root) {
- dev_err(&pdev->dev, "failed to create debugfs directory\n");
- return;
- }
tegra->debugfs_dir = root;
- file = debugfs_create_file("reg_contents", 0644, root,
- pdev, &regs_fops);
- if (!file) {
- dev_err(&pdev->dev, "failed to create debugfs file\n");
- debugfs_remove_recursive(tegra->debugfs_dir);
- tegra->debugfs_dir = NULL;
- }
+ debugfs_create_file("reg_contents", 0644, root, pdev, &regs_fops);
}
#else
static inline void soctherm_debug_init(struct platform_device *pdev) {}
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 10b56c66fec3..5668a44e0653 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1967,10 +1967,10 @@ struct tb_sw_lookup {
u64 route;
};
-static int tb_switch_match(struct device *dev, void *data)
+static int tb_switch_match(struct device *dev, const void *data)
{
struct tb_switch *sw = tb_to_switch(dev);
- struct tb_sw_lookup *lookup = data;
+ const struct tb_sw_lookup *lookup = data;
if (!sw)
return 0;
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index 6de6d4a1a221..7af54d6ed5b8 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -107,6 +107,14 @@ static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count)
return got;
}
+/**
+ * hvterm_raw_put_chars: send characters to firmware for given vterm adapter
+ * @vtermno: The virtual terminal number.
+ * @buf: The characters to send. Because of the underlying hypercall in
+ * hvc_put_chars(), this buffer must be at least 16 bytes long, even if
+ * you are sending fewer chars.
+ * @count: number of chars to send.
+ */
static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count)
{
struct hvterm_priv *pv = hvterm_privs[vtermno];
@@ -219,6 +227,7 @@ static const struct hv_ops hvterm_hvsi_ops = {
static void udbg_hvc_putc(char c)
{
int count = -1;
+ unsigned char bounce_buffer[16];
if (!hvterm_privs[0])
return;
@@ -229,7 +238,12 @@ static void udbg_hvc_putc(char c)
do {
switch(hvterm_privs[0]->proto) {
case HV_PROTOCOL_RAW:
- count = hvterm_raw_put_chars(0, &c, 1);
+ /*
+ * hvterm_raw_put_chars requires at least a 16-byte
+ * buffer, so go via the bounce buffer
+ */
+ bounce_buffer[0] = c;
+ count = hvterm_raw_put_chars(0, bounce_buffer, 1);
break;
case HV_PROTOCOL_HVSI:
count = hvterm_hvsi_put_chars(0, &c, 1);
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 63e34d868de8..f8503f8fc44e 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -397,7 +397,7 @@ static const struct uart_ops sunhv_pops = {
static struct uart_driver sunhv_reg = {
.owner = THIS_MODULE,
.driver_name = "sunhv",
- .dev_name = "ttyS",
+ .dev_name = "ttyHV",
.major = TTY_MAJOR,
};
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 94573fb68304..6e59d370ef81 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -45,6 +45,7 @@ config USB_ARCH_HAS_HCD
config USB
tristate "Support for Host-side USB"
depends on USB_ARCH_HAS_HCD
+ select GENERIC_ALLOCATOR
select USB_COMMON
select NLS # for UTF-8 strings
---help---
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index f641342cdec0..1359b78a624e 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
+#include <linux/genalloc.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -67,7 +68,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
if (!IS_ENABLED(CONFIG_HAS_DMA) ||
(!is_device_dma_capable(hcd->self.sysdev) &&
- !(hcd->driver->flags & HCD_LOCAL_MEM)))
+ !hcd->localmem_pool))
return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
@@ -124,10 +125,12 @@ void *hcd_buffer_alloc(
if (size == 0)
return NULL;
+ if (hcd->localmem_pool)
+ return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
+
/* some USB hosts just use PIO */
if (!IS_ENABLED(CONFIG_HAS_DMA) ||
- (!is_device_dma_capable(bus->sysdev) &&
- !(hcd->driver->flags & HCD_LOCAL_MEM))) {
+ !is_device_dma_capable(bus->sysdev)) {
*dma = ~(dma_addr_t) 0;
return kmalloc(size, mem_flags);
}
@@ -152,9 +155,13 @@ void hcd_buffer_free(
if (!addr)
return;
+ if (hcd->localmem_pool) {
+ gen_pool_free(hcd->localmem_pool, (unsigned long)addr, size);
+ return;
+ }
+
if (!IS_ENABLED(CONFIG_HAS_DMA) ||
- (!is_device_dma_capable(bus->sysdev) &&
- !(hcd->driver->flags & HCD_LOCAL_MEM))) {
+ !is_device_dma_capable(bus->sysdev)) {
kfree(addr);
return;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index e2f316ac8b01..b265ab5405f9 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -942,9 +942,9 @@ error:
return ret;
}
-static int match_devt(struct device *dev, void *data)
+static int match_devt(struct device *dev, const void *data)
{
- return dev->devt == (dev_t) (unsigned long) data;
+ return dev->devt == (dev_t)(unsigned long)(void *)data;
}
static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 94d22551fc1b..88533938ce19 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -29,6 +29,8 @@
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
#include <linux/phy/phy.h>
#include <linux/usb.h>
@@ -1345,14 +1347,14 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
* using regular system memory - like pci devices doing bus mastering.
*
* To support host controllers with limited dma capabilities we provide dma
- * bounce buffers. This feature can be enabled using the HCD_LOCAL_MEM flag.
+ * bounce buffers. This feature can be enabled by initializing
+ * hcd->localmem_pool using usb_hcd_setup_local_mem().
* For this to work properly the host controller code must first use the
* function dma_declare_coherent_memory() to point out which memory area
* that should be used for dma allocations.
*
- * The HCD_LOCAL_MEM flag then tells the usb code to allocate all data for
- * dma using dma_alloc_coherent() which in turn allocates from the memory
- * area pointed out with dma_declare_coherent_memory().
+ * The initialized hcd->localmem_pool then tells the usb code to allocate all
+ * data for dma using the genalloc API.
*
* So, to summarize...
*
@@ -1362,9 +1364,6 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
* (a) "normal" kernel memory is no good, and
* (b) there's not enough to share
*
- * - The only *portable* hook for such stuff in the
- * DMA framework is dma_declare_coherent_memory()
- *
* - So we use that, even though the primary requirement
* is that the memory be "local" (hence addressable
* by that device), not "coherent".
@@ -1531,7 +1530,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
urb->setup_dma))
return -EAGAIN;
urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
- } else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+ } else if (hcd->localmem_pool) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->setup_dma,
@@ -1601,7 +1600,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
else
urb->transfer_flags |= URB_DMA_MAP_SINGLE;
}
- } else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+ } else if (hcd->localmem_pool) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->transfer_dma,
@@ -3039,6 +3038,40 @@ usb_hcd_platform_shutdown(struct platform_device *dev)
}
EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
+int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
+ dma_addr_t dma, size_t size)
+{
+ int err;
+ void *local_mem;
+
+ hcd->localmem_pool = devm_gen_pool_create(hcd->self.sysdev, 4,
+ dev_to_node(hcd->self.sysdev),
+ dev_name(hcd->self.sysdev));
+ if (IS_ERR(hcd->localmem_pool))
+ return PTR_ERR(hcd->localmem_pool);
+
+ local_mem = devm_memremap(hcd->self.sysdev, phys_addr,
+ size, MEMREMAP_WC);
+ if (!local_mem)
+ return -ENOMEM;
+
+ /*
+ * Here we pass a dma_addr_t but the arg type is a phys_addr_t.
+ * It's not backed by system memory and thus there's no kernel mapping
+ * for it.
+ */
+ err = gen_pool_add_virt(hcd->localmem_pool, (unsigned long)local_mem,
+ dma, size, dev_to_node(hcd->self.sysdev));
+ if (err < 0) {
+ dev_err(hcd->self.sysdev, "gen_pool_add_virt failed with %d\n",
+ err);
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_setup_local_mem);
+
/*-------------------------------------------------------------------------*/
#if IS_ENABLED(CONFIG_USB_MON)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 5a0df527a8ca..0ab8738047da 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -325,9 +325,9 @@ struct find_interface_arg {
struct device_driver *drv;
};
-static int __find_interface(struct device *dev, void *data)
+static int __find_interface(struct device *dev, const void *data)
{
- struct find_interface_arg *arg = data;
+ const struct find_interface_arg *arg = data;
struct usb_interface *intf;
if (!is_usb_interface(dev))
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index cdafa97f632d..9da7e22848c9 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -559,7 +559,7 @@ static int ehci_init(struct usb_hcd *hcd)
ehci->command = temp;
/* Accept arbitrarily long scatter-gather lists */
- if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ if (!hcd->localmem_pool)
hcd->self.sg_tablesize = ~0;
/* Prepare for unlinking active QHs */
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index e835a22b12af..77cc36efae95 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -4996,7 +4996,7 @@ static int hcd_fotg210_init(struct usb_hcd *hcd)
fotg210->command = temp;
/* Accept arbitrarily long scatter-gather lists */
- if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ if (!hcd->localmem_pool)
hcd->self.sg_tablesize = ~0;
return 0;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 210181fd98d2..b457fdaff297 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -40,6 +40,7 @@
#include <linux/dmapool.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
+#include <linux/genalloc.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -447,7 +448,7 @@ static int ohci_init (struct ohci_hcd *ohci)
struct usb_hcd *hcd = ohci_to_hcd(ohci);
/* Accept arbitrarily long scatter-gather lists */
- if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ if (!hcd->localmem_pool)
hcd->self.sg_tablesize = ~0;
if (distrust_firmware)
@@ -505,8 +506,15 @@ static int ohci_init (struct ohci_hcd *ohci)
timer_setup(&ohci->io_watchdog, io_watchdog_func, 0);
ohci->prev_frame_no = IO_WATCHDOG_OFF;
- ohci->hcca = dma_alloc_coherent (hcd->self.controller,
- sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
+ if (hcd->localmem_pool)
+ ohci->hcca = gen_pool_dma_alloc_align(hcd->localmem_pool,
+ sizeof(*ohci->hcca),
+ &ohci->hcca_dma, 256);
+ else
+ ohci->hcca = dma_alloc_coherent(hcd->self.controller,
+ sizeof(*ohci->hcca),
+ &ohci->hcca_dma,
+ GFP_KERNEL);
if (!ohci->hcca)
return -ENOMEM;
@@ -990,9 +998,14 @@ static void ohci_stop (struct usb_hcd *hcd)
remove_debug_files (ohci);
ohci_mem_cleanup (ohci);
if (ohci->hcca) {
- dma_free_coherent (hcd->self.controller,
- sizeof *ohci->hcca,
- ohci->hcca, ohci->hcca_dma);
+ if (hcd->localmem_pool)
+ gen_pool_free(hcd->localmem_pool,
+ (unsigned long)ohci->hcca,
+ sizeof(*ohci->hcca));
+ else
+ dma_free_coherent(hcd->self.controller,
+ sizeof(*ohci->hcca),
+ ohci->hcca, ohci->hcca_dma);
ohci->hcca = NULL;
ohci->hcca_dma = 0;
}
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 3965ac0341eb..1425335c6baf 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -36,6 +36,13 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
static int ohci_mem_init (struct ohci_hcd *ohci)
{
+ /*
+ * HCs with local memory allocate from localmem_pool so there's
+ * no need to create the below dma pools.
+ */
+ if (ohci_to_hcd(ohci)->localmem_pool)
+ return 0;
+
ohci->td_cache = dma_pool_create ("ohci_td",
ohci_to_hcd(ohci)->self.controller,
sizeof (struct td),
@@ -84,8 +91,13 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
{
dma_addr_t dma;
struct td *td;
+ struct usb_hcd *hcd = ohci_to_hcd(hc);
- td = dma_pool_zalloc (hc->td_cache, mem_flags, &dma);
+ if (hcd->localmem_pool)
+ td = gen_pool_dma_zalloc_align(hcd->localmem_pool,
+ sizeof(*td), &dma, 32);
+ else
+ td = dma_pool_zalloc(hc->td_cache, mem_flags, &dma);
if (td) {
/* in case hc fetches it, make it look dead */
td->hwNextTD = cpu_to_hc32 (hc, dma);
@@ -99,6 +111,7 @@ static void
td_free (struct ohci_hcd *hc, struct td *td)
{
struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
+ struct usb_hcd *hcd = ohci_to_hcd(hc);
while (*prev && *prev != td)
prev = &(*prev)->td_hash;
@@ -106,7 +119,12 @@ td_free (struct ohci_hcd *hc, struct td *td)
*prev = td->td_hash;
else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
ohci_dbg (hc, "no hash for td %p\n", td);
- dma_pool_free (hc->td_cache, td, td->td_dma);
+
+ if (hcd->localmem_pool)
+ gen_pool_free(hcd->localmem_pool, (unsigned long)td,
+ sizeof(*td));
+ else
+ dma_pool_free(hc->td_cache, td, td->td_dma);
}
/*-------------------------------------------------------------------------*/
@@ -117,8 +135,13 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
{
dma_addr_t dma;
struct ed *ed;
+ struct usb_hcd *hcd = ohci_to_hcd(hc);
- ed = dma_pool_zalloc (hc->ed_cache, mem_flags, &dma);
+ if (hcd->localmem_pool)
+ ed = gen_pool_dma_zalloc_align(hcd->localmem_pool,
+ sizeof(*ed), &dma, 16);
+ else
+ ed = dma_pool_zalloc(hc->ed_cache, mem_flags, &dma);
if (ed) {
INIT_LIST_HEAD (&ed->td_list);
ed->dma = dma;
@@ -129,6 +152,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
static void
ed_free (struct ohci_hcd *hc, struct ed *ed)
{
- dma_pool_free (hc->ed_cache, ed, ed->dma);
+ struct usb_hcd *hcd = ohci_to_hcd(hc);
+
+ if (hcd->localmem_pool)
+ gen_pool_free(hcd->localmem_pool, (unsigned long)ed,
+ sizeof(*ed));
+ else
+ dma_pool_free(hc->ed_cache, ed, ed->dma);
}
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index c26228c25f99..c158cda9e4b9 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -49,7 +49,7 @@ static const struct hc_driver ohci_sm501_hc_driver = {
* generic hardware linkage
*/
.irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM,
+ .flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
@@ -110,40 +110,18 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
goto err0;
}
- /* The sm501 chip is equipped with local memory that may be used
- * by on-chip devices such as the video controller and the usb host.
- * This driver uses dma_declare_coherent_memory() to make sure
- * usb allocations with dma_alloc_coherent() allocate from
- * this local memory. The dma_handle returned by dma_alloc_coherent()
- * will be an offset starting from 0 for the first local memory byte.
- *
- * So as long as data is allocated using dma_alloc_coherent() all is
- * fine. This is however not always the case - buffers may be allocated
- * using kmalloc() - so the usb core needs to be told that it must copy
- * data into our local memory if the buffers happen to be placed in
- * regular memory. The HCD_LOCAL_MEM flag does just that.
- */
-
- retval = dma_declare_coherent_memory(dev, mem->start,
- mem->start - mem->parent->start,
- resource_size(mem));
- if (retval) {
- dev_err(dev, "cannot declare coherent memory\n");
- goto err1;
- }
-
/* allocate, reserve and remap resources for registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(dev, "no resource definition for registers\n");
retval = -ENOENT;
- goto err2;
+ goto err1;
}
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
- goto err2;
+ goto err1;
}
hcd->rsrc_start = res->start;
@@ -164,6 +142,25 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
ohci_hcd_init(hcd_to_ohci(hcd));
+ /* The sm501 chip is equipped with local memory that may be used
+ * by on-chip devices such as the video controller and the usb host.
+ * This driver uses genalloc so that usb allocations with
+ * gen_pool_dma_alloc() allocate from this local memory. The dma_handle
+ * returned by gen_pool_dma_alloc() will be an offset starting from 0
+ * for the first local memory byte.
+ *
+ * So as long as data is allocated using gen_pool_dma_alloc() all is
+ * fine. This is however not always the case - buffers may be allocated
+ * using kmalloc() - so the usb core needs to be told that it must copy
+ * data into our local memory if the buffers happen to be placed in
+ * regular memory. A non-null hcd->localmem_pool initialized by the
+ * the call to usb_hcd_setup_local_mem() below does just that.
+ */
+
+ if (usb_hcd_setup_local_mem(hcd, mem->start,
+ mem->start - mem->parent->start,
+ resource_size(mem)) < 0)
+ goto err5;
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval)
goto err5;
@@ -181,8 +178,6 @@ err4:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err3:
usb_put_hcd(hcd);
-err2:
- dma_release_declared_memory(dev);
err1:
release_mem_region(mem->start, resource_size(mem));
err0:
@@ -197,7 +192,6 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
- dma_release_declared_memory(&pdev->dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (mem)
release_mem_region(mem->start, resource_size(mem));
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index f88a0370659f..d5a293a707b6 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -153,7 +153,7 @@ static const struct hc_driver ohci_tmio_hc_driver = {
/* generic hardware linkage */
.irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM,
+ .flags = HCD_USB11 | HCD_MEMORY,
/* basic lifecycle operations */
.start = ohci_tmio_start,
@@ -224,11 +224,6 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
goto err_ioremap_regs;
}
- ret = dma_declare_coherent_memory(&dev->dev, sram->start, sram->start,
- resource_size(sram));
- if (ret)
- goto err_dma_declare;
-
if (cell->enable) {
ret = cell->enable(dev);
if (ret)
@@ -239,6 +234,11 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
ohci = hcd_to_ohci(hcd);
ohci_hcd_init(ohci);
+ ret = usb_hcd_setup_local_mem(hcd, sram->start, sram->start,
+ resource_size(sram));
+ if (ret < 0)
+ goto err_enable;
+
ret = usb_add_hcd(hcd, irq, 0);
if (ret)
goto err_add_hcd;
@@ -254,8 +254,6 @@ err_add_hcd:
if (cell->disable)
cell->disable(dev);
err_enable:
- dma_release_declared_memory(&dev->dev);
-err_dma_declare:
iounmap(hcd->regs);
err_ioremap_regs:
iounmap(tmio->ccr);
@@ -276,7 +274,6 @@ static int ohci_hcd_tmio_drv_remove(struct platform_device *dev)
tmio_stop_hc(dev);
if (cell->disable)
cell->disable(dev);
- dma_release_declared_memory(&dev->dev);
iounmap(hcd->regs);
iounmap(tmio->ccr);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index ef4813bfc5bf..b015b00774b2 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -385,6 +385,8 @@ struct ohci_hcd {
/*
* memory management for queue data structures
+ *
+ * @td_cache and @ed_cache are %NULL if &usb_hcd.localmem_pool is used.
*/
struct dma_pool *td_cache;
struct dma_pool *ed_cache;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 98deb5f64268..03bc59755123 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -581,7 +581,7 @@ static int uhci_start(struct usb_hcd *hcd)
hcd->uses_new_polling = 1;
/* Accept arbitrarily long scatter-gather lists */
- if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ if (!hcd->localmem_pool)
hcd->self.sg_tablesize = ~0;
spin_lock_init(&uhci->lock);
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index a3cb25cb74f8..d16dfc320faa 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -118,9 +118,9 @@ static const struct of_device_id omap_control_usb_id_table[] = {
MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
static struct platform_driver am335x_control_driver;
-static int match(struct device *dev, void *data)
+static int match(struct device *dev, const void *data)
{
- struct device_node *node = (struct device_node *)data;
+ const struct device_node *node = (const struct device_node *)data;
return dev->of_node == node &&
dev->driver == &am335x_control_driver.driver;
}
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index 93b7d6a30aad..6cf6fbd39237 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -142,9 +142,9 @@ static struct i2c_driver isp1301_driver = {
module_i2c_driver(isp1301_driver);
-static int match(struct device *dev, void *data)
+static int match(struct device *dev, const void *data)
{
- struct device_node *node = (struct device_node *)data;
+ const struct device_node *node = (const struct device_node *)data;
return (dev->of_node == node) &&
(dev->driver == &isp1301_driver.driver);
}
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index 0adf0683cf08..99941ae1f3a1 100644
--- a/drivers/video/fbdev/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
@@ -340,14 +340,12 @@ int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
*/
int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
{
- struct au1100fb_device *fbdev;
-
- fbdev = to_au1100fb_device(fbi);
+ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
- return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
+ return dma_mmap_coherent(fbdev->dev, vma, fbdev->fb_mem, fbdev->fb_phys,
+ fbdev->fb_len);
}
static struct fb_ops au1100fb_ops =
@@ -412,7 +410,6 @@ static int au1100fb_drv_probe(struct platform_device *dev)
{
struct au1100fb_device *fbdev;
struct resource *regs_res;
- unsigned long page;
struct clk *c;
/* Allocate new device private */
@@ -424,6 +421,7 @@ static int au1100fb_drv_probe(struct platform_device *dev)
goto failed;
platform_set_drvdata(dev, (void *)fbdev);
+ fbdev->dev = &dev->dev;
/* Allocate region for our registers and map them */
regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
@@ -472,20 +470,6 @@ static int au1100fb_drv_probe(struct platform_device *dev)
au1100fb_fix.smem_start = fbdev->fb_phys;
au1100fb_fix.smem_len = fbdev->fb_len;
- /*
- * Set page reserved so that mmap will work. This is necessary
- * since we'll be remapping normal memory.
- */
- for (page = (unsigned long)fbdev->fb_mem;
- page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
- page += PAGE_SIZE) {
-#ifdef CONFIG_DMA_NONCOHERENT
- SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
-#else
- SetPageReserved(virt_to_page(page));
-#endif
- }
-
print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
diff --git a/drivers/video/fbdev/au1100fb.h b/drivers/video/fbdev/au1100fb.h
index 9af19939a9c6..e7239bceefd3 100644
--- a/drivers/video/fbdev/au1100fb.h
+++ b/drivers/video/fbdev/au1100fb.h
@@ -110,6 +110,7 @@ struct au1100fb_device {
dma_addr_t fb_phys;
int panel_idx;
struct clk *lcdclk;
+ struct device *dev;
};
/********************************************************************/
diff --git a/drivers/visorbus/visorbus_main.c b/drivers/visorbus/visorbus_main.c
index 0b2434cc4ecd..152fd29f04f2 100644
--- a/drivers/visorbus/visorbus_main.c
+++ b/drivers/visorbus/visorbus_main.c
@@ -171,10 +171,10 @@ struct visor_busdev {
u32 dev_no;
};
-static int match_visorbus_dev_by_id(struct device *dev, void *data)
+static int match_visorbus_dev_by_id(struct device *dev, const void *data)
{
struct visor_device *vdev = to_visor_device(dev);
- struct visor_busdev *id = data;
+ const struct visor_busdev *id = data;
if (vdev->chipset_bus_no == id->bus_no &&
vdev->chipset_dev_no == id->dev_no)
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index e2ad44816359..921291025680 100644
--- a/drivers/watchdog/bcm_kona_wdt.c
+++ b/drivers/watchdog/bcm_kona_wdt.c
@@ -143,24 +143,18 @@ static void bcm_kona_wdt_debug_init(struct platform_device *pdev)
wdt->debugfs = NULL;
dir = debugfs_create_dir(BCM_KONA_WDT_NAME, NULL);
- if (IS_ERR_OR_NULL(dir))
- return;
- if (debugfs_create_file("info", S_IFREG | S_IRUGO, dir, wdt,
- &bcm_kona_fops))
- wdt->debugfs = dir;
- else
- debugfs_remove_recursive(dir);
+ debugfs_create_file("info", S_IFREG | S_IRUGO, dir, wdt,
+ &bcm_kona_fops);
+ wdt->debugfs = dir;
}
static void bcm_kona_wdt_debug_exit(struct platform_device *pdev)
{
struct bcm_kona_wdt *wdt = platform_get_drvdata(pdev);
- if (wdt && wdt->debugfs) {
+ if (wdt)
debugfs_remove_recursive(wdt->debugfs);
- wdt->debugfs = NULL;
- }
}
#else
diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c
index 8023cf28657a..96a770938ff0 100644
--- a/drivers/watchdog/mei_wdt.c
+++ b/drivers/watchdog/mei_wdt.c
@@ -539,38 +539,23 @@ static void dbgfs_unregister(struct mei_wdt *wdt)
wdt->dbgfs_dir = NULL;
}
-static int dbgfs_register(struct mei_wdt *wdt)
+static void dbgfs_register(struct mei_wdt *wdt)
{
- struct dentry *dir, *f;
+ struct dentry *dir;
dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!dir)
- return -ENOMEM;
-
wdt->dbgfs_dir = dir;
- f = debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state);
- if (!f)
- goto err;
- f = debugfs_create_file("activation", S_IRUSR,
- dir, wdt, &dbgfs_fops_activation);
- if (!f)
- goto err;
+ debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state);
- return 0;
-err:
- dbgfs_unregister(wdt);
- return -ENODEV;
+ debugfs_create_file("activation", S_IRUSR, dir, wdt,
+ &dbgfs_fops_activation);
}
#else
static inline void dbgfs_unregister(struct mei_wdt *wdt) {}
-
-static inline int dbgfs_register(struct mei_wdt *wdt)
-{
- return 0;
-}
+static inline void dbgfs_register(struct mei_wdt *wdt) {}
#endif /* CONFIG_DEBUG_FS */
static int mei_wdt_probe(struct mei_cl_device *cldev,
@@ -623,8 +608,7 @@ static int mei_wdt_probe(struct mei_cl_device *cldev,
if (ret)
goto err_disable;
- if (dbgfs_register(wdt))
- dev_warn(&cldev->dev, "cannot register debugfs\n");
+ dbgfs_register(wdt);
return 0;
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 469dfbd6cf90..4c339c7e66e5 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -264,8 +264,7 @@ void gntdev_put_map(struct gntdev_priv *priv, struct gntdev_grant_map *map)
/* ------------------------------------------------------------------ */
-static int find_grant_ptes(pte_t *pte, pgtable_t token,
- unsigned long addr, void *data)
+static int find_grant_ptes(pte_t *pte, unsigned long addr, void *data)
{
struct gntdev_grant_map *map = data;
unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT;
@@ -292,8 +291,7 @@ static int find_grant_ptes(pte_t *pte, pgtable_t token,
}
#ifdef CONFIG_X86
-static int set_grant_ptes_as_special(pte_t *pte, pgtable_t token,
- unsigned long addr, void *data)
+static int set_grant_ptes_as_special(pte_t *pte, unsigned long addr, void *data)
{
set_pte_at(current->mm, addr, pte, pte_mkspecial(*pte));
return 0;
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 1ff38d8036e9..2f5ce7230a43 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -731,8 +731,7 @@ struct remap_pfn {
unsigned long i;
};
-static int remap_pfn_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
- void *data)
+static int remap_pfn_fn(pte_t *ptep, unsigned long addr, void *data)
{
struct remap_pfn *r = data;
struct page *page = r->pages[r->i];
@@ -966,8 +965,7 @@ static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
* on a per pfn/pte basis. Mapping calls that fail with ENOENT
* can be then retried until success.
*/
-static int is_mapped_fn(pte_t *pte, struct page *pmd_page,
- unsigned long addr, void *data)
+static int is_mapped_fn(pte_t *pte, unsigned long addr, void *data)
{
return pte_none(*pte) ? 0 : -EBUSY;
}
diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
index e7df65d32c91..ba883a80b3c0 100644
--- a/drivers/xen/xlate_mmu.c
+++ b/drivers/xen/xlate_mmu.c
@@ -93,8 +93,7 @@ static void setup_hparams(unsigned long gfn, void *data)
info->fgfn++;
}
-static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
- void *data)
+static int remap_pte_fn(pte_t *ptep, unsigned long addr, void *data)
{
struct remap_data *info = data;
struct page *page = info->pages[info->index++];