summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml45
-rw-r--r--Documentation/devicetree/bindings/display/bridge/lontium,lt8912.txt62
-rw-r--r--Documentation/devicetree/bindings/hwmon/sht3x.txt16
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt16
-rw-r--r--Documentation/devicetree/bindings/mfd/nxp,pca9450.txt10
-rw-r--r--Documentation/devicetree/bindings/net/can/microchip,mcp25xxfd.txt39
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt6
-rw-r--r--Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt3
-rw-r--r--Documentation/devicetree/bindings/usb/usb3503.txt7
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml2
-rw-r--r--arch/arm/boot/dts/Makefile20
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-aster.dts219
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-cam-eval-v3.dts327
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts168
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-iris-v2.dts268
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-iris.dts195
-rw-r--r--arch/arm/boot/dts/imx6q-apalis-eval.dts278
-rw-r--r--arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts296
-rw-r--r--arch/arm/boot/dts/imx6q-apalis-ixora-v1.2.dts525
-rw-r--r--arch/arm/boot/dts/imx6q-apalis-ixora.dts257
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi5
-rw-r--r--arch/arm/boot/dts/imx6qdl-apalis.dtsi524
-rw-r--r--arch/arm/boot/dts/imx6qdl-colibri.dtsi469
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-aster.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-aster.dtsi317
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts4
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi235
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris-v2.dtsi370
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris.dtsi351
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi139
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts16
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi139
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri.dtsi334
-rw-r--r--arch/arm/boot/dts/imx6ull.dtsi1
-rw-r--r--arch/arm/boot/dts/imx7-colibri-aster.dtsi283
-rw-r--r--arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi229
-rw-r--r--arch/arm/boot/dts/imx7-colibri-iris-v2.dtsi333
-rw-r--r--arch/arm/boot/dts/imx7-colibri-iris.dtsi301
-rw-r--r--arch/arm/boot/dts/imx7-colibri.dtsi311
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-aster.dts20
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts21
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts4
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-emmc-iris-v2.dts21
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-emmc-iris.dts21
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-emmc.dtsi36
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-eval-v3.dts3
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-iris-v2.dts25
-rw-r--r--arch/arm/boot/dts/imx7d-colibri-iris.dts25
-rw-r--r--arch/arm/boot/dts/imx7d-colibri.dtsi46
-rw-r--r--arch/arm/boot/dts/imx7d.dtsi150
-rw-r--r--arch/arm/boot/dts/imx7s-colibri-aster.dts16
-rw-r--r--arch/arm/boot/dts/imx7s-colibri-eval-v3.dts45
-rw-r--r--arch/arm/boot/dts/imx7s-colibri-iris-v2.dts16
-rw-r--r--arch/arm/boot/dts/imx7s-colibri-iris.dts16
-rw-r--r--arch/arm/boot/dts/imx7s-colibri.dtsi41
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi163
-rw-r--r--arch/arm/configs/apalis_imx6_defconfig525
-rw-r--r--arch/arm/configs/colibri-imx6ull_defconfig494
-rw-r--r--arch/arm/configs/colibri_imx6_defconfig523
-rw-r--r--arch/arm/configs/colibri_imx7_defconfig508
-rw-r--r--arch/arm/configs/nit6xlite_defconfig303
-rw-r--r--arch/arm/kernel/reboot.c3
-rw-r--r--arch/arm/mach-imx/Kconfig3
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c12
-rw-r--r--arch/arm/mach-imx/cpu.c44
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6ul.c2
-rw-r--r--arch/arm/mach-imx/gpc.c2
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c72
-rw-r--r--arch/arm/mach-imx/mach-imx7d.c42
-rw-r--r--arch/arm/mach-imx/mu.c9
-rw-r--r--arch/arm/mach-imx/pm-imx6.c45
-rw-r--r--arch/arm/mach-imx/pm-imx7.c4
-rw-r--r--arch/arm/mm/dma-mapping.c5
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile26
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi425
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi477
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi1846
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi33
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi48
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h24
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-dahlia.dtsi20
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi107
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dahlia.dts18
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dev.dts18
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dahlia.dts19
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dev.dts19
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi.dtsi75
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-v1.1.dtsi1310
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dahlia.dts18
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dev.dts18
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dahlia.dts19
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dev.dts19
-rwxr-xr-xarch/arm64/boot/dts/freescale/imx8mm-verdin-wifi.dtsi96
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi211
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis-eval.dts16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis-ixora-v1.1.dts20
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-eval.dts17
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-ixora-v1.1.dts18
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1.dtsi26
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi354
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-eval.dts19
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-ixora-v1.1.dts20
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1.dtsi25
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dts16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dtsi316
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-apalis.dtsi1388
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-aster.dts45
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-dsihdmi-eval-v3.dts30
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dts16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi221
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-dual-eval-v3.dts30
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-single-eval-v3.dts36
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri.dtsi1302
-rw-r--r--arch/arm64/configs/defconfig723
-rw-r--r--drivers/ata/ahci_imx.c17
-rw-r--r--drivers/base/soc.c7
-rw-r--r--drivers/clk/imx/clk-gate2.c2
-rw-r--r--drivers/clk/imx/clk-imx7d.c8
-rw-r--r--drivers/clk/imx/clk-imx8qxp.c1
-rw-r--r--drivers/clk/imx/clk-pfd.c2
-rw-r--r--drivers/clk/imx/clk-pllv3.c2
-rw-r--r--drivers/clk/imx/clk.h8
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c2
-rw-r--r--drivers/crypto/caam/secvio.c2
-rw-r--r--drivers/dma/pxp/pxp_dma_v3.c4
-rw-r--r--drivers/extcon/extcon-usb-gpio.c2
-rwxr-xr-xdrivers/firmware/imx/scu-pd.c4
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-fxl6408.c261
-rw-r--r--drivers/gpio/gpio-mxc.c100
-rw-r--r--drivers/gpu/drm/bridge/Kconfig10
-rw-r--r--drivers/gpu/drm/bridge/Makefile2
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c47
-rw-r--r--drivers/gpu/drm/bridge/dumb-vga-dac.c7
-rw-r--r--drivers/gpu/drm/bridge/lt8912.c684
-rw-r--r--drivers/gpu/drm/bridge/sn65dsi83/Kconfig7
-rw-r--r--drivers/gpu/drm/bridge/sn65dsi83/Makefile2
-rw-r--r--drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c388
-rw-r--r--drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h55
-rw-r--r--drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c408
-rw-r--r--drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h33
-rw-r--r--drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c32
-rw-r--r--drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c29
-rw-r--r--drivers/gpu/drm/imx/cdns-mhdp-imx.h1
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_crtc.c8
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c73
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.h1
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_out.c2
-rw-r--r--drivers/gpu/drm/panel/panel-lvds.c46
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c91
-rw-r--r--drivers/hwmon/sht3x.c28
-rw-r--r--drivers/input/touchscreen/Kconfig23
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/ar1020-i2c.c500
-rw-r--r--drivers/input/touchscreen/fusion_F0710A.c507
-rw-r--r--drivers/input/touchscreen/fusion_F0710A.h88
-rw-r--r--drivers/media/platform/Kconfig1
-rw-r--r--drivers/media/platform/mxc/capture/Kconfig28
-rw-r--r--drivers/media/platform/mxc/capture/Makefile12
-rw-r--r--drivers/media/platform/mxc/capture/adv7180.c263
-rw-r--r--drivers/media/platform/mxc/capture/adv7280.c1080
-rw-r--r--drivers/media/platform/mxc/capture/ipu_csi_enc.c2
-rw-r--r--drivers/media/platform/mxc/capture/ipu_prp_enc.c16
-rw-r--r--drivers/media/platform/mxc/capture/max9526.c1153
-rw-r--r--drivers/media/platform/mxc/capture/mxc_mipi_csi.c59
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.c181
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.h9
-rw-r--r--drivers/media/platform/mxc/capture/ov5640_mipi.c224
-rw-r--r--drivers/media/platform/mxc/capture/ov5640_mipi_nv.c1509
-rw-r--r--drivers/media/platform/mxc/capture/tc358743_h2c.c3401
-rw-r--r--drivers/media/platform/mxc/output/mxc_vout.c3
-rw-r--r--drivers/mfd/pca9450.c15
-rw-r--r--drivers/mmc/host/sdhci.c5
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c28
-rwxr-xr-xdrivers/mxc/hantro_845_h1/Kconfig1
-rw-r--r--drivers/mxc/ipu3/ipu_common.c6
-rw-r--r--drivers/mxc/mipi/mxc_mipi_csi2.c2
-rw-r--r--drivers/net/can/flexcan.c9
-rw-r--r--drivers/net/can/spi/Kconfig2
-rw-r--r--drivers/net/can/spi/Makefile2
-rw-r--r--drivers/net/can/spi/mcp25xxfd/Kconfig17
-rw-r--r--drivers/net/can/spi/mcp25xxfd/Makefile19
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.c286
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.h14
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c687
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.h56
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.c232
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.h45
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.c352
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.h16
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_id.h69
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.c740
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.h17
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h204
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c521
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.h18
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.c781
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.h83
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.c498
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.h28
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.c392
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.h86
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.c88
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.h17
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.c112
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.h29
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.c75
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.h16
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.c241
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.h31
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.c73
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.h15
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_priv.h94
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_regs.h681
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c8
-rw-r--r--drivers/net/phy/micrel.c72
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c5
-rw-r--r--drivers/of/irq.c1
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c206
-rw-r--r--drivers/pci/quirks.c24
-rw-r--r--drivers/power/reset/gpio-poweroff.c27
-rw-r--r--drivers/regulator/bd718x7-regulator.c13
-rw-r--r--drivers/regulator/pca9450-regulator.c6
-rw-r--r--drivers/regulator/pfuze100-regulator.c86
-rw-r--r--drivers/rpmsg/Kconfig8
-rw-r--r--drivers/rpmsg/imx_rpmsg_tty.c28
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c347
-rw-r--r--drivers/rtc/rtc-ds1307.c58
-rw-r--r--drivers/spi/spi-fsl-lpspi.c32
-rw-r--r--drivers/spi/spidev.c24
-rw-r--r--drivers/thermal/imx_thermal.c4
-rw-r--r--drivers/tty/serial/fsl_lpuart.c102
-rw-r--r--drivers/tty/serial/imx.c12
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/core.c96
-rw-r--r--drivers/usb/misc/usb3503.c49
-rw-r--r--drivers/usb/phy/phy-generic.c40
-rw-r--r--drivers/usb/phy/phy-generic.h1
-rw-r--r--drivers/video/backlight/pwm_bl.c4
-rw-r--r--drivers/video/fbdev/mxc/Makefile2
-rw-r--r--drivers/video/fbdev/mxc/ldb.c59
-rw-r--r--drivers/video/fbdev/mxc/mxc_hdmi.c151
-rw-r--r--drivers/video/fbdev/mxc/mxc_ipuv3_fb.c26
-rw-r--r--drivers/video/fbdev/mxc/mxc_lcdif.c60
-rw-r--r--drivers/video/fbdev/mxc/mxc_vdacif.c356
-rw-r--r--drivers/video/fbdev/mxsfb.c139
-rw-r--r--drivers/video/logo/Kconfig4
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/logo/logo.c4
-rw-r--r--drivers/watchdog/imx_sc_wdt.c13
-rwxr-xr-xinclude/drm/bridge/cdns-mhdp-common.h2
-rw-r--r--include/linux/input/fusion_F0710A.h20
-rw-r--r--include/linux/linux_logo.h1
-rw-r--r--include/linux/mfd/pca9450.h4
-rw-r--r--include/linux/pinctrl/devinfo.h4
-rw-r--r--include/linux/platform_data/usb3503.h2
-rw-r--r--include/linux/sync.h390
-rw-r--r--include/linux/sys_soc.h1
-rw-r--r--include/media/v4l2-chip-ident.h3
-rw-r--r--include/video/mxc_hdmi.h7
-rw-r--r--net/bluetooth/hci_conn.c15
-rw-r--r--net/wireless/Kconfig4
-rw-r--r--sound/soc/codecs/Kconfig2
-rw-r--r--sound/soc/codecs/sgtl5000.c26
-rw-r--r--sound/soc/codecs/wm8904.c7
-rw-r--r--sound/soc/fsl/fsl_dsp.c74
-rw-r--r--sound/soc/fsl/fsl_spdif.c4
275 files changed, 38690 insertions, 2051 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 000000000000..00a9a12c1233
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,45 @@
+variables:
+# uncomment for the pipeline debug purpose
+# CI_DEBUG_TRACE: "true"
+ CI_IMAGE: gitlab.int.toradex.com:4567/philippe.schenker/linux-toradex/ci-kernel-builder:gcc9
+ DOCKER_HOST: tcp://docker:2375
+ DOCKER_DRIVER: overlay2
+ DOCKER_TLS_CERTDIR: ""
+
+stages:
+ - build-kernel
+
+build_kernel:
+ stage: build-kernel
+ image: $CI_IMAGE
+ variables:
+ GIT_STRATEGY: fetch
+ GIT_DEPTH: "1"
+ script: |
+ echo "GCC used to build binaries is"
+ which ${CROSS_COMPILE}gcc
+ ${CROSS_COMPILE}gcc --version
+ echo -e "Arch is \e[36m$ARCH\e[39m"
+ echo "Current directory: ${PWD}"
+ THREADS=$(grep processor /proc/cpuinfo -c)
+ echo "building with $THREADS parallel threads"
+ cd $CI_PROJECT_DIR
+ DEVICETREES=$(find arch/arm/boot/dts/ -regextype posix-extended -regex "^.*\/imx.*(apalis|colibri|verdin).*\.dts" | sed 's/arch\/arm\/boot\/dts\///' | sed 's/\.dts/\.dtb/')
+ make multi_v7_defconfig
+ echo -e "building: \n$DEVICETREES"
+ make -j$THREADS $DEVICETREES
+ make -j$THREADS
+ make mrproper
+ source /select_64bit_toolchain.sh
+ echo "GCC used to build binaries is"
+ which ${CROSS_COMPILE}gcc
+ ${CROSS_COMPILE}gcc --version
+ echo -e "Arch is \e[36m$ARCH\e[39m"
+ echo "Current directory: ${PWD}"
+ echo "building with $THREADS parallel threads"
+ DEVICETREES=$(find arch/arm64/boot/dts/ -regextype posix-extended -regex "^.*\/fsl.*(apalis|colibri|verdin).*\.dts" | sed 's/arch\/arm64\/boot\/dts\///' | sed 's/\.dts/\.dtb/')
+ make defconfig
+ echo -e "building: \n$DEVICETREES"
+ make -j$THREADS $DEVICETREES
+ make -j$THREADS
+ make mrproper
diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt8912.txt b/Documentation/devicetree/bindings/display/bridge/lontium,lt8912.txt
new file mode 100644
index 000000000000..b66eae06f194
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt8912.txt
@@ -0,0 +1,62 @@
+Lontium LT8912 MIPI-DSI to LVDS and HDMI/MHL bridge bindings
+
+Required properties and nodes:
+ - compatible: "lontium,lt8912"
+ - hpd-gpios: a GPIO spec for the hot-plug detect pin
+ - port: node referencing the MIPI-DSI source
+ - reg: i2c address of the bridge
+ - i2c-bus: phandle of an I2C controller used for register access
+ One of:
+ - ddc-i2c-bus: reference to a DDC-I2C bus for EDID retrival
+ - display-timings: hardcoded display timings if ddc-i2c-bus does not exist.
+ Refer to binding doc display-timing.txt for details
+
+Optional properties:
+ - reset-gpios: a GPIO spec for the reset pin
+
+Examples:
+&i2c1 {
+ lt8912@48 {
+ compatible = "lontium,lt8912";
+ ddc-i2c-bus = <&i2c0>;
+ hpd-gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+ reg = <0x48>;
+
+ port {
+ lt8912_1_in: endpoint {
+ remote-endpoint = <&mipi_dsi_bridge1_out>;
+ };
+ };
+
+&i2c2 {
+ lt8912@48 {
+ compatible = "lontium,lt8912";
+ hpd-gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+ reg = <0x48>;
+
+ port {
+ lt8912_1_in: endpoint {
+ remote-endpoint = <&mipi_dsi_bridge1_out>;
+ };
+ };
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <74250000>;
+ hactive = <1280>;
+ vactive = <720>;
+ hfront-porch = <110>;
+ hsync-len = <40>;
+ hback-porch = <220>;
+ vfront-porch = <5>;
+ vsync-len = <5>;
+ vback-porch = <20>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/hwmon/sht3x.txt b/Documentation/devicetree/bindings/hwmon/sht3x.txt
new file mode 100644
index 000000000000..e54327436605
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/sht3x.txt
@@ -0,0 +1,16 @@
+Sensirion SHT3x Humidity and Temperature Sensor
+
+Required node properties:
+- compatible: "sensirion,sht3x" or "sensirion,sts3x"
+- reg: I2C bus address of the device
+
+Optional properties:
+- sensirion,blocking-io: enable blocking mode on i2c
+- sensirion,no-high-precision: disable high accuracy
+
+Example sht3x node:
+
+sensor {
+ compatible = "sensirion,sht3x";
+ reg = <0x4a>;
+}
diff --git a/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt
index 2e1490a8fe74..192574f38ddb 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt
@@ -3,15 +3,16 @@
Required Properties:
- compatible must be toradex,vf50-touchscreen
- io-channels: adc channels being used by the Colibri VF50 module
+ IIO ADC for Y-, X-, Y+, X+ connections
- xp-gpios: FET gate driver for input of X+
- xm-gpios: FET gate driver for input of X-
- yp-gpios: FET gate driver for input of Y+
- ym-gpios: FET gate driver for input of Y-
-- interrupts: pen irq interrupt for touch detection
-- pinctrl-names: "idle", "default", "gpios"
-- pinctrl-0: pinctrl node for pen/touch detection state pinmux
+- interrupts: pen irq interrupt for touch detection, signal from X plate
+- pinctrl-names: "idle", "default"
+- pinctrl-0: pinctrl node for pen/touch detection, pinctrl must provide
+ pull-up resistor on X+, X-.
- pinctrl-1: pinctrl node for X/Y and pressure measurement (ADC) state pinmux
-- pinctrl-2: pinctrl node for gpios functioning as FET gate drivers
- vf50-ts-min-pressure: pressure level at which to stop measuring X/Y values
Example:
@@ -19,7 +20,7 @@ Example:
touchctrl: vf50_touchctrl {
compatible = "toradex,vf50-touchscreen";
io-channels = <&adc1 0>,<&adc0 0>,
- <&adc0 1>,<&adc1 2>;
+ <&adc0 1>,<&adc1 2>;
xp-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
xm-gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>;
yp-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
@@ -27,8 +28,7 @@ Example:
interrupt-parent = <&gpio0>;
interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "idle","default","gpios";
- pinctrl-0 = <&pinctrl_touchctrl_idle>;
- pinctrl-1 = <&pinctrl_touchctrl_default>;
- pinctrl-2 = <&pinctrl_touchctrl_gpios>;
+ pinctrl-0 = <&pinctrl_touchctrl_idle>, <&pinctrl_touchctrl_gpios> ;
+ pinctrl-1 = <&pinctrl_touchctrl_default>, <&pinctrl_touchctrl_gpios>;
vf50-ts-min-pressure = <200>;
};
diff --git a/Documentation/devicetree/bindings/mfd/nxp,pca9450.txt b/Documentation/devicetree/bindings/mfd/nxp,pca9450.txt
index f296c7d2e6ad..dd0fb3aec299 100644
--- a/Documentation/devicetree/bindings/mfd/nxp,pca9450.txt
+++ b/Documentation/devicetree/bindings/mfd/nxp,pca9450.txt
@@ -9,6 +9,15 @@ Required properties:
initialization data. Including 6 buck regulators
and 5 ldo regulators.
+Optional properties:
+ - i2c-lt-en : Sets I2C level translator enable in CONFIG2, valid:
+ 0x100 = Forced Disable
+ 0x101 = Enable only when STANDBY and RUN mode
+ 0x102 = Enable only when RUN mode
+ 0x103 = Forced enable
+ Any other value or if the property is missing CONFIG2
+ is not changed.
+
Example:
pmic: pca9450@25 {
reg = <0x25>;
@@ -16,6 +25,7 @@ Example:
/* PMIC PCA9450 PMIC_nINT GPIO1_IO3 */
pinctrl-0 = <&pinctrl_pmic>;
gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;
+ i2c-lt-en = <0x101>;
regulators {
#address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp25xxfd.txt b/Documentation/devicetree/bindings/net/can/microchip,mcp25xxfd.txt
new file mode 100644
index 000000000000..33c5c28f1455
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/microchip,mcp25xxfd.txt
@@ -0,0 +1,39 @@
+* Microchip MCP2517 stand-alone CAN controller device tree bindings
+
+Required properties:
+ - compatible: Should be one of the following:
+ - "microchip,mcp2517fd" for MCP2517fd.
+ - "microchip,mcp2518fd" for MCP2518fd.
+ - reg: SPI chip select.
+ - clocks: The clock feeding the CAN controller.
+ - interrupt-parent: The parent interrupt controller.
+ - interrupts: Should contain IRQ line for the CAN controller.
+ - gpio-controller: Marks the device node as a GPIO controller
+
+Optional properties:
+ - vdd-supply: Regulator that powers the CAN controller.
+ - xceiver-supply: Regulator that powers the CAN transceiver.
+ - microchip,clock-out-div = <0|1|2|4|10>: Clock output pin divider
+ 0 = Start of Frame output
+ default: 10
+ - microchip,clock-allways-on: bool: Do not disable the clock if CAN
+ is inactive. Thus a clock on the
+ clko pin will not be stopped.
+ This results in a higher standby
+ current.
+ - microchip,clock-div2: bool: divide the internal clock by 2
+ - microchip,gpio-open-drain: bool: enable open-drain for all pins
+ (except cantx)
+ - microchip,gpio0-xstandby: bool: enable xstandby functionality on gpio 0
+
+Example:
+ can0: can@1 {
+ compatible = "microchip,mcp2517fd";
+ reg = <1>;
+ clocks = <&clk24m>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <13 0x8>;
+ vdd-supply = <&reg5v0>;
+ xceiver-supply = <&reg5v0>;
+ gpio-controller;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt
index 8ac1d0851a0f..118d9852d3da 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt
@@ -47,10 +47,10 @@ PAD_CTL_PUE (1 << 4)
PAD_CTL_HYS (1 << 3)
PAD_CTL_SRE_SLOW (1 << 2)
PAD_CTL_SRE_FAST (0 << 2)
-PAD_CTL_DSE_X1 (0 << 0)
-PAD_CTL_DSE_X4 (1 << 0)
+PAD_CTL_DSE_X1 (min curr.) (0 << 0)
PAD_CTL_DSE_X2 (2 << 0)
-PAD_CTL_DSE_X6 (3 << 0)
+PAD_CTL_DSE_X4 (1 << 0)
+PAD_CTL_DSE_X6 (max curr.) (3 << 0)
Examples:
While iomuxc-lpsr is intended to be used by dedicated peripherals to take
diff --git a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
index 3e56c1b34a4c..2056e299a472 100644
--- a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
+++ b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
@@ -31,6 +31,9 @@ Optional properties:
- inactive-delay-ms: Delay (default 100) to wait after driving gpio inactive
- timeout-ms: Time to wait before asserting a WARN_ON(1). If nothing is
specified, 3000 ms is used.
+- force-mode: Force replacing pm_power_off kernel hook.
+ If this optional property is not specified, the driver will fail to
+ load if someone has registered the pm_power_off hook earlier.
Examples:
diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt
index 057dd384d473..7ccedf6cc4d5 100644
--- a/Documentation/devicetree/bindings/usb/usb3503.txt
+++ b/Documentation/devicetree/bindings/usb/usb3503.txt
@@ -1,16 +1,21 @@
SMSC USB3503 High-Speed Hub Controller
Required properties:
-- compatible: Should be "smsc,usb3503" or "smsc,usb3503a".
+- compatible: Should be "smsc,usb3503" or "smsc,usb3503a" or "smsc,usb3803".
Optional properties:
- reg: Specifies the i2c slave address, it is required and should be 0x08
if I2C is used.
+- bypass-gpios: Should specify GPIO for bypass.
+ Follows the state of reset-gpios and is meant to be used with
+ usb3803's bypass pin.
- connect-gpios: Should specify GPIO for connect.
- disabled-ports: Should specify the ports unused.
'1' or '2' or '3' are available for this property to describe the port
number. 1~3 property values are possible to be described.
Do not describe this property if all ports have to be enabled.
+- non-removable-devices: Should specify the ports going to non removable
+ devices. See disabled-ports for the syntax.
- intn-gpios: Should specify GPIO for interrupt.
- reset-gpios: Should specify GPIO for reset.
- initial-mode: Should specify initial mode.
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index fa5e531928df..b72195020009 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -545,6 +545,8 @@ patternProperties:
description: Logic PD, Inc.
"^longcheer,.*":
description: Longcheer Technology (Shanghai) Co., Ltd.
+ "^lontium,.*":
+ description: Lontium Semiconductor Corporation
"^lsi,.*":
description: LSI Corp. (LSI Logic)
"^lwn,.*":
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 70250bd6f961..56990cfc3c5b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -401,7 +401,11 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-aristainetos_7.dtb \
imx6dl-aristainetos2_4.dtb \
imx6dl-aristainetos2_7.dtb \
+ imx6dl-colibri-aster.dtb \
+ imx6dl-colibri-cam-eval-v3.dtb \
imx6dl-colibri-eval-v3.dtb \
+ imx6dl-colibri-iris.dtb \
+ imx6dl-colibri-iris-v2.dtb \
imx6dl-cubox-i.dtb \
imx6dl-cubox-i-emmc-som-v15.dtb \
imx6dl-cubox-i-som-v15.dtb \
@@ -471,6 +475,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-apalis-eval.dtb \
imx6q-apalis-ixora.dtb \
imx6q-apalis-ixora-v1.1.dtb \
+ imx6q-apalis-ixora-v1.2.dtb \
imx6q-apf6dev.dtb \
imx6q-arm2.dtb \
imx6q-b450v3.dtb \
@@ -640,7 +645,13 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ull-9x9-evk-ldo.dtb \
imx6ull-9x9-evk-btwifi.dtb \
imx6ull-9x9-evk-btwifi-oob.dtb \
+ imx6ull-colibri-aster.dtb \
+ imx6ull-colibri-iris.dtb \
+ imx6ull-colibri-iris-v2.dtb \
imx6ull-colibri-eval-v3.dtb \
+ imx6ull-colibri-wifi-aster.dtb \
+ imx6ull-colibri-wifi-iris.dtb \
+ imx6ull-colibri-wifi-iris-v2.dtb \
imx6ull-colibri-wifi-eval-v3.dtb \
imx6ull-phytec-segin-ff-rdk-nand.dtb \
imx6ull-phytec-segin-ff-rdk-emmc.dtb \
@@ -651,6 +662,12 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
imx6ulz-14x14-evk-emmc.dtb
dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-cl-som-imx7.dtb \
+ imx7d-colibri-aster.dtb \
+ imx7d-colibri-iris.dtb \
+ imx7d-colibri-iris-v2.dtb \
+ imx7d-colibri-emmc-aster.dtb \
+ imx7d-colibri-emmc-iris.dtb \
+ imx7d-colibri-emmc-iris-v2.dtb \
imx7d-colibri-emmc-eval-v3.dtb \
imx7d-colibri-eval-v3.dtb \
imx7d-mba7.dtb \
@@ -659,6 +676,9 @@ dtb-$(CONFIG_SOC_IMX7D) += \
imx7d-pico-hobbit.dtb \
imx7d-pico-pi.dtb \
imx7d-sbc-imx7.dtb \
+ imx7s-colibri-aster.dtb \
+ imx7s-colibri-iris.dtb \
+ imx7s-colibri-iris-v2.dtb \
imx7d-sdb.dtb \
imx7d-sdb-epdc.dtb \
imx7d-sdb-mipi-dsi.dtb \
diff --git a/arch/arm/boot/dts/imx6dl-colibri-aster.dts b/arch/arm/boot/dts/imx6dl-colibri-aster.dts
new file mode 100644
index 000000000000..d149c02932cb
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-colibri-aster.dts
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2014-2018 Toradex AG
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "imx6dl.dtsi"
+#include "imx6qdl-colibri.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6DL/S on Colibri Aster Board";
+ compatible = "toradex,colibri_imx6dl-aster", "toradex,colibri_imx6dl", "fsl,imx6dl";
+
+ aliases {
+ i2c0 = &i2cddc;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ };
+
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &snvs_rtc;
+ };
+
+ aliases {
+ /* the following, together with kernel patches, forces a fixed assignment
+ between device id and usdhc controller */
+ /* i.e. the eMMC on usdhc3 will be /dev/mmcblk0 */
+ mmc0 = &usdhc3; /* eMMC */
+ mmc1 = &usdhc1; /* MMC 4bit slot */
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ wakeup {
+ label = "Wake-Up";
+ gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+};
+
+&reg_usb_host_vbus {
+ status = "okay";
+};
+
+&backlight {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm3 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&ecspi4 {
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <
+ &gpio5 2 GPIO_ACTIVE_HIGH
+ &gpio5 4 GPIO_ACTIVE_HIGH
+ >;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi4 &pinctrl_csi_gpio_2>;
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ };
+
+ spidev1: spidev@1 {
+ compatible = "toradex,evalspi";
+ reg = <1>;
+ spi-max-frequency = <23000000>;
+ };
+};
+
+/*
+ * I2C: I2C3_SDA/SCL on SODIMM 194/196 (e.g. RTC on carrier
+ * board)
+ */
+&i2c3 {
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mxt_ts>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ /*
+ * Note: When the status is set to okay, to avoid pinmux
+ * conflict, one should remove the pinctrl_weim_cs1 and
+ * pinctrl_weim_cs2 pingroup from the weim pinctrl-0
+ * property or disable weim node.
+ */
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&iomuxc {
+ /*
+ * Mux all pins which are unused to be GPIOs
+ * so they are ready for export to user space
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_weim_gpio_1 &pinctrl_weim_gpio_2
+ &pinctrl_weim_gpio_3 &pinctrl_weim_gpio_4
+ &pinctrl_weim_gpio_5 &pinctrl_weim_gpio_6
+ &pinctrl_csi_gpio_1
+ &pinctrl_gpio_1
+ &pinctrl_gpio_2
+ &pinctrl_usbh_oc_1 &pinctrl_usbc_id_1
+ >;
+
+ gpio {
+ pinctrl_gpios: gpios {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* SODIMM 28 */
+ MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x1b0b0 /* SODIMM 30 */
+ >;
+ };
+
+ pinctrl_mxt_ts: mxt-ts {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x130b0 /* SODIMM 107 */
+ MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x130b0 /* SODIMM 106 */
+ >;
+ };
+ };
+};
+
+&lcd {
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&pwm3 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&usbh1 {
+ status = "okay";
+};
+
+&usbotg {
+ status = "okay";
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+};
+
+/* MMC */
+&usdhc1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-colibri-cam-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-cam-eval-v3.dts
new file mode 100644
index 000000000000..5f22b31753e2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-colibri-cam-eval-v3.dts
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2014-2018 Toradex AG
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "imx6dl.dtsi"
+#include "imx6qdl-colibri.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6DL/S on Colibri Evaluation Board V3";
+ compatible = "toradex,colibri_imx6dl-eval", "toradex,colibri_imx6dl", "fsl,imx6dl";
+
+ aliases {
+ i2c0 = &i2cddc;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ };
+
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &snvs_rtc;
+ };
+
+ aliases {
+ /* the following, together with kernel patches, forces a fixed assignment
+ between device id and usdhc controller */
+ /* i.e. the eMMC on usdhc3 will be /dev/mmcblk0 */
+ mmc0 = &usdhc3; /* eMMC */
+ mmc1 = &usdhc1; /* MMC 4bit slot */
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ wakeup {
+ label = "Wake-Up";
+ gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+};
+
+&reg_usb_host_vbus {
+ status = "okay";
+};
+
+/ {
+ clocks {
+ /* fixed crystal dedicated to mcp251x */
+ clk16m: clk16m {
+ compatible = "fixed-clock";
+ clock-frequency = <16000000>;
+ clock-output-names = "clk16m";
+ #clock-cells = <0>;
+ };
+ };
+};
+
+/* Colibri SPI */
+&ecspi4 {
+ status = "okay";
+
+ mcp251x0: mcp251x@0 {
+ compatible = "microchip,mcp2515";
+ reg = <0>;
+ clocks = <&clk16m>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <27 0x2>;
+ spi-max-frequency = <10000000>;
+ status = "okay";
+ };
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "disabled";
+ };
+};
+
+&gpio3 {
+ camera_nreset {
+ gpio-hog;
+ gpios = <26 0>; /* SODIMM 71 */
+ output-high;
+ };
+};
+
+/*
+ * I2C: I2C3_SDA/SCL on SODIMM 194/196 (e.g. RTC on carrier
+ * board)
+ */
+&i2c3 {
+ status = "okay";
+
+/* the PCAPs use SODIMM 28/30, also used for PWM<B>, PWM<C>, aka pwm1, pwm4.
+ so if you enable one of the PCAP controllers disable the pwms */
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcap_1>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 28 */
+ reset-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; /* SODIMM 30 */
+ status = "disabled";
+ };
+
+ pcap: pcap@10 {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ compatible = "touchrevolution,fusion-f0710a";
+ reg = <0x10>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcap_1>;
+ gpios = <&gpio1 9 0 /* SODIMM 28, Pen down interrupt */
+ &gpio2 10 0 /* SODIMM 30, Reset */
+ >;
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+
+ adv7280: adv7280@21 {
+ compatible = "adv7280";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ DVDD-supply = <&reg_3p3v>;
+ PVDD-supply = <&reg_3p3v>;
+ csi_id = <1>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ status = "okay";
+ };
+
+ /* Video ADC on Analog Camera Module */
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ PVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <1>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ cvbs = <1>;
+ status = "disabled";
+ };
+ max9526: max9526@20 {
+ compatible = "maxim,max9526";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DVDDIO-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-suplsply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <1>;
+ mclk = <24000000>;
+ mclk_source = <0>;
+ cvbs = <1>;
+ status = "okay";
+ };
+};
+
+&iomuxc {
+ /*
+ * Mux all pins which are unused to be GPIOs
+ * so they are ready for export to user space
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_weim_gpio_1 &pinctrl_weim_gpio_2
+ &pinctrl_weim_gpio_3 &pinctrl_weim_gpio_4
+ &pinctrl_weim_gpio_5 &pinctrl_weim_gpio_6
+ &pinctrl_gpio_1
+ &pinctrl_gpio_2
+ &pinctrl_gpio_bl_on
+ &pinctrl_usbh_oc_1 &pinctrl_usbc_id_1
+ >;
+
+ gpio {
+ pinctrl_pcap_1: pcap-1 {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* SODIMM 28 */
+ MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x1b0b0 /* SODIMM 30 */
+ >;
+ };
+
+ pinctrl_mxt_ts: mxt-ts {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x130b0 /* SODIMM 107 */
+ MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x130b0 /* SODIMM 106 */
+ >;
+ };
+ };
+};
+
+&lcd {
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+/* the PCAPs use SODIMM 28/30, also used for PWM<B>, PWM<C>, aka pwm1, pwm4.
+ so if you enable one of the PCAP controllers disable the pwms */
+&pwm1 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+#if 0
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+#endif
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&usbh1 {
+ status = "okay";
+};
+
+&usbotg {
+ status = "okay";
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+};
+
+/* MMC */
+&usdhc1 {
+ status = "okay";
+};
+
+&weim {
+ status = "okay";
+ fsl,weim-cs-gpr = <&gpr>;
+ /* weim memory map: 32MB on CS0, 32MB on CS1, 32MB on CS2, 32MB on CS3 */
+ ranges = <0 0 0x08000000 0x02000000
+ 1 0 0x0a000000 0x02000000
+ 2 0 0x0c000000 0x02000000
+ 3 0 0x0e000000 0x02000000>;
+ /* SRAM on CS0 */
+ sram@0,0 {
+ compatible = "cypress,cy7c1019dv33-10zsxi, mtd-ram";
+ reg = <0 0 0x00010000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bank-width = <2>;
+ fsl,weim-cs-timing = <0x00010081 0x00000000 0x04000000
+ 0x00000000 0x04000040 0x00000000>;
+ };
+ /* SRAM on CS1 */
+ sram@1,0 {
+ compatible = "cypress,cy7c1019dv33-10zsxi, mtd-ram";
+ reg = <1 0 0x00010000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bank-width = <2>;
+ fsl,weim-cs-timing = <0x00010081 0x00000000 0x04000000
+ 0x00000000 0x04000040 0x00000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
index 9a5d6c94cca4..57ec1d15ac19 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
@@ -1,50 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
/*
- * Copyright 2014-2016 Toradex AG
+ * Copyright 2014-2020 Toradex
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
*/
/dts-v1/;
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
#include "imx6dl.dtsi"
#include "imx6qdl-colibri.dtsi"
@@ -69,6 +34,24 @@
rtc1 = &snvs_rtc;
};
+ aliases {
+ /*
+ * the following, together with kernel patches, forces a fixed
+ * assignment between device id and usdhc controller
+ * i.e. the eMMC on usdhc3 will be /dev/mmcblk0
+ */
+ mmc0 = &usdhc3; /* eMMC */
+ mmc1 = &usdhc1; /* MMC 4bit slot */
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -94,52 +77,12 @@
wakeup-source;
};
};
-
- lcd_display: disp0 {
- compatible = "fsl,imx-parallel-display";
- #address-cells = <1>;
- #size-cells = <0>;
- interface-pix-fmt = "bgr666";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ipu1_lcdif>;
- status = "okay";
-
- port@0 {
- reg = <0>;
-
- lcd_display_in: endpoint {
- remote-endpoint = <&ipu1_di0_disp0>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- lcd_display_out: endpoint {
- remote-endpoint = <&lcd_panel_in>;
- };
- };
- };
-
- panel: panel {
- /*
- * edt,et057090dhu: EDT 5.7" LCD TFT
- * edt,et070080dh6: EDT 7.0" LCD TFT
- */
- compatible = "edt,et057090dhu";
- backlight = <&backlight>;
-
- port {
- lcd_panel_in: endpoint {
- remote-endpoint = <&lcd_display_out>;
- };
- };
- };
};
&backlight {
- brightness-levels = <0 127 191 223 239 247 251 255>;
- default-brightness-level = <1>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm3 0 6666667 PWM_POLARITY_INVERTED>;
status = "okay";
};
@@ -156,10 +99,12 @@
spi-max-frequency = <10000000>;
status = "okay";
};
-};
-
-&hdmi {
- status = "okay";
+ spidev0: spidev@1 {
+ compatible = "toradex,evalspi";
+ reg = <1>;
+ spi-max-frequency = <23000000>;
+ status = "disabled";
+ };
};
/*
@@ -168,6 +113,22 @@
&i2c3 {
status = "okay";
+ /*
+ * the PCAPs use SODIMM 28/30, also used for PWM<B>, PWM<C>, aka pwm1,
+ * pwm4. So if you enable one of the PCAP controllers disable the pwms.
+ */
+ pcap: pcap@10 {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ compatible = "touchrevolution,fusion-f0710a";
+ reg = <0x10>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcap_1>;
+ gpios = <&gpio1 9 0 /* SODIMM 28, Pen down interrupt */
+ &gpio2 10 0 /* SODIMM 30, Reset */
+ >;
+ status = "disabled";
+ };
+
/* M41T0M6 real time clock on carrier board */
rtc_i2c: rtc@68 {
compatible = "st,m41t0";
@@ -175,8 +136,38 @@
};
};
-&ipu1_di0_disp0 {
- remote-endpoint = <&lcd_display_in>;
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_weim_gpio_1 &pinctrl_weim_gpio_2
+ &pinctrl_weim_gpio_3 &pinctrl_weim_gpio_4
+ &pinctrl_weim_gpio_5 &pinctrl_weim_gpio_6
+ &pinctrl_csi_gpio_1
+ &pinctrl_gpio_1
+ &pinctrl_gpio_2
+ &pinctrl_usbh_oc_1 &pinctrl_usbc_id_1
+ >;
+
+ gpio {
+ pinctrl_pcap_1: pcap-1 {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* SODIMM 28 */
+ MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x1b0b0 /* SODIMM 30 */
+ >;
+ };
+ };
+};
+
+&lcd {
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
};
&pwm1 {
@@ -218,6 +209,7 @@
&usbotg {
status = "okay";
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
};
/* Colibri MMC */
@@ -227,7 +219,7 @@
&weim {
status = "okay";
-
+ fsl,weim-cs-gpr = <&gpr>;
/* weim memory map: 32MB on CS0, CS1, CS2 and CS3 */
ranges = <0 0 0x08000000 0x02000000
1 0 0x0a000000 0x02000000
diff --git a/arch/arm/boot/dts/imx6dl-colibri-iris-v2.dts b/arch/arm/boot/dts/imx6dl-colibri-iris-v2.dts
new file mode 100644
index 000000000000..ef019a950655
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-colibri-iris-v2.dts
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "imx6dl.dtsi"
+#include "imx6qdl-colibri.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6DL/S on Colibri Iris V2 Board";
+ compatible = "toradex,colibri_imx6dl-iris-v2", \
+ "toradex,colibri_imx6dl", "fsl,imx6dl";
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ reg_3v3_vmmc: regulator-3v3-vmmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enable_3v3_vmmc>;
+ regulator-name = "3v3_vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+};
+
+&backlight {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm3 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+/* Colibri SSP */
+&ecspi4 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+/*
+ * I2C: I2C3_SDA/SCL on SODIMM 194/196 (e.g. RTC on carrier
+ * board)
+ */
+&i2c3 {
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mxt_ts>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "okay";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcd {
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&pwm3 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&reg_usb_host_vbus {
+ status = "okay";
+};
+
+/* Colibri UART_A */
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_dte &pinctrl_uart1_ctrl
+ &pinctrl_uart1_forceoff>;
+};
+
+/* Colibri UART_B */
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_dte &pinctrl_uart23_forceoff>;
+};
+
+/* Colibri UART_C */
+&uart3 {
+ status = "okay";
+ /*
+ * Note that UART3 is on the same tranceiver as UART2 and this needs
+ * to be enabled with the pinmuxing &pinctrl_uart23_forceoff
+ */
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+&usbotg {
+ status = "okay";
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+};
+
+&usdhc1 {
+/*
+ * The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control which is supported starting
+ * with hardware revision V1.1A.
+ */
+/* #define SD_1_8 */
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_mmc_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_mmc_cd>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_mmc_cd>;
+ pinctrl-3 = <&pinctrl_usdhc1_sleep &pinctrl_mmc_cd_sleep>;
+ vqmmc-supply = <&vgen3_reg>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+#else
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_mmc_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_sleep &pinctrl_mmc_cd_sleep>;
+ no-1-8-v;
+#endif
+ cap-power-off-card;
+ /delete-property/ keep-power-in-suspend;
+ vmmc-supply = <&reg_3v3_vmmc>;
+ status = "okay";
+};
+
+&gpio1 {
+ /*
+ * This turns the LVDS transceiver on. If one wants to turn the
+ * transceiver off, that property has to be deleted and the gpio handled
+ * in userspace.
+ */
+ lvds_tx_on {
+ gpio-hog;
+ gpios = <12 0>;
+ output-high;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lvds_transceiver &pinctrl_gpio_iris>;
+
+ gpio {
+ pinctrl_mxt_ts: mxt-ts {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x130b0 /* SODIMM 107 */
+ MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x130b0 /* SODIMM 106 */
+ >;
+ };
+
+ pinctrl_lvds_transceiver: lvds-tx {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* SODIMM 55 */
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x130b0 /* SODIMM 63 */
+ MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x130b0 /* SODIMM 95 */
+ MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0 /* SODIMM_99 */
+ >;
+ };
+
+ pinctrl_gpio_iris: gpio-iris {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0 /* SODIMM 98 */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0 /* SODIMM 133 */
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0 /* SODIMM 103 */
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 /* SODIMM 101 */
+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b0 /* SODIMM 97 */
+ MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b0 /* SODIMM 85 */
+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b0 /* SODIMM 79 */
+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 /* SODIMM 45 */
+ >;
+ };
+ };
+
+ uart {
+ pinctrl_uart1_forceoff: uart1_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ >;
+ };
+
+ pinctrl_uart23_forceoff: uart23_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT0__GPIO2_IO08 0x1b0b0
+ >;
+ };
+ };
+
+ usdhc {
+ pinctrl_enable_3v3_vmmc: enable_3v3_vmmc {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b0
+ >;
+ };
+
+ pinctrl_mmc_cd_sleep: gpiommccdgrpslp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x0
+ >;
+ };
+
+ pinctrl_usdhc1_sleep: usdhc1grp_sleep {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x3000
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x3000
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x3000
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x3000
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x3000
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x3000
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dl-colibri-iris.dts b/arch/arm/boot/dts/imx6dl-colibri-iris.dts
new file mode 100644
index 000000000000..7927b3534e91
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-colibri-iris.dts
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "imx6dl.dtsi"
+#include "imx6qdl-colibri.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6DL/S on Colibri Iris Board";
+ compatible = "toradex,colibri_imx6dl-iris", \
+ "toradex,colibri_imx6dl", "fsl,imx6dl";
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+};
+
+&backlight {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm3 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+/* Colibri SSP */
+&ecspi4 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+/*
+ * I2C: I2C3_SDA/SCL on SODIMM 194/196 (e.g. RTC on carrier
+ * board)
+ */
+&i2c3 {
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mxt_ts>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "okay";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcd {
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&pwm3 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&reg_usb_host_vbus {
+ status = "okay";
+};
+
+/* Colibri UART_A */
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_dte &pinctrl_uart1_ctrl
+ &pinctrl_uart1_forceoff>;
+};
+
+/* Colibri UART_B */
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_dte &pinctrl_uart23_forceoff>;
+};
+
+/* Colibri UART_C */
+&uart3 {
+ status = "okay";
+ /*
+ * Note that UART3 is on the same tranceiver as UART2 and this needs
+ * to be enabled with the pinmuxing &pinctrl_uart23_forceoff
+ */
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+&usbotg {
+ status = "okay";
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+};
+
+&usdhc1 {
+ status = "okay";
+};
+
+&gpio1 {
+ /*
+ * This turns the LVDS transceiver on. If one wants to turn the
+ * transceiver off, that property has to be deleted and the gpio handled
+ * in userspace.
+ */
+ lvds_tx_on {
+ gpio-hog;
+ gpios = <12 0>;
+ output-high;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_iris>;
+
+ gpio {
+ pinctrl_mxt_ts: mxt-ts {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x130b0 /* SODIMM 107 */
+ MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x130b0 /* SODIMM 106 */
+ >;
+ };
+
+ pinctrl_gpio_iris: gpio-iris {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0 /* SODIMM 98 */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0 /* SODIMM 133 */
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0 /* SODIMM 103 */
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 /* SODIMM 101 */
+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b0 /* SODIMM 97 */
+ MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b0 /* SODIMM 85 */
+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b0 /* SODIMM 79 */
+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 /* SODIMM 45 */
+ >;
+ };
+ };
+
+ uart {
+ pinctrl_uart1_forceoff: uart1_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ >;
+ };
+
+ pinctrl_uart23_forceoff: uart23_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT0__GPIO2_IO08 0x1b0b0
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-apalis-eval.dts b/arch/arm/boot/dts/imx6q-apalis-eval.dts
index 0edd3043d9c1..0dd30ef267a5 100644
--- a/arch/arm/boot/dts/imx6q-apalis-eval.dts
+++ b/arch/arm/boot/dts/imx6q-apalis-eval.dts
@@ -1,44 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
/*
- * Copyright 2014-2017 Toradex AG
+ * Copyright 2014-2020 Toradex
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
*/
/dts-v1/;
@@ -46,6 +10,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
#include "imx6q.dtsi"
#include "imx6qdl-apalis.dtsi"
@@ -80,48 +45,6 @@
};
};
- lcd_display: disp0 {
- compatible = "fsl,imx-parallel-display";
- #address-cells = <1>;
- #size-cells = <0>;
- interface-pix-fmt = "rgb24";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ipu1_lcdif>;
- status = "okay";
-
- port@0 {
- reg = <0>;
-
- lcd_display_in: endpoint {
- remote-endpoint = <&ipu1_di1_disp1>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- lcd_display_out: endpoint {
- remote-endpoint = <&lcd_panel_in>;
- };
- };
- };
-
- panel: panel {
- /*
- * edt,et057090dhu: EDT 5.7" LCD TFT
- * edt,et070080dh6: EDT 7.0" LCD TFT
- */
- compatible = "edt,et057090dhu";
- backlight = <&backlight>;
- power-supply = <&reg_3v3_sw>;
-
- port {
- lcd_panel_in: endpoint {
- remote-endpoint = <&lcd_display_out>;
- };
- };
- };
-
reg_pcie_switch: regulator-pcie-switch {
compatible = "regulator-fixed";
regulator-name = "pcie_switch";
@@ -140,12 +63,37 @@
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
+
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+ v4l2_cap_1 { // second parallel camera
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <1>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+ v4l2_cap_2 { // mipi-csi2 camera
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
};
&backlight {
- brightness-levels = <0 127 191 223 239 247 251 255>;
- default-brightness-level = <1>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
power-supply = <&reg_3v3_sw>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
status = "okay";
};
@@ -159,7 +107,41 @@
status = "okay";
};
-&hdmi {
+/* Apalis SPI1 */
+&ecspi1 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
+};
+
+/* Apalis SPI2 */
+&ecspi2 {
+ status = "okay";
+
+ spidev1: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ status = "okay";
+};
+
+&hdmi_core {
+ status = "okay";
+};
+
+&hdmi_video {
status = "okay";
};
@@ -167,6 +149,15 @@
&i2c1 {
status = "okay";
+ pcap@10 {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ compatible = "touchrevolution,fusion-f0710a";
+ reg = <0x10>;
+ gpios = <&gpio6 10 GPIO_ACTIVE_HIGH /* MXM3 11, Pen down interrupt */
+ &gpio6 9 GPIO_ACTIVE_HIGH /* MXM3 13, Reset */
+ >;
+ };
+
pcie-switch@58 {
compatible = "plx,pex8605";
reg = <0x58>;
@@ -185,13 +176,105 @@
*/
&i2c3 {
status = "okay";
+
+ adv7280: adv7280@21 {
+ compatible = "adv7280";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ DVDD-supply = <&reg_3p3v>;
+ PVDD-supply = <&reg_3p3v>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ status = "okay";
+ };
+
+ /* Video ADC on Analog Camera Module */
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ PVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "disabled";
+ };
+
+ max9526: max9526@20 {
+ compatible = "maxim,max9526";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DVDDIO-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "okay";
+ };
+
+ ov5640_mipi@3c {
+ compatible = "ovti,ov564x_mipi";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_1p8v>;
+ AVDD-supply = <&reg_2p5v>;
+ DVDD-supply = <&reg_1p8v>;
+ pwn-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk = <22000000>;
+ mclk_source = <0>;
+ status = "okay";
+ };
};
-&ipu1_di1_disp1 {
- remote-endpoint = <&lcd_display_in>;
+/*
+ * DDC_I2C: I2C2_SDA/SCL on MXM3 205/207
+ */
+&i2cddc {
+ status = "okay";
+
+ hdmi_ddc: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+};
+
+&mipi_csi {
+ ipu_id = <0>;
+ csi_id = <1>;
+ v_channel = <0>;
+ lanes = <2>;
+ status = "okay";
};
-&ldb {
+&mxcfb2 {
+ status = "okay";
+};
+
+&mxcfb4 {
status = "okay";
};
@@ -200,7 +283,6 @@
pinctrl-0 = <&pinctrl_reset_moci>;
/* active-high meaning opposite of regular PERST# active-low polarity */
reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
- reset-gpio-active-high;
vpcie-supply = <&reg_pcie_switch>;
status = "okay";
};
@@ -221,11 +303,11 @@
status = "okay";
};
-&reg_usb_otg_vbus {
+&reg_usb_host_vbus {
status = "okay";
};
-&reg_usb_host_vbus {
+&reg_usb_otg_vbus {
status = "okay";
};
@@ -233,6 +315,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&sound_spdif {
status = "okay";
};
@@ -247,6 +333,11 @@
&uart2 {
status = "okay";
+#if 0
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+#endif
};
&uart4 {
@@ -283,14 +374,15 @@
status = "okay";
};
+&vdac {
+ status = "okay";
+};
+
&iomuxc {
- /*
- * Mux the Apalis GPIOs
- */
+ /* Mux the Apalis GPIOs */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_apalis_gpio1 &pinctrl_apalis_gpio2
&pinctrl_apalis_gpio3 &pinctrl_apalis_gpio4
- &pinctrl_apalis_gpio5 &pinctrl_apalis_gpio6
&pinctrl_apalis_gpio7 &pinctrl_apalis_gpio8
>;
};
diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts
index b94bb687be6b..cb864a5109c9 100644
--- a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts
+++ b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts
@@ -1,44 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
/*
- * Copyright 2014-2017 Toradex AG
+ * Copyright 2014-2020 Toradex
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
*/
/dts-v1/;
@@ -46,6 +10,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
#include "imx6q.dtsi"
#include "imx6qdl-apalis.dtsi"
@@ -107,21 +72,6 @@
};
};
- panel: panel {
- /*
- * edt,et057090dhu: EDT 5.7" LCD TFT
- * edt,et070080dh6: EDT 7.0" LCD TFT
- */
- compatible = "edt,et057090dhu";
- backlight = <&backlight>;
-
- port {
- lcd_panel_in: endpoint {
- remote-endpoint = <&lcd_display_out>;
- };
- };
- };
-
leds {
compatible = "gpio-leds";
@@ -148,23 +98,101 @@
gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
};
};
+
+ panel: panel {
+ /*
+ * edt,et057090dhu: EDT 5.7" LCD TFT
+ * edt,et070080dh6: EDT 7.0" LCD TFT
+ */
+ compatible = "edt,et057090dhu";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3_sw>;
+
+ port {
+ lcd_panel_in: endpoint {
+ remote-endpoint = <&lcd_display_out>;
+ };
+ };
+ };
+
+ reg_3v3_sw: regulator-3v3-sw {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V_SW";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+ v4l2_cap_2 { // mipi-csi2 camera
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
};
&backlight {
- brightness-levels = <0 127 191 223 239 247 251 255>;
- default-brightness-level = <1>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ power-supply = <&reg_3v3_sw>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
status = "okay";
};
&can1 {
+ xceiver-supply = <&reg_3v3_sw>;
status = "okay";
};
&can2 {
+ xceiver-supply = <&reg_3v3_sw>;
status = "okay";
};
-&hdmi {
+/* Apalis SPI1 */
+&ecspi1 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
+};
+
+/* Apalis SPI2 */
+&ecspi2 {
+ status = "okay";
+
+ spidev1: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ status = "okay";
+};
+
+&hdmi_core {
+ status = "okay";
+};
+
+&hdmi_video {
status = "okay";
};
@@ -172,6 +200,15 @@
&i2c1 {
status = "okay";
+ pcap@10 {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ compatible = "touchrevolution,fusion-f0710a";
+ reg = <0x10>;
+ gpios = <&gpio6 10 GPIO_ACTIVE_HIGH /* MXM3 11, Pen down interrupt */
+ &gpio6 9 GPIO_ACTIVE_HIGH /* MXM3 13, Reset */
+ >;
+ };
+
/* M41T0M6 real time clock on carrier board */
rtc_i2c: rtc@68 {
compatible = "st,m41t0";
@@ -185,22 +222,133 @@
*/
&i2c3 {
status = "okay";
+
+ adv7280: adv7280@21 {
+ compatible = "adv7280";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ DVDD-supply = <&reg_3p3v>;
+ PVDD-supply = <&reg_3p3v>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ status = "okay";
+ };
+
+ /* Video ADC on Analog Camera Module */
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ PVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "disabled";
+ };
+
+ max9526: max9526@20 {
+ compatible = "maxim,max9526";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DVDDIO-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "okay";
+ };
+
+ ov5640_mipi@3c {
+ compatible = "ovti,ov564x_mipi";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_1p8v>;
+ AVDD-supply = <&reg_2p5v>;
+ DVDD-supply = <&reg_1p8v>;
+ pwn-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk = <22000000>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+};
+
+/*
+ * DDC_I2C: I2C2_SDA/SCL on MXM3 205/207
+ */
+&i2cddc {
+ status = "okay";
+
+ hdmi_ddc: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&ipu1_di1_disp1 {
remote-endpoint = <&lcd_display_in>;
};
+&lcd {
+ status = "okay";
+};
+
&ldb {
status = "okay";
};
+&mipi_csi {
+ ipu_id = <0>;
+ csi_id = <1>;
+ v_channel = <0>;
+ lanes = <2>;
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&mxcfb3 {
+ status = "okay";
+};
+
+&mxcfb4 {
+ status = "okay";
+};
+
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_reset_moci>;
/* active-high meaning opposite of regular PERST# active-low polarity */
reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
- reset-gpio-active-high;
status = "okay";
};
@@ -220,11 +368,11 @@
status = "okay";
};
-&reg_usb_otg_vbus {
+&reg_usb_host_vbus {
status = "okay";
};
-&reg_usb_host_vbus {
+&reg_usb_otg_vbus {
status = "okay";
};
@@ -232,6 +380,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&sound_spdif {
status = "okay";
};
@@ -246,10 +398,21 @@
&uart2 {
status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_dte &pinctrl_uart24_forceoff>;
+#if 0
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+#endif
};
&uart4 {
status = "okay";
+ /*
+ * note that uart4 is only working with pinctrl_uart24_forceoff that is
+ * already defined in &uart2
+ */
};
&uart5 {
@@ -275,14 +438,15 @@
status = "okay";
};
+&vdac {
+ status = "okay";
+};
+
&iomuxc {
- /*
- * Mux the Apalis GPIOs
- */
+ /* Mux the Apalis GPIOs */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_apalis_gpio1 &pinctrl_apalis_gpio2
&pinctrl_apalis_gpio3 &pinctrl_apalis_gpio4
- &pinctrl_apalis_gpio5 &pinctrl_apalis_gpio6
&pinctrl_apalis_gpio7 &pinctrl_apalis_gpio8
>;
@@ -294,4 +458,10 @@
MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
>;
};
+
+ pinctrl_uart24_forceoff: uart24_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.2.dts b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.2.dts
new file mode 100644
index 000000000000..3a22cf10c713
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.2.dts
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Copyright 2014-2020 Toradex
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "imx6q.dtsi"
+#include "imx6qdl-apalis.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX6Q/D Module on Ixora Carrier Board V1.1";
+ compatible = "toradex,apalis_imx6q-ixora-v1.1",
+ "toradex,apalis_imx6q-ixora", "toradex,apalis_imx6q",
+ "fsl,imx6q";
+
+ aliases {
+ i2c0 = &i2c1;
+ i2c1 = &i2c3;
+ i2c2 = &i2c2;
+ rtc0 = &rtc_i2c;
+ rtc1 = &snvs_rtc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ wakeup {
+ label = "Wake-Up";
+ gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ wakeup-source;
+ };
+ };
+
+ lcd_display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_lcdif>;
+ status = "okay";
+
+ port@0 {
+ reg = <0>;
+
+ lcd_display_in: endpoint {
+ remote-endpoint = <&ipu1_di1_disp1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ lcd_display_out: endpoint {
+ remote-endpoint = <&lcd_panel_in>;
+ };
+ };
+ };
+
+ panel: panel {
+ /*
+ * edt,et057090dhu: EDT 5.7" LCD TFT
+ * edt,et070080dh6: EDT 7.0" LCD TFT
+ */
+ compatible = "edt,et057090dhu";
+ backlight = <&backlight>;
+
+ port {
+ lcd_panel_in: endpoint {
+ remote-endpoint = <&lcd_display_out>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_leds_ixora>;
+
+ led4-green {
+ label = "LED_4_GREEN";
+ gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+ };
+
+ led4-red {
+ label = "LED_4_RED";
+ gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ };
+
+ led5-green {
+ label = "LED_5_GREEN";
+ gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ led5-red {
+ label = "LED_5_RED";
+ gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+ v4l2_cap_2 { // mipi-csi2 camera
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+
+#if 0
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
+ };
+#endif
+
+ reg_3v3_vmmc: regulator-3v3-vmmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enable_3v3_vmmc>;
+ regulator-name = "3v3_vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 0 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+
+ reg_can1_supply: regulator-can1-supply {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enable_can1_power>;
+ regulator-name = "can1_supply";
+ gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can2_supply: regulator-can2-supply {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enable_can2_power>;
+ regulator-name = "can2_supply";
+ gpio = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&backlight {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+/* Apalis SPI1 */
+&ecspi1 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
+};
+
+&can1 {
+ status = "okay";
+ xceiver-supply = <&reg_can1_supply>;
+};
+
+&can2 {
+ status = "okay";
+ xceiver-supply = <&reg_can2_supply>;
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ status = "okay";
+};
+
+&hdmi_core {
+ status = "okay";
+};
+
+&hdmi_video {
+ status = "okay";
+};
+
+/* I2C1_SDA/SCL on MXM3 209/211 (e.g. RTC on carrier board) */
+&i2c1 {
+ status = "okay";
+
+ pcap@10 {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ compatible = "touchrevolution,fusion-f0710a";
+ reg = <0x10>;
+ gpios = <&gpio6 10 GPIO_ACTIVE_HIGH /* MXM3 11, Pen down interrupt */
+ &gpio6 9 GPIO_ACTIVE_HIGH /* MXM3 13, Reset */
+ >;
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+
+ eeprom: eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+};
+
+/*
+ * I2C3_SDA/SCL (CAM) on MXM3 pin 201/203 (e.g. camera sensor on carrier
+ * board)
+ */
+&i2c3 {
+ status = "okay";
+
+ adv7280: adv7280@21 {
+ compatible = "adv7280";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ DVDD-supply = <&reg_3p3v>;
+ PVDD-supply = <&reg_3p3v>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ status = "okay";
+ };
+
+ /* Video ADC on Analog Camera Module */
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ PVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "disabled";
+ };
+
+ max9526: max9526@20 {
+ compatible = "maxim,max9526";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DVDDIO-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "okay";
+ };
+
+ ov5640_mipi@3c {
+ compatible = "ovti,ov564x_mipi";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_1p8v>;
+ AVDD-supply = <&reg_2p5v>;
+ DVDD-supply = <&reg_1p8v>;
+ pwn-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+ ipu_id = <0>;
+ csi_id = <1>;
+ mclk = <22000000>;
+ mclk_source = <0>;
+ status = "okay";
+ };
+};
+
+/*
+ * DDC_I2C: I2C2_SDA/SCL on MXM3 205/207
+ */
+&i2cddc {
+ status = "okay";
+
+ hdmi_ddc: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+};
+
+&lcd {
+ status = "okay";
+};
+
+&mipi_csi {
+ ipu_id = <0>;
+ csi_id = <1>;
+ v_channel = <0>;
+ lanes = <2>;
+ status = "okay";
+};
+
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&mxcfb3 {
+ status = "okay";
+};
+
+&mxcfb4 {
+ status = "okay";
+};
+
+&ipu1_di1_disp1 {
+ remote-endpoint = <&lcd_display_in>;
+};
+
+&ldb {
+ status = "okay";
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reset_moci>;
+ /* active-high meaning opposite of regular PERST# active-low polarity */
+ reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&pwm3 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&reg_usb_otg_vbus {
+ status = "okay";
+};
+
+&reg_usb_host_vbus {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&sound_hdmi {
+ status = "okay";
+};
+
+&sound_spdif {
+ status = "okay";
+};
+
+&spdif {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_dte &pinctrl_uart24_forceoff>;
+#if 0
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+#endif
+};
+
+&uart4 {
+ status = "okay";
+ /*
+ * note that uart4 is only working with pinctrl_uart24_forceoff that is
+ * already defined in &uart2
+ */
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ status = "okay";
+};
+
+/* MMC1 */
+&usdhc1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1_4bit &pinctrl_mmc_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_4bit_sleep &pinctrl_mmc_cd_sleep>;
+ bus-width = <4>;
+ status = "okay";
+ cap-power-off-card;
+ vmmc-supply = <&reg_3v3_vmmc>;
+};
+
+&iomuxc {
+ /*
+ * Mux the Apalis GPIOs
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_apalis_gpio1 &pinctrl_apalis_gpio2
+ &pinctrl_apalis_gpio3 &pinctrl_apalis_gpio4
+ &pinctrl_apalis_gpio7 &pinctrl_apalis_gpio8
+ >;
+
+ pinctrl_leds_ixora: ledsixoragrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x1b0b0
+ MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ >;
+ };
+
+ pinctrl_uart24_forceoff: uart24_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0
+ >;
+ };
+
+ pinctrl_enable_3v3_vmmc: enable_3v3_vmmc {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+ >;
+ };
+
+ pinctrl_enable_can1_power: enable_can1_power {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ >;
+ };
+
+ pinctrl_enable_can2_power: enable_can2_power {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x1b0b0
+ >;
+ };
+
+ pinctrl_mmc_cd_sleep: gpiommccdgrpslp {
+ fsl,pins = <
+ /* MMC1 CD */
+ MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x0
+ >;
+ };
+
+ pinctrl_usdhc1_4bit_sleep: usdhc1grp_4bit_sleep {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x3000
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x3000
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x3000
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x3000
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x3000
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x3000
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
index 302fd6adc8a7..5a1b3ce1bfce 100644
--- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts
+++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
@@ -1,44 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
/*
- * Copyright 2014-2017 Toradex AG
+ * Copyright 2014-2020 Toradex
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
*/
/dts-v1/;
@@ -46,6 +10,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
#include "imx6q.dtsi"
#include "imx6qdl-apalis.dtsi"
@@ -106,21 +71,6 @@
};
};
- panel: panel {
- /*
- * edt,et057090dhu: EDT 5.7" LCD TFT
- * edt,et070080dh6: EDT 7.0" LCD TFT
- */
- compatible = "edt,et057090dhu";
- backlight = <&backlight>;
-
- port {
- lcd_panel_in: endpoint {
- remote-endpoint = <&lcd_display_out>;
- };
- };
- };
-
leds {
compatible = "gpio-leds";
@@ -147,23 +97,93 @@
gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
};
};
+
+ panel: panel {
+ /*
+ * edt,et057090dhu: EDT 5.7" LCD TFT
+ * edt,et070080dh6: EDT 7.0" LCD TFT
+ */
+ compatible = "edt,et057090dhu";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3_sw>;
+
+ port {
+ lcd_panel_in: endpoint {
+ remote-endpoint = <&lcd_display_out>;
+ };
+ };
+ };
+
+ reg_3v3_sw: regulator-3v3-sw {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V_SW";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ v4l2_cap_0 {
+ compatible = "fsl,imx6q-v4l2-capture";
+ ipu_id = <0>;
+ csi_id = <0>;
+ mclk_source = <0>;
+ status = "okay";
+ };
};
&backlight {
- brightness-levels = <0 127 191 223 239 247 251 255>;
- default-brightness-level = <1>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ power-supply = <&reg_3v3_sw>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
status = "okay";
};
&can1 {
+ xceiver-supply = <&reg_3v3_sw>;
status = "okay";
};
&can2 {
+ xceiver-supply = <&reg_3v3_sw>;
+ status = "okay";
+};
+
+/* Apalis SPI1 */
+&ecspi1 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
+};
+
+/* Apalis SPI2 */
+&ecspi2 {
status = "okay";
+
+ spidev1: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <18000000>;
+ };
};
-&hdmi {
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_cec {
+ status = "okay";
+};
+
+&hdmi_core {
+ status = "okay";
+};
+
+&hdmi_video {
status = "okay";
};
@@ -171,6 +191,15 @@
&i2c1 {
status = "okay";
+ pcap@10 {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ compatible = "touchrevolution,fusion-f0710a";
+ reg = <0x10>;
+ gpios = <&gpio6 10 GPIO_ACTIVE_HIGH /* MXM3 11, Pen down interrupt */
+ &gpio6 9 GPIO_ACTIVE_HIGH /* MXM3 13, Reset */
+ >;
+ };
+
eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
@@ -189,22 +218,106 @@
*/
&i2c3 {
status = "okay";
+
+ adv7280: adv7280@21 {
+ compatible = "adv7280";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ DVDD-supply = <&reg_3p3v>;
+ PVDD-supply = <&reg_3p3v>;
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ status = "okay";
+ };
+
+ /* Video ADC on Analog Camera Module */
+ adv7180: adv7180@21 {
+ compatible = "adv,adv7180";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DOVDD-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ PVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "disabled";
+ };
+
+ max9526: max9526@20 {
+ compatible = "maxim,max9526";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_csi0 &pinctrl_cam_mclk>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "csi_mclk";
+ DVDDIO-supply = <&reg_3p3v>; /* 3.3v */
+ AVDD-supply = <&reg_3p3v>; /* 1.8v */
+ DVDD-supply = <&reg_3p3v>; /* 1.8v */
+ csi_id = <0>;
+ mclk = <24000000>;
+ mclk_source = <1>;
+ cvbs = <1>;
+ status = "okay";
+ };
+};
+
+/*
+ * DDC_I2C: I2C2_SDA/SCL on MXM3 205/207
+ */
+&i2cddc {
+ status = "okay";
+
+ hdmi_ddc: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
};
&ipu1_di1_disp1 {
remote-endpoint = <&lcd_display_in>;
};
+&lcd {
+ status = "okay";
+};
+
&ldb {
status = "okay";
};
+&mxcfb1 {
+ status = "okay";
+};
+
+&mxcfb2 {
+ status = "okay";
+};
+
+&mxcfb3 {
+ status = "okay";
+};
+
+&mxcfb4 {
+ status = "okay";
+};
+
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_reset_moci>;
/* active-high meaning opposite of regular PERST# active-low polarity */
reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
- reset-gpio-active-high;
status = "okay";
};
@@ -224,11 +337,11 @@
status = "okay";
};
-&reg_usb_otg_vbus {
+&reg_usb_host_vbus {
status = "okay";
};
-&reg_usb_host_vbus {
+&reg_usb_otg_vbus {
status = "okay";
};
@@ -236,6 +349,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&sound_spdif {
status = "okay";
};
@@ -250,10 +367,21 @@
&uart2 {
status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_dte &pinctrl_uart24_forceoff>;
+#if 0
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+#endif
};
&uart4 {
status = "okay";
+ /*
+ * note that uart4 is only working with pinctrl_uart24_forceoff that is
+ * already defined in &uart2
+ */
};
&uart5 {
@@ -278,12 +406,15 @@
status = "okay";
};
+&vdac {
+ status = "okay";
+};
+
&iomuxc {
/* Mux the Apalis GPIOs */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_apalis_gpio1 &pinctrl_apalis_gpio2
&pinctrl_apalis_gpio3 &pinctrl_apalis_gpio4
- &pinctrl_apalis_gpio5 &pinctrl_apalis_gpio6
&pinctrl_apalis_gpio7 &pinctrl_apalis_gpio8
>;
@@ -295,4 +426,10 @@
MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
>;
};
+
+ pinctrl_uart24_forceoff: uart24_forceoff {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x1b0b0
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 2d3e137fc1fc..eed3f9d47f8c 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -236,8 +236,9 @@
interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_SATA>,
<&clks IMX6QDL_CLK_SATA_REF_100M>,
- <&clks IMX6QDL_CLK_AHB>;
- clock-names = "sata", "sata_ref", "ahb";
+ <&clks IMX6QDL_CLK_AHB>,
+ <&clks IMX6QDL_CLK_DUMMY>;
+ clock-names = "sata", "sata_ref", "ahb", "sata_ext";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
index 7c4ad541c3f5..77f590c7d40f 100644
--- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
@@ -46,22 +46,118 @@
/ {
model = "Toradex Apalis iMX6Q/D Module";
compatible = "toradex,apalis_imx6q", "fsl,imx6q";
-
/* Will be filled by the bootloader */
memory@10000000 {
device_type = "memory";
reg = <0x10000000 0>;
};
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ mxcfb2 = &mxcfb3;
+ mxcfb3 = &mxcfb4;
+ };
+
backlight: backlight {
compatible = "pwm-backlight";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_bl_on>;
- pwms = <&pwm4 0 5000000>;
enable-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
+ /* DDC_I2C: I2C2_SDA/SCL on MXM3 205/207 */
+ i2cddc: i2c@0 {
+ compatible = "i2c-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c_ddc>;
+ gpios = <&gpio3 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* sda */
+ &gpio2 30 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* scl */
+ >;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lcd: lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <1>;
+ default_ifmt = "RGB24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_lcdif>;
+ status = "disabled";
+ };
+
+ mxcfb1: fb@0 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "ldb";
+ interface_pix_fmt = "RGB666";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ mxcfb2: fb@1 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "hdmi";
+ interface_pix_fmt = "RGB24";
+ mode_str ="1920x1080M@60";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ mxcfb3: fb@2 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "lcd";
+ interface_pix_fmt = "RGB24";
+ mode_str ="CLAA-WVGA";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ mxcfb4: fb@3 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "vdac";
+ interface_pix_fmt = "RGB565";
+ mode_str ="LDB-XGA";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "1P8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_2p5v: regulator-2p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
reg_module_3v3: regulator-module-3v3 {
compatible = "regulator-fixed";
regulator-name = "+V3.3";
@@ -131,6 +227,14 @@
mux-ext-port = <4>;
};
+ sound_hdmi: sound-hdmi {
+ compatible = "fsl,imx6q-audio-hdmi",
+ "fsl,imx-audio-hdmi";
+ model = "imx-audio-hdmi";
+ hdmi-controller = <&hdmi_audio>;
+ status = "disabled";
+ };
+
sound_spdif: sound-spdif {
compatible = "fsl,imx-audio-spdif";
model = "imx-spdif";
@@ -139,6 +243,21 @@
spdif-out;
status = "disabled";
};
+
+ vdac: vdac@0 {
+ compatible = "fsl,vdac";
+ ipu_id = <1>;
+ disp_id = <0>;
+ default_ifmt = "RGB565";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu2_vdac>;
+ status = "disabled";
+ };
+
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
+ };
};
&audmux {
@@ -148,14 +267,16 @@
};
&can1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_flexcan1>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_flexcan1_default>;
+ pinctrl-1 = <&pinctrl_flexcan1_sleep>;
status = "disabled";
};
&can2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_flexcan2>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_flexcan2_default>;
+ pinctrl-1 = <&pinctrl_flexcan2_sleep>;
status = "disabled";
};
@@ -175,10 +296,203 @@
status = "disabled";
};
+&gpio1 {
+ gpio-line-names = "MXM3_84",
+ "MXM3_4",
+ "MXM3_15/GPIO7",
+ "MXM3_96",
+ "MXM3_37",
+ "",
+ "MXM3_17/GPIO8",
+ "MXM3_14",
+ "MXM3_12",
+ "MXM3_2",
+ "MXM3_184",
+ "MXM3_180",
+ "MXM3_178",
+ "MXM3_176",
+ "MXM3_188",
+ "MXM3_186",
+ "MXM3_160",
+ "MXM3_162",
+ "MXM3_150",
+ "MXM3_144",
+ "MXM3_154",
+ "MXM3_146",
+ "",
+ "",
+ "MXM3_72";
+};
+
+&gpio2 {
+ gpio-line-names = "MXM3_148",
+ "MXM3_152",
+ "MXM3_156",
+ "MXM3_158",
+ "MXM3_1/GPIO1",
+ "MXM3_3/GPIO2",
+ "MXM3_5/GPIO3",
+ "MXM3_7/GPIO4",
+ "MXM3_95",
+ "MXM3_6",
+ "MXM3_8",
+ "MXM3_123",
+ "MXM3_126",
+ "MXM3_128",
+ "MXM3_130",
+ "MXM3_132",
+ "MXM3_253",
+ "MXM3_251",
+ "MXM3_283",
+ "MXM3_281",
+ "MXM3_279",
+ "MXM3_277",
+ "MXM3_243",
+ "MXM3_235",
+ "MXM3_231",
+ "MXM3_229",
+ "MXM3_233",
+ "MXM3_198",
+ "MXM3_275",
+ "MXM3_273",
+ "MXM3_207",
+ "MXM3_122";
+};
+
+&gpio3 {
+ gpio-line-names = "MXM3_271",
+ "MXM3_269",
+ "MXM3_301",
+ "MXM3_299",
+ "MXM3_297",
+ "MXM3_295",
+ "MXM3_293",
+ "MXM3_291",
+ "MXM3_289",
+ "MXM3_287",
+ "MXM3_249",
+ "MXM3_247",
+ "MXM3_245",
+ "MXM3_286",
+ "MXM3_239",
+ "MXM3_35",
+ "MXM3_205",
+ "MXM3_203",
+ "MXM3_201",
+ "MXM3_116",
+ "MXM3_114",
+ "MXM3_262",
+ "MXM3_274",
+ "MXM3_124",
+ "MXM3_110",
+ "MXM3_120",
+ "MXM3_263",
+ "MXM3_265",
+ "",
+ "MXM3_135",
+ "MXM3_261",
+ "MXM3_259";
+};
+
+&gpio4 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_194",
+ "MXM3_136",
+ "MXM3_134",
+ "MXM3_140",
+ "MXM3_138",
+ "",
+ "MXM3_220",
+ "",
+ "",
+ "MXM3_18",
+ "MXM3_16",
+ "",
+ "",
+ "MXM3_214",
+ "MXM3_216",
+ "MXM3_164";
+};
+
+&gpio5 {
+ gpio-line-names = "MXM3_159",
+ "",
+ "",
+ "",
+ "MXM3_257",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_200",
+ "MXM3_196",
+ "MXM3_204",
+ "MXM3_202",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_191",
+ "MXM3_197",
+ "MXM3_77",
+ "MXM3_195",
+ "MXM3_221",
+ "MXM3_225",
+ "MXM3_223",
+ "MXM3_227",
+ "MXM3_209",
+ "MXM3_211",
+ "MXM3_118",
+ "MXM3_112",
+ "MXM3_187",
+ "MXM3_185";
+};
+
+&gpio6 {
+ gpio-line-names = "MXM3_183",
+ "MXM3_181",
+ "MXM3_179",
+ "MXM3_177",
+ "MXM3_175",
+ "MXM3_173",
+ "MXM3_255",
+ "MXM3_83",
+ "MXM3_91",
+ "MXM3_13/GPIO6",
+ "MXM3_11/GPIO5",
+ "MXM3_79",
+ "",
+ "",
+ "MXM3_190",
+ "MXM3_193",
+ "MXM3_89";
+};
+
+&gpio7 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_99",
+ "MXM3_85",
+ "MXM3_217",
+ "MXM3_215";
+};
+
&fec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
+ phy-mode = "rgmii-id";
phy-handle = <&ethphy>;
phy-reset-duration = <10>;
phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
@@ -196,17 +510,32 @@
};
};
-&hdmi {
+&hdmi_cec {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hdmi_ddc>;
+ pinctrl-0 = <&pinctrl_hdmi_cec>;
+ status = "disabled";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <0>;
+ status = "disabled";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
status = "disabled";
};
/* I2C1_SDA/SCL on MXM3 209/211 (e.g. RTC on carrier board) */
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_recovery>;
+ scl-gpios = <&gpio5 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "disabled";
};
@@ -216,13 +545,17 @@
*/
&i2c2 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_recovery>;
+ scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
pmic: pfuze100@8 {
compatible = "fsl,pfuze100";
reg = <0x08>;
+ fsl,pmic-stby-poweroff;
regulators {
sw1a_reg: sw1ab {
@@ -372,7 +705,7 @@
*/
&i2c3 {
clock-frequency = <100000>;
- pinctrl-names = "default", "recovery";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
pinctrl-1 = <&pinctrl_i2c3_recovery>;
scl-gpios = <&gpio3 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
@@ -380,25 +713,151 @@
status = "disabled";
};
+&ldb {
+// split-mode;
+// dual-mode;
+
+ lvds-channel@0 {
+ reg = <0>;
+ fsl,data-mapping = "spwg"; /* "jeida"; */
+ fsl,data-width = <24>;
+ crtc = "ipu2-di1";
+ primary;
+
+ display-timings {
+ native-mode = <&timing_xga>;
+ /* LDB-AM-800600LTNQW-A0H */
+ timing_svga: 800x600 {
+ clock-frequency = <55000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <112>;
+ hfront-porch = <32>;
+ vback-porch = <3>;
+ vfront-porch = <17>;
+ hsync-len = <80>;
+ vsync-len = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ timing_wxga: 1280x800 {
+ clock-frequency = <68930000>;
+ hactive = <1280>;
+ vactive = <800>;
+ hback-porch = <64>;
+ hfront-porch = <64>;
+ vback-porch = <5>;
+ vfront-porch = <5>;
+ hsync-len = <40>;
+ vsync-len = <6>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* LTTD1280800101-L4WH-CT1, note that it needs
+ fsl,data-mapping = "spwg"; fsl,data-width = <24>; */
+ timing_wxga1: 1280x800-1 {
+ clock-frequency = <71100000>;
+ hactive = <1280>;
+ vactive = <800>;
+ hback-porch = <60>;
+ hfront-porch = <60>;
+ vback-porch = <7>;
+ vfront-porch = <7>;
+ hsync-len = <40>;
+ vsync-len = <9>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ timing_fullhd: 1920x1080 {
+ clock-frequency = <138500000>;
+ hactive = <1920>;
+ vactive = <1080>;
+ hback-porch = <80>;
+ hfront-porch = <48>;
+ vback-porch = <23>;
+ vfront-porch = <3>;
+ hsync-len = <32>;
+ vsync-len = <5>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+
+ lvds-channel@1 {
+ reg = <1>;
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ crtc = "ipu1-di0";
+
+ display-timings {
+/* native-mode = <&timing_svga_ch2>;*/
+ /* LDB-AM-800600LTNQW-A0H */
+ timing_svga_ch2: 800x600 {
+ clock-frequency = <55000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <112>;
+ hfront-porch = <32>;
+ vback-porch = <3>;
+ vfront-porch = <17>;
+ hsync-len = <80>;
+ vsync-len = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pcie {
+ /* Gen2 does not work on Apalis iMX6 */
+ fsl,max-link-speed = <1>;
+};
+
&pwm1 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1>;
status = "disabled";
};
&pwm2 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm2>;
status = "disabled";
};
&pwm3 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm3>;
status = "disabled";
};
&pwm4 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm4>;
status = "disabled";
@@ -599,19 +1058,32 @@
>;
};
- pinctrl_flexcan1: flexcan1grp {
+ pinctrl_flexcan1_default: flexcan1defgrp {
fsl,pins = <
MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0
>;
};
- pinctrl_flexcan2: flexcan2grp {
+ pinctrl_flexcan1_sleep: flexcan1slpgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x0
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x0
+ >;
+ };
+
+ pinctrl_flexcan2_default: flexcan2defgrp {
fsl,pins = <
MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0
MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b0
>;
};
+ pinctrl_flexcan2_sleep: flexcan2slpgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x0
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x0
+ >;
+ };
pinctrl_gpio_bl_on: gpioblon {
fsl,pins = <
@@ -632,6 +1104,14 @@
>;
};
+ pinctrl_i2c_ddc: gpioi2cddcgrp {
+ fsl,pins = <
+ /* DDC bitbang */
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
+ MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x1b0b0
+ >;
+ };
+
pinctrl_hdmi_ddc: hdmiddcgrp {
fsl,pins = <
MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
@@ -641,8 +1121,15 @@
pinctrl_i2c1: i2c1grp {
fsl,pins = <
- MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c1_recovery: i2c1recoverygrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x4001b8b1
>;
};
@@ -653,6 +1140,13 @@
>;
};
+ pinctrl_i2c2_recovery: i2c2recoverygrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b1
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
index 019dda6b88ad..2e51c2ab5a80 100644
--- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
@@ -47,11 +47,15 @@
model = "Toradex Colibri iMX6DL/S Module";
compatible = "toradex,colibri_imx6dl", "fsl,imx6dl";
+ aliases {
+ mxcfb0 = &mxcfb1;
+ mxcfb1 = &mxcfb2;
+ };
+
backlight: backlight {
compatible = "pwm-backlight";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_bl_on>;
- pwms = <&pwm3 0 5000000>;
enable-gpios = <&gpio3 26 GPIO_ACTIVE_HIGH>; /* Colibri BL_ON */
status = "disabled";
};
@@ -83,6 +87,76 @@
status = "disabled";
};
+ reg_2p5v: 2p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: 3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+/*
+ * DDC_I2C: I2C2_SDA/SCL on X2 16/15
+ */
+ i2cddc: i2c@0 {
+ compatible = "i2c-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c_ddc>;
+ gpios = <&gpio4 13 0 /* sda */
+ &gpio4 12 0 /* scl */
+ >;
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ /* Extension connector pin 15/16 */
+ hdmi_ddc: edid@50 {
+ compatible = "fsl,imx6-hdmi-i2c";
+ reg = <0x50>;
+ };
+ };
+
+ lcd: lcd@0 {
+ compatible = "fsl,lcd";
+ ipu_id = <0>;
+ disp_id = <0>;
+ default_ifmt = "RGB666";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1_lcdif>;
+ status = "disabled";
+ };
+
+ mxcfb1: fb@0 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "lcd";
+ interface_pix_fmt = "RGB666";
+ mode_str ="640x480M@60";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
+ mxcfb2: fb@1 {
+ compatible = "fsl,mxc_sdc_fb";
+ disp_dev = "hdmi";
+ interface_pix_fmt = "RGB24";
+ mode_str ="640x480M@60";
+ default_bpp = <16>;
+ int_clk = <0>;
+ late_init = <0>;
+ status = "disabled";
+ };
+
sound {
compatible = "fsl,imx-audio-sgtl5000";
model = "imx6dl-colibri-sgtl5000";
@@ -97,6 +171,15 @@
mux-ext-port = <5>;
};
+ /* On-module HDMI interface */
+ sound_hdmi: sound-hdmi {
+ compatible = "fsl,imx6q-audio-hdmi",
+ "fsl,imx-audio-hdmi";
+ model = "imx-audio-hdmi";
+ hdmi-controller = <&hdmi_audio>;
+ status = "okay";
+ };
+
/* Optional S/PDIF in on SODIMM 88 and out on SODIMM 90, 137 or 168 */
sound_spdif: sound-spdif {
compatible = "fsl,imx-audio-spdif";
@@ -106,6 +189,11 @@
spdif-out;
status = "disabled";
};
+
+ v4l2_out {
+ compatible = "fsl,mxc_v4l2_output";
+ status = "okay";
+ };
};
&audmux {
@@ -154,10 +242,238 @@
};
};
-&hdmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hdmi_ddc>;
- status = "disabled";
+&gpio1 {
+ gpio-line-names = "",
+ "SODIMM_67", /* Can be SODIMM_135, see page 4 */
+ "SODIMM_180",
+ "SODIMM_196",
+ "SODIMM_174",
+ "SODIMM_176",
+ "SODIMM_194",
+ "SODIMM_55",
+ "SODIMM_63",
+ "SODIMM_28",
+ "SODIMM_93",
+ "SODIMM_69",
+ "SODIMM_99",
+ "SODIMM_130",
+ "SODIMM_106",
+ "SODIMM_98",
+ "SODIMM_192",
+ "SODIMM_49",
+ "SODIMM_190",
+ "SODIMM_51",
+ "SODIMM_47",
+ "SODIMM_53",
+ "",
+ "SODIMM_22";
+};
+
+&gpio2 {
+ gpio-line-names = "SODIMM_132",
+ "SODIMM_134",
+ "SODIMM_135", /* Can be 67, see page 4 */
+ "SODIMM_133",
+ "SODIMM_102",
+ "SODIMM_43",
+ "SODIMM_127",
+ "SODIMM_37",
+ "SODIMM_104",
+ "SODIMM_59",
+ "SODIMM_30",
+ "SODIMM_100",
+ "SODIMM_38",
+ "SODIMM_34",
+ "SODIMM_32",
+ "SODIMM_36",
+ "SODIMM_59",
+ "SODIMM_67",
+ "SODIMM_97",
+ "SODIMM_79",
+ "SODIMM_103",
+ "SODIMM_101",
+ "SODIMM_45",
+ "SODIMM_105",
+ "SODIMM_107",
+ "SODIMM_91",
+ "SODIMM_89",
+ "SODIMM_150",
+ "SODIMM_126",
+ "SODIMM_128",
+ "",
+ "SODIMM_94";
+};
+
+&gpio3 {
+ gpio-line-names = "SODIMM_111",
+ "SODIMM_113",
+ "SODIMM_115",
+ "SODIMM_117",
+ "SODIMM_119",
+ "SODIMM_121",
+ "SODIMM_123",
+ "SODIMM_125",
+ "SODIMM_110",
+ "SODIMM_112",
+ "SODIMM_114",
+ "SODIMM_116",
+ "SODIMM_118",
+ "SODIMM_120",
+ "SODIMM_122",
+ "SODIMM_124",
+ "",
+ "SODIMM_96",
+ "SODIMM_77",
+ "SODIMM_25",
+ "SODIMM_27",
+ "SODIMM_88",
+ "SODIMM_90",
+ "SODIMM_31",
+ "SODIMM_23",
+ "SODIMM_29",
+ "SODIMM_71",
+ "SODIMM_73",
+ "SODIMM_92",
+ "SODIMM_81",
+ "SODIMM_131",
+ "SODIMM_129";
+};
+
+&gpio4 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_168",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_184",
+ "SODIMM_186",
+ "HDMI_15",
+ "HDMI_16",
+ "SODIMM_178",
+ "SODIMM_188",
+ "SODIMM_56",
+ "SODIMM_44",
+ "SODIMM_68",
+ "SODIMM_82",
+ "SODIMM_24",
+ "SODIMM_76",
+ "SODIMM_70",
+ "SODIMM_60",
+ "SODIMM_58",
+ "SODIMM_78",
+ "SODIMM_72",
+ "SODIMM_80",
+ "SODIMM_46",
+ "SODIMM_62",
+ "SODIMM_48",
+ "SODIMM_74";
+};
+
+&gpio5 {
+ gpio-line-names = "SODIMM_95",
+ "",
+ "SODIMM_86",
+ "",
+ "SODIMM_65",
+ "SODIMM_50",
+ "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_66",
+ "SODIMM_64",
+ "SODIMM_57",
+ "SODIMM_61",
+ "SODIMM_136",
+ "SODIMM_138",
+ "SODIMM_140",
+ "SODIMM_142",
+ "SODIMM_144",
+ "SODIMM_146",
+ "SODIMM_172",
+ "SODIMM_170",
+ "SODIMM_149",
+ "SODIMM_151",
+ "SODIMM_153",
+ "SODIMM_155",
+ "SODIMM_157",
+ "SODIMM_159",
+ "SODIMM_161",
+ "SODIMM_163",
+ "SODIMM_33",
+ "SODIMM_35",
+ "SODIMM_165",
+ "SODIMM_167";
+};
+
+&gpio6 {
+ gpio-line-names = "SODIMM_169",
+ "SODIMM_171",
+ "SODIMM_173",
+ "SODIMM_175",
+ "SODIMM_177",
+ "SODIMM_179",
+ "SODIMM_85",
+ "SODIMM_166",
+ "SODIMM_160",
+ "SODIMM_162",
+ "SODIMM_158",
+ "SODIMM_164",
+ "",
+ "",
+ "SODIMM_156",
+ "SODIMM_75",
+ "SODIMM_154",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_152";
+};
+
+&gpio7 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_19",
+ "SODIMM_21",
+ "",
+ "SODIMM_137";
+};
+
+&hdmi_audio {
+ status = "okay";
+};
+
+&hdmi_core {
+ ipu_id = <0>;
+ disp_id = <1>;
+ status = "okay";
+};
+
+&hdmi_video {
+ fsl,phy_reg_vlev = <0x0294>;
+ fsl,phy_reg_cksymtx = <0x800d>;
+ status = "okay";
};
/*
@@ -166,13 +482,17 @@
*/
&i2c2 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_recovery>;
+ scl-gpios = <&gpio2 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio3 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
pmic: pfuze100@8 {
compatible = "fsl,pfuze100";
reg = <0x08>;
+ fsl,pmic-stby-poweroff;
regulators {
sw1a_reg: sw1ab {
@@ -226,7 +546,12 @@
regulator-always-on;
};
- /* vgen3: unused */
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
vgen4_reg: vgen4 {
regulator-min-microvolt = <1800000>;
@@ -312,7 +637,7 @@
*/
&i2c3 {
clock-frequency = <100000>;
- pinctrl-names = "default", "recovery";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
pinctrl-1 = <&pinctrl_i2c3_recovery>;
scl-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
@@ -322,6 +647,7 @@
/* Colibri PWM<B> */
&pwm1 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1>;
status = "disabled";
@@ -329,6 +655,7 @@
/* Colibri PWM<D> */
&pwm2 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm2>;
status = "disabled";
@@ -336,6 +663,7 @@
/* Colibri PWM<A> */
&pwm3 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm3>;
status = "disabled";
@@ -343,6 +671,7 @@
/* Colibri PWM<C> */
&pwm4 {
+ #pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm4>;
status = "disabled";
@@ -356,6 +685,7 @@
};
&ssi1 {
+ fsl,mode = "i2s-slave";
status = "okay";
};
@@ -388,19 +718,40 @@
&usbotg {
pinctrl-names = "default";
disable-over-current;
- dr_mode = "peripheral";
+ dr_mode = "otg";
status = "disabled";
};
/* Colibri MMC */
&usdhc1 {
+/*
+ * The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control which is supported starting
+ * with hardware revision V1.1A.
+ */
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_mmc_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_mmc_cd>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_mmc_cd>;
+ vqmmc-supply = <&vgen3_reg>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+#else
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_mmc_cd>;
+ no-1-8-v;
+#endif
+ label = "MMC1";
cd-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; /* MMCD */
disable-wp;
- vqmmc-supply = <&reg_module_3v3>;
+ enable-sdio-wakeup;
+ keep-power-in-suspend;
+ vmmc-supply = <&reg_3p3v>;
bus-width = <4>;
- no-1-8-v;
status = "disabled";
};
@@ -426,6 +777,53 @@
};
&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi_gpio_1 &pinctrl_csi_gpio_2>;
+
+ imx6qdl-colibri {
+
+ /* CSI pins used as GPIO */
+ pinctrl_csi_gpio_1: csi_gpio-1 {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0
+ MX6QDL_PAD_EIM_D18__GPIO3_IO18 0x1b0b0
+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b0
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x130b0
+ MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b0
+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b0
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0
+ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b0
+ MX6QDL_PAD_EIM_D17__GPIO3_IO17 0x1b0b0
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0
+ >;
+ };
+ pinctrl_csi_gpio_2: csi_gpio-2 {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x1b0b0
+ >;
+ };
+
+ pinctrl_gpio_1: gpio-1 {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x1b0b0
+ MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23 0x1b0b0
+ MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x1b0b0
+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b0
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ MX6QDL_PAD_SD4_DAT0__GPIO2_IO08 0x1b0b0
+ >;
+ };
+ pinctrl_gpio_2: gpio-2 {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0
+ >;
+ };
+
pinctrl_audmux: audmuxgrp {
fsl,pins = <
MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
@@ -495,10 +893,10 @@
>;
};
- pinctrl_hdmi_ddc: hdmiddcgrp {
+ pinctrl_i2c_ddc: i2c_ddc {
fsl,pins = <
- MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
+ MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b0b0 /* DDC bitbang */
+ MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0 /* DDC bitbang */
>;
};
@@ -508,6 +906,12 @@
MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
>;
};
+ pinctrl_i2c2_recovery: i2c2-recoverygrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x4001b8b1
+ MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x4001b8b1
+ >;
+ };
pinctrl_i2c3: i2c3grp {
fsl,pins = <
@@ -615,6 +1019,13 @@
>;
};
+ pinctrl_usbh_oc_1: usbh_oc-1 {
+ fsl,pins = <
+ /* USBH_OC */
+ MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x1b0b0
+ >;
+ };
+
pinctrl_spdif: spdifgrp {
fsl,pins = <
MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
@@ -681,6 +1092,13 @@
>;
};
+ pinctrl_usbc_id_1: usbc_id-1 {
+ fsl,pins = <
+ /* USBC_ID */
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17071
@@ -692,6 +1110,28 @@
>;
};
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170b1
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100b1
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170b1
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170b1
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170b1
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170b1
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170f1
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100f1
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170f1
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170f1
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170f1
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170f1
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
@@ -861,4 +1301,5 @@
MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0
>;
};
+ };
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index a8d043e21b48..b6010f153f0a 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -376,7 +376,7 @@
clocks = <&clks IMX6QDL_CLK_SPDIF_GCLK>, <&clks IMX6QDL_CLK_OSC>,
<&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_ASRC>,
<&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_ESAI_EXTAL>,
- <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_MLB>,
+ <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_DUMMY>,
<&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_SPBA>;
clock-names = "core", "rxtx0",
"rxtx1", "rxtx2",
diff --git a/arch/arm/boot/dts/imx6ull-colibri-aster.dts b/arch/arm/boot/dts/imx6ull-colibri-aster.dts
new file mode 100644
index 000000000000..c3adb82acf86
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-aster.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx6ull-colibri-nonwifi.dtsi"
+#include "imx6ull-colibri-aster.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6ULL 256MB on Colibri Aster";
+ compatible = "toradex,colibri-imx6ull-aster",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-aster.dtsi b/arch/arm/boot/dts/imx6ull-colibri-aster.dtsi
new file mode 100644
index 000000000000..b18337d49606
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-aster.dtsi
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2018 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_usbc_det>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+ vin-supply = <&reg_5v0>;
+ };
+};
+
+&bl {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&ecspi1 {
+ status = "okay";
+
+ fsl,spi-num-chipselects = <2>;
+ /* Note, gpio4 11 is muxed by hoggrp-4 */
+ cs-gpios = <
+ &gpio3 26 GPIO_ACTIVE_HIGH
+ &gpio4 28 GPIO_ACTIVE_HIGH
+ >;
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+
+ spidev1: spidev@1 {
+ compatible = "toradex,evalspi";
+ reg = <1>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ sda-gpios = <&gpio1 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio1 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ reg = <0x4a>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ display = <&display0>;
+ status = "okay";
+
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* WVGA Timing, TouchRevolution Fusion 7" */
+ timing_wvga2: 800x480pixclkact {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <1>;
+ };
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+ /* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
+ timing_wsvga: 1024x600 {
+ clock-frequency = <48000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hback-porch = <104>;
+ hfront-porch = <43>;
+ vback-porch = <24>;
+ vfront-porch = <20>;
+ hsync-len = <5>;
+ vsync-len = <5>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+/* PWM <A> */
+&pwm4 {
+ status = "okay";
+};
+
+/* PWM <B> */
+&pwm5 {
+ status = "okay";
+};
+
+/* PWM <C> */
+&pwm6 {
+ status = "okay";
+};
+
+/* PWM <D> */
+&pwm7 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det &extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+/* The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control.
+ */
+/* #define SD_1_8 */
+&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-3 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+ vqmmc-supply = <&reg_sd1_vqmmc>;
+#else
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
+ keep-power-in-suspend;
+ status = "okay";
+ vmmc-supply = <&reg_3v3>;
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts
index 08669a18349e..671109d57e1c 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts
@@ -10,5 +10,7 @@
/ {
model = "Toradex Colibri iMX6ULL 256MB on Colibri Evaluation Board V3";
- compatible = "toradex,colibri-imx6ull-eval", "fsl,imx6ull";
+ compatible = "toradex,colibri-imx6ull-eval",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi
index b6147c76d159..96f4438a3569 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi
@@ -3,11 +3,26 @@
* Copyright 2017 Toradex AG
*/
+#include <dt-bindings/pwm/pwm.h>
+
/ {
chosen {
stdout-path = "serial0:115200n8";
};
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_gpiokeys>;
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ wakeup-source;
+ };
+ };
+
/* fixed crystal dedicated to mcp2515 */
clk16m: clk16m {
compatible = "fixed-clock";
@@ -15,16 +30,12 @@
clock-frequency = <16000000>;
};
- panel: panel {
- compatible = "edt,et057090dhu";
- backlight = <&bl>;
- power-supply = <&reg_3v3>;
-
- port {
- panel_in: endpoint {
- remote-endpoint = <&lcdif_out>;
- };
- };
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_usbc_det>;
};
reg_3v3: regulator-3v3 {
@@ -58,10 +69,14 @@
};
&bl {
- brightness-levels = <0 4 8 16 32 64 128 255>;
- default-brightness-level = <6>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
power-supply = <&reg_3v3>;
- pwms = <&pwm4 0 5000000 1>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&pxp {
status = "okay";
};
@@ -81,11 +96,58 @@
xceiver-supply = <&reg_5v0>;
status = "okay";
};
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "disabled";
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "disabled";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "disabled";
};
&i2c1 {
status = "okay";
+ /*
+ * the PCAPs use SODIMM 28/30, also used for PWM<B>, PWM<C>, aka pwm5,
+ * pwm6. so if you enable one of the PCAP controllers disable the pwms
+ */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <16 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 28 */
+ reset-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* SODIMM 30 */
+ status = "disabled";
+ };
+
+ touch: touchrevf0710a@10 {
+ compatible = "touchrevolution,fusion-f0710a";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x10>;
+ /* SODIMM 28, Pen down interrupt */
+ gpios = <&gpio4 16 GPIO_ACTIVE_HIGH
+ /* SODIMM 30, Reset interrupt */
+ &gpio2 5 GPIO_ACTIVE_LOW
+ >;
+ status = "disabled";
+ };
+
/* M41T0M6 real time clock on carrier board */
m41t0m6: rtc@68 {
compatible = "st,m41t0";
@@ -94,11 +156,119 @@
};
&lcdif {
+ display = <&display0>;
status = "okay";
- port {
- lcdif_out: endpoint {
- remote-endpoint = <&panel_in>;
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* WVGA Timing, TouchRevolution Fusion 7" */
+ timing_wvga2: 800x480pixclkact {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <1>;
+ };
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+ /* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
+ timing_wsvga: 1024x600 {
+ clock-frequency = <48000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hback-porch = <104>;
+ hfront-porch = <43>;
+ vback-porch = <24>;
+ vfront-porch = <20>;
+ hsync-len = <5>;
+ vsync-len = <5>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
};
};
};
@@ -136,6 +306,8 @@
};
&usbotg1 {
+ extcon = <&extcon_usbc_det &extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
status = "okay";
};
@@ -144,21 +316,40 @@
status = "okay";
};
+/* The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control.
+ */
+/* #define SD_1_8 */
&usdhc1 {
+#ifdef SD_1_8
pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_snvs_usdhc1_cd>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_snvs_usdhc1_cd>;
- pinctrl-3 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_sleep_cd>;
+ pinctrl-3 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+#else
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+ no-1-8-v;
+#endif
cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ vqmmc-supply = <&reg_sd1_vqmmc>;
disable-wp;
wakeup-source;
keep-power-in-suspend;
vmmc-supply = <&reg_3v3>;
- vqmmc-supply = <&reg_sd1_vmmc>;
- sd-uhs-sdr12;
- sd-uhs-sdr25;
- sd-uhs-sdr50;
- sd-uhs-sdr104;
status = "okay";
};
+
+&iomuxc {
+ imx6ull-colibri {
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ MX6UL_PAD_NAND_DQS__GPIO4_IO16 0x74
+ MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x14
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts b/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts
new file mode 100644
index 000000000000..fc93eb3b16ee
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 Toradex AG
+ */
+
+/dts-v1/;
+
+#include "imx6ull-colibri-nonwifi.dtsi"
+#include "imx6ull-colibri-iris-v2.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6ULL 256MB on Colibri Iris V2";
+ compatible = "toradex,colibri-imx6ull-iris-v2",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dtsi b/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dtsi
new file mode 100644
index 000000000000..4aaac29a374b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dtsi
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_usbc_det>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_3v3_vmmc: regulator-3v3-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "3v3_vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+ vin-supply = <&reg_5v0>;
+ };
+};
+
+&bl {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&ecspi1 {
+ status = "okay";
+
+ fsl,spi-num-chipselects = <2>;
+ /* Note, gpio4 11 is muxed by hoggrp-4 */
+ cs-gpios = <
+ &gpio3 26 GPIO_ACTIVE_HIGH
+ &gpio4 28 GPIO_ACTIVE_HIGH
+ >;
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ sda-gpios = <&gpio1 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio1 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "okay";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ display = <&display0>;
+ status = "okay";
+
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* WVGA Timing, TouchRevolution Fusion 7" */
+ timing_wvga2: 800x480pixclkact {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <1>;
+ };
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+ /* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
+ timing_wsvga: 1024x600 {
+ clock-frequency = <48000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hback-porch = <104>;
+ hfront-porch = <43>;
+ vback-porch = <24>;
+ vfront-porch = <20>;
+ hsync-len = <5>;
+ vsync-len = <5>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+/* PWM <A> */
+&pwm4 {
+ status = "okay";
+};
+
+/* PWM <B> */
+&pwm5 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
+
+/* PWM <C> */
+&pwm6 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
+
+/* PWM <D> */
+&pwm7 {
+ status = "okay";
+};
+
+/* Colibri UART_A */
+&uart1 {
+ status = "okay";
+};
+
+/* Colibri UART_B */
+&uart2 {
+ status = "okay";
+};
+
+/* Colibri UART_C */
+&uart5 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det &extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+/*
+ * The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control which is supported starting
+ * with hardware revision V1.1A.
+ */
+/* #define SD_1_8 */
+&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-3 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+ vqmmc-supply = <&reg_sd1_vqmmc>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+#else
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
+ cap-power-off-card;
+ vmmc-supply = <&reg_3v3_vmmc>;
+ status = "okay";
+};
+
+&gpio1 {
+ /*
+ * lvds_tx_on turns the LVDS transceiver on. If one wants to turn the
+ * transceiver off, that property has to be deleted and the gpio handled
+ * in userspace.
+ * The same applies to uart25_tx_on and uart1_tx_on, where the UART
+ * transceiver is turned on.
+ */
+ lvds_tx_on {
+ gpio-hog;
+ gpios = <14 0>;
+ output-high;
+ };
+
+ uart25_tx_on {
+ gpio-hog;
+ gpios = <15 0>;
+ output-high;
+ };
+};
+
+&gpio2 {
+ uart1_tx_on {
+ gpio-hog;
+ gpios = <7 0>;
+ output-high;
+ };
+};
+
+&iomuxc {
+ imx6ull-colibri {
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ MX6UL_PAD_NAND_DQS__GPIO4_IO16 0x74
+ MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x14
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris.dts b/arch/arm/boot/dts/imx6ull-colibri-iris.dts
new file mode 100644
index 000000000000..e3b8877613a5
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 Toradex AG
+ */
+
+/dts-v1/;
+
+#include "imx6ull-colibri-nonwifi.dtsi"
+#include "imx6ull-colibri-iris.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6ULL 256MB on Colibri Iris";
+ compatible = "toradex,colibri-imx6ull-iris",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi b/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi
new file mode 100644
index 000000000000..23f2afc61a52
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_usbc_det>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+ vin-supply = <&reg_5v0>;
+ };
+};
+
+&bl {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm4 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&pxp {
+ status = "okay";
+};
+
+&ecspi1 {
+ status = "okay";
+
+ fsl,spi-num-chipselects = <2>;
+ /* Note, gpio4 11 is muxed by hoggrp-4 */
+ cs-gpios = <
+ &gpio3 26 GPIO_ACTIVE_HIGH
+ &gpio4 28 GPIO_ACTIVE_HIGH
+ >;
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ sda-gpios = <&gpio1 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio1 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ display = <&display0>;
+ status = "okay";
+
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* WVGA Timing, TouchRevolution Fusion 7" */
+ timing_wvga2: 800x480pixclkact {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <1>;
+ };
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+ /* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
+ timing_wsvga: 1024x600 {
+ clock-frequency = <48000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hback-porch = <104>;
+ hfront-porch = <43>;
+ vback-porch = <24>;
+ vfront-porch = <20>;
+ hsync-len = <5>;
+ vsync-len = <5>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+/* PWM <A> */
+&pwm4 {
+ status = "okay";
+};
+
+/* PWM <B> */
+&pwm5 {
+ status = "okay";
+};
+
+/* PWM <C> */
+&pwm6 {
+ status = "okay";
+};
+
+/* PWM <D> */
+&pwm7 {
+ status = "okay";
+};
+
+/* Colibri UART_A */
+&uart1 {
+ status = "okay";
+};
+
+/* Colibri UART_B */
+&uart2 {
+ status = "okay";
+};
+
+/* Colibri UART_C */
+&uart5 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det &extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+/*
+ * The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control which is supported starting
+ * with hardware revision V1.1A.
+ */
+/* #define SD_1_8 */
+&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-3 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+ vqmmc-supply = <&reg_sd1_vqmmc>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+#else
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc1 &pinctrl_snvs_usdhc1_cd_sleep>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
+ keep-power-in-suspend;
+ vmmc-supply = <&reg_3v3>;
+ status = "okay";
+};
+
+&gpio1 {
+ /*
+ * uart25_tx_on turns the UART transceiver on. If one wants to turn the
+ * transceiver off, that property has to be deleted and the gpio handled
+ * in userspace.
+ * The same applies to uart1_tx_on.
+ */
+ uart25_tx_on {
+ gpio-hog;
+ gpios = <15 0>;
+ output-high;
+ };
+};
+
+&gpio2 {
+ uart1_tx_on {
+ gpio-hog;
+ gpios = <7 0>;
+ output-high;
+ };
+};
+
+&iomuxc {
+ imx6ull-colibri {
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ MX6UL_PAD_NAND_DQS__GPIO4_IO16 0x74
+ MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x14
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi
index fb213bec4654..0af6f0d0b1b5 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi
@@ -12,10 +12,147 @@
};
};
+&gpio1 {
+ gpio-line-names = "SODIMM_8",
+ "SODIMM_6",
+ "SODIMM_129",
+ "SODIMM_89",
+ "SODIMM_19",
+ "SODIMM_21",
+ "UNUSABLE_SODIMM_180",
+ "UNUSABLE_SODIMM_184",
+ "SODIMM_4",
+ "SODIMM_2",
+ "SODIMM_106",
+ "SODIMM_71",
+ "SODIMM_23",
+ "SODIMM_31",
+ "SODIMM_99",
+ "SODIMM_102",
+ "SODIMM_33",
+ "SODIMM_35",
+ "SODIMM_25",
+ "SODIMM_27",
+ "SODIMM_36",
+ "SODIMM_38",
+ "SODIMM_32",
+ "SODIMM_34",
+ "SODIMM_135",
+ "SODIMM_77",
+ "SODIMM_100",
+ "SODIMM_186",
+ "SODIMM_196",
+ "SODIMM_194";
+};
+
+&gpio2 {
+ gpio-line-names = "SODIMM_55",
+ "SODIMM_63",
+ "SODIMM_178",
+ "SODIMM_188",
+ "SODIMM_73",
+ "SODIMM_30",
+ "SODIMM_67",
+ "SODIMM_104",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_190",
+ "SODIMM_47",
+ "SODIMM_192",
+ "SODIMM_49",
+ "SODIMM_51",
+ "SODIMM_53";
+};
+
+&gpio3 {
+ gpio-line-names = "SODIMM_56",
+ "SODIMM_44",
+ "SODIMM_68",
+ "SODIMM_82",
+ "",
+ "SODIMM_76",
+ "SODIMM_70",
+ "SODIMM_60",
+ "SODIMM_58",
+ "SODIMM_78",
+ "SODIMM_72",
+ "SODIMM_80",
+ "SODIMM_46",
+ "SODIMM_62",
+ "SODIMM_48",
+ "SODIMM_74",
+ "SODIMM_50",
+ "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_66",
+ "SODIMM_64",
+ "SODIMM_57",
+ "SODIMM_61",
+ "SODIMM_29",
+ "SODIMM_37",
+ "SODIMM_88",
+ "SODIMM_86",
+ "SODIMM_92",
+ "SODIMM_90";
+};
+
+&gpio4 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_59",
+ "",
+ "",
+ "SODIMM_133",
+ "",
+ "SODIMM_28",
+ "SODIMM_75",
+ "SODIMM_96",
+ "SODIMM_81",
+ "SODIMM_94",
+ "SODIMM_101",
+ "SODIMM_103",
+ "SODIMM_79",
+ "SODIMM_97",
+ "SODIMM_69",
+ "SODIMM_98",
+ "SODIMM_85",
+ "SODIMM_65";
+};
+
+&gpio5 {
+ gpio-line-names = "SODIMM_43",
+ "SODIMM_45",
+ "SODIMM_137",
+ "SODIMM_95",
+ "SODIMM_107",
+ "SODIMM_131",
+ "SODIMM_93",
+ "",
+ "SODIMM_138",
+ "",
+ "SODIMM_105",
+ "SODIMM_127";
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3
- &pinctrl_gpio4 &pinctrl_gpio5 &pinctrl_gpio6>;
+ &pinctrl_gpio4 &pinctrl_gpio5 &pinctrl_gpio6 &pinctrl_gpio7>;
};
&iomuxc_snvs {
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts
new file mode 100644
index 000000000000..d23fc5de772c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx6ull-colibri-wifi.dtsi"
+#include "imx6ull-colibri-aster.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6ULL 512MB on Colibri Aster";
+ compatible = "toradex,colibri-imx6ull-wifi-aster",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts
new file mode 100644
index 000000000000..202b50fc2cfa
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 Toradex AG
+ */
+
+/dts-v1/;
+
+#include "imx6ull-colibri-wifi.dtsi"
+#include "imx6ull-colibri-iris-v2.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6ULL 512MB on Colibri Iris V2";
+ compatible = "toradex,colibri-imx6ull-wifi-iris-v2",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts
new file mode 100644
index 000000000000..966d02a07b1c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 Toradex AG
+ */
+
+/dts-v1/;
+
+#include "imx6ull-colibri-wifi.dtsi"
+#include "imx6ull-colibri-iris.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX6ULL 512MB on Colibri Iris";
+ compatible = "toradex,colibri-imx6ull-wifi-iris",
+ "toradex,colibri-imx6ull",
+ "fsl,imx6ull";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
index 038d8c90f6df..ea27dca26204 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
@@ -19,14 +19,146 @@
};
};
-&cpu0 {
- clock-frequency = <792000000>;
+&gpio1 {
+ gpio-line-names = "SODIMM_8",
+ "SODIMM_6",
+ "SODIMM_129",
+ "",
+ "SODIMM_19",
+ "SODIMM_21",
+ "UNUSABLE_SODIMM_180",
+ "UNUSABLE_SODIMM_184",
+ "SODIMM_4",
+ "SODIMM_2",
+ "SODIMM_106",
+ "SODIMM_71",
+ "SODIMM_23",
+ "SODIMM_31",
+ "SODIMM_99",
+ "SODIMM_102",
+ "SODIMM_33",
+ "SODIMM_35",
+ "SODIMM_25",
+ "SODIMM_27",
+ "SODIMM_36",
+ "SODIMM_38",
+ "SODIMM_32",
+ "SODIMM_34",
+ "SODIMM_135",
+ "SODIMM_77",
+ "SODIMM_100",
+ "SODIMM_186",
+ "SODIMM_196",
+ "SODIMM_194";
+};
+
+&gpio2 {
+ gpio-line-names = "SODIMM_55",
+ "SODIMM_63",
+ "SODIMM_178",
+ "SODIMM_188",
+ "SODIMM_73",
+ "SODIMM_30",
+ "SODIMM_67",
+ "SODIMM_104",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_190",
+ "SODIMM_47",
+ "SODIMM_192",
+ "SODIMM_49",
+ "SODIMM_51",
+ "SODIMM_53";
+};
+
+&gpio3 {
+ gpio-line-names = "SODIMM_56",
+ "SODIMM_44",
+ "SODIMM_68",
+ "SODIMM_82",
+ "",
+ "SODIMM_76",
+ "SODIMM_70",
+ "SODIMM_60",
+ "SODIMM_58",
+ "SODIMM_78",
+ "SODIMM_72",
+ "SODIMM_80",
+ "SODIMM_46",
+ "SODIMM_62",
+ "SODIMM_48",
+ "SODIMM_74",
+ "SODIMM_50",
+ "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_66",
+ "SODIMM_64",
+ "SODIMM_57",
+ "SODIMM_61",
+ "SODIMM_29",
+ "SODIMM_37",
+ "SODIMM_88",
+ "SODIMM_86",
+ "SODIMM_92",
+ "SODIMM_90";
+};
+
+&gpio4 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_59",
+ "",
+ "",
+ "SODIMM_133",
+ "",
+ "SODIMM_28",
+ "SODIMM_75",
+ "SODIMM_96",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_69",
+ "SODIMM_98",
+ "SODIMM_85",
+ "SODIMM_65";
+};
+
+&gpio5 {
+ gpio-line-names = "SODIMM_43",
+ "SODIMM_45",
+ "SODIMM_137",
+ "SODIMM_95",
+ "SODIMM_107",
+ "SODIMM_131",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_105";
};
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3
- &pinctrl_gpio4 &pinctrl_gpio5>;
+ &pinctrl_gpio4 &pinctrl_gpio5 &pinctrl_gpio7>;
};
@@ -48,5 +180,6 @@
non-removable;
vmmc-supply = <&reg_module_3v3>;
wakeup-source;
+ wifi-host;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6ull-colibri.dtsi b/arch/arm/boot/dts/imx6ull-colibri.dtsi
index d56728f03c35..10d3605e0ac4 100644
--- a/arch/arm/boot/dts/imx6ull-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri.dtsi
@@ -11,6 +11,23 @@
ethernet1 = &fec1;
};
+ memory {
+ reg = <0x80000000 0x10000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x08000000>;
+ linux,cma-default;
+ };
+ };
+
bl: backlight {
compatible = "pwm-backlight";
pinctrl-names = "default";
@@ -19,6 +36,12 @@
status = "disabled";
};
+ pxp_v4l2_out {
+ compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", \
+ "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
reg_module_3v3: regulator-module-3v3 {
compatible = "regulator-fixed";
regulator-always-on;
@@ -35,9 +58,9 @@
regulator-max-microvolt = <3300000>;
};
- reg_sd1_vmmc: regulator-sd1-vmmc {
+ reg_sd1_vqmmc: regulator-sd1-vqmmc {
compatible = "regulator-gpio";
- gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_snvs_reg_sd>;
regulator-always-on;
@@ -47,11 +70,38 @@
states = <1800000 0x1 3300000 0x0>;
vin-supply = <&reg_module_3v3>;
};
+
+ reg_soc_in: regulator-soc-in {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <1275000>;
+ regulator-max-microvolt = <1275000>;
+ regulator-name = "soc_in";
+ regulator-type = "voltage";
+ vin-supply = <&reg_module_3v3>;
+ };
+
+ reg_eth_phy: regulator-eth-phy {
+ compatible = "regulator-fixed-clock";
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "eth_phy";
+ regulator-type = "voltage";
+ vin-supply = <&reg_module_3v3>;
+ clocks = <&clks IMX6UL_CLK_ENET2_REF_125M>;
+ startup-delay-us = <150000>;
+ };
};
&adc1 {
num-channels = <10>;
vref-supply = <&reg_module_3v3_avdd>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc1>;
+};
+
+&cpu0 {
+ dc-supply = <&reg_soc_in>;
};
/* Colibri SPI */
@@ -62,10 +112,12 @@
};
&fec2 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_enet2>;
+ pinctrl-1 = <&pinctrl_enet2_sleep>;
phy-mode = "rmii";
phy-handle = <&ethphy1>;
+ phy-supply = <&reg_eth_phy>;
status = "okay";
mdio {
@@ -80,6 +132,14 @@
};
};
+&gpc {
+ fsl,cpu_pupscr_sw2iso = <0x1>;
+ fsl,cpu_pupscr_sw = <0x0>;
+ fsl,cpu_pdnscr_iso2sw = <0x1>;
+ fsl,cpu_pdnscr_iso = <0x1>;
+ fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
+};
+
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
@@ -99,6 +159,8 @@
};
&i2c2 {
+ /* use low frequency to compensate for the high pull up values */
+ clock-frequency = <40000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
pinctrl-1 = <&pinctrl_i2c2_gpio>;
@@ -153,6 +215,10 @@
#pwm-cells = <3>;
};
+&pxp {
+ status = "okay";
+};
+
&sdma {
status = "okay";
};
@@ -164,14 +230,14 @@
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_ctrl1>;
- uart-has-rtscts;
+ fsl,uart-has-rtscts;
fsl,dte-mode;
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
- uart-has-rtscts;
+ fsl,uart-has-rtscts;
fsl,dte-mode;
};
@@ -198,10 +264,26 @@
assigned-clock-rates = <0>, <198000000>;
};
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
+
&iomuxc {
+ imx6ull-colibri {
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0x3000 /* SODIMM 8 */
+ MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x3000 /* SODIMM 6 */
+ MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x3000 /* SODIMM 4 */
+ MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x3000 /* SODIMM 2 */
+ >;
+ };
+
pinctrl_can_int: canint-grp {
fsl,pins = <
- MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04 0X14 /* SODIMM 73 */
+ MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04 0x13010 /* SODIMM 73 */
>;
};
@@ -220,17 +302,39 @@
>;
};
+ pinctrl_enet2_sleep: enet2sleepgrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO06__GPIO1_IO06 0x0
+ MX6UL_PAD_GPIO1_IO07__GPIO1_IO07 0x0
+ MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08 0x0
+ MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09 0x0
+ MX6UL_PAD_ENET2_RX_EN__GPIO2_IO10 0x0
+ MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0x0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
+ MX6UL_PAD_ENET2_TX_DATA0__GPIO2_IO11 0x0
+ MX6UL_PAD_ENET2_TX_DATA1__GPIO2_IO12 0x0
+ MX6UL_PAD_ENET2_TX_EN__GPIO2_IO13 0x0
+ >;
+ };
+
pinctrl_ecspi1_cs: ecspi1-cs-grp {
fsl,pins = <
- MX6UL_PAD_LCD_DATA21__GPIO3_IO26 0x000a0
+ MX6UL_PAD_LCD_DATA21__GPIO3_IO26 0x70a0 /* SODIMM 86 */
>;
};
pinctrl_ecspi1: ecspi1-grp {
fsl,pins = <
- MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK 0x000a0
- MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI 0x000a0
- MX6UL_PAD_LCD_DATA23__ECSPI1_MISO 0x100a0
+ MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK 0x000a0 /* SODIMM 88 */
+ MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI 0x000a0 /* SODIMM 92 */
+ MX6UL_PAD_LCD_DATA23__ECSPI1_MISO 0x100a0 /* SODIMM 90 */
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1-grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX 0x1b020
+ MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX 0x1b020
>;
};
@@ -243,63 +347,68 @@
pinctrl_gpio_bl_on: gpio-bl-on-grp {
fsl,pins = <
- MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x000a0
+ MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x30a0 /* SODIMM 71 */
>;
};
pinctrl_gpio1: gpio1-grp {
fsl,pins = <
- MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00 0x74 /* SODIMM 55 */
- MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01 0x74 /* SODIMM 63 */
- MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25 0X14 /* SODIMM 77 */
- MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x14 /* SODIMM 99 */
- MX6UL_PAD_NAND_CE1_B__GPIO4_IO14 0x14 /* SODIMM 133 */
- MX6UL_PAD_UART3_TX_DATA__GPIO1_IO24 0x14 /* SODIMM 135 */
- MX6UL_PAD_UART3_CTS_B__GPIO1_IO26 0x14 /* SODIMM 100 */
- MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x14 /* SODIMM 102 */
- MX6UL_PAD_ENET1_RX_ER__GPIO2_IO07 0x14 /* SODIMM 104 */
- MX6UL_PAD_UART3_RTS_B__GPIO1_IO27 0x14 /* SODIMM 186 */
+ MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25 0x10b0 /* SODIMM 77 */
+ MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x70a0 /* SODIMM 99 */
+ MX6UL_PAD_NAND_CE1_B__GPIO4_IO14 0x10b0 /* SODIMM 133 */
+ MX6UL_PAD_UART3_TX_DATA__GPIO1_IO24 0x10b0 /* SODIMM 135 */
+ MX6UL_PAD_UART3_CTS_B__GPIO1_IO26 0x10b0 /* SODIMM 100 */
+ MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x70a0 /* SODIMM 102 */
+ MX6UL_PAD_ENET1_RX_ER__GPIO2_IO07 0x10b0 /* SODIMM 104 */
+ MX6UL_PAD_UART3_RTS_B__GPIO1_IO27 0x10b0 /* SODIMM 186 */
>;
};
pinctrl_gpio2: gpio2-grp { /* Camera */
fsl,pins = <
- MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x74 /* SODIMM 69 */
- MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0x14 /* SODIMM 75 */
- MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x14 /* SODIMM 85 */
- MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18 0x14 /* SODIMM 96 */
- MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x14 /* SODIMM 98 */
+ MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x10b0 /* SODIMM 69 */
+ MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0x10b0 /* SODIMM 75 */
+ MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x10b0 /* SODIMM 85 */
+ MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18 0x10b0 /* SODIMM 96 */
+ MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x10b0 /* SODIMM 98 */
>;
};
pinctrl_gpio3: gpio3-grp { /* CAN2 */
fsl,pins = <
- MX6UL_PAD_ENET1_RX_EN__GPIO2_IO02 0x14 /* SODIMM 178 */
- MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03 0x14 /* SODIMM 188 */
+ MX6UL_PAD_ENET1_RX_EN__GPIO2_IO02 0x10b0 /* SODIMM 178 */
+ MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03 0x10b0 /* SODIMM 188 */
>;
};
pinctrl_gpio4: gpio4-grp {
fsl,pins = <
- MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x74 /* SODIMM 65 */
+ MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x10b0 /* SODIMM 65 */
>;
};
pinctrl_gpio5: gpio5-grp { /* ATMEL MXT TOUCH */
fsl,pins = <
- MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x74 /* SODIMM 106 */
+ MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0xb0a0 /* SODIMM 106 */
>;
};
pinctrl_gpio6: gpio6-grp { /* Wifi pins */
fsl,pins = <
- MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x14 /* SODIMM 89 */
- MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x14 /* SODIMM 79 */
- MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x14 /* SODIMM 81 */
- MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x14 /* SODIMM 97 */
- MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x14 /* SODIMM 101 */
- MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x14 /* SODIMM 103 */
- MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x14 /* SODIMM 94 */
+ MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10b0 /* SODIMM 89 */
+ MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x10b0 /* SODIMM 79 */
+ MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x10b0 /* SODIMM 81 */
+ MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x10b0 /* SODIMM 97 */
+ MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x10b0 /* SODIMM 101 */
+ MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x10b0 /* SODIMM 103 */
+ MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x10b0 /* SODIMM 94 */
+ >;
+ };
+
+ pinctrl_gpio7: gpio7-grp { /* CAN1 */
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00 0xb0b0 /* SODIMM 55 */
+ MX6UL_PAD_ENET1_RX_DATA1__GPIO2_IO01 0xb0b0 /* SODIMM 63 */
>;
};
@@ -324,135 +433,135 @@
pinctrl_i2c1: i2c1-grp {
fsl,pins = <
- MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
- MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+ MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0 /* SODIMM 196 */
+ MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0 /* SODIMM 194 */
>;
};
pinctrl_i2c1_gpio: i2c1-gpio-grp {
fsl,pins = <
- MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28 0x4001b8b0
- MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29 0x4001b8b0
+ MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28 0x4001b8b0 /* SODIMM 196 */
+ MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29 0x4001b8b0 /* SODIMM 194 */
>;
};
pinctrl_i2c2: i2c2-grp {
fsl,pins = <
- MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
- MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
+ MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001f8b0
+ MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001f8b0
>;
};
pinctrl_i2c2_gpio: i2c2-gpio-grp {
fsl,pins = <
- MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x4001b8b0
- MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x4001b8b0
+ MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x4001f8b0
+ MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x4001f8b0
>;
};
pinctrl_lcdif_dat: lcdif-dat-grp {
fsl,pins = <
- MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x00079
- MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x00079
- MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x00079
- MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x00079
- MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x00079
- MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x00079
- MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x00079
- MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x00079
- MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x00079
- MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x00079
- MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x00079
- MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x00079
- MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x00079
- MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x00079
- MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x00079
- MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x00079
- MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x00079
- MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x00079
+ MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x00079 /* SODIMM 76 */
+ MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x00079 /* SODIMM 70 */
+ MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x00079 /* SODIMM 60 */
+ MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x00079 /* SODIMM 58 */
+ MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x00079 /* SODIMM 78 */
+ MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x00079 /* SODIMM 72 */
+ MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x00079 /* SODIMM 80 */
+ MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x00079 /* SODIMM 46 */
+ MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x00079 /* SODIMM 62 */
+ MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x00079 /* SODIMM 48 */
+ MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x00079 /* SODIMM 74 */
+ MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x00079 /* SODIMM 50 */
+ MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x00079 /* SODIMM 52 */
+ MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x00079 /* SODIMM 54 */
+ MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x00079 /* SODIMM 66 */
+ MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x00079 /* SODIMM 64 */
+ MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x00079 /* SODIMM 57 */
+ MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x00079 /* SODIMM 61 */
>;
};
pinctrl_lcdif_ctrl: lcdif-ctrl-grp {
fsl,pins = <
- MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x00079
- MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x00079
- MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x00079
- MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x00079
+ MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x00079 /* SODIMM 56 */
+ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x00079 /* SODIMM 44 */
+ MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x00079 /* SODIMM 68 */
+ MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x00079 /* SODIMM 82 */
>;
};
pinctrl_pwm4: pwm4-grp {
fsl,pins = <
- MX6UL_PAD_NAND_WP_B__PWM4_OUT 0x00079
+ MX6UL_PAD_NAND_WP_B__PWM4_OUT 0x00079 /* SODIMM 59 */
>;
};
pinctrl_pwm5: pwm5-grp {
fsl,pins = <
- MX6UL_PAD_NAND_DQS__PWM5_OUT 0x00079
+ MX6UL_PAD_NAND_DQS__PWM5_OUT 0x00079 /* SODIMM 28 */
>;
};
pinctrl_pwm6: pwm6-grp {
fsl,pins = <
- MX6UL_PAD_ENET1_TX_EN__PWM6_OUT 0x00079
+ MX6UL_PAD_ENET1_TX_EN__PWM6_OUT 0x00079 /* SODIMM 30 */
>;
};
pinctrl_pwm7: pwm7-grp {
fsl,pins = <
- MX6UL_PAD_ENET1_TX_CLK__PWM7_OUT 0x00079
+ MX6UL_PAD_ENET1_TX_CLK__PWM7_OUT 0x00079 /* SODIMM 67 */
>;
};
pinctrl_uart1: uart1-grp {
fsl,pins = <
- MX6UL_PAD_UART1_TX_DATA__UART1_DTE_RX 0x1b0b1
- MX6UL_PAD_UART1_RX_DATA__UART1_DTE_TX 0x1b0b1
- MX6UL_PAD_UART1_RTS_B__UART1_DTE_CTS 0x1b0b1
- MX6UL_PAD_UART1_CTS_B__UART1_DTE_RTS 0x1b0b1
+ MX6UL_PAD_UART1_TX_DATA__UART1_DTE_RX 0x1b0b1 /* SODIMM 33 */
+ MX6UL_PAD_UART1_RX_DATA__UART1_DTE_TX 0x1b0b1 /* SODIMM 35 */
+ MX6UL_PAD_UART1_RTS_B__UART1_DTE_CTS 0x1b0b1 /* SODIMM 27 */
+ MX6UL_PAD_UART1_CTS_B__UART1_DTE_RTS 0x1b0b1 /* SODIMM 25 */
>;
};
pinctrl_uart1_ctrl1: uart1-ctrl1-grp { /* Additional DTR, DCD */
fsl,pins = <
- MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x1b0b1 /* DCD */
- MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x1b0b1 /* DSR */
- MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x1b0b1 /* DTR */
- MX6UL_PAD_LCD_DATA19__GPIO3_IO24 0x1b0b1 /* RI */
+ MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x70a0 /* SODIMM 31 */
+ MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x10b0 /* SODIMM 29 */
+ MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x90b1 /* SODIMM 23 */
+ MX6UL_PAD_LCD_DATA19__GPIO3_IO24 0x10b0 /* SODIMM 37 */
>;
};
pinctrl_uart2: uart2-grp {
fsl,pins = <
- MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX 0x1b0b1
- MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX 0x1b0b1
- MX6UL_PAD_UART2_CTS_B__UART2_DTE_RTS 0x1b0b1
- MX6UL_PAD_UART2_RTS_B__UART2_DTE_CTS 0x1b0b1
+ MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX 0x1b0b1 /* SODIMM 36 */
+ MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX 0x1b0b1 /* SODIMM 38 */
+ MX6UL_PAD_UART2_CTS_B__UART2_DTE_RTS 0x1b0b1 /* SODIMM 32 */
+ MX6UL_PAD_UART2_RTS_B__UART2_DTE_CTS 0x1b0b1 /* SODIMM 34 */
>;
};
pinctrl_uart5: uart5-grp {
fsl,pins = <
- MX6UL_PAD_GPIO1_IO04__UART5_DTE_RX 0x1b0b1
- MX6UL_PAD_GPIO1_IO05__UART5_DTE_TX 0x1b0b1
+ MX6UL_PAD_GPIO1_IO04__UART5_DTE_RX 0x1b0b1 /* SODIMM 19 */
+ MX6UL_PAD_GPIO1_IO05__UART5_DTE_TX 0x1b0b1 /* SODIMM 21 */
>;
};
pinctrl_usbh_reg: gpio-usbh-reg {
fsl,pins = <
- MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x1b0b1 /* SODIMM 129 USBH PEN */
+ MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x10b0 /* SODIMM 129 */
>;
};
pinctrl_usdhc1: usdhc1-grp {
fsl,pins = <
- MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x17059
- MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x10059
- MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
- MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
- MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
- MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x17059 /* SODIMM 47 */
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x10059 /* SODIMM 190 */
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 /* SODIMM 192 */
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 /* SODIMM 49 */
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 /* SODIMM 51 */
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 /* SODIMM 53 */
>;
};
@@ -487,61 +596,74 @@
MX6UL_PAD_CSI_HSYNC__USDHC2_CMD 0x17059
MX6UL_PAD_CSI_VSYNC__USDHC2_CLK 0x17059
- MX6UL_PAD_GPIO1_IO03__OSC32K_32K_OUT 0x14
+ MX6UL_PAD_GPIO1_IO03__OSC32K_32K_OUT 0x10
>;
};
+
+ pinctrl_wdog: wdog-grp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+ }; /* imx6ull { */
};
&iomuxc_snvs {
pinctrl_snvs_gpio1: snvs-gpio1-grp {
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x14 /* SODIMM 93 */
- MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x14 /* SODIMM 95 */
- MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x74 /* SODIMM 105 */
- MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x14 /* SODIMM 131 USBH OC */
- MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x74 /* SODIMM 138 */
+ MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x110a0 /* SODIMM 93 */
+ MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x110a0 /* SODIMM 95 */
+ MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x1b0a0 /* SODIMM 105 */
+ MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x0b0a0 /* SODIMM 131 */
+ MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x110a0 /* SODIMM 138 */
>;
};
pinctrl_snvs_gpio2: snvs-gpio2-grp { /* ATMEL MXT TOUCH */
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x74 /* SODIMM 107 */
+ MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0xb0a0 /* SODIMM 107 */
>;
};
pinctrl_snvs_gpio3: snvs-gpio3-grp { /* Wifi pins */
fsl,pins = <
- MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x14 /* SODIMM 127 */
+ MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x130a0 /* SODIMM 127 */
>;
};
pinctrl_snvs_ad7879_int: snvs-ad7879-int-grp { /* TOUCH Interrupt */
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b0b0
+ MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b0a0
>;
};
pinctrl_snvs_reg_sd: snvs-reg-sd-grp {
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x4001b8b0
+ MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x130a0
>;
};
pinctrl_snvs_usbc_det: snvs-usbc-det-grp {
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0
+ MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x130a0 /* SODIMM 137 */
>;
};
pinctrl_snvs_gpiokeys: snvs-gpiokeys-grp {
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x130b0
+ MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x130a0 /* SODIMM 45 */
>;
};
pinctrl_snvs_usdhc1_cd: snvs-usdhc1-cd-grp {
fsl,pins = <
- MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0b0 /* CD */
+ MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0a0 /* SODIMM 43 */
+ >;
+ };
+
+ pinctrl_snvs_usdhc1_cd_sleep: snvs-usdhc1-cd-slp-grp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x0
>;
};
@@ -553,7 +675,7 @@
pinctrl_snvs_wifi_pdn: snvs-wifi-pdn-grp {
fsl,pins = <
- MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x14
+ MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x130a0
>;
};
};
diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi
index f9ce39bf55be..2629aefc19c4 100644
--- a/arch/arm/boot/dts/imx6ull.dtsi
+++ b/arch/arm/boot/dts/imx6ull.dtsi
@@ -3,6 +3,7 @@
// Copyright 2016 Freescale Semiconductor, Inc.
#include "imx6ul.dtsi"
+#include <dt-bindings/input/input.h>
#include "imx6ull-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
diff --git a/arch/arm/boot/dts/imx7-colibri-aster.dtsi b/arch/arm/boot/dts/imx7-colibri-aster.dtsi
new file mode 100644
index 000000000000..3b53ed1a97ae
--- /dev/null
+++ b/arch/arm/boot/dts/imx7-colibri-aster.dtsi
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2017 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ vin-supply = <&reg_5v0>;
+ };
+};
+
+&bl {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm1 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&adc2 {
+ status = "okay";
+};
+
+&epxp {
+ status = "okay";
+};
+
+&ecspi3 {
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <
+ &gpio4 11 GPIO_ACTIVE_HIGH
+ &gpio4 23 GPIO_ACTIVE_HIGH
+ >;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3 &pinctrl_ecspi3_cs &pinctrl_gpio5>;
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ };
+
+ spidev1: spidev@1 {
+ compatible = "toradex,evalspi";
+ reg = <1>;
+ spi-max-frequency = <23000000>;
+ };
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ reg = <0x4a>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ display = <&display0>;
+ status = "okay";
+
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&pwm3 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+/* The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control.
+ * All pins supplied with NVCC_SD1 must be able to cope with this
+ * and must (MUST!!!) not be driven with a voltage higher than 1.8V or
+ * the interface will not work.
+ */
+/* #define SD_1_8 */
+&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_cd_usdhc1>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_cd_usdhc1>;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_LDO2>;
+#else
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4>;
+};
diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
index 3f2746169181..44ee002d8848 100644
--- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
@@ -40,7 +40,15 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
/ {
+ aliases {
+ rtc0 = &rtc;
+ rtc1 = &snvs_rtc;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -52,15 +60,25 @@
clock-frequency = <16000000>;
};
- panel: panel {
- compatible = "edt,et057090dhu";
- backlight = <&bl>;
- power-supply = <&reg_3v3>;
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
- port {
- panel_in: endpoint {
- remote-endpoint = <&lcdif_out>;
- };
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
};
};
@@ -91,10 +109,10 @@
};
&bl {
- brightness-levels = <0 4 8 16 32 64 128 255>;
- default-brightness-level = <6>;
power-supply = <&reg_3v3>;
-
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm1 0 6666667 PWM_POLARITY_INVERTED>;
status = "okay";
};
@@ -106,6 +124,10 @@
status = "okay";
};
+&epxp {
+ status = "okay";
+};
+
&ecspi3 {
status = "okay";
@@ -122,6 +144,13 @@
xceiver-supply = <&reg_5v0>;
status = "okay";
};
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "disabled";
+ };
};
&fec1 {
@@ -131,6 +160,33 @@
&i2c4 {
status = "okay";
+/* the PCAPs use SODIMM 28/30, also used for PWM<B>, PWM<C>, aka pwm2, pwm3.
+ so if you enable one of the PCAP controllers disable the pwms */
+ /* Atmel maxtouch controller */
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 28 */
+ reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; /* SODIMM 30 */
+ status = "disabled";
+ };
+
+ touch: touchrevf0710a@10 {
+ compatible = "touchrevolution,fusion-f0710a";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x10>;
+ /* SODIMM 28, Pen down interrupt */
+ gpios = <&gpio1 9 GPIO_ACTIVE_HIGH
+ /* SODIMM 30, Reset interrupt */
+ &gpio1 10 GPIO_ACTIVE_LOW
+ >;
+ status = "disabled";
+ };
+
/* M41T0M6 real time clock on carrier board */
rtc: m41t0m6@68 {
compatible = "st,m41t0";
@@ -139,11 +195,123 @@
};
&lcdif {
+ display = <&display0>;
status = "okay";
- port {
- lcdif_out: endpoint {
- remote-endpoint = <&panel_in>;
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, TouchRevolution Fusion 7" */
+ timing_wvga2: 800x480pixclkact {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <1>;
+ };
+
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ /* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
+ timing_wsvga: 1024x600 {
+ clock-frequency = <48000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hback-porch = <104>;
+ hfront-porch = <43>;
+ vback-porch = <24>;
+ vfront-porch = <20>;
+ hsync-len = <5>;
+ vsync-len = <5>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
};
};
};
@@ -177,12 +345,45 @@
};
&usbotg1 {
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
status = "okay";
};
+/* The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control.
+ * All pins supplied with NVCC_SD1 must be able to cope with this
+ * and must (MUST!!!) not be driven with a voltage higher than 1.8V or
+ * the interface will not work.
+ */
+/* #define SD_1_8 */
&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_cd_usdhc1>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_cd_usdhc1>;
+ vqmmc-supply = <&reg_LDO2>;
+#else
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
keep-power-in-suspend;
wakeup-source;
vmmc-supply = <&reg_3v3>;
status = "okay";
};
+
+&iomuxc {
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x74
+ MX7D_PAD_GPIO1_IO10__GPIO1_IO10 0x14
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7-colibri-iris-v2.dtsi b/arch/arm/boot/dts/imx7-colibri-iris-v2.dtsi
new file mode 100644
index 000000000000..0abbe70f78b4
--- /dev/null
+++ b/arch/arm/boot/dts/imx7-colibri-iris-v2.dtsi
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ reg_3v3_vmmc: regulator-3v3-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "3v3_vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ vin-supply = <&reg_5v0>;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&bl {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm1 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&adc2 {
+ status = "okay";
+};
+
+&epxp {
+ status = "okay";
+};
+
+&ecspi3 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "okay";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ display = <&display0>;
+ status = "okay";
+
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ /* The pwm2 pins are used by atmel_mxt_ts touchscreen. */
+ status = "disabled";
+};
+
+&pwm3 {
+ /* The pwm3 pins are used by atmel_mxt_ts touchscreen. */
+ status = "disabled";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+&gpio2 {
+ /*
+ * uart25 turns the UART transceiver for UART2 and 5 on. If one wants to
+ * turn the transceiver off, that property has to be deleted and the
+ * gpio handled in userspace.
+ * The same applies to uart1_tx_on and lvds_tx_on, where the UART / LVDS
+ * transceiver is turned on.
+ */
+ uart25_tx_on {
+ gpio-hog;
+ gpios = <27 0>; /* SODIMM 104 */
+ output-high;
+ };
+};
+
+&gpio5 {
+ uart1_tx_on {
+ gpio-hog;
+ gpios = <17 0>; /* SODIMM 102 */
+ output-high;
+ };
+};
+
+&gpio7 {
+ lvds_tx_on {
+ gpio-hog;
+ gpios = <11 0>; /* SODIMM 99 */
+ output-high;
+ };
+};
+
+/* The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control.
+ * All pins supplied with NVCC_SD1 must be able to cope with this
+ * and must (MUST!!!) not be driven with a voltage higher than 1.8V or
+ * the interface will not work.
+ */
+#define SD_1_8
+&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_cd_usdhc1>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_cd_usdhc1>;
+ pinctrl-3 = <&pinctrl_usdhc1_sleep &pinctrl_cd_usdhc1_sleep>;
+ vqmmc-supply = <&reg_LDO2>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+#else
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_sleep &pinctrl_cd_usdhc1_sleep>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
+ cap-power-off-card;
+ wakeup-source;
+ vmmc-supply = <&reg_3v3_vmmc>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_usdhc1_sleep: usdhc1-slp-grp {
+ fsl,pins = <
+ MX7D_PAD_SD1_CMD__SD1_CMD 0x10
+ MX7D_PAD_SD1_CLK__SD1_CLK 0x10
+ MX7D_PAD_SD1_DATA0__SD1_DATA0 0x10
+ MX7D_PAD_SD1_DATA1__SD1_DATA1 0x10
+ MX7D_PAD_SD1_DATA2__SD1_DATA2 0x10
+ MX7D_PAD_SD1_DATA3__SD1_DATA3 0x10
+ >;
+ };
+
+ pinctrl_cd_usdhc1_sleep: usdhc1-cd-slp-grp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO00__GPIO1_IO0 0x0 /* CD */
+ >;
+ };
+
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x74
+ MX7D_PAD_GPIO1_IO10__GPIO1_IO10 0x14
+ >;
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx7-colibri-iris.dtsi b/arch/arm/boot/dts/imx7-colibri-iris.dtsi
new file mode 100644
index 000000000000..f03a553a5b65
--- /dev/null
+++ b/arch/arm/boot/dts/imx7-colibri-iris.dtsi
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_reg>;
+ regulator-name = "VCC_USB[1-4]";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ vin-supply = <&reg_5v0>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&bl {
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ default-brightness-level = <4>;
+ pwms = <&pwm1 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&adc2 {
+ status = "okay";
+};
+
+&epxp {
+ status = "okay";
+};
+
+&ecspi3 {
+ status = "okay";
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <23000000>;
+ status = "okay";
+ };
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x4a>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; /* SODIMM 107 */
+ reset-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* SODIMM 106 */
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ display = <&display0>;
+ status = "okay";
+
+ display0: lcd-display {
+ bits-per-pixel = <16>;
+ bus-width = <18>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+
+ de-active = <1>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+
+ de-active = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&pwm3 {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det>, <&extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
+
+&gpio2 {
+ /*
+ * uart25 turns the UART transceiver for UART2 and 5 on. If one wants to
+ * turn the transceiver off, that property has to be deleted and the
+ * gpio handled in userspace.
+ * The same applies to uart1_tx_on where the UART transceiver is
+ * turned on.
+ */
+ uart25_tx_on {
+ gpio-hog;
+ gpios = <27 0>; /* SODIMM 104 */
+ output-high;
+ };
+};
+
+&gpio5 {
+ uart1_tx_on {
+ gpio-hog;
+ gpios = <17 0>; /* SODIMM 102 */
+ output-high;
+ };
+};
+
+/* The define SD_1_8 allows to use the SD interface at a higher speed mode
+ * if the card supports it. For this the signaling voltage is switched from
+ * 3.3V to 1.8V under the usdhc1's drivers control.
+ * All pins supplied with NVCC_SD1 must be able to cope with this
+ * and must (MUST!!!) not be driven with a voltage higher than 1.8V or
+ * the interface will not work.
+ */
+#define SD_1_8
+&usdhc1 {
+#ifdef SD_1_8
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz &pinctrl_cd_usdhc1>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz &pinctrl_cd_usdhc1>;
+ vqmmc-supply = <&reg_LDO2>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+#else
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
+ no-1-8-v;
+#endif
+ cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ enable-sdio-wakeup;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <&reg_3v3>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x74
+ MX7D_PAD_GPIO1_IO10__GPIO1_IO10 0x14
+ >;
+ };
+};
+
diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index 8bba03de51ad..8e84a303fca6 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
* Copyright 2016 Toradex AG
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
*/
/ {
@@ -45,10 +8,15 @@
compatible = "pwm-backlight";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_bl_on>;
- pwms = <&pwm1 0 5000000 0>;
enable-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
};
+ pxp_v4l2_out {
+ compatible = "fsl,imx7d-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", \
+ "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
reg_module_3v3: regulator-module-3v3 {
compatible = "regulator-fixed";
regulator-name = "+V3.3";
@@ -80,6 +48,11 @@
clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
};
};
+
+ m4_tcm: tcml@007f8000 {
+ compatible = "fsl, m4_tcml";
+ reg = <0x007f8000 0x8000>;
+ };
};
&adc1 {
@@ -116,6 +89,19 @@
phy-mode = "rmii";
phy-supply = <&reg_LDO1>;
fsl,magic-packet;
+ phy-handle = <&ethphy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ max-speed = <100>;
+ micrel,led-mode = <0>;
+ reg = <0>;
+ };
+ };
};
&flexcan1 {
@@ -130,6 +116,184 @@
status = "disabled";
};
+&gpio1 {
+ gpio-line-names = "SODIMM_43",
+ "SODIMM_45",
+ "SODIMM_135",
+ "SODIMM_22",
+ "",
+ "",
+ "SODIMM_37",
+ "SODIMM_29",
+ "SODIMM_59",
+ "SODIMM_28",
+ "SODIMM_30",
+ "SODIMM_67",
+ "",
+ "",
+ "SODIMM_188",
+ "SODIMM_178";
+};
+
+&gpio2 {
+ gpio-line-names = "SODIMM_111",
+ "SODIMM_113",
+ "SODIMM_115",
+ "SODIMM_117",
+ "SODIMM_119",
+ "SODIMM_121",
+ "SODIMM_123",
+ "SODIMM_125",
+ "SODIMM_91",
+ "SODIMM_89",
+ "SODIMM_105",
+ "SODIMM_152",
+ "SODIMM_150",
+ "SODIMM_95",
+ "SODIMM_126",
+ "SODIMM_107",
+ "SODIMM_114",
+ "SODIMM_116",
+ "SODIMM_118",
+ "SODIMM_120",
+ "SODIMM_122",
+ "SODIMM_124",
+ "SODIMM_127",
+ "SODIMM_130",
+ "SODIMM_132",
+ "SODIMM_134",
+ "SODIMM_133",
+ "SODIMM_104",
+ "SODIMM_106",
+ "SODIMM_110",
+ "SODIMM_112",
+ "SODIMM_128";
+};
+
+&gpio3 {
+ gpio-line-names = "SODIMM_56",
+ "SODIMM_44",
+ "SODIMM_68",
+ "SODIMM_82",
+ "SODIMM_93",
+ "SODIMM_76",
+ "SODIMM_70",
+ "SODIMM_60",
+ "SODIMM_58",
+ "SODIMM_78",
+ "SODIMM_72",
+ "SODIMM_80",
+ "SODIMM_46",
+ "SODIMM_62",
+ "SODIMM_48",
+ "SODIMM_74",
+ "SODIMM_50",
+ "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_66",
+ "SODIMM_64",
+ "SODIMM_57",
+ "SODIMM_61",
+ "SODIMM_136",
+ "SODIMM_138",
+ "SODIMM_140",
+ "SODIMM_142",
+ "SODIMM_144",
+ "SODIMM_146";
+};
+
+&gpio4 {
+ gpio-line-names = "SODIMM_35",
+ "SODIMM_33",
+ "SODIMM_38",
+ "SODIMM_36",
+ "SODIMM_21",
+ "SODIMM_19",
+ "SODIMM_131",
+ "SODIMM_129",
+ "SODIMM_90",
+ "SODIMM_92",
+ "SODIMM_88",
+ "SODIMM_86",
+ "SODIMM_81",
+ "SODIMM_94",
+ "SODIMM_96",
+ "SODIMM_75",
+ "SODIMM_101",
+ "SODIMM_103",
+ "SODIMM_79",
+ "SODIMM_97",
+ "SODIMM_67",
+ "SODIMM_59",
+ "SODIMM_85",
+ "SODIMM_65";
+};
+
+&gpio5 {
+ gpio-line-names = "SODIMM_69",
+ "SODIMM_71",
+ "SODIMM_73",
+ "SODIMM_47",
+ "SODIMM_190",
+ "SODIMM_192",
+ "SODIMM_49",
+ "SODIMM_51",
+ "SODIMM_53",
+ "",
+ "",
+ "SODIMM_98",
+ "SODIMM_184",
+ "SODIMM_186",
+ "SODIMM_23",
+ "SODIMM_31",
+ "SODIMM_100",
+ "SODIMM_102";
+};
+
+&gpio6 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_169",
+ "",
+ "",
+ "",
+ "SODIMM_77",
+ "SODIMM_24",
+ "",
+ "SODIMM_25",
+ "SODIMM_27",
+ "SODIMM_32",
+ "SODIMM_34";
+};
+
+&gpio7 {
+ gpio-line-names = "",
+ "",
+ "SODIMM_63",
+ "SODIMM_55",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_196",
+ "SODIMM_194",
+ "",
+ "SODIMM_99",
+ "",
+ "",
+ "SODIMM_137";
+};
+
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
@@ -259,6 +423,16 @@
&pinctrl_lcdif_ctrl>;
};
+&ocram {
+ reg = <0x00901000 0xf000>;
+};
+
+&rpmsg {
+ vdev-nums = <1>;
+ reg = <0x8fff0000 0x10000>;
+ status = "okay";
+};
+
&pwm1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1>;
@@ -279,10 +453,6 @@
pinctrl-0 = <&pinctrl_pwm4>;
};
-&reg_1p0d {
- vin-supply = <&reg_DCDC3>;
-};
-
&sai1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai1>;
@@ -316,13 +486,12 @@
};
&usbotg1 {
- dr_mode = "host";
+ dr_mode = "otg";
};
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
- no-1-8-v;
cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
disable-wp;
vqmmc-supply = <&reg_LDO2>;
@@ -336,7 +505,6 @@
assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
assigned-clock-rates = <400000000>;
bus-width = <8>;
- fsl,tuning-step = <2>;
vmmc-supply = <&reg_module_3v3>;
vqmmc-supply = <&reg_DCDC3>;
non-removable;
@@ -346,7 +514,7 @@
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4
- &pinctrl_gpio7 &pinctrl_usbc_det>;
+ &pinctrl_gpio5 &pinctrl_gpio6 &pinctrl_gpio7>;
pinctrl_gpio1: gpio1-grp {
fsl,pins = <
@@ -357,7 +525,6 @@
MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x14 /* SODIMM 95 */
MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11 0x14 /* SODIMM 99 */
MX7D_PAD_EPDC_DATA10__GPIO2_IO10 0x74 /* SODIMM 105 */
- MX7D_PAD_EPDC_DATA15__GPIO2_IO15 0x74 /* SODIMM 107 */
MX7D_PAD_EPDC_DATA00__GPIO2_IO0 0x14 /* SODIMM 111 */
MX7D_PAD_EPDC_DATA01__GPIO2_IO1 0x14 /* SODIMM 113 */
MX7D_PAD_EPDC_DATA02__GPIO2_IO2 0x14 /* SODIMM 115 */
@@ -374,7 +541,6 @@
MX7D_PAD_SD2_DATA2__GPIO5_IO16 0x14 /* SODIMM 100 */
MX7D_PAD_SD2_DATA3__GPIO5_IO17 0x14 /* SODIMM 102 */
MX7D_PAD_EPDC_GDSP__GPIO2_IO27 0x14 /* SODIMM 104 */
- MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x74 /* SODIMM 106 */
MX7D_PAD_EPDC_BDR1__GPIO2_IO29 0x14 /* SODIMM 110 */
MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30 0x14 /* SODIMM 112 */
MX7D_PAD_EPDC_SDCLK__GPIO2_IO16 0x14 /* SODIMM 114 */
@@ -397,7 +563,6 @@
pinctrl_gpio2: gpio2-grp { /* On X22 Camera interface */
fsl,pins = <
- MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x14 /* SODIMM 65 */
MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x74 /* SODIMM 69 */
MX7D_PAD_I2C4_SDA__GPIO4_IO15 0x14 /* SODIMM 75 */
MX7D_PAD_ECSPI1_MISO__GPIO4_IO18 0x14 /* SODIMM 79 */
@@ -430,6 +595,20 @@
>;
};
+ pinctrl_gpio5: spigpios {
+ fsl,pins = <
+ /* CS1 */
+ MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x74 /* SODIMM 65 */
+ >;
+ };
+
+ pinctrl_gpio6: gpio6-grp { /* ATMEL MXT TOUCH */
+ fsl,pins = <
+ MX7D_PAD_EPDC_DATA15__GPIO2_IO15 0x74 /* SODIMM 107 */
+ MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x74 /* SODIMM 106 */
+ >;
+ };
+
pinctrl_gpio7: gpio7-grp { /* Alternatively CAN1 */
fsl,pins = <
MX7D_PAD_ENET1_RGMII_RD3__GPIO7_IO3 0x14 /* SODIMM 55 */
@@ -647,8 +826,7 @@
MX7D_PAD_UART3_RX_DATA__UART3_DTE_TX 0x79
>;
};
-
- pinctrl_usbc_det: gpio-usbc-det {
+ pinctrl_usbc_det: gpio_usbc_det {
fsl,pins = <
MX7D_PAD_ENET1_CRS__GPIO7_IO14 0x14
>;
@@ -671,6 +849,28 @@
>;
};
+ pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
+ fsl,pins = <
+ MX7D_PAD_SD1_CMD__SD1_CMD 0x5a
+ MX7D_PAD_SD1_CLK__SD1_CLK 0x1a
+ MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5a
+ MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5a
+ MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5a
+ MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5a
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp_200mhz {
+ fsl,pins = <
+ MX7D_PAD_SD1_CMD__SD1_CMD 0x5b
+ MX7D_PAD_SD1_CLK__SD1_CLK 0x1b
+ MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5b
+ MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5b
+ MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5b
+ MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5b
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX7D_PAD_SD3_CMD__SD3_CMD 0x59
@@ -741,12 +941,17 @@
pinctrl_gpio_lpsr: gpio1-grp {
fsl,pins = <
- MX7D_PAD_LPSR_GPIO1_IO01__GPIO1_IO1 0x59
MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x59
MX7D_PAD_LPSR_GPIO1_IO03__GPIO1_IO3 0x59
>;
};
+ pinctrl_gpiokeys: gpiokeysgrp {
+ fsl,pins = <
+ MX7D_PAD_LPSR_GPIO1_IO01__GPIO1_IO1 0x19
+ >;
+ };
+
pinctrl_i2c1: i2c1-grp {
fsl,pins = <
MX7D_PAD_LPSR_GPIO1_IO05__I2C1_SDA 0x4000007f
diff --git a/arch/arm/boot/dts/imx7d-colibri-aster.dts b/arch/arm/boot/dts/imx7d-colibri-aster.dts
new file mode 100644
index 000000000000..7a132d8abf95
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-colibri-aster.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7d-colibri.dtsi"
+#include "imx7-colibri-aster.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7D on Colibri Aster Board";
+ compatible = "toradex,colibri-imx7d-aster",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts b/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts
new file mode 100644
index 000000000000..f61ad3a1e046
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7d-colibri-emmc.dtsi"
+#include "imx7-colibri-aster.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7D 1GB on Colibri Aster Board";
+ compatible = "toradex,colibri-imx7d-emmc-aster",
+ "toradex,colibri-imx7d-emmc",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts b/arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts
index 8ee73c870b12..404c98703d9a 100644
--- a/arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts
+++ b/arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts
@@ -10,7 +10,9 @@
/ {
model = "Toradex Colibri iMX7D 1GB (eMMC) on Colibri Evaluation Board V3";
compatible = "toradex,colibri-imx7d-emmc-eval-v3",
- "toradex,colibri-imx7d-emmc", "fsl,imx7d";
+ "toradex,colibri-imx7d-emmc",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
};
&usbotg2 {
diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-iris-v2.dts b/arch/arm/boot/dts/imx7d-colibri-emmc-iris-v2.dts
new file mode 100644
index 000000000000..c02276cd4550
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-colibri-emmc-iris-v2.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7d-colibri-emmc.dtsi"
+#include "imx7-colibri-iris-v2.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7D 1GB on Colibri Iris V2 Board";
+ compatible = "toradex,colibri-imx7d-emmc-iris-v2",
+ "toradex,colibri-imx7d-emmc",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-iris.dts b/arch/arm/boot/dts/imx7d-colibri-emmc-iris.dts
new file mode 100644
index 000000000000..26ed20287d11
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-colibri-emmc-iris.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7d-colibri-emmc.dtsi"
+#include "imx7-colibri-iris.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7D 1GB on Colibri Iris Board";
+ compatible = "toradex,colibri-imx7d-emmc-iris",
+ "toradex,colibri-imx7d-emmc",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi b/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi
index 898f4b8d7421..b16389dfd5a6 100644
--- a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi
+++ b/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi
@@ -7,12 +7,46 @@
#include "imx7-colibri.dtsi"
/ {
- memory@80000000 {
+ aliases {
+ /* the following, together with kernel patches, forces a fixed assignment
+ between device id and usdhc controller */
+ /* i.e. the eMMC on usdhc3 will be /dev/mmcblk0 */
+ mmc0 = &usdhc3; /* eMMC */
+ mmc1 = &usdhc1; /* MMC 4bit slot */
+ };
+
+ memory {
device_type = "memory";
reg = <0x80000000 0x40000000>;
};
};
+&gpio6 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_169",
+ "SODIMM_157",
+ "",
+ "SODIMM_163",
+ "SODIMM_77",
+ "SODIMM_24",
+ "",
+ "SODIMM_25",
+ "SODIMM_27",
+ "SODIMM_32",
+ "SODIMM_34";
+};
+
&usbotg2 {
dr_mode = "host";
};
diff --git a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts b/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
index 136e11ab4893..3d2b48e730bf 100644
--- a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
@@ -46,7 +46,8 @@
/ {
model = "Toradex Colibri iMX7D on Colibri Evaluation Board V3";
- compatible = "toradex,colibri-imx7d-eval-v3", "toradex,colibri-imx7d",
+ compatible = "toradex,colibri-imx7d-eval-v3",
+ "toradex,colibri-imx7d",
"fsl,imx7d";
};
diff --git a/arch/arm/boot/dts/imx7d-colibri-iris-v2.dts b/arch/arm/boot/dts/imx7d-colibri-iris-v2.dts
new file mode 100644
index 000000000000..3ae2933e5f20
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-colibri-iris-v2.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/dts-v1/;
+#include "imx7d-colibri.dtsi"
+#include "imx7-colibri-iris-v2.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7D on Colibri Iris V2 Board";
+ compatible = "toradex,colibri-imx7d-iris-v2",
+ "toradex,colibri-imx7d",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-colibri-iris.dts b/arch/arm/boot/dts/imx7d-colibri-iris.dts
new file mode 100644
index 000000000000..b2883b6b506e
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-colibri-iris.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/dts-v1/;
+#include "imx7d-colibri.dtsi"
+#include "imx7-colibri-iris.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7D on Colibri Iris Board";
+ compatible = "toradex,colibri-imx7d-iris",
+ "toradex,colibri-imx7d",
+ "toradex,colibri-imx7d",
+ "fsl,imx7d";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usbh_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-colibri.dtsi b/arch/arm/boot/dts/imx7d-colibri.dtsi
index e2e327f437e3..a294043c517c 100644
--- a/arch/arm/boot/dts/imx7d-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7d-colibri.dtsi
@@ -1,49 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
- * Copyright 2016 Toradex AG
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * Copyright 2016-2020 Toradex
*/
#include "imx7d.dtsi"
#include "imx7-colibri.dtsi"
/ {
+ aliases {
+ ethernet0 = &fec1;
+ ethernet1 = &fec2;
+ };
+
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>;
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index b620366fb01c..166a2b1d2e83 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -68,56 +68,6 @@
};
soc {
- busfreq {
- compatible = "fsl,imx_busfreq";
- fsl,max_ddr_freq = <533000000>;
- clocks = <&clks IMX7D_OSC_24M_CLK>, <&clks IMX7D_MAIN_AXI_ROOT_SRC>,
- <&clks IMX7D_AHB_CHANNEL_ROOT_SRC>, <&clks IMX7D_PLL_SYS_PFD0_392M_CLK>,
- <&clks IMX7D_DRAM_ROOT_SRC>, <&clks IMX7D_DRAM_ALT_ROOT_SRC>,
- <&clks IMX7D_PLL_DRAM_MAIN_CLK>, <&clks IMX7D_DRAM_ALT_ROOT_CLK>,
- <&clks IMX7D_PLL_SYS_PFD2_270M_CLK>, <&clks IMX7D_PLL_SYS_PFD1_332M_CLK>,
- <&clks IMX7D_AHB_CHANNEL_ROOT_DIV>, <&clks IMX7D_MAIN_AXI_ROOT_DIV>;
- clock-names = "osc", "axi_sel", "ahb_sel", "pfd0_392m", "dram_root",
- "dram_alt_sel", "pll_dram", "dram_alt_root", "pfd2_270m",
- "pfd1_332m", "ahb", "axi";
- interrupts = <0 112 0x04>, <0 113 0x04>;
- interrupt-names = "irq_busfreq_0", "irq_busfreq_1";
- };
-
- ocrams_ddr: sram@900000 {
- compatible = "fsl,ddr-lpm-sram";
- reg = <0x900000 0x1000>;
- clocks = <&clks IMX7D_OCRAM_CLK>;
- };
-
- ocram: sram@901000 {
- compatible = "mmio-sram";
- reg = <0x901000 0x1f000>;
- clocks = <&clks IMX7D_OCRAM_CLK>;
- };
-
- ocrams: sram@180000 {
- compatible = "fsl,lpm-sram";
- reg = <0x180000 0x8000>;
- clocks = <&clks IMX7D_OCRAM_S_CLK>;
- status = "disabled";
- };
-
- ocram_optee {
- compatible = "fsl,optee-lpm-sram";
- reg = <0x180000 0x8000>;
- overw_reg = <&ocrams_ddr 0x904000 0x1000>,
- <&ocram 0x905000 0x1b000>,
- <&ocrams 0x900000 0x4000>;
- overw_clock = <&ocrams &clks IMX7D_OCRAM_CLK>;
- };
-
- ocrams_mf: sram-mf@900000 {
- compatible = "fsl,mega-fast-sram";
- reg = <0x900000 0x20000>;
- clocks = <&clks IMX7D_OCRAM_CLK>;
- };
-
etm@3007d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x3007d000 0x1000>;
@@ -165,26 +115,6 @@
status = "disabled";
};
- system_counter_rd: system-counter-rd@306a0000 {
- compatible = "fsl,imx7d-system-counter-rd";
- reg = <0x306a0000 0x10000>;
- status = "disabled";
- };
-
- system_counter_cmp: system-counter-cmp@306b0000 {
- compatible = "fsl,imx7d-system-counter-cmp";
- reg = <0x306b0000 0x10000>;
- status = "disabled";
- };
-
- system_counter_ctrl: system-counter-ctrl@306c0000 {
- compatible = "fsl,imx7d-system-counter-ctrl";
- reg = <0x306c0000 0x10000>;
- interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
- status = "disabled";
- };
-
epdc: epdc@306f0000 {
compatible = "fsl,imx7d-epdc";
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
@@ -196,27 +126,6 @@
status = "disabled";
};
- epxp: epxp@30700000 {
- compatible = "fsl,imx7d-pxp-dma";
- interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x30700000 0x10000>;
- clocks = <&clks IMX7D_PXP_IPG_CLK>, <&clks IMX7D_PXP_AXI_CLK>;
- clock-names = "pxp_ipg", "pxp_axi";
- status = "disabled";
- };
-
- csi1: csi1@30710000 {
- compatible = "fsl,imx7d-csi", "fsl,imx6s-csi";
- reg = <0x30710000 0x10000>;
- interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
- <&clks IMX7D_CSI_MCLK_ROOT_CLK>,
- <&clks IMX7D_CLK_DUMMY>;
- clock-names = "disp-axi", "csi_mclk", "disp_dcic";
- status = "disabled";
- };
-
mipi_csi: mipi-csi@30750000 {
compatible = "fsl,imx7d-mipi-csi";
reg = <0x30750000 0x10000>;
@@ -232,17 +141,6 @@
/delete-node/ port@1;
};
- mipi_dsi: mipi-dsi@30760000 {
- compatible = "fsl,imx7d-mipi-dsi";
- reg = <0x30760000 0x10000>;
- interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_MIPI_DSI_ROOT_CLK>,
- <&clks IMX7D_MIPI_DPHY_ROOT_CLK>;
- clock-names = "mipi_cfg_clk", "mipi_pllref_clk";
- power-domains = <&pgc_mipi_phy>;
- status = "disabled";
- };
-
qosc: qosc@307f0000 {
compatible = "fsl,imx7d-qosc", "syscon";
reg = <0x307f0000 0x4000>;
@@ -250,15 +148,6 @@
};
&aips3 {
- mu: mu@30aa0000 {
- compatible = "fsl,imx7d-mu", "fsl,imx6sx-mu";
- reg = <0x30aa0000 0x10000>;
- interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_MU_ROOT_CLK>;
- clock-names = "mu";
- #mbox-cells = <2>;
- };
-
mu_lp: mu_lp@30aa0000 {
compatible = "fsl,imx7d-mu-lp", "fsl,imx6sx-mu-lp";
reg = <0x30aa0000 0x10000>;
@@ -268,24 +157,6 @@
status = "okay";
};
- sema4: sema4@30ac0000 {
- compatible = "fsl,imx7d-sema4";
- reg = <0x30ac0000 0x10000>;
- interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_SEMA4_HS_ROOT_CLK>;
- clock-names = "sema4";
- status = "okay";
- };
-
- sim1: sim@30b90000 {
- compatible = "fsl,imx7d-sim";
- reg = <0x30b90000 0x10000>;
- interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_SIM1_ROOT_CLK>;
- clock-names = "sim";
- status = "disabled";
- };
-
qspi1: spi@30bb0000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -299,13 +170,6 @@
status = "disabled";
};
- sim2: sim@30ba0000 {
- compatible = "fsl,imx7d-sim";
- reg = <0x30ba0000 0x10000>;
- interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
- status = "disabled";
- };
-
usbotg2: usb@30b20000 {
compatible = "fsl,imx7d-usb", "fsl,imx27-usb";
reg = <0x30b20000 0x200>;
@@ -386,20 +250,6 @@
fsl,imx7d-pcie-phy = <&pcie_phy>;
status = "disabled";
};
-
- rpmsg: rpmsg{
- compatible = "fsl,imx7d-rpmsg";
- /* up to now, the following channels are used in imx rpmsg
- * - tx1/rx1: messages channel.
- * - general interrupt1: remote proc finish re-init rpmsg stack
- * when A core is partition reset.
- */
- mbox-names = "tx", "rx", "rxdb";
- mboxes = <&mu 0 1
- &mu 1 1
- &mu 3 1>;
- status = "disabled";
- };
};
&ca_funnel_in_ports {
diff --git a/arch/arm/boot/dts/imx7s-colibri-aster.dts b/arch/arm/boot/dts/imx7s-colibri-aster.dts
new file mode 100644
index 000000000000..269db1d42e3b
--- /dev/null
+++ b/arch/arm/boot/dts/imx7s-colibri-aster.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7s-colibri.dtsi"
+#include "imx7-colibri-aster.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7S on Colibri Aster Board";
+ compatible = "toradex,colibri-imx7s-aster",
+ "toradex,colibri-imx7s",
+ "toradex,colibri-imx7s",
+ "fsl,imx7s";
+};
diff --git a/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts b/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts
index bd2a49c1ade6..6a1dbc6bc6ce 100644
--- a/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
- * Copyright 2016 Toradex AG
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * Copyright 2016-2020 Toradex
*/
/dts-v1/;
@@ -46,6 +9,8 @@
/ {
model = "Toradex Colibri iMX7S on Colibri Evaluation Board V3";
- compatible = "toradex,colibri-imx7s-eval-v3", "toradex,colibri-imx7s",
+ compatible = "toradex,colibri-imx7s-eval-v3",
+ "toradex,colibri-imx7s",
+ "toradex,colibri-imx7s",
"fsl,imx7s";
};
diff --git a/arch/arm/boot/dts/imx7s-colibri-iris-v2.dts b/arch/arm/boot/dts/imx7s-colibri-iris-v2.dts
new file mode 100644
index 000000000000..26a9171b06f8
--- /dev/null
+++ b/arch/arm/boot/dts/imx7s-colibri-iris-v2.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7s-colibri.dtsi"
+#include "imx7-colibri-iris-v2.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7S on Colibri Iris V2 Board";
+ compatible = "toradex,colibri-imx7s-iris-v2",
+ "toradex,colibri-imx7s",
+ "toradex,colibri-imx7s",
+ "fsl,imx7s";
+};
diff --git a/arch/arm/boot/dts/imx7s-colibri-iris.dts b/arch/arm/boot/dts/imx7s-colibri-iris.dts
new file mode 100644
index 000000000000..84473f7468be
--- /dev/null
+++ b/arch/arm/boot/dts/imx7s-colibri-iris.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+/dts-v1/;
+#include "imx7s-colibri.dtsi"
+#include "imx7-colibri-iris.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX7S on Colibri Iris Board";
+ compatible = "toradex,colibri-imx7s-iris",
+ "toradex,colibri-imx7s",
+ "toradex,colibri-imx7s",
+ "fsl,imx7s";
+};
diff --git a/arch/arm/boot/dts/imx7s-colibri.dtsi b/arch/arm/boot/dts/imx7s-colibri.dtsi
index 6d16e32aed89..94de220a5965 100644
--- a/arch/arm/boot/dts/imx7s-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7s-colibri.dtsi
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
- * Copyright 2016 Toradex AG
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- * b) Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * Copyright 2016-2020 Toradex
*/
#include "imx7s.dtsi"
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 0f428e36dac8..3de4e24b24f0 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -60,6 +60,19 @@
clock-frequency = <792000000>;
clock-latency = <61036>; /* two CLK32 periods */
clocks = <&clks IMX7D_CLK_ARM>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ };
+ };
+
+ cpu0_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-792000000 {
+ opp-hz = /bits/ 64 <792000000>;
+ opp-microvolt = <1000000>;
+ clock-latency-ns = <150000>;
+ opp-supported-hw = <0xf>, <0xf>;
};
};
@@ -151,6 +164,56 @@
interrupt-parent = <&gpc>;
ranges;
+ busfreq {
+ compatible = "fsl,imx_busfreq";
+ fsl,max_ddr_freq = <533000000>;
+ clocks = <&clks IMX7D_OSC_24M_CLK>, <&clks IMX7D_MAIN_AXI_ROOT_SRC>,
+ <&clks IMX7D_AHB_CHANNEL_ROOT_SRC>, <&clks IMX7D_PLL_SYS_PFD0_392M_CLK>,
+ <&clks IMX7D_DRAM_ROOT_SRC>, <&clks IMX7D_DRAM_ALT_ROOT_SRC>,
+ <&clks IMX7D_PLL_DRAM_MAIN_CLK>, <&clks IMX7D_DRAM_ALT_ROOT_CLK>,
+ <&clks IMX7D_PLL_SYS_PFD2_270M_CLK>, <&clks IMX7D_PLL_SYS_PFD1_332M_CLK>,
+ <&clks IMX7D_AHB_CHANNEL_ROOT_DIV>, <&clks IMX7D_MAIN_AXI_ROOT_DIV>;
+ clock-names = "osc", "axi_sel", "ahb_sel", "pfd0_392m", "dram_root",
+ "dram_alt_sel", "pll_dram", "dram_alt_root", "pfd2_270m",
+ "pfd1_332m", "ahb", "axi";
+ interrupts = <0 112 0x04>, <0 113 0x04>;
+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1";
+ };
+
+ ocrams_ddr: sram@900000 {
+ compatible = "fsl,ddr-lpm-sram";
+ reg = <0x900000 0x1000>;
+ clocks = <&clks IMX7D_OCRAM_CLK>;
+ };
+
+ ocram: sram@901000 {
+ compatible = "mmio-sram";
+ reg = <0x901000 0x1f000>;
+ clocks = <&clks IMX7D_OCRAM_CLK>;
+ };
+
+ ocrams: sram@180000 {
+ compatible = "fsl,lpm-sram";
+ reg = <0x180000 0x8000>;
+ clocks = <&clks IMX7D_OCRAM_S_CLK>;
+ status = "disabled";
+ };
+
+ ocrams_mf: sram-mf@900000 {
+ compatible = "fsl,mega-fast-sram";
+ reg = <0x900000 0x20000>;
+ clocks = <&clks IMX7D_OCRAM_CLK>;
+ };
+
+ ocram_optee {
+ compatible = "fsl,optee-lpm-sram";
+ reg = <0x180000 0x8000>;
+ overw_reg = <&ocrams_ddr 0x904000 0x1000>,
+ <&ocram 0x905000 0x1b000>,
+ <&ocrams 0x900000 0x4000>;
+ overw_clock = <&ocrams &clks IMX7D_OCRAM_CLK>;
+ };
+
funnel@30041000 {
compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
reg = <0x30041000 0x1000>;
@@ -727,6 +790,38 @@
status = "disabled";
};
+ epxp: epxp@30700000 {
+ compatible = "fsl,imx7d-pxp-dma";
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x30700000 0x10000>;
+ clocks = <&clks IMX7D_PXP_IPG_CLK>, <&clks IMX7D_PXP_AXI_CLK>;
+ clock-names = "pxp_ipg", "pxp_axi";
+ status = "disabled";
+ };
+
+ csi1: csi1@30710000 {
+ compatible = "fsl,imx7d-csi", "fsl,imx6s-csi";
+ reg = <0x30710000 0x10000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_CLK_DUMMY>,
+ <&clks IMX7D_CSI_MCLK_ROOT_CLK>,
+ <&clks IMX7D_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ status = "disabled";
+ };
+
+ mipi_dsi: mipi-dsi@30760000 {
+ compatible = "fsl,imx7d-mipi-dsi";
+ reg = <0x30760000 0x10000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_MIPI_DSI_ROOT_CLK>,
+ <&clks IMX7D_MIPI_DPHY_ROOT_CLK>;
+ clock-names = "mipi_cfg_clk", "mipi_pllref_clk";
+ power-domains = <&pgc_mipi_phy>;
+ status = "disabled";
+ };
+
pwm1: pwm@30660000 {
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
reg = <0x30660000 0x10000>;
@@ -771,6 +866,26 @@
status = "disabled";
};
+ system_counter_rd: system-counter-rd@306a0000 {
+ compatible = "fsl,imx7d-system-counter-rd";
+ reg = <0x306a0000 0x10000>;
+ status = "disabled";
+ };
+
+ system_counter_cmp: system-counter-cmp@306b0000 {
+ compatible = "fsl,imx7d-system-counter-cmp";
+ reg = <0x306b0000 0x10000>;
+ status = "disabled";
+ };
+
+ system_counter_ctrl: system-counter-ctrl@306c0000 {
+ compatible = "fsl,imx7d-system-counter-ctrl";
+ reg = <0x306c0000 0x10000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
csi: csi@30710000 {
compatible = "fsl,imx7-csi";
reg = <0x30710000 0x10000>;
@@ -1111,6 +1226,15 @@
status = "disabled";
};
+ mu: mu@30aa0000 {
+ compatible = "fsl,imx7d-mu", "fsl,imx6sx-mu";
+ reg = <0x30aa0000 0x10000>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_MU_ROOT_CLK>;
+ clock-names = "mu";
+ #mbox-cells = <2>;
+ };
+
mu0a: mailbox@30aa0000 {
compatible = "fsl,imx7s-mu", "fsl,imx6sx-mu";
reg = <0x30aa0000 0x10000>;
@@ -1130,6 +1254,15 @@
status = "disabled";
};
+ sema4: sema4@30ac0000 {
+ compatible = "fsl,imx7d-sema4";
+ reg = <0x30ac0000 0x10000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_SEMA4_HS_ROOT_CLK>;
+ clock-names = "sema4";
+ status = "okay";
+ };
+
usbotg1: usb@30b10000 {
compatible = "fsl,imx7d-usb", "fsl,imx27-usb";
reg = <0x30b10000 0x200>;
@@ -1209,6 +1342,22 @@
status = "disabled";
};
+ sim1: sim@30b90000 {
+ compatible = "fsl,imx7d-sim";
+ reg = <0x30b90000 0x10000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX7D_SIM1_ROOT_CLK>;
+ clock-names = "sim";
+ status = "disabled";
+ };
+
+ sim2: sim@30ba0000 {
+ compatible = "fsl,imx7d-sim";
+ reg = <0x30ba0000 0x10000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
sdma: sdma@30bd0000 {
compatible = "fsl,imx7d-sdma", "fsl,imx35-sdma";
reg = <0x30bd0000 0x10000>;
@@ -1239,6 +1388,20 @@
fsl,num-rx-queues = <3>;
status = "disabled";
};
+
+ rpmsg: rpmsg{
+ compatible = "fsl,imx7d-rpmsg";
+ /* up to now, the following channels are used in imx rpmsg
+ * - tx1/rx1: messages channel.
+ * - general interrupt1: remote proc finish re-init rpmsg stack
+ * when A core is partition reset.
+ */
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&mu 0 1
+ &mu 1 1
+ &mu 3 1>;
+ status = "disabled";
+ };
};
dma_apbh: dma-apbh@33000000 {
diff --git a/arch/arm/configs/apalis_imx6_defconfig b/arch/arm/configs/apalis_imx6_defconfig
new file mode 100644
index 000000000000..268f9b9b00dd
--- /dev/null
+++ b/arch/arm/configs/apalis_imx6_defconfig
@@ -0,0 +1,525 @@
+CONFIG_BUILD_SALT="n"
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_CPU_ISOLATION is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_NAMESPACES=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_IO_URING is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_RSEQ is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_ARM_PSCI=y
+CONFIG_HIGHMEM=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_SECCOMP=y
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_ARM_IMX6Q_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+# CONFIG_STACKPROTECTOR is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_IPV6_SIT=m
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_MASQ=y
+CONFIG_NFT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_NFACCT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_L2TP=m
+CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_TSN=y
+CONFIG_CAN=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_FLEXCAN=m
+CONFIG_CAN_MCP251X=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+# CONFIG_BT_HS is not set
+# CONFIG_BT_LE is not set
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTUSB_BCM is not set
+# CONFIG_BT_HCIBTUSB_RTL is not set
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_IMX6=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_IMX=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+CONFIG_HNS_DSAF=m
+CONFIG_HNS_ENET=m
+CONFIG_E1000E=m
+CONFIG_IGB=m
+CONFIG_IGBVF=m
+CONFIG_SKY2=m
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+CONFIG_QCOM_EMAC=m
+CONFIG_SMC91X=m
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+CONFIG_STMMAC_ETH=m
+# CONFIG_DWMAC_IMX8 is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+CONFIG_AT803X_PHY=m
+CONFIG_MARVELL_PHY=m
+CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=m
+CONFIG_ROCKCHIP_PHY=m
+CONFIG_PPP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_NXP is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
+CONFIG_IVSHMEM_NET=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_ADC=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_FUSION_F0710A=m
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_GPIO=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_HWMON is not set
+CONFIG_SENSORS_MAG3110=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_STMPE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_PFUZE100=y
+CONFIG_RC_CORE=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=y
+CONFIG_IR_RC5_DECODER=y
+CONFIG_IR_RC6_DECODER=y
+CONFIG_IR_JVC_DECODER=y
+CONFIG_IR_SONY_DECODER=y
+CONFIG_IR_SANYO_DECODER=y
+CONFIG_IR_SHARP_DECODER=y
+CONFIG_IR_MCE_KBD_DECODER=y
+CONFIG_IR_XMP_DECODER=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_MXC_VADC=m
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5640_V2=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_TVIN_ADV7180=m
+CONFIG_MXC_TVIN_ADV7280=m
+CONFIG_MXC_TVIN_MAX9526=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
+CONFIG_VIDEO_MXC_IPU_OUTPUT=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
+CONFIG_DRM=y
+CONFIG_DRM_PANEL_LVDS=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_DRM_LEGACY=y
+CONFIG_DRM_VIVANTE=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_OVERLAY=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_EINK_PANEL=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_SPDIF=y
+CONFIG_SND_SOC_IMX_HDMI=y
+CONFIG_HIDRAW=y
+CONFIG_HID_MULTITOUCH=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=m
+CONFIG_MXC_PXP_V2=y
+CONFIG_STAGING=y
+CONFIG_R8188EU=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_IIO=y
+CONFIG_STMPE_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX27=y
+# CONFIG_IMX_IRQSTEER is not set
+# CONFIG_RESET_DISPMIX is not set
+# CONFIG_PHY_FSL_IMX_PCIE is not set
+CONFIG_MXC_IPU=y
+CONFIG_MXC_MLB150=y
+CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_MXC_HDMI_CEC=y
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_OVERLAY_FS=y
+# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_SECURITYFS=y
+CONFIG_LSM="n"
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECDH=y
+CONFIG_CRYPTO_ECHAINIV=m
+CONFIG_CRYPTO_TLS=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=m
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=m
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=320
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_MISC is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/colibri-imx6ull_defconfig b/arch/arm/configs/colibri-imx6ull_defconfig
new file mode 100644
index 000000000000..15b84356953e
--- /dev/null
+++ b/arch/arm/configs/colibri-imx6ull_defconfig
@@ -0,0 +1,494 @@
+CONFIG_BUILD_SALT="n"
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_CPU_ISOLATION is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_NAMESPACES=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_IO_URING is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_RSEQ is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX6UL=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_857271=y
+CONFIG_ARM_ERRATA_857272=y
+CONFIG_SMP=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_ARM_PSCI=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+# CONFIG_STACKPROTECTOR is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_IPV6_SIT=m
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_MASQ=y
+CONFIG_NFT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_NFACCT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_L2TP=m
+CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_TSN=y
+CONFIG_CAN=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_FLEXCAN=m
+CONFIG_CAN_MCP251X=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+# CONFIG_BT_HS is not set
+# CONFIG_BT_LE is not set
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTUSB_BCM is not set
+# CONFIG_BT_HCIBTUSB_RTL is not set
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=m
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+CONFIG_AT803X_PHY=m
+CONFIG_MARVELL_PHY=m
+CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=m
+CONFIG_ROCKCHIP_PHY=m
+CONFIG_PPP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
+CONFIG_INPUT_POLLDEV=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_ADC=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_SNVS_PWRKEY=y
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7879=y
+CONFIG_TOUCHSCREEN_AD7879_I2C=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_FUSION_F0710A=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_GPIO=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_HWMON is not set
+# CONFIG_MXC_MMA8451 is not set
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_RC_CORE=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=y
+CONFIG_IR_RC5_DECODER=y
+CONFIG_IR_RC6_DECODER=y
+CONFIG_IR_JVC_DECODER=y
+CONFIG_IR_SONY_DECODER=y
+CONFIG_IR_SANYO_DECODER=y
+CONFIG_IR_SHARP_DECODER=y
+CONFIG_IR_MCE_KBD_DECODER=y
+CONFIG_IR_XMP_DECODER=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+# CONFIG_USB_GSPCA is not set
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_IMX_PXP=y
+CONFIG_FB=y
+CONFIG_FB_MXS=y
+# CONFIG_FB_MXC_EDID is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+CONFIG_HIDRAW=y
+CONFIG_HID_MULTITOUCH=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=m
+CONFIG_MXS_DMA=y
+CONFIG_MXC_PXP_V2=y
+CONFIG_MXC_PXP_V3=y
+# CONFIG_MX3_IPU is not set
+# CONFIG_VIRTIO_MENU is not set
+CONFIG_STAGING=y
+CONFIG_R8188EU=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_IMX7D_ADC=y
+CONFIG_VF610_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX27=y
+# CONFIG_IMX_IRQSTEER is not set
+# CONFIG_RESET_DISPMIX is not set
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_FSL_IMX_PCIE is not set
+CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_NVMEM_SNVS_LPGPR=y
+CONFIG_MXC_SIM=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_OVERLAY_FS=y
+# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_SECURITYFS=y
+CONFIG_LSM="n"
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECDH=y
+CONFIG_CRYPTO_ECHAINIV=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=m
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=m
+CONFIG_CRYPTO_DEV_MXS_DCP=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_CMA_SIZE_PERCENTAGE=50
+CONFIG_CMA_SIZE_SEL_MIN=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_MISC is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/colibri_imx6_defconfig b/arch/arm/configs/colibri_imx6_defconfig
new file mode 100644
index 000000000000..ad273b2a077f
--- /dev/null
+++ b/arch/arm/configs/colibri_imx6_defconfig
@@ -0,0 +1,523 @@
+CONFIG_BUILD_SALT="n"
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_CPU_ISOLATION is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_NAMESPACES=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_IO_URING is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_RSEQ is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_ARM_PSCI=y
+CONFIG_HIGHMEM=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_SECCOMP=y
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_ARM_IMX6Q_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+# CONFIG_STACKPROTECTOR is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_IPV6_SIT=m
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_MASQ=y
+CONFIG_NFT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_NFACCT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_L2TP=m
+CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_CAN=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_FLEXCAN=m
+CONFIG_CAN_MCP251X=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+# CONFIG_BT_HS is not set
+# CONFIG_BT_LE is not set
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTUSB_BCM is not set
+# CONFIG_BT_HCIBTUSB_RTL is not set
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_IMX_WEIM=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=m
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+CONFIG_AT803X_PHY=m
+CONFIG_MARVELL_PHY=m
+CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=m
+CONFIG_ROCKCHIP_PHY=m
+CONFIG_PPP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_NXP is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_ADC=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_FUSION_F0710A=m
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_GPIO=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_HWMON is not set
+CONFIG_SENSORS_MAG3110=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_STMPE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_PFUZE100=y
+CONFIG_RC_CORE=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=y
+CONFIG_IR_RC5_DECODER=y
+CONFIG_IR_RC6_DECODER=y
+CONFIG_IR_JVC_DECODER=y
+CONFIG_IR_SONY_DECODER=y
+CONFIG_IR_SANYO_DECODER=y
+CONFIG_IR_SHARP_DECODER=y
+CONFIG_IR_MCE_KBD_DECODER=y
+CONFIG_IR_XMP_DECODER=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_MXC_VADC=m
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5640_V2=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_TVIN_ADV7180=m
+CONFIG_MXC_TVIN_ADV7280=m
+CONFIG_MXC_TVIN_MAX9526=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
+CONFIG_VIDEO_MXC_IPU_OUTPUT=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
+CONFIG_DRM=y
+CONFIG_DRM_PANEL_LVDS=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_DRM_LEGACY=y
+CONFIG_DRM_VIVANTE=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_OVERLAY=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_EINK_PANEL=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_SPDIF=y
+CONFIG_SND_SOC_IMX_HDMI=y
+CONFIG_HIDRAW=y
+CONFIG_HID_MULTITOUCH=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=m
+CONFIG_MXC_PXP_V2=y
+CONFIG_STAGING=y
+CONFIG_R8188EU=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_STMPE_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX27=y
+# CONFIG_IMX_IRQSTEER is not set
+# CONFIG_RESET_DISPMIX is not set
+# CONFIG_PHY_FSL_IMX_PCIE is not set
+CONFIG_MXC_IPU=y
+CONFIG_MXC_MLB150=y
+CONFIG_MXC_IPU_V3_PRE=y
+CONFIG_MXC_HDMI_CEC=y
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_OVERLAY_FS=y
+# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_SECURITYFS=y
+CONFIG_LSM="n"
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECDH=y
+CONFIG_CRYPTO_ECHAINIV=m
+CONFIG_CRYPTO_TLS=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=m
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=m
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_CMA_SIZE_PERCENTAGE=50
+CONFIG_CMA_SIZE_SEL_MIN=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_MISC is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/colibri_imx7_defconfig b/arch/arm/configs/colibri_imx7_defconfig
new file mode 100644
index 000000000000..4f2b5ebb4c72
--- /dev/null
+++ b/arch/arm/configs/colibri_imx7_defconfig
@@ -0,0 +1,508 @@
+CONFIG_BUILD_SALT="n"
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_CPU_ISOLATION is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_NAMESPACES=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_IO_URING is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_RSEQ is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX7D=y
+# CONFIG_ARM_ERRATA_643719 is not set
+CONFIG_SMP=y
+# CONFIG_ARM_CPU_TOPOLOGY is not set
+CONFIG_VMSPLIT_2G=y
+CONFIG_ARM_PSCI=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+# CONFIG_STACKPROTECTOR is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_IPV6_SIT=m
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_MASQ=y
+CONFIG_NFT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_NFACCT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_L2TP=m
+CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_TSN=y
+CONFIG_CAN=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_FLEXCAN=m
+CONFIG_CAN_MCP251X=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+# CONFIG_BT_HS is not set
+# CONFIG_BT_LE is not set
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTUSB_BCM is not set
+# CONFIG_BT_HCIBTUSB_RTL is not set
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_IMX_WEIM=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_ECC_SW_BCH=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_IPVLAN=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=m
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+CONFIG_AT803X_PHY=m
+CONFIG_MARVELL_PHY=m
+CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=m
+CONFIG_ROCKCHIP_PHY=m
+CONFIG_PPP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_ADC=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7879=y
+CONFIG_TOUCHSCREEN_AD7879_I2C=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_FUSION_F0710A=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX_GPIO=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_FSL_QUADSPI=y
+CONFIG_SPI_NXP_FLEXSPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_HWMON is not set
+# CONFIG_MXC_MMA8451 is not set
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_RN5T618_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_RN5T618=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_RN5T618=y
+CONFIG_RC_CORE=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=y
+CONFIG_IR_RC5_DECODER=y
+CONFIG_IR_RC6_DECODER=y
+CONFIG_IR_JVC_DECODER=y
+CONFIG_IR_SONY_DECODER=y
+CONFIG_IR_SANYO_DECODER=y
+CONFIG_IR_SHARP_DECODER=y
+CONFIG_IR_MCE_KBD_DECODER=y
+CONFIG_IR_XMP_DECODER=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+# CONFIG_USB_GSPCA is not set
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_CODA=y
+CONFIG_VIDEO_IMX_PXP=y
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+CONFIG_FB=y
+# CONFIG_FB_MX3 is not set
+CONFIG_FB_MXS=y
+# CONFIG_FB_MXC_EDID is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_FSL_ASRC=y
+CONFIG_SND_SOC_FSL_SPDIF=y
+CONFIG_SND_SOC_IMX_AUDMUX=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_IMX_AUDMIX=y
+CONFIG_SND_SOC_SGTL5000=m
+CONFIG_SND_SIMPLE_CARD=y
+CONFIG_HIDRAW=y
+CONFIG_HID_MULTITOUCH=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=m
+CONFIG_MXS_DMA=y
+CONFIG_MXC_PXP_V2=y
+CONFIG_MXC_PXP_V3=y
+# CONFIG_VIRTIO_MENU is not set
+CONFIG_STAGING=y
+CONFIG_R8188EU=m
+CONFIG_MAILBOX=y
+CONFIG_IMX_MBOX=y
+# CONFIG_IMX_GPCV2_PM_DOMAINS is not set
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_IMX7D_ADC=y
+CONFIG_VF610_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX27=y
+# CONFIG_IMX_IRQSTEER is not set
+# CONFIG_RESET_DISPMIX is not set
+# CONFIG_PHY_FSL_IMX_PCIE is not set
+CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_MXC_SIM=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_OVERLAY_FS=y
+# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_SECURITYFS=y
+CONFIG_LSM="n"
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECDH=y
+CONFIG_CRYPTO_ECHAINIV=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=m
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=m
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_CMA_SIZE_PERCENTAGE=50
+CONFIG_CMA_SIZE_SEL_MIN=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_MISC is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SINK_TPIU=y
+CONFIG_CORESIGHT_SINK_ETBV10=y
+CONFIG_CORESIGHT_SOURCE_ETM3X=y
diff --git a/arch/arm/configs/nit6xlite_defconfig b/arch/arm/configs/nit6xlite_defconfig
new file mode 100644
index 000000000000..dfc1a38b3c4a
--- /dev/null
+++ b/arch/arm/configs/nit6xlite_defconfig
@@ -0,0 +1,303 @@
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_GPIO_PCA953X=y
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_IMX6=y
+CONFIG_RC_MODE_IN_EP_RC_SYS=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_ARM_IMX6_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_IMX_WEIM=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_IMX=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MICREL_PHY=y
+CONFIG_BRCMFMAC=m
+CONFIG_IWLWIFI=m
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AR1020_I2C=y
+CONFIG_TOUCHSCREEN_EGALAX=y
+CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_FT5X06_SINGLE_TOUCH=y
+CONFIG_TOUCHSCREEN_TSC2004=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SENSORS_MAG3110=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_VIDEO_V4L2_INT_DEVICE=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CAPTURE=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
+CONFIG_VIDEO_MXC_IPU_OUTPUT=y
+CONFIG_SOC_CAMERA=y
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+# CONFIG_DVB_AU8522_V4L is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
+# CONFIG_DVB_TUNER_DIB0090 is not set
+CONFIG_DRM=y
+CONFIG_DRM_VIVANTE=y
+CONFIG_FB=y
+CONFIG_FB_MXS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_MIPI_DSI=y
+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_HDMI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_PHY=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_MXC_IPU=y
+CONFIG_MXC_GPU_VIV=y
+CONFIG_MXC_ASRC=y
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_ISL1208=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+# CONFIG_MX3_IPU is not set
+CONFIG_MXC_PXP_V2=y
+CONFIG_IMX_SDMA=y
+CONFIG_STAGING=y
+CONFIG_COMMON_CLK_DEBUG=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PWM=y
+CONFIG_PWM_IMX=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTS=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c
index bb18ed0539f4..d78e5baf42cf 100644
--- a/arch/arm/kernel/reboot.c
+++ b/arch/arm/kernel/reboot.c
@@ -120,6 +120,9 @@ void machine_power_off(void)
if (pm_power_off)
pm_power_off();
+ /* shoud pm_power_off not exist of fail, then at least do a halt*/
+ pr_err("%s pm_power_off() did return\n",__func__);
+ machine_halt();
}
/*
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index b80a060a0a7f..5f37a3da0201 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -46,6 +46,7 @@ config HAVE_IMX_GPCV2
config HAVE_IMX_MMDC
bool
+ select HAVE_IMX_BUSFREQ
config HAVE_IMX_AMP
bool
@@ -525,6 +526,7 @@ config SOC_IMX6SLL
bool "i.MX6 SoloLiteLite support"
select PINCTRL_IMX6SLL
select SOC_IMX6
+ select ARM_IMX6Q_CPUFREQ
help
This enables support for Freescale i.MX6 SoloLiteLite processor.
@@ -547,6 +549,7 @@ config SOC_IMX6UL
select PINCTRL_IMX6UL
select SOC_IMX6
select ARM_ERRATA_814220
+ select ARM_IMX6Q_CPUFREQ
help
This enables support for Freescale i.MX6 UltraLite processor.
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e4cd47d2a144..2bd45510d443 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -82,7 +82,7 @@ obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
obj-$(CONFIG_HAVE_IMX_DDRC) += ddrc.o
obj-$(CONFIG_HAVE_IMX_MU) += mu.o
-ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
+ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D)$(CONFIG_SOC_LS1021A),)
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c
index 026f9a8090ae..8c4858dd46ce 100644
--- a/arch/arm/mach-imx/busfreq-imx.c
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -185,6 +185,8 @@ int unregister_busfreq_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL(unregister_busfreq_notifier);
+#ifdef CONFIG_ARM_IMX6Q_CPUFREQ
+
static struct clk *origin_step_parent;
/*
@@ -213,6 +215,16 @@ static void imx6ull_lower_cpu_rate(bool enter)
clk_set_parent(pll1_bypass_clk, pll1_clk);
}
}
+#else
+static void imx6ull_lower_cpu_rate(bool enter)
+{
+ /* this stub should never be called.
+ configure with CONFIG_ARM_IMX6Q_CPUFREQ
+ */
+ (void) enter;
+ BUG();
+}
+#endif
/*
* enter_lpm_imx6_up and exit_lpm_imx6_up is used by
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index cd83ca08826e..728c6ea042ab 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -78,6 +78,50 @@ void __init imx_aips_allow_unprivileged_access(
}
}
+static unsigned long long __init imx_get_soc_uid(void)
+{
+ struct device_node *np;
+ void __iomem *ocotp_base;
+ u64 uid = 0ull;
+
+ if (__mxc_cpu_type == MXC_CPU_IMX6DL || __mxc_cpu_type == MXC_CPU_IMX6SX ||
+ __mxc_cpu_type == MXC_CPU_IMX6Q) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
+ } else if (__mxc_cpu_type == MXC_CPU_IMX6SL) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-ocotp");
+ } else if (__mxc_cpu_type == MXC_CPU_IMX6UL) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
+ } else if (__mxc_cpu_type == MXC_CPU_IMX6ULL) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6ull-ocotp");;
+ } else if (__mxc_cpu_type == MXC_CPU_IMX7D) {
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-ocotp");
+ } else {
+ return uid;
+ }
+
+ if (!np) {
+ pr_warn("failed to find ocotp node\n");
+ return uid;
+ }
+
+ ocotp_base = of_iomap(np, 0);
+ if (!ocotp_base) {
+ pr_warn("failed to map ocotp\n");
+ goto put_node;
+ }
+
+ uid = readl_relaxed(ocotp_base + 0x420);
+ uid = (uid << 0x20);
+ uid |= readl_relaxed(ocotp_base + 0x410);
+
+ iounmap(ocotp_base);
+
+put_node:
+ of_node_put(np);
+
+ return uid;
+}
+
struct device * __init imx_soc_device_init(void)
{
struct soc_device_attribute *soc_dev_attr;
diff --git a/arch/arm/mach-imx/cpuidle-imx6ul.c b/arch/arm/mach-imx/cpuidle-imx6ul.c
index 4f22b8f0d02b..f45ca55f984d 100644
--- a/arch/arm/mach-imx/cpuidle-imx6ul.c
+++ b/arch/arm/mach-imx/cpuidle-imx6ul.c
@@ -93,10 +93,12 @@ static void (*imx6ul_wfi_in_iram_fn)(void __iomem *iram_vbase);
static int imx6ul_idle_finish(unsigned long val)
{
+#if defined(CONFIG_ARM_PSCI_FW)
if (psci_ops.cpu_suspend)
psci_ops.cpu_suspend(MX6UL_POWERDWN_IDLE_PARAM,
__pa(cpu_resume));
else
+#endif
imx6ul_wfi_in_iram_fn(wfi_iram_base);
return 0;
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 838d93381c07..d4461648b8e9 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -150,6 +150,7 @@ unsigned int imx_gpc_is_mf_mix_off(void)
static void imx_gpc_mf_mix_off(void)
{
+#if 0
int i;
for (i = 0; i < IMR_NUM; i++)
@@ -160,6 +161,7 @@ static void imx_gpc_mf_mix_off(void)
pr_info("Turn off M/F mix!\n");
/* turn off mega/fast mix */
writel_relaxed(0x1, gpc_base + GPC_PGC_MF_PDN);
+#endif
}
void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 730ce83eee0e..a22cff64c631 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -15,6 +15,7 @@
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pm_opp.h>
@@ -33,6 +34,37 @@
#include "cpuidle.h"
#include "hardware.h"
+/* The PCIe switch on the Apalis Evaluation Board requires to have its reset
+ * deasserted some time before the reset of the downstream endpoints.
+ * The downstream endpoints use RESET_MOCI while the PCIe switch uses GPIO7
+ * for reset.
+ * Handle RESET_MOCI when the PCIe driver is not configured or disabled in
+ * the device tree */
+static void apalis_reset_moci(void)
+{
+ struct device_node *np;
+ int ret, reset_moci_gpio, no_pcie;
+#ifdef CONFIG_PCI_IMX6
+ no_pcie = 0;
+#else
+ no_pcie = 1;
+#endif
+
+ np = of_find_node_by_name(NULL, "pcie");
+ if (!of_device_is_available(np) || no_pcie) {
+ reset_moci_gpio = of_get_named_gpio(np, "reset-ep-gpio", 0);
+ if (gpio_is_valid(reset_moci_gpio)) {
+ ret = gpio_request_one(reset_moci_gpio,
+ GPIOF_OUT_INIT_LOW,
+ "RESET_MOCI");
+ if (ret) {
+ pr_err("%s(): unable to get RESET_MOCI gpio"
+ " from dt pcie node\n", __func__);
+ }
+ }
+ }
+}
+
/* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
static int ksz9021rn_phy_fixup(struct phy_device *phydev)
{
@@ -61,6 +93,14 @@ static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
phy_write(dev, 0x0e, val);
}
+static int mmd_read_reg(struct phy_device *dev, int device, int reg)
+{
+ phy_write(dev, 0x0d, device);
+ phy_write(dev, 0x0e, reg);
+ phy_write(dev, 0x0d, (1 << 14) | device);
+ return phy_read(dev, 0x0e);
+}
+
static int ksz9031rn_phy_fixup(struct phy_device *dev)
{
/*
@@ -74,6 +114,33 @@ static int ksz9031rn_phy_fixup(struct phy_device *dev)
return 0;
}
+#define KSZ9131_RXTXDLL_BYPASS 12
+
+static int ksz9131rn_phy_fixup(struct phy_device *dev)
+{
+ int tmp;
+
+ tmp = mmd_read_reg(dev, 2, 0x4c);
+ /* disable rxdll bypass (enable 2ns skew delay on RXC) */
+ tmp &= ~(1 << KSZ9131_RXTXDLL_BYPASS);
+ mmd_write_reg(dev, 2, 0x4c, tmp);
+
+ tmp = mmd_read_reg(dev, 2, 0x4d);
+ /* disable txdll bypass (enable 2ns skew delay on TXC) */
+ tmp &= ~(1 << KSZ9131_RXTXDLL_BYPASS);
+ mmd_write_reg(dev, 2, 0x4d, tmp);
+
+ /*
+ * Subtract ~0.6ns from txdll = ~1.4ns delay.
+ * leave RXC path untouched
+ */
+ mmd_write_reg(dev, 2, 4, 0x007d);
+ mmd_write_reg(dev, 2, 6, 0xdddd);
+ mmd_write_reg(dev, 2, 8, 0x0007);
+
+ return 0;
+}
+
/*
* fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
* as they are used for slots1-7 PERST#
@@ -179,6 +246,8 @@ static void __init imx6q_enet_phy_init(void)
ksz9021rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
ksz9031rn_phy_fixup);
+ phy_register_fixup_for_uid(PHY_ID_KSZ9131, MICREL_PHY_ID_MASK,
+ ksz9131rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef,
@@ -341,6 +410,9 @@ static void __init imx6q_init_machine(void)
imx6q_csi_mux_init();
cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
imx6q_axi_init();
+
+ if (of_machine_is_compatible("toradex,apalis_imx6q"))
+ apalis_reset_moci();
}
static void __init imx6q_init_late(void)
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index 7ad5e6f240dd..57681fbe7a19 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
*/
+#include <linux/clk.h>
#include <linux/irqchip.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
@@ -83,15 +84,48 @@ static void __init imx7d_enet_mdio_fixup(void)
static void __init imx7d_enet_clk_sel(void)
{
+ struct device_node *np = NULL;
+ struct clk *enet_out_clk;
struct regmap *gpr;
gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr");
- if (!IS_ERR(gpr)) {
- regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, 0);
- regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, 0);
- } else {
+ if (IS_ERR(gpr)) {
pr_err("failed to find fsl,imx7d-iomux-gpr regmap\n");
+ return;
}
+
+ do {
+ int id;
+ u32 clk_sel_mask, clk_dir_mask;
+
+ np = of_find_compatible_node(np, NULL, "fsl,imx7d-fec");
+ if (!np)
+ return;
+
+ /* Determine controller ID by ethernet alias */
+ id = of_alias_get_id(np, "ethernet");
+ clk_sel_mask = id == 0 ? IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK :
+ IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK;
+ clk_dir_mask = id == 0 ? IMX7D_GPR1_ENET1_CLK_DIR_MASK :
+ IMX7D_GPR1_ENET2_CLK_DIR_MASK;
+
+ enet_out_clk = of_clk_get_by_name(np, "enet_out");
+
+ if (IS_ERR(enet_out_clk)) {
+ pr_info("%s: fec%d: failed to get enet_out clock, assuming ext. clock source\n",
+ __func__, id + 1);
+ /* use external clock for PHY */
+ regmap_update_bits(gpr, IOMUXC_GPR1, clk_sel_mask, clk_sel_mask);
+ regmap_update_bits(gpr, IOMUXC_GPR1, clk_dir_mask, 0);
+ } else {
+ pr_info("%s: fec%d: found enet_out clock, assuming internal clock source\n",
+ __func__, id + 1);
+ /* use internal clock generation and output it to PHY */
+ regmap_update_bits(gpr, IOMUXC_GPR1, clk_sel_mask, 0);
+ regmap_update_bits(gpr, IOMUXC_GPR1, clk_dir_mask, clk_dir_mask);
+ clk_put(enet_out_clk);
+ }
+ } while (np);
}
static inline void imx7d_enet_init(void)
diff --git a/arch/arm/mach-imx/mu.c b/arch/arm/mach-imx/mu.c
index 1a250b07b256..f8844e6a3bee 100644
--- a/arch/arm/mach-imx/mu.c
+++ b/arch/arm/mach-imx/mu.c
@@ -37,6 +37,8 @@
#define MU_LPM_HANDSHAKE_INDEX 0
#define MU_RPMSG_HANDSHAKE_INDEX 1
+#define MU_LPM_M4_LPM_READY 0xFFFF4444
+#define MU_LPM_M4_LPM_SLEEP 0xFFFF5555
#define MU_LPM_BUS_HIGH_READY_FOR_M4 0xFFFF6666
#define MU_LPM_M4_FREQ_CHANGE_READY 0xFFFF7777
#define MU_LPM_M4_REQUEST_HIGH_BUS 0x2222CCCC
@@ -279,10 +281,13 @@ int imx_mu_lpm_ready(bool ready)
writel_relaxed(val & ~BIT(0), mu_base + MX7ULP_MU_CR);
} else {
val = readl_relaxed(mu_base + MU_ACR);
- if (ready)
+ if (ready) {
+ imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX, MU_LPM_M4_LPM_READY);
writel_relaxed(val | BIT(0), mu_base + MU_ACR);
- else
+ } else {
+ imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX, MU_LPM_M4_LPM_SLEEP);
writel_relaxed(val & ~BIT(0), mu_base + MU_ACR);
+ }
}
return 0;
}
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 9f44f0fa121f..2fe25594480c 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -751,10 +751,12 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
static int imx6q_suspend_finish(unsigned long val)
{
+#if defined(CONFIG_ARM_PSCI_FW)
if (psci_ops.cpu_suspend) {
return psci_ops.cpu_suspend(MX6Q_SUSPEND_PARAM,
__pa(cpu_resume));
}
+#endif
if (!imx6_suspend_in_ocram_fn) {
cpu_do_idle();
@@ -1284,17 +1286,60 @@ void __init imx6_pm_ccm_init(const char *ccm_compat)
writel_relaxed(val, ccm_base + CLPCR);
}
+void imx6_stop_mode_poweroff(void)
+{
+ /* compare with imx6q_set_lpm */
+ u32 val = readl_relaxed(ccm_base + CLPCR);
+
+ val &= ~BM_CLPCR_LPM;
+ /*
+ * mask all but the currently running processor,
+ * otherwise we will not enter stop mode
+ */
+ val |= smp_processor_id() != 0 ? BM_CLPCR_MASK_CORE0_WFI : 0;
+ val |= smp_processor_id() != 1 ? BM_CLPCR_MASK_CORE1_WFI : 0;
+ val |= smp_processor_id() != 2 ? BM_CLPCR_MASK_CORE2_WFI : 0;
+ val |= smp_processor_id() != 3 ? BM_CLPCR_MASK_CORE3_WFI : 0;
+ val |= BM_CLPCR_MASK_SCU_IDLE;
+ val |= 0x2 << BP_CLPCR_LPM;
+ val |= 0x3 << BP_CLPCR_STBY_COUNT;
+ val |= BM_CLPCR_VSTBY;
+ val |= BM_CLPCR_SBYOS;
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+
+ imx_gpc_hwirq_unmask(0);
+ writel_relaxed(val, ccm_base + CLPCR);
+ imx_gpc_hwirq_mask(0);
+ imx_gpc_mask_all();
+ cpu_do_idle();
+}
+
void __init imx6q_pm_init(void)
{
if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
imx6_pm_common_init(&imx6q_lpddr2_pm_data);
else
imx6_pm_common_init(&imx6q_pm_data);
+ /*
+ * if no specific power off function in board file, power off system by
+ * stop mode
+ */
+ if (!pm_power_off)
+ if (of_machine_is_compatible("toradex,apalis_imx6q"))
+ pm_power_off = imx6_stop_mode_poweroff;
}
void __init imx6dl_pm_init(void)
{
imx6_pm_common_init(&imx6dl_pm_data);
+
+ /*
+ * if no specific power off function in board file, power off system by
+ * stop mode
+ */
+ if (!pm_power_off)
+ if (of_machine_is_compatible("toradex,colibri_imx6dl"))
+ pm_power_off = imx6_stop_mode_poweroff;
}
void __init imx6sl_pm_init(void)
diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c
index e59cbee6dfc2..c0eba02e280f 100644
--- a/arch/arm/mach-imx/pm-imx7.c
+++ b/arch/arm/mach-imx/pm-imx7.c
@@ -44,6 +44,7 @@
#include "hardware.h"
#include "cpuidle.h"
+#define MX7_SUSPEND_OCRAM_OFFSET 0x4000
#define MX7_SUSPEND_OCRAM_SIZE 0x1000
#define MX7_MAX_DDRC_NUM 32
#define MX7_MAX_DDRC_PHY_NUM 16
@@ -892,7 +893,8 @@ static int __init imx7_dt_find_lpsram(unsigned long node, const char *uname,
if (!prop)
return -EINVAL;
- lpram_addr = be32_to_cpup(prop);
+ /* Add offset so we can use a full vector table for M4 */
+ lpram_addr = be32_to_cpup(prop) + MX7_SUSPEND_OCRAM_OFFSET;
/* We need to create a 1M page table entry. */
iram_tlb_io_desc.virtual = IMX_IO_P2V(lpram_addr & 0xFFF00000);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 15c8733ce44a..8b2d8df31241 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -340,7 +340,12 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
pgprot_t prot, struct page **ret_page,
const void *caller, bool want_vaddr);
+#if IS_ENABLED(CONFIG_VIDEO_TW68)
+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_32M
+#else
#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
+#endif
+
static struct gen_pool *atomic_pool __ro_after_init;
static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE;
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index d5eb439fe4a6..a45e8def8d39 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -52,7 +52,15 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb imx8mm-evk-rpmsg.dtb imx8mm-evk-rm67191
imx8mm-ddr4-evk.dtb imx8mm-evk-root.dtb imx8mm-evk-inmate.dtb \
imx8mm-ddr4-evk-rm67191.dtb imx8mm-evk-revb.dtb imx8mm-ddr4-evk-revb.dtb \
imx8mm-ddr4-evk-revb-rm67191.dtb imx8mm-ddr3l-val.dtb \
- imx8mm-evk-usd-wifi.dtb
+ imx8mm-evk-usd-wifi.dtb \
+ imx8mm-verdin-nonwifi-dahlia.dtb \
+ imx8mm-verdin-nonwifi-dev.dtb \
+ imx8mm-verdin-nonwifi-v1.1-dahlia.dtb \
+ imx8mm-verdin-nonwifi-v1.1-dev.dtb \
+ imx8mm-verdin-wifi-dahlia.dtb \
+ imx8mm-verdin-wifi-dev.dtb \
+ imx8mm-verdin-wifi-v1.1-dahlia.dtb \
+ imx8mm-verdin-wifi-v1.1-dev.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk-ak4497.dtb imx8mm-evk-ak5558.dtb imx8mm-evk-audio-tdm.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk-8mic-revE.dtb imx8mm-evk-8mic-swpdm.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-ab2.dtb
@@ -91,7 +99,13 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qm-mek.dtb imx8qm-mek-ov5640.dtb \
imx8qm-lpddr4-val-ca72.dtb imx8qm-ddr4-val.dtb \
imx8qm-lpddr4-val-lpspi.dtb imx8qm-lpddr4-val-lpspi-slave.dtb \
imx8qm-mek-dsi-rm67191.dtb imx8qm-lpddr4-val-dp.dtb\
- imx8qp-lpddr4-val.dtb imx8dm-lpddr4-val.dtb imx8qm-pcieax2pciebx1.dtb
+ imx8qp-lpddr4-val.dtb imx8dm-lpddr4-val.dtb imx8qm-pcieax2pciebx1.dtb \
+ imx8qm-apalis-eval.dtb \
+ imx8qm-apalis-ixora-v1.1.dtb \
+ imx8qm-apalis-v1.1-eval.dtb \
+ imx8qm-apalis-v1.1-ixora-v1.1.dtb \
+ imx8qp-apalis-v1.1-eval.dtb \
+ imx8qp-apalis-v1.1-ixora-v1.1.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qm-mek-dom0.dtb imx8qm-mek-domu.dtb \
imx8qm-mek-root.dtb imx8qm-mek-inmate.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-ai_ml.dtb
@@ -134,7 +148,13 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb imx8qxp-mek-dsp.dtb imx8qxp-mek-ov5640
imx8qxp-lpddr4-val-lpspi.dtb imx8qxp-lpddr4-val-lpspi-slave.dtb \
imx8qxp-lpddr4-val-spdif.dtb imx8qxp-lpddr4-val-gpmi-nand.dtb imx8dxp-lpddr4-val.dtb \
imx8qxp-17x17-val.dtb imx8dx-lpddr4-val.dtb imx8dx-17x17-val.dtb \
- imx8qxp-lpddr4-val-mlb.dtb
+ imx8qxp-lpddr4-val-mlb.dtb \
+ imx8qxp-colibri-aster.dtb \
+ imx8qxp-colibri-dsihdmi-eval-v3.dtb \
+ imx8qxp-colibri-eval-v3.dtb \
+ imx8qxp-colibri-lvds-dual-eval-v3.dtb \
+ imx8qxp-colibri-lvds-single-eval-v3.dtb \
+ imx8qxp-apalis-eval.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek-dom0.dtb imx8qxp-mek-root.dtb \
imx8qxp-mek-inmate.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8dxl-evk.dtb imx8dxl-evk-rpmsg.dtb \
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi
new file mode 100644
index 000000000000..62af86afb69e
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019-2020 Toradex
+ */
+
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &rtc;
+ };
+
+ reg_usb_host_vbus: regulator-usb-host-vbus {
+ regulator-name = "VCC USBH2(ABCD) / USBH(3|4)";
+ };
+};
+
+&adc0 {
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&amix {
+ status = "okay";
+};
+
+&asrc0 {
+ status = "okay";
+};
+
+&backlight {
+ default-brightness-level = <4>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ pwms = <&pwm_lvds1 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&dc0_dpr1_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel3 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel3 {
+ status = "okay";
+};
+
+&dc0_pc {
+ status = "okay";
+};
+
+&dc0_prg1 {
+ status = "okay";
+};
+
+&dc0_prg2 {
+ status = "okay";
+};
+
+&dc0_prg3 {
+ status = "okay";
+};
+
+&dc0_prg4 {
+ status = "okay";
+};
+
+&dc0_prg5 {
+ status = "okay";
+};
+
+&dc0_prg6 {
+ status = "okay";
+};
+
+&dc0_prg7 {
+ status = "okay";
+};
+
+&dc0_prg8 {
+ status = "okay";
+};
+
+&dc0_prg9 {
+ status = "okay";
+};
+
+&dc1_dpr1_channel1 {
+ status = "okay";
+};
+
+&dc1_dpr1_channel2 {
+ status = "okay";
+};
+
+&dc1_dpr1_channel3 {
+ status = "okay";
+};
+
+&dc1_dpr2_channel1 {
+ status = "okay";
+};
+
+&dc1_dpr2_channel2 {
+ status = "okay";
+};
+
+&dc1_dpr2_channel3 {
+ status = "okay";
+};
+
+&dc1_pc {
+ status = "okay";
+};
+
+&dc1_prg1 {
+ status = "okay";
+};
+
+&dc1_prg2 {
+ status = "okay";
+};
+
+&dc1_prg3 {
+ status = "okay";
+};
+
+&dc1_prg4 {
+ status = "okay";
+};
+
+&dc1_prg5 {
+ status = "okay";
+};
+
+&dc1_prg6 {
+ status = "okay";
+};
+
+&dc1_prg7 {
+ status = "okay";
+};
+
+&dc1_prg8 {
+ status = "okay";
+};
+
+&dc1_prg9 {
+ status = "okay";
+};
+
+&dpu1 {
+ status = "okay";
+};
+
+&dpu2 {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&flexcan1 {
+ status = "okay";
+};
+
+&flexcan2 {
+ status = "okay";
+};
+
+&gpu_3d0{
+ status = "okay";
+};
+
+&gpu_3d1{
+ status = "okay";
+};
+
+/* Apalis HDMI1 */
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_lpcg_apb {
+ status = "okay";
+};
+
+&hdmi_lpcg_apb_mux_csr {
+ status = "okay";
+};
+
+&hdmi_lpcg_apb_mux_ctrl {
+ status = "okay";
+};
+
+&hdmi_lpcg_gpio_ipg {
+ status = "okay";
+};
+
+&hdmi_lpcg_i2c0 {
+ status = "okay";
+};
+
+&hdmi_lpcg_i2s {
+ status = "okay";
+};
+
+&hdmi_lpcg_lis_ipg {
+ status = "okay";
+};
+
+&hdmi_lpcg_msi_hclk {
+ status = "okay";
+};
+
+&hdmi_lpcg_phy {
+ status = "okay";
+};
+
+&hdmi_lpcg_pwm_ipg {
+ status = "okay";
+};
+
+&hdmi_lpcg_pxl {
+ status = "okay";
+};
+
+/* Apalis I2C2 (DDC) */
+&i2c0 {
+ status = "okay";
+};
+
+/* Apalis I2C1 */
+&i2c2 {
+ status = "okay";
+
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5>, <&pinctrl_gpio6>;
+ reg = <0x4a>;
+ interrupt-parent = <&lsio_gpio4>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>; /* Apalis GPIO5 */
+ reset-gpios = <&lsio_gpio4 2 GPIO_ACTIVE_HIGH>; /* Apalis GPIO6 */
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+/* Apalis I2C3 (CAM) */
+&i2c3 {
+ status = "okay";
+};
+
+&imx8_gpu_ss {
+ status = "okay";
+};
+
+&irqsteer_csi0 {
+ status = "okay";
+};
+
+&irqsteer_csi1 {
+ status = "okay";
+};
+
+&irqsteer_hdmi {
+ status = "okay";
+};
+
+/* Apalis SPI1 */
+&lpspi0 {
+ status = "okay";
+};
+
+/* Apalis SPI2 */
+&lpspi2 {
+ status = "okay";
+};
+
+/* Apalis UART3 */
+&lpuart0 {
+ status = "okay";
+};
+
+/* Apalis UART1 */
+&lpuart1 {
+ status = "okay";
+};
+
+/* Apalis UART4 */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Apalis UART2 */
+&lpuart3 {
+ status = "okay";
+};
+
+/* Apalis PCIE1 */
+&pciea{
+ status = "okay";
+};
+
+/* Apalis PWM3, MXM3 pin 6 */
+&pwm0 {
+ status = "okay";
+};
+
+/* Apalis PWM4, MXM3 pin 8 */
+&pwm1 {
+ status = "okay";
+};
+
+/* Apalis PWM1, MXM3 pin 2 */
+&pwm2 {
+ status = "okay";
+};
+
+/* Apalis PWM2, MXM3 pin 4 */
+&pwm3 {
+ status = "okay";
+};
+
+&pwm_lvds1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_bkl>;
+ status = "okay";
+};
+
+&sai1 {
+ status = "okay";
+};
+
+&sai5 {
+ status = "okay";
+};
+
+&sai5_lpcg {
+ status = "okay";
+};
+
+/* Apalis SATA1 */
+&sata {
+ status = "okay";
+};
+
+/* Apalis SPDIF1 */
+&spdif0 {
+ status = "okay";
+};
+
+&spdif1 {
+ status = "okay";
+};
+
+&spdif1_lpcg {
+ status = "okay";
+};
+
+/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
+&usbh1 {
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+/* Apalis USBO1 */
+&usbotg1 {
+ status = "okay";
+};
+
+/* Apalis USBH4 SuperSpeed */
+&usbotg3 {
+ dr_mode = "host";
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+/* Apalis MMC1 */
+&usdhc2 {
+ status = "okay";
+};
+
+/* Apalis SD1 */
+&usdhc3 {
+ status = "okay";
+};
+
+&vpu_decoder {
+ status = "okay";
+};
+
+&vpu_encoder {
+ status = "okay";
+};
+
+&wakeup_key {
+ status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
new file mode 100644
index 000000000000..7440b83c1424
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
@@ -0,0 +1,477 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019-2020 Toradex
+ */
+
+/ {
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &rtc;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_leds_ixora>;
+
+ /* MXM3_188 */
+ led4-green {
+ label = "LED_4_GREEN";
+ gpios = <&lsio_gpio5 27 GPIO_ACTIVE_HIGH>;
+ };
+ /* MXM3_178 */
+ led4-red {
+ label = "LED_4_RED";
+ gpios = <&lsio_gpio5 29 GPIO_ACTIVE_HIGH>;
+ };
+ /* MXM3_152 */
+ led5-green {
+ label = "LED_5_GREEN";
+ gpios = <&lsio_gpio5 20 GPIO_ACTIVE_HIGH>;
+ };
+ /* MXM3_156 */
+ led5-red {
+ label = "LED_5_RED";
+ gpios = <&lsio_gpio5 21 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ reg_usb_host_vbus: regulator-usb-host-vbus {
+ regulator-name = "VCC_USBH(2|4)";
+ };
+};
+
+&adc0 {
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&amix {
+ status = "okay";
+};
+
+&asrc0 {
+ status = "okay";
+};
+
+&backlight {
+ default-brightness-level = <4>;
+ brightness-levels = <0 45 63 88 119 158 203 255>;
+ pwms = <&pwm_lvds1 0 6666667 PWM_POLARITY_INVERTED>;
+ status = "okay";
+};
+
+&dc0_dpr1_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel3 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel3 {
+ status = "okay";
+};
+
+&dc0_pc {
+ status = "okay";
+};
+
+&dc0_prg1 {
+ status = "okay";
+};
+
+&dc0_prg2 {
+ status = "okay";
+};
+
+&dc0_prg3 {
+ status = "okay";
+};
+
+&dc0_prg4 {
+ status = "okay";
+};
+
+&dc0_prg5 {
+ status = "okay";
+};
+
+&dc0_prg6 {
+ status = "okay";
+};
+
+&dc0_prg7 {
+ status = "okay";
+};
+
+&dc0_prg8 {
+ status = "okay";
+};
+
+&dc0_prg9 {
+ status = "okay";
+};
+
+&dc1_dpr1_channel1 {
+ status = "okay";
+};
+
+&dc1_dpr1_channel2 {
+ status = "okay";
+};
+
+&dc1_dpr1_channel3 {
+ status = "okay";
+};
+
+&dc1_dpr2_channel1 {
+ status = "okay";
+};
+
+&dc1_dpr2_channel2 {
+ status = "okay";
+};
+
+&dc1_dpr2_channel3 {
+ status = "okay";
+};
+
+&dc1_pc {
+ status = "okay";
+};
+
+&dc1_prg1 {
+ status = "okay";
+};
+
+&dc1_prg2 {
+ status = "okay";
+};
+
+&dc1_prg3 {
+ status = "okay";
+};
+
+&dc1_prg4 {
+ status = "okay";
+};
+
+&dc1_prg5 {
+ status = "okay";
+};
+
+&dc1_prg6 {
+ status = "okay";
+};
+
+&dc1_prg7 {
+ status = "okay";
+};
+
+&dc1_prg8 {
+ status = "okay";
+};
+
+&dc1_prg9 {
+ status = "okay";
+};
+
+&dpu1 {
+ status = "okay";
+};
+
+&dpu2 {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&gpu_3d0{
+ status = "okay";
+};
+
+&gpu_3d1{
+ status = "okay";
+};
+
+/* Apalis HDMI1 */
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_lpcg_apb {
+ status = "okay";
+};
+
+&hdmi_lpcg_apb_mux_csr {
+ status = "okay";
+};
+
+&hdmi_lpcg_apb_mux_ctrl {
+ status = "okay";
+};
+
+&hdmi_lpcg_gpio_ipg {
+ status = "okay";
+};
+
+&hdmi_lpcg_i2c0 {
+ status = "okay";
+};
+
+&hdmi_lpcg_i2s {
+ status = "okay";
+};
+
+&hdmi_lpcg_lis_ipg {
+ status = "okay";
+};
+
+&hdmi_lpcg_msi_hclk {
+ status = "okay";
+};
+
+&hdmi_lpcg_phy {
+ status = "okay";
+};
+
+&hdmi_lpcg_pwm_ipg {
+ status = "okay";
+};
+
+&hdmi_lpcg_pxl {
+ status = "okay";
+};
+
+/* Apalis I2C2 (DDC) */
+&i2c0 {
+ status = "okay";
+};
+
+/* Apalis I2C1 */
+&i2c2 {
+ status = "okay";
+
+ atmel_mxt_ts: atmel_mxt_ts@4a {
+ compatible = "atmel,maxtouch";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5>, <&pinctrl_gpio6>;
+ reg = <0x4a>;
+ interrupt-parent = <&lsio_gpio4>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>; /* Apalis GPIO5 */
+ reset-gpios = <&lsio_gpio4 2 GPIO_ACTIVE_HIGH>; /* Apalis GPIO6 */
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+/* Apalis I2C3 (CAM) */
+&i2c3 {
+ status = "okay";
+};
+
+&imx8_gpu_ss {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
+ <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
+ <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_usbh_oc_n>,
+ <&pinctrl_lpuart1ctrl>, <&pinctrl_lvds0_i2c0_gpio>,
+ <&pinctrl_lvds1_i2c0_gpios>, <&pinctrl_mipi_dsi_0_1_en>,
+ <&pinctrl_mipi_dsi1_gpios>, <&pinctrl_mlb_gpios>,
+ <&pinctrl_qspi1a_gpios>, <&pinctrl_sata1_act>,
+ <&pinctrl_sim0_gpios>, <&pinctrl_usdhc1_gpios>,
+ <&pinctrl_uart24_forceoff>;
+
+ pinctrl_leds_ixora: ledsixoragrp {
+ fsl,pins = <
+ IMX8QM_USDHC2_DATA1_LSIO_GPIO5_IO27 0x41 /* LED_4_GREEN */
+ IMX8QM_USDHC2_DATA3_LSIO_GPIO5_IO29 0x41 /* LED_4_RED */
+ IMX8QM_USDHC1_DATA5_LSIO_GPIO5_IO20 0x41 /* LED_5_GREEN */
+ IMX8QM_USDHC1_DATA6_LSIO_GPIO5_IO21 0x41 /* LED_5_RED */
+ >;
+ };
+
+ pinctrl_uart24_forceoff: uart24forceoffgrp {
+ fsl,pins = <
+ IMX8QM_USDHC2_CMD_LSIO_GPIO5_IO25 0x21
+ >;
+ };
+};
+
+&irqsteer_csi0 {
+ status = "okay";
+};
+
+&irqsteer_csi1 {
+ status = "okay";
+};
+
+&irqsteer_hdmi {
+ status = "okay";
+};
+
+&lsio_gpio5 {
+ ngpios = <32>;
+ gpio-line-names = "gpio5-00", "gpio5-01", "gpio5-02", "gpio5-03",
+ "gpio5-04", "gpio5-05", "gpio5-06", "gpio5-07",
+ "gpio5-08", "gpio5-09", "gpio5-10", "gpio5-11",
+ "gpio5-12", "gpio5-13", "gpio5-14", "gpio5-15",
+ "gpio5-16", "gpio5-17", "gpio5-18", "gpio5-19",
+ "LED-5-GREEN", "LED-5-RED", "gpio5-22", "gpio5-23",
+ "gpio5-24", "UART24-FORCEOFF", "gpio5-26",
+ "LED-4-GREEN", "gpio5-28", "LED-4-RED", "gpio5-30",
+ "gpio5-31";
+};
+
+/* Apalis SPI1 */
+&lpspi0 {
+ status = "okay";
+};
+
+/* Apalis SPI2 */
+&lpspi2 {
+ status = "okay";
+};
+
+/* Apalis UART3 */
+&lpuart0 {
+ status = "okay";
+};
+
+/* Apalis UART1 */
+&lpuart1 {
+ status = "okay";
+};
+
+/* Apalis UART4 */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Apalis UART2 */
+&lpuart3 {
+ status = "okay";
+};
+
+/* Apalis PCIE1 */
+&pciea{
+ status = "okay";
+};
+
+/* Apalis PWM3, MXM3 pin 6 */
+&pwm0 {
+ status = "okay";
+};
+
+/* Apalis PWM4, MXM3 pin 8 */
+&pwm1 {
+ status = "okay";
+};
+
+/* Apalis PWM1, MXM3 pin 2 */
+&pwm2 {
+ status = "okay";
+};
+
+/* Apalis PWM2, MXM3 pin 4 */
+&pwm3 {
+ status = "okay";
+};
+
+&pwm_lvds1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_bkl>;
+ status = "okay";
+};
+
+&sai1 {
+ status = "okay";
+};
+
+&sai5 {
+ status = "okay";
+};
+
+&sai5_lpcg {
+ status = "okay";
+};
+
+/* Apalis SATA1 */
+&sata {
+ status = "okay";
+};
+
+/* Apalis SPDIF1 */
+&spdif0 {
+ status = "okay";
+};
+
+&spdif1 {
+ status = "okay";
+};
+
+&spdif1_lpcg {
+ status = "okay";
+};
+
+/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
+&usbh1 {
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+/* Apalis USBO1 */
+&usbotg1 {
+ status = "okay";
+};
+
+/* Apalis USBH4 SuperSpeed */
+&usbotg3 {
+ dr_mode = "host";
+ vbus-supply = <&reg_usb_host_vbus>;
+ status = "okay";
+};
+
+/* Apalis MMC1 */
+&usdhc2 {
+ status = "okay";
+};
+
+&vpu_decoder {
+ status = "okay";
+};
+
+&vpu_encoder {
+ status = "okay";
+};
+
+&wakeup_key {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
new file mode 100644
index 000000000000..63e3341a677e
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -0,0 +1,1846 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ chosen {
+ stdout-path = &lpuart1;
+ };
+
+ /* Apalis BKL1 */
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_bkl_on>;
+ enable-gpios = <&lsio_gpio1 4 GPIO_ACTIVE_HIGH>; /* Apalis BKL1_ON */
+ };
+
+ gpio-fan {
+ compatible = "gpio-fan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio8>;
+ gpios = <&lsio_gpio3 28 GPIO_ACTIVE_HIGH>;
+ gpio-fan,speed-map = < 0 0
+ 3000 1>;
+ };
+
+ /* Apalis WAKE1_MICO */
+ wakeup_key: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+ status = "disabled";
+
+ wakeup-key {
+ label = "Wake-Up";
+ gpios = <&lsio_gpio2 20 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ wakeup-source;
+ };
+ };
+
+ panel_lvds: panel-lvds {
+ compatible = "panel-lvds";
+ backlight = <&backlight>;
+
+ status = "disabled";
+
+ port {
+ panel_lvds_in: endpoint {
+ remote-endpoint = <&lvds1_out>;
+ };
+ };
+ };
+
+ pcie_sata_refclk: sata-clock-generator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
+
+ pcie_sata_refclk_gate: sata-ref-clock {
+ compatible = "gpio-gate-clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie_sata_refclk>;
+ #clock-cells = <0>;
+ clocks = <&pcie_sata_refclk>;
+ enable-gpios = <&lsio_gpio4 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ /*
+ * Power management bus used to control LDO1OUT of the
+ * second PMIC PF8100. This is used for controlling voltage levels of
+ * typespecific RGMII signals and Apalis UART2_RTS UART2_CTS.
+ *
+ * IMX_SC_R_BOARD_R1 for 3.3V
+ * IMX_SC_R_BOARD_R2 for 1.8V
+ * IMX_SC_R_BOARD_R3 for 2.5V
+ * Note that for 2.5V operation the pad muxing needs to be changed,
+ * compare with PSW_OVR field of IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA_PAD.
+ *
+ * those power domains are mutually exclusive.
+ */
+ pmbus_external_rgmii: pmbusextrgmii {
+ compatible = "simple-pm-bus";
+ power-domains = <&pd IMX_SC_R_BOARD_R1>;
+ };
+
+ pcie_wifi_refclk: wifi-clock-generator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
+
+ pcie_wifi_refclk_gate: wifi-ref-clock {
+ compatible = "gpio-gate-clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie_wifi_refclk>;
+ #clock-cells = <0>;
+ clocks = <&pcie_wifi_refclk>;
+ enable-gpios = <&lsio_gpio2 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_module_3v3: regulator-module-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "+V3.3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_module_3v3_avdd: regulator-module-3v3-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "+V3.3_AUDIO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_module_wifi: regulator-module-wifi {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&lsio_gpio1 28 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi_pdn>;
+ regulator-name = "wifi_pwrdn_fake_regulator";
+ regulator-settling-time-us = <100>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ reg_pcie_switch: regulator-pcie-switch {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio7>;
+ enable-active-high;
+ gpio = <&lsio_gpio3 26 GPIO_ACTIVE_HIGH>;
+ regulator-name = "pcie_switch";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us = <100000>;
+ };
+
+ reg_usb_host_vbus: regulator-usb-host-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_en>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ /* Apalis USBH_EN */
+ gpio = <&lsio_gpio4 4 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
+ };
+
+ reg_vref_1v8: regulator-vref-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "+V1.8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ decoder_boot: decoder_boot@0x84000000 {
+ no-map;
+ reg = <0 0x84000000 0 0x2000000>;
+ };
+ encoder_boot: encoder_boot@0x86000000 {
+ no-map;
+ reg = <0 0x86000000 0 0x400000>;
+ };
+ /*
+ * reserved-memory layout
+ * 0x8800_0000 ~ 0x8FFF_FFFF is reserved for M4
+ * Shouldn't be used at A core and Linux side.
+ *
+ */
+ m4_reserved: m4@0x88000000 {
+ no-map;
+ reg = <0 0x88000000 0 0x8000000>;
+ };
+ rpmsg_reserved: rpmsg@0x90000000 {
+ no-map;
+ reg = <0 0x90200000 0 0x200000>;
+ };
+ decoder_rpc: decoder_rpc@0x92000000 {
+ no-map;
+ reg = <0 0x92000000 0 0x200000>;
+ };
+ encoder_rpc: encoder_rpc@0x92200000 {
+ no-map;
+ reg = <0 0x92200000 0 0x200000>;
+ };
+ dsp_reserved: dsp@0x92400000 {
+ no-map;
+ reg = <0 0x92400000 0 0x2000000>;
+ };
+ encoder_reserved: encoder_reserved@0x94400000 {
+ no-map;
+ reg = <0 0x94400000 0 0x800000>;
+ };
+ ts_boot: ts_boot@0x95000000 {
+ no-map;
+ reg = <0 0x95000000 0 0x400000>;
+ };
+
+ vdevbuffer: vdevbuffer {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90400000 0 0x100000>;
+ no-map;
+ };
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x3c000000>;
+ alloc-ranges = <0 0x96000000 0 0x3c000000>;
+ linux,cma-default;
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&dailink_master>;
+ /* simple-audio-card,mclk-fs = <1>; */
+ simple-audio-card,name = "apalis-imx8qm-sgtl5000";
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai1>;
+ };
+
+ dailink_master: simple-audio-card,codec {
+ clocks = <&mclkout0_lpcg 0>;
+ sound-dai = <&sgtl5000>;
+ };
+ };
+
+ sound-hdmi {
+ compatible = "fsl,imx-audio-cdnhdmi";
+ model = "imx-audio-hdmi-tx";
+ audio-cpu = <&sai5>;
+ protocol = <1>;
+ hdmi-out;
+ };
+
+ sound-hdmi-arc {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-hdmi-arc";
+ spdif-controller = <&spdif1>;
+ spdif-in;
+ spdif-out;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif0>;
+ spdif-in;
+ spdif-out;
+ };
+
+ touchscreen: vf50-touchscreen {
+ compatible = "toradex,vf50-touchscreen";
+ io-channels = <&adc1 2>,<&adc1 1>,
+ <&adc1 0>,<&adc1 3>;
+ xp-gpios = <&lsio_gpio2 4 GPIO_ACTIVE_LOW>;
+ xm-gpios = <&lsio_gpio2 5 GPIO_ACTIVE_HIGH>;
+ yp-gpios = <&lsio_gpio2 17 GPIO_ACTIVE_LOW>;
+ ym-gpios = <&lsio_gpio2 21 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&lsio_gpio3>;
+ interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "idle","default";
+ pinctrl-0 = <&pinctrl_touchctrl_idle>, <&pinctrl_touchctrl_gpios>;
+ pinctrl-1 = <&pinctrl_adc1>, <&pinctrl_touchctrl_gpios>;
+ vf50-ts-min-pressure = <200>;
+ /* NOTE: you must remove the pinctrl-adc1 from the adc1
+ node below to use the touchscreen */
+ status = "disabled";
+ };
+
+};
+
+&adc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0>;
+ vref-supply = <&reg_vref_1v8>;
+};
+
+&adc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc1>;
+ vref-supply = <&reg_vref_1v8>;
+};
+
+&asrc0 {
+ fsl,asrc-rate = <48000>;
+};
+
+/* Apalis GLAN */
+&fec1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_fec1>;
+ pinctrl-1 = <&pinctrl_fec1_sleep>;
+ fsl,magic-packet;
+ fsl,rgmii_txc_dly;
+ fsl,mii-exclusive;
+ phy-handle = <&ethphy0>;
+ phy-mode = "rgmii-rxid";
+ phy-reset-duration = <10>;
+ phy-reset-gpios = <&lsio_gpio1 11 GPIO_ACTIVE_LOW>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@7 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ interrupt-parent = <&lsio_gpio1>;
+ interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+ micrel,led-mode = <0>;
+ power-domains = <&pd IMX_SC_R_BOARD_R0>;
+ reg = <7>;
+ };
+ };
+};
+
+/* Apalis CAN1 */
+&flexcan1 {
+ /* define the following property to disable CAN-FD mode */
+ /* disable-fd-mode; */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ /* xceiver-supply = <&reg_can_stby>; */
+};
+
+/* Apalis CAN2 */
+&flexcan2 {
+ /* define the following property to disable CAN-FD mode */
+ /* disable-fd-mode; */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ /* xceiver-supply = <&reg_can_stby>; */
+};
+
+/* Apalis HDMI1 */
+&hdmi {
+ compatible = "cdn,imx8qm-hdmi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_ctrl>;
+ firmware-name = "imx/hdmi/hdmitxfw.bin";
+ hdmi-ctrl-gpios = <&lsio_gpio1 30 GPIO_ACTIVE_HIGH>;
+ lane-mapping = <0x93>;
+};
+
+&hsio_refa_clk {
+ status = "disabled";
+};
+
+&hsio_refb_clk {
+ status = "disabled";
+};
+
+/* On-module I2C */
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ sgtl5000: codec@a {
+ compatible = "fsl,sgtl5000";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sgtl5000>;
+ #sound-dai-cells = <0>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&mclkout0_lpcg 0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <12288000>;
+ clocks = <&mclkout0_lpcg 0>;
+ clock-names = "mclk";
+ reg = <0x0a>;
+ VDDA-supply = <&reg_module_3v3_avdd>;
+ VDDD-supply = <&reg_vref_1v8>;
+ VDDIO-supply = <&reg_module_3v3>;
+ };
+
+ /* USB3503A */
+ usb3503@8 {
+ compatible = "smsc,usb3503a";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb3503a>;
+ connect-gpios = <&lsio_gpio0 31 GPIO_ACTIVE_LOW>;
+ initial-mode = <1>;
+ intn-gpios = <&lsio_gpio1 1 GPIO_ACTIVE_LOW>;
+ refclk-frequency = <25000000>;
+ reg = <0x08>;
+ reset-gpios = <&lsio_gpio1 2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+/* Apalis I2C1 */
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+};
+
+/* Apalis I2C3 (CAM) */
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
+ <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
+ <&pinctrl_gpio3>, <&pinctrl_gpio4>,
+ <&pinctrl_gpio_usbh_oc_n>, <&pinctrl_lpuart1ctrl>,
+ <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
+ <&pinctrl_mipi_dsi_0_1_en>, <&pinctrl_mipi_dsi1_gpios>,
+ <&pinctrl_mlb_gpios>, <&pinctrl_qspi1a_gpios>,
+ <&pinctrl_sata1_act>, <&pinctrl_sim0_gpios>,
+ <&pinctrl_usdhc1_gpios>;
+
+ apalis-imx8qm {
+ /* Apalis AN1_ADC */
+ pinctrl_adc0: adc0grp {
+ fsl,pins = <
+ /* Apalis AN1_ADC0 */
+ IMX8QM_ADC_IN0_DMA_ADC0_IN0 0xc0000060
+ /* Apalis AN1_ADC1 */
+ IMX8QM_ADC_IN1_DMA_ADC0_IN1 0xc0000060
+ /* Apalis AN1_ADC2 */
+ IMX8QM_ADC_IN2_DMA_ADC0_IN2 0xc0000060
+ /* Apalis AN1_TSWIP_ADC3 */
+ IMX8QM_ADC_IN3_DMA_ADC0_IN3 0xc0000060
+ >;
+ };
+
+ /* Apalis AN1_TS */
+ pinctrl_adc1: adc1grp {
+ fsl,pins = <
+ /* Apalis AN1_TSPX */
+ IMX8QM_ADC_IN4_DMA_ADC1_IN0 0xc0000060
+ /* Apalis AN1_TSMX */
+ IMX8QM_ADC_IN5_DMA_ADC1_IN1 0xc0000060
+ /* Apalis AN1_TSPY */
+ IMX8QM_ADC_IN6_DMA_ADC1_IN2 0xc0000060
+ /* Apalis AN1_TSMY */
+ IMX8QM_ADC_IN7_DMA_ADC1_IN3 0xc0000060
+ >;
+ };
+
+ /* Apalis BKL_ON */
+ pinctrl_gpio_bkl_on: gpio-bkl-on {
+ fsl,pins = <
+ IMX8QM_LVDS0_GPIO00_LSIO_GPIO1_IO04 0x00000021
+ >;
+ };
+
+ /* Apalis BKL1_PWM */
+ pinctrl_pwm_bkl: pwmbklgrp {
+ fsl,pins = <
+ IMX8QM_LVDS1_GPIO00_LVDS1_PWM0_OUT 0x00000020
+ >;
+ };
+
+ /* Apalis CAM1 */
+ pinctrl_cam1_gpios: cam1gpiosgrp {
+ fsl,pins = <
+ /* Apalis CAM1_D7 */
+ IMX8QM_MIPI_DSI1_I2C0_SCL_LSIO_GPIO1_IO20 0x00000021
+ /* Apalis CAM1_D6 */
+ IMX8QM_MIPI_DSI1_I2C0_SDA_LSIO_GPIO1_IO21 0x00000021
+ /* Apalis CAM1_D5 */
+ IMX8QM_ESAI0_TX0_LSIO_GPIO2_IO26 0x00000021
+ /* Apalis CAM1_D4 */
+ IMX8QM_ESAI0_TX1_LSIO_GPIO2_IO27 0x00000021
+ /* Apalis CAM1_D3 */
+ IMX8QM_ESAI0_TX2_RX3_LSIO_GPIO2_IO28 0x00000021
+ /* Apalis CAM1_D2 */
+ IMX8QM_ESAI0_TX3_RX2_LSIO_GPIO2_IO29 0x00000021
+ /* Apalis CAM1_D1 */
+ IMX8QM_ESAI0_TX4_RX1_LSIO_GPIO2_IO30 0x00000021
+ /* Apalis CAM1_D0 */
+ IMX8QM_ESAI0_TX5_RX0_LSIO_GPIO2_IO31 0x00000021
+ /* Apalis CAM1_PCLK */
+ IMX8QM_MCLK_IN0_LSIO_GPIO3_IO00 0x00000021
+ /* Apalis CAM1_MCLK */
+ IMX8QM_SPI3_SDO_LSIO_GPIO2_IO18 0x00000021
+ /* Apalis CAM1_VSYNC */
+ IMX8QM_ESAI0_SCKR_LSIO_GPIO2_IO24 0x00000021
+ /* Apalis CAM1_HSYNC */
+ IMX8QM_ESAI0_SCKT_LSIO_GPIO2_IO25 0x00000021
+ >;
+ };
+
+ /* Apalis CAN1 */
+ pinctrl_flexcan1: flexcan0grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN0_TX_DMA_FLEXCAN0_TX 0x21
+ IMX8QM_FLEXCAN0_RX_DMA_FLEXCAN0_RX 0x21
+ >;
+ };
+
+ /* Apalis CAN2 */
+ pinctrl_flexcan2: flexcan1grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN1_TX_DMA_FLEXCAN1_TX 0x21
+ IMX8QM_FLEXCAN1_RX_DMA_FLEXCAN1_RX 0x21
+ >;
+ };
+
+ /* Apalis DAP1 */
+ pinctrl_dap1_gpios: dap1gpiosgrp {
+ fsl,pins = <
+ /* Apalis DAP1_MCLK */
+ IMX8QM_SPI3_SDI_LSIO_GPIO2_IO19 0x00000021
+ /* Apalis DAP1_D_OUT */
+ IMX8QM_SAI1_RXC_LSIO_GPIO3_IO12 0x00000021
+ /* Apalis DAP1_RESET */
+ IMX8QM_ESAI1_SCKT_LSIO_GPIO2_IO07 0x00000021
+ /* Apalis DAP1_BIT_CLK */
+ IMX8QM_SPI0_CS1_LSIO_GPIO3_IO06 0x00000021
+ /* Apalis DAP1_D_IN */
+ IMX8QM_SAI1_RXFS_LSIO_GPIO3_IO14 0x00000021
+ /* Apalis DAP1_SYNC */
+ IMX8QM_SPI2_CS1_LSIO_GPIO3_IO11 0x00000021
+ /* On-module Wi-Fi_I2S_EN# */
+ IMX8QM_ESAI1_TX5_RX0_LSIO_GPIO2_IO13 0x00000021
+ >;
+ };
+
+ /* Apalis GPIO1 */
+ pinctrl_gpio1: gpio1grp {
+ fsl,pins = <
+ IMX8QM_M40_GPIO0_00_LSIO_GPIO0_IO08 0x06000021
+ >;
+ };
+
+ /* Apalis GPIO2 */
+ pinctrl_gpio2: gpio2grp {
+ fsl,pins = <
+ IMX8QM_M40_GPIO0_01_LSIO_GPIO0_IO09 0x06000021
+ >;
+ };
+
+ /* Apalis GPIO3 */
+ pinctrl_gpio3: gpio3grp {
+ fsl,pins = <
+ IMX8QM_M41_GPIO0_00_LSIO_GPIO0_IO12 0x06000021
+ >;
+ };
+
+ /* Apalis GPIO4 */
+ pinctrl_gpio4: gpio4grp {
+ fsl,pins = <
+ IMX8QM_M41_GPIO0_01_LSIO_GPIO0_IO13 0x06000021
+ >;
+ };
+
+ /* Apalis GPIO5 */
+ pinctrl_gpio5: gpio5grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN2_RX_LSIO_GPIO4_IO01 0x06000021
+ >;
+ };
+
+ /* Apalis GPIO6 */
+ pinctrl_gpio6: gpio6grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN2_TX_LSIO_GPIO4_IO02 0x00000021
+ >;
+ };
+
+ /* Apalis GPIO7 */
+ pinctrl_gpio7: gpio7grp {
+ fsl,pins = <
+ IMX8QM_MLB_SIG_LSIO_GPIO3_IO26 0x00000021
+ >;
+ };
+
+ /* Apalis GPIO8 */
+ pinctrl_gpio8: gpio8grp {
+ fsl,pins = <
+ IMX8QM_MLB_DATA_LSIO_GPIO3_IO28 0x00000021
+ >;
+ };
+
+ /* Apalis I2C1 */
+ pinctrl_lpi2c2: lpi2c2grp {
+ fsl,pins = <
+ IMX8QM_GPT1_CLK_DMA_I2C2_SCL 0x04000020
+ IMX8QM_GPT1_CAPTURE_DMA_I2C2_SDA 0x04000020
+ >;
+ };
+
+ /* Apalis I2C3 (CAM) */
+ pinctrl_lpi2c3: lpi2c3grp {
+ fsl,pins = <
+ IMX8QM_SIM0_PD_DMA_I2C3_SCL 0x04000020
+ IMX8QM_SIM0_POWER_EN_DMA_I2C3_SDA 0x04000020
+ >;
+ };
+
+ /* Apalis LCD1_G1+2 */
+ pinctrl_esai0_gpios: esai0gpiosgrp {
+ fsl,pins = <
+ /* Apalis LCD1_G1 */
+ IMX8QM_ESAI0_FSR_LSIO_GPIO2_IO22 0x00000021
+ /* Apalis LCD1_G2 */
+ IMX8QM_ESAI0_FST_LSIO_GPIO2_IO23 0x00000021
+ >;
+ };
+
+ /* Apalis LCD1_G6+7 */
+ pinctrl_lvds1_i2c0_gpios: lvds1i2c0gpiosgrp {
+ fsl,pins = <
+ /* Apalis LCD1_G6 */
+ IMX8QM_LVDS1_I2C0_SCL_LSIO_GPIO1_IO12 0x00000021
+ /* Apalis LCD1_G7 */
+ IMX8QM_LVDS1_I2C0_SDA_LSIO_GPIO1_IO13 0x00000021
+ >;
+ };
+
+ /* Apalis LCD1_ */
+ pinctrl_fec2_gpios: fec2gpiosgrp {
+ fsl,pins = <
+ IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA_PAD 0x000014a0
+ /* Apalis LCD1_R1 */
+ IMX8QM_ENET1_MDC_LSIO_GPIO4_IO18 0x00000021
+ /* Apalis LCD1_R0 */
+ IMX8QM_ENET1_MDIO_LSIO_GPIO4_IO17 0x00000021
+ /* Apalis LCD1_G0 */
+ IMX8QM_ENET1_REFCLK_125M_25M_LSIO_GPIO4_IO16 0x00000021
+ /* Apalis LCD1_R7 */
+ IMX8QM_ENET1_RGMII_RX_CTL_LSIO_GPIO6_IO17 0x00000021
+ /* Apalis LCD1_DE */
+ IMX8QM_ENET1_RGMII_RXD0_LSIO_GPIO6_IO18 0x00000021
+ /* Apalis LCD1_HSYNC */
+ IMX8QM_ENET1_RGMII_RXD1_LSIO_GPIO6_IO19 0x00000021
+ /* Apalis LCD1_VSYNC */
+ IMX8QM_ENET1_RGMII_RXD2_LSIO_GPIO6_IO20 0x00000021
+ /* Apalis LCD1_PCLK */
+ IMX8QM_ENET1_RGMII_RXD3_LSIO_GPIO6_IO21 0x00000021
+ /* Apalis LCD1_R6 */
+ IMX8QM_ENET1_RGMII_TX_CTL_LSIO_GPIO6_IO11 0x00000021
+ /* Apalis LCD1_R5 */
+ IMX8QM_ENET1_RGMII_TXC_LSIO_GPIO6_IO10 0x00000021
+ /* Apalis LCD1_R4 */
+ IMX8QM_ENET1_RGMII_TXD0_LSIO_GPIO6_IO12 0x00000021
+ /* Apalis LCD1_R3 */
+ IMX8QM_ENET1_RGMII_TXD1_LSIO_GPIO6_IO13 0x00000021
+ /* Apalis LCD1_R2 */
+ IMX8QM_ENET1_RGMII_TXD2_LSIO_GPIO6_IO14 0x00000021
+ >;
+ };
+
+ /* Apalis LCD1_ */
+ pinctrl_qspi1a_gpios: qspi1agpiosgrp {
+ fsl,pins = <
+ /* Apalis LCD1_B0 */
+ IMX8QM_QSPI1A_DATA0_LSIO_GPIO4_IO26 0x00000021
+ /* Apalis LCD1_B1 */
+ IMX8QM_QSPI1A_DATA1_LSIO_GPIO4_IO25 0x00000021
+ /* Apalis LCD1_B2 */
+ IMX8QM_QSPI1A_DATA2_LSIO_GPIO4_IO24 0x00000021
+ /* Apalis LCD1_B3 */
+ IMX8QM_QSPI1A_DATA3_LSIO_GPIO4_IO23 0x00000021
+ /* Apalis LCD1_B5 */
+ IMX8QM_QSPI1A_DQS_LSIO_GPIO4_IO22 0x00000021
+ /* Apalis LCD1_B7 */
+ IMX8QM_QSPI1A_SCLK_LSIO_GPIO4_IO21 0x00000021
+ /* Apalis LCD1_B4 */
+ IMX8QM_QSPI1A_SS0_B_LSIO_GPIO4_IO19 0x00000021
+ /* Apalis LCD1_B6 */
+ IMX8QM_QSPI1A_SS1_B_LSIO_GPIO4_IO20 0x00000021
+ >;
+ };
+
+ /* Apalis LCD1_ */
+ pinctrl_sim0_gpios: sim0gpiosgrp {
+ fsl,pins = <
+ /* Apalis LCD1_G5 */
+ IMX8QM_SIM0_CLK_LSIO_GPIO0_IO00 0x00000021
+ /* Apalis LCD1_G3 */
+ IMX8QM_SIM0_GPIO0_00_LSIO_GPIO0_IO05 0x00000021
+ /* Apalis TS_5 */
+ IMX8QM_SIM0_IO_LSIO_GPIO0_IO02 0x00000021
+ /* Apalis LCD1_G4 */
+ IMX8QM_SIM0_RST_LSIO_GPIO0_IO01 0x00000021
+ >;
+ };
+
+ /* Apalis MMC1_CD# */
+ pinctrl_mmc1_cd: mmc1cdgrp {
+ fsl,pins = <
+ IMX8QM_ESAI1_TX1_LSIO_GPIO2_IO09 0x00000021
+ >;
+ };
+
+ /* Apalis MMC1 */
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ IMX8QM_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041
+ IMX8QM_USDHC1_CMD_CONN_USDHC1_CMD 0x00000021
+ IMX8QM_USDHC1_DATA0_CONN_USDHC1_DATA0 0x00000021
+ IMX8QM_USDHC1_DATA1_CONN_USDHC1_DATA1 0x00000021
+ IMX8QM_USDHC1_DATA2_CONN_USDHC1_DATA2 0x00000021
+ IMX8QM_USDHC1_DATA3_CONN_USDHC1_DATA3 0x00000021
+ IMX8QM_USDHC1_DATA4_CONN_USDHC1_DATA4 0x00000021
+ IMX8QM_USDHC1_DATA5_CONN_USDHC1_DATA5 0x00000021
+ IMX8QM_USDHC1_DATA6_CONN_USDHC1_DATA6 0x00000021
+ IMX8QM_USDHC1_DATA7_CONN_USDHC1_DATA7 0x00000021
+ /* On-module PMIC use */
+ IMX8QM_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x00000021
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ IMX8QM_USDHC1_CLK_CONN_USDHC1_CLK 0x06000040
+ IMX8QM_USDHC1_CMD_CONN_USDHC1_CMD 0x00000020
+ IMX8QM_USDHC1_DATA0_CONN_USDHC1_DATA0 0x00000020
+ IMX8QM_USDHC1_DATA1_CONN_USDHC1_DATA1 0x00000020
+ IMX8QM_USDHC1_DATA2_CONN_USDHC1_DATA2 0x00000020
+ IMX8QM_USDHC1_DATA3_CONN_USDHC1_DATA3 0x00000020
+ IMX8QM_USDHC1_DATA4_CONN_USDHC1_DATA4 0x00000020
+ IMX8QM_USDHC1_DATA5_CONN_USDHC1_DATA5 0x00000020
+ IMX8QM_USDHC1_DATA6_CONN_USDHC1_DATA6 0x00000020
+ IMX8QM_USDHC1_DATA7_CONN_USDHC1_DATA7 0x00000020
+ /* On-module PMIC use */
+ IMX8QM_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x00000020
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ IMX8QM_USDHC1_CLK_CONN_USDHC1_CLK 0x06000040
+ IMX8QM_USDHC1_CMD_CONN_USDHC1_CMD 0x00000020
+ IMX8QM_USDHC1_DATA0_CONN_USDHC1_DATA0 0x00000020
+ IMX8QM_USDHC1_DATA1_CONN_USDHC1_DATA1 0x00000020
+ IMX8QM_USDHC1_DATA2_CONN_USDHC1_DATA2 0x00000020
+ IMX8QM_USDHC1_DATA3_CONN_USDHC1_DATA3 0x00000020
+ IMX8QM_USDHC1_DATA4_CONN_USDHC1_DATA4 0x00000020
+ IMX8QM_USDHC1_DATA5_CONN_USDHC1_DATA5 0x00000020
+ IMX8QM_USDHC1_DATA6_CONN_USDHC1_DATA6 0x00000020
+ IMX8QM_USDHC1_DATA7_CONN_USDHC1_DATA7 0x00000020
+ /* On-module PMIC use */
+ IMX8QM_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x00000020
+ >;
+ };
+
+ /* Apalis PWM1 */
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ IMX8QM_GPT1_COMPARE_LSIO_PWM2_OUT 0x00000020
+ >;
+ };
+
+ /* Apalis PWM2 */
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ IMX8QM_GPT0_COMPARE_LSIO_PWM3_OUT 0x00000020
+ >;
+ };
+
+ /* Apalis PWM3 */
+ pinctrl_pwm0: pwm0grp {
+ fsl,pins = <
+ IMX8QM_UART0_RTS_B_LSIO_PWM0_OUT 0x00000020
+ >;
+ };
+
+ /* Apalis PWM4 */
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ IMX8QM_UART0_CTS_B_LSIO_PWM1_OUT 0x00000020
+ >;
+ };
+
+ /* Apalis SATA1_ACT# */
+ pinctrl_sata1_act: sata1actgrp {
+ fsl,pins = <
+ IMX8QM_ESAI1_TX0_LSIO_GPIO2_IO08 0x00000021
+ >;
+ };
+
+ /* Apalis SD1_CD# */
+ pinctrl_sd1_cd: sd1cdgrp {
+ fsl,pins = <
+ IMX8QM_USDHC2_CD_B_LSIO_GPIO4_IO12 0x00000021
+ >;
+ };
+
+ /* Apalis SD1 */
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ IMX8QM_USDHC2_CLK_CONN_USDHC2_CLK 0x06000041
+ IMX8QM_USDHC2_CMD_CONN_USDHC2_CMD 0x00000021
+ IMX8QM_USDHC2_DATA0_CONN_USDHC2_DATA0 0x00000021
+ IMX8QM_USDHC2_DATA1_CONN_USDHC2_DATA1 0x00000021
+ IMX8QM_USDHC2_DATA2_CONN_USDHC2_DATA2 0x00000021
+ IMX8QM_USDHC2_DATA3_CONN_USDHC2_DATA3 0x00000021
+ /* On-module PMIC use */
+ IMX8QM_USDHC2_VSELECT_CONN_USDHC2_VSELECT 0x00000021
+ >;
+ };
+
+ pinctrl_touchctrl_idle: touchctrl_idle {
+ fsl,pins = <
+ IMX8QM_ADC_IN4_LSIO_GPIO3_IO22 0x00000021
+ IMX8QM_ADC_IN5_LSIO_GPIO3_IO23 0x00000021
+ IMX8QM_ADC_IN6_LSIO_GPIO3_IO24 0x00000021
+ IMX8QM_ADC_IN7_LSIO_GPIO3_IO25 0x00000021
+ >;
+ };
+
+ pinctrl_touchctrl_gpios: touchctrl_gpios {
+ fsl,pins = <
+ IMX8QM_ESAI1_FSR_LSIO_GPIO2_IO04 0x00000021
+ IMX8QM_ESAI1_FST_LSIO_GPIO2_IO05 0x00000041
+ IMX8QM_SPI3_SCK_LSIO_GPIO2_IO17 0x00000021
+ IMX8QM_SPI3_CS1_LSIO_GPIO2_IO21 0x00000041
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+ fsl,pins = <
+ IMX8QM_USDHC2_CLK_CONN_USDHC2_CLK 0x06000041
+ IMX8QM_USDHC2_CMD_CONN_USDHC2_CMD 0x00000021
+ IMX8QM_USDHC2_DATA0_CONN_USDHC2_DATA0 0x00000021
+ IMX8QM_USDHC2_DATA1_CONN_USDHC2_DATA1 0x00000021
+ IMX8QM_USDHC2_DATA2_CONN_USDHC2_DATA2 0x00000021
+ IMX8QM_USDHC2_DATA3_CONN_USDHC2_DATA3 0x00000021
+ /* On-module PMIC use */
+ IMX8QM_USDHC2_VSELECT_CONN_USDHC2_VSELECT 0x00000021
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+ fsl,pins = <
+ IMX8QM_USDHC2_CLK_CONN_USDHC2_CLK 0x06000041
+ IMX8QM_USDHC2_CMD_CONN_USDHC2_CMD 0x00000021
+ IMX8QM_USDHC2_DATA0_CONN_USDHC2_DATA0 0x00000021
+ IMX8QM_USDHC2_DATA1_CONN_USDHC2_DATA1 0x00000021
+ IMX8QM_USDHC2_DATA2_CONN_USDHC2_DATA2 0x00000021
+ IMX8QM_USDHC2_DATA3_CONN_USDHC2_DATA3 0x00000021
+ /* On-module PMIC use */
+ IMX8QM_USDHC2_VSELECT_CONN_USDHC2_VSELECT 0x00000021
+ >;
+ };
+
+ /* Apalis SPDIF */
+ pinctrl_spdif0: spdif0grp {
+ fsl,pins = <
+ IMX8QM_SPDIF0_TX_AUD_SPDIF0_TX 0xc6000040
+ IMX8QM_SPDIF0_RX_AUD_SPDIF0_RX 0xc6000040
+ >;
+ };
+
+ /* Apalis SPI1 */
+ pinctrl_lpspi0: lpspi0grp {
+ fsl,pins = <
+ IMX8QM_SPI0_SCK_DMA_SPI0_SCK 0x0600004c
+ IMX8QM_SPI0_SDO_DMA_SPI0_SDO 0x0600004c
+ IMX8QM_SPI0_SDI_DMA_SPI0_SDI 0x0600004c
+ IMX8QM_SPI0_CS0_LSIO_GPIO3_IO05 0x0600004c
+ >;
+ };
+
+ /* Apalis SPI2 */
+ pinctrl_lpspi2: lpspi2grp {
+ fsl,pins = <
+ IMX8QM_SPI2_SCK_DMA_SPI2_SCK 0x0600004c
+ IMX8QM_SPI2_SDO_DMA_SPI2_SDO 0x0600004c
+ IMX8QM_SPI2_SDI_DMA_SPI2_SDI 0x0600004c
+ IMX8QM_SPI2_CS0_LSIO_GPIO3_IO10 0x0600004c
+ >;
+ };
+
+ /* Apalis TS_1 */
+ pinctrl_mlb_gpios: mlbgpiosgrp {
+ fsl,pins = <
+ IMX8QM_MLB_CLK_LSIO_GPIO3_IO27 0x00000021
+ >;
+ };
+
+ /* Apalis TS_2 */
+ pinctrl_lvds0_i2c0_gpio: lvds0i2c0gpio {
+ fsl,pins = <
+ IMX8QM_LVDS0_I2C0_SCL_LSIO_GPIO1_IO06 0x00000021
+ >;
+ };
+
+ /* Apalis TS_3 */
+ pinctrl_mipi_dsi_0_1_en: mipi_dsi_0_1_en {
+ fsl,pins = <
+ IMX8QM_LVDS0_I2C0_SDA_LSIO_GPIO1_IO07 0x00000021
+ >;
+ };
+
+ /* Apalis TS_4 */
+ pinctrl_mipi_dsi1_gpios: mipidsi1gpiosgrp {
+ fsl,pins = <
+ IMX8QM_MIPI_DSI1_GPIO0_00_LSIO_GPIO1_IO22 0x00000021
+ >;
+ };
+
+ /* Apalis TS_6 */
+ pinctrl_usdhc1_gpios: usdhc1gpiosgrp {
+ fsl,pins = <
+ IMX8QM_USDHC1_STROBE_LSIO_GPIO5_IO23 0x00000021
+ >;
+ };
+
+ /* Apalis UART1 */
+ pinctrl_lpuart1: lpuart1grp {
+ fsl,pins = <
+ IMX8QM_UART1_RX_DMA_UART1_RX 0x06000020
+ IMX8QM_UART1_TX_DMA_UART1_TX 0x06000020
+ IMX8QM_UART1_CTS_B_DMA_UART1_CTS_B 0x06000020
+ IMX8QM_UART1_RTS_B_DMA_UART1_RTS_B 0x06000020
+ >;
+ };
+
+ /* Apalis UART1_ */
+ pinctrl_lpuart1ctrl: lpuart1ctrlgrp {
+ fsl,pins = <
+ /* Apalis UART1_DTR */
+ IMX8QM_M40_I2C0_SCL_LSIO_GPIO0_IO06 0x00000021
+ /* Apalis UART1_DSR */
+ IMX8QM_M40_I2C0_SDA_LSIO_GPIO0_IO07 0x00000021
+ /* Apalis UART1_DCD */
+ IMX8QM_M41_I2C0_SCL_LSIO_GPIO0_IO10 0x00000021
+ /* Apalis UART1_RI */
+ IMX8QM_M41_I2C0_SDA_LSIO_GPIO0_IO11 0x00000021
+ >;
+ };
+
+ /* Apalis UART2 */
+ pinctrl_lpuart3: lpuart3grp {
+ fsl,pins = <
+ IMX8QM_LVDS1_I2C1_SCL_DMA_UART3_TX 0x06000020
+ IMX8QM_LVDS1_I2C1_SDA_DMA_UART3_RX 0x06000020
+ IMX8QM_ENET1_RGMII_TXD3_DMA_UART3_RTS_B 0x06000020
+ IMX8QM_ENET1_RGMII_RXC_DMA_UART3_CTS_B 0x06000020
+ >;
+ };
+
+ /* Apalis UART3 */
+ pinctrl_lpuart0: lpuart0grp {
+ fsl,pins = <
+ IMX8QM_UART0_RX_DMA_UART0_RX 0x06000020
+ IMX8QM_UART0_TX_DMA_UART0_TX 0x06000020
+ >;
+ };
+
+ /* Apalis UART4 */
+ pinctrl_lpuart2: lpuart2grp {
+ fsl,pins = <
+ IMX8QM_LVDS0_I2C1_SCL_DMA_UART2_TX 0x06000020
+ IMX8QM_LVDS0_I2C1_SDA_DMA_UART2_RX 0x06000020
+ >;
+ };
+
+ /* Apalis USBH_EN */
+ pinctrl_usbh_en: usbhen {
+ fsl,pins = <
+ IMX8QM_USB_SS3_TC1_LSIO_GPIO4_IO04 0x00000021
+ >;
+ };
+
+ /* Apalis USBH_OC# */
+ pinctrl_gpio_usbh_oc_n: gpiousbhocn {
+ fsl,pins = <
+ IMX8QM_USB_SS3_TC3_LSIO_GPIO4_IO06 0x04000021
+ >;
+ };
+
+ /* Apalis USBO1 */
+ pinctrl_usbotg1: usbotg1 {
+ fsl,pins = <
+ /* Apalis USBO1_EN */
+ IMX8QM_USB_SS3_TC0_CONN_USB_OTG1_PWR 0x00000021
+ /* Apalis USBO1_OC# */
+ IMX8QM_USB_SS3_TC2_CONN_USB_OTG1_OC 0x04000021
+ >;
+ };
+
+ /* Apalis WAKE1_MICO */
+ pinctrl_gpio_keys: gpio-keys {
+ fsl,pins = <
+ IMX8QM_SPI3_CS0_LSIO_GPIO2_IO20 0x06700021
+ >;
+ };
+
+ /* On-module eMMC */
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD 0x00000021
+ IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000021
+ IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000021
+ IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000021
+ IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000021
+ IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4 0x00000021
+ IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5 0x00000021
+ IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6 0x00000021
+ IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7 0x00000021
+ IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE 0x06000041
+ IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x00000021
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000040
+ IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD 0x00000020
+ IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000020
+ IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000020
+ IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000020
+ IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000020
+ IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4 0x00000020
+ IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5 0x00000020
+ IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6 0x00000020
+ IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7 0x00000020
+ IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE 0x06000040
+ IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x00000020
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000040
+ IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD 0x00000020
+ IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000020
+ IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000020
+ IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000020
+ IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000020
+ IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4 0x00000020
+ IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5 0x00000020
+ IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6 0x00000020
+ IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7 0x00000020
+ IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE 0x06000040
+ IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x00000020
+ >;
+ };
+
+ /* On-module Gigabit Ethernet PHY Micrel KSZ9031 for Apalis GLAN */
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB_PAD 0x000014a0 /* Use pads in 3.3V mode */
+ IMX8QM_ENET0_MDC_CONN_ENET0_MDC 0x06000020
+ IMX8QM_ENET0_MDIO_CONN_ENET0_MDIO 0x06000020
+ IMX8QM_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x06000020
+ IMX8QM_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC 0x06000020
+ IMX8QM_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x06000020
+ IMX8QM_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x06000020
+ IMX8QM_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2 0x06000020
+ IMX8QM_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3 0x06000020
+ IMX8QM_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC 0x06000020
+ IMX8QM_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x06000020
+ IMX8QM_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x06000020
+ IMX8QM_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x06000020
+ IMX8QM_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2 0x06000020
+ IMX8QM_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3 0x06000020
+ IMX8QM_ENET0_REFCLK_125M_25M_CONN_ENET0_REFCLK_125M_25M 0x06000020
+ /* On-module ETH_RESET# */
+ IMX8QM_LVDS1_GPIO01_LSIO_GPIO1_IO11 0x06000020
+ /* On-module ETH_INT# */
+ IMX8QM_MIPI_CSI1_MCLK_OUT_LSIO_GPIO1_IO29 0x04000060
+ >;
+ };
+
+ pinctrl_fec1_sleep: fec1-sleepgrp {
+ fsl,pins = <
+ IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB_PAD 0x000014a0
+ IMX8QM_ENET0_MDC_LSIO_GPIO4_IO14 0x04000040
+ IMX8QM_ENET0_MDIO_LSIO_GPIO4_IO13 0x04000040
+ IMX8QM_ENET0_RGMII_TX_CTL_LSIO_GPIO5_IO31 0x04000040
+ IMX8QM_ENET0_RGMII_TXC_LSIO_GPIO5_IO30 0x04000040
+ IMX8QM_ENET0_RGMII_TXD0_LSIO_GPIO6_IO00 0x04000040
+ IMX8QM_ENET0_RGMII_TXD1_LSIO_GPIO6_IO01 0x04000040
+ IMX8QM_ENET0_RGMII_TXD2_LSIO_GPIO6_IO02 0x04000040
+ IMX8QM_ENET0_RGMII_TXD3_LSIO_GPIO6_IO03 0x04000040
+ IMX8QM_ENET0_RGMII_RXC_LSIO_GPIO6_IO04 0x04000040
+ IMX8QM_ENET0_RGMII_RX_CTL_LSIO_GPIO6_IO05 0x04000040
+ IMX8QM_ENET0_RGMII_RXD0_LSIO_GPIO6_IO06 0x04000040
+ IMX8QM_ENET0_RGMII_RXD1_LSIO_GPIO6_IO07 0x04000040
+ IMX8QM_ENET0_RGMII_RXD2_LSIO_GPIO6_IO08 0x04000040
+ IMX8QM_ENET0_RGMII_RXD3_LSIO_GPIO6_IO09 0x04000040
+ IMX8QM_ENET0_REFCLK_125M_25M_LSIO_GPIO4_IO15 0x04000040
+ IMX8QM_LVDS1_GPIO01_LSIO_GPIO1_IO11 0x04000040
+ IMX8QM_MIPI_CSI1_MCLK_OUT_LSIO_GPIO1_IO29 0x04000040
+ >;
+ };
+
+ /* On-module HDMI_CTRL */
+ pinctrl_hdmi_ctrl: hdmictrlgrp {
+ fsl,pins = <
+ IMX8QM_MIPI_CSI1_GPIO0_00_LSIO_GPIO1_IO30 0x00000061
+ >;
+ };
+
+ /* On-module I2C */
+ pinctrl_lpi2c1: lpi2c1grp {
+ fsl,pins = <
+ IMX8QM_GPT0_CLK_DMA_I2C1_SCL 0x04000020
+ IMX8QM_GPT0_CAPTURE_DMA_I2C1_SDA 0x04000020
+ >;
+ };
+
+ /* On-module I2S SGTL5000 for Apalis Analogue Audio */
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ IMX8QM_SAI1_TXD_AUD_SAI1_TXD 0xc600006c
+ IMX8QM_SAI1_RXD_AUD_SAI1_RXD 0xc600004c
+ IMX8QM_SAI1_TXC_AUD_SAI1_TXC 0xc600004c
+ IMX8QM_SAI1_TXFS_AUD_SAI1_TXFS 0xc600004c
+ >;
+ };
+
+ /* On-module I2S SGTL5000 SYS_MCLK */
+ pinctrl_sgtl5000: sgtl5000grp {
+ fsl,pins = <
+ IMX8QM_MCLK_OUT0_AUD_ACM_MCLK_OUT0 0xc600004c
+ >;
+ };
+
+ /* On-module PCIe_CLK_EN1 */
+ pinctrl_pcie_sata_refclk: pciesatarefclkgrp {
+ fsl,pins = <
+ IMX8QM_USDHC2_WP_LSIO_GPIO4_IO11 0x00000021
+ >;
+ };
+
+ /* On-module PCIe_CLK_EN2 */
+ pinctrl_pcie_wifi_refclk: pciewifirefclkgrp {
+ fsl,pins = <
+ IMX8QM_ESAI1_TX3_RX2_LSIO_GPIO2_IO11 0x00000021
+ >;
+ };
+
+ /* On-module PCIe_Wi-Fi */
+ pinctrl_pcieb: pciebgrp {
+ fsl,pins = <
+ IMX8QM_PCIE_CTRL1_CLKREQ_B_LSIO_GPIO4_IO30 0x00000021
+ IMX8QM_PCIE_CTRL1_WAKE_B_LSIO_GPIO4_IO31 0x00000021
+ IMX8QM_PCIE_CTRL1_PERST_B_LSIO_GPIO5_IO00 0x00000021
+ >;
+ };
+
+ /* On-module RESET_MOCI#_DRV */
+ pinctrl_reset_moci: resetmocigrp {
+ fsl,pins = <
+ IMX8QM_SCU_GPIO0_02_LSIO_GPIO0_IO30 0x00000021
+ >;
+ };
+
+ /* On-module USB HSIC HUB */
+ pinctrl_usb3503a: usb3503agrp {
+ fsl,pins = <
+ /* On-module HSIC_HUB_CONNECT */
+ IMX8QM_SCU_GPIO0_03_LSIO_GPIO0_IO31 0x00000041
+ /* On-module HSIC_INT_N */
+ IMX8QM_SCU_GPIO0_05_LSIO_GPIO1_IO01 0x00000021
+ /* On-module HSIC_RESET_N */
+ IMX8QM_SCU_GPIO0_06_LSIO_GPIO1_IO02 0x00000041
+ >;
+ };
+
+ /* On-module USB HSIC HUB (idle) */
+ pinctrl_usb_hsic_idle: usbh1_1 {
+ fsl,pins = <
+ IMX8QM_USB_HSIC0_DATA_CONN_USB_HSIC0_DATA 0xc60000c5
+ IMX8QM_USB_HSIC0_STROBE_CONN_USB_HSIC0_STROBE 0xc60000c5
+ >;
+ };
+
+ /* On-module USB HSIC HUB (active) */
+ pinctrl_usb_hsic_active: usbh1_2 {
+ fsl,pins = <
+ IMX8QM_USB_HSIC0_STROBE_CONN_USB_HSIC0_STROBE 0xc60000d5
+ >;
+ };
+
+ /* On-module Wi-Fi */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ /* On-module Wi-Fi_SUSCLK_32k */
+ IMX8QM_SCU_GPIO0_07_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0x06000021
+ /* On-module Wi-Fi_PCIE_W_DISABLE */
+ IMX8QM_MIPI_CSI0_MCLK_OUT_LSIO_GPIO1_IO24 0x06000021
+ >;
+ };
+
+ pinctrl_wifi_pdn: wifipdngrp {
+ fsl,pins = <
+ /* On-module Wi-Fi_POWER_DOWN */
+ IMX8QM_MIPI_CSI0_GPIO0_01_LSIO_GPIO1_IO28 0x06000021
+ >;
+ };
+ };
+};
+
+&jpegdec {
+ status = "okay";
+};
+
+&jpegenc {
+ status = "okay";
+};
+
+&ldb2_phy {
+ status = "disabled";
+};
+
+&ldb2 {
+ status = "disabled";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "okay";
+
+ port@1 {
+ reg = <1>;
+
+ lvds1_out: endpoint {
+ remote-endpoint = <&panel_lvds_in>;
+ };
+ };
+ };
+};
+
+/* Apalis SPI1 */
+&lpspi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&lsio_gpio3 5 GPIO_ACTIVE_LOW>;
+
+ spidev0: spi@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <4000000>;
+ };
+};
+
+/* Apalis SPI2 */
+&lpspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&lsio_gpio3 10 GPIO_ACTIVE_LOW>;
+
+ spidev1: spi@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <4000000>;
+ };
+};
+
+/* Apalis UART3 */
+&lpuart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart0>;
+};
+
+/* Apalis UART1 */
+&lpuart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart1>;
+};
+
+/* Apalis UART4 */
+&lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart2>;
+};
+
+/* Apalis UART2 */
+&lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart3>;
+};
+
+&lsio_gpio0 {
+ gpio-line-names = "MXM3_279",
+ "MXM3_277",
+ "MXM3_135",
+ "MXM3_203",
+ "MXM3_201",
+ "MXM3_275",
+ "MXM3_110",
+ "MXM3_120",
+ "MXM3_1/GPIO1",
+ "MXM3_3/GPIO2",
+ "MXM3_124",
+ "MXM3_122",
+ "MXM3_5/GPIO3",
+ "MXM3_7/GPIO4",
+ "",
+ "",
+ "MXM3_4",
+ "MXM3_211",
+ "MXM3_209",
+ "MXM3_2",
+ "MXM3_136",
+ "MXM3_134",
+ "MXM3_6",
+ "MXM3_8",
+ "MXM3_112",
+ "MXM3_118",
+ "MXM3_114",
+ "MXM3_116";
+};
+
+&lsio_gpio1 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "MXM3_286",
+ "",
+ "MXM3_87",
+ "MXM3_99",
+ "MXM3_138",
+ "MXM3_140",
+ "MXM3_239",
+ "",
+ "MXM3_281",
+ "MXM3_283",
+ "MXM3_126",
+ "MXM3_132",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_173",
+ "MXM3_175",
+ "MXM3_123";
+};
+
+&lsio_gpio2 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_198",
+ "MXM3_35",
+ "MXM3_164",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_217",
+ "MXM3_215",
+ "",
+ "",
+ "MXM3_193",
+ "MXM3_194",
+ "MXM3_37",
+ "",
+ "MXM3_271",
+ "MXM3_273",
+ "MXM3_195",
+ "MXM3_197",
+ "MXM3_177",
+ "MXM3_179",
+ "MXM3_181",
+ "MXM3_183",
+ "MXM3_185",
+ "MXM3_187";
+
+ /*
+ * Add GPIO2_20 as a wakeup source:
+ * Pin: SC_P_SPI3_CS0 (MXM3_37/WAKE1_MICO)
+ * Type: SC_PAD_WAKEUP_FALL_EDGE
+ * Line: 20
+ */
+ pad-wakeup = <101 5 20>;
+ pad-wakeup-num = <1>;
+};
+
+&lsio_gpio3 {
+ gpio-line-names = "MXM3_191",
+ "",
+ "MXM3_221",
+ "MXM3_225",
+ "MXM3_223",
+ "MXM3_227",
+ "MXM3_200",
+ "MXM3_235",
+ "MXM3_231",
+ "MXM3_229",
+ "MXM3_233",
+ "MXM3_204",
+ "MXM3_196",
+ "",
+ "MXM3_202",
+ "",
+ "",
+ "",
+ "MXM3_305",
+ "MXM3_307",
+ "MXM3_309",
+ "MXM3_311",
+ "MXM3_315",
+ "MXM3_317",
+ "MXM3_319",
+ "MXM3_321",
+ "MXM3_15/GPIO7",
+ "MXM3_63",
+ "MXM3_17/GPIO8",
+ "MXM3_12",
+ "MXM3_14",
+ "MXM3_16";
+};
+
+&lsio_gpio4 {
+ gpio-line-names = "MXM3_18",
+ "MXM3_11/GPIO5",
+ "MXM3_13/GPIO6",
+ "MXM3_274",
+ "MXM3_84",
+ "MXM3_262",
+ "MXM3_96",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_190",
+ "",
+ "",
+ "",
+ "MXM3_269",
+ "MXM3_251",
+ "MXM3_253",
+ "MXM3_295",
+ "MXM3_299",
+ "MXM3_301",
+ "MXM3_297",
+ "MXM3_293",
+ "MXM3_291",
+ "MXM3_289",
+ "MXM3_287";
+};
+
+&lsio_gpio5 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_150",
+ "MXM3_160",
+ "MXM3_162",
+ "MXM3_144",
+ "MXM3_146",
+ "MXM3_148",
+ "MXM3_152",
+ "MXM3_156",
+ "MXM3_158",
+ "MXM3_159",
+ "MXM3_184",
+ "MXM3_180",
+ "MXM3_186",
+ "MXM3_188",
+ "MXM3_176",
+ "MXM3_178";
+};
+
+&lsio_gpio6 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_261",
+ "MXM3_263",
+ "MXM3_259",
+ "MXM3_257",
+ "MXM3_255",
+ "MXM3_128",
+ "MXM3_130",
+ "MXM3_265",
+ "MXM3_249",
+ "MXM3_247",
+ "MXM3_245",
+ "MXM3_243";
+};
+
+&mu_m0{
+ interrupts = <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mu1_m0{
+ interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mu2_m0{
+ interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+};
+
+&mu3_m0{
+ interrupts = <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+};
+
+/* Apalis PCIE1 */
+&pciea {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reset_moci>;
+ clocks = <&pciea_lpcg 0>,
+ <&pciea_lpcg 1>,
+ <&pciea_lpcg 2>,
+ <&phyx2_lpcg 0>,
+ <&phyx2_crr0_lpcg 0>,
+ <&pciea_crr2_lpcg 0>,
+ <&misc_crr5_lpcg 0>,
+ <&pcie_sata_refclk_gate>;
+ clock-names = "pcie", "pcie_bus", "pcie_inbound_axi",
+ "pcie_phy", "phy_per", "pcie_per", "misc_per",
+ "pcie_ext";
+
+ ext_osc = <1>;
+ fsl,max-link-speed = <1>;
+ reset-gpio = <&lsio_gpio0 30 GPIO_ACTIVE_LOW>;
+ vpcie-supply = <&reg_pcie_switch>;
+};
+
+/* On-module Wi-Fi */
+&pcieb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcieb &pinctrl_wifi>;
+ clocks = <&pcieb_lpcg 0>,
+ <&pcieb_lpcg 1>,
+ <&pcieb_lpcg 2>,
+ <&phyx2_lpcg 1>,
+ <&phyx2_lpcg 0>,
+ <&phyx2_crr0_lpcg 0>,
+ <&pcieb_crr3_lpcg 0>,
+ <&pciea_crr2_lpcg 0>,
+ <&misc_crr5_lpcg 0>,
+ <&pcie_wifi_refclk_gate>;
+ clock-names = "pcie", "pcie_bus", "pcie_inbound_axi",
+ "pcie_phy", "pcie_phy_pclk", "phy_per",
+ "pcie_per", "pciex2_per", "misc_per",
+ "pcie_ext";
+ epdev_on-supply = <&reg_module_wifi>;
+ ext_osc = <1>;
+ fsl,max-link-speed = <1>;
+ reset-gpio = <&lsio_gpio5 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&pwm_lvds1 {
+ #pwm-cells = <3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_bkl>;
+};
+
+/* Apalis PWM3, MXM3 pin 6 */
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0>;
+ #pwm-cells = <3>;
+};
+
+/* Apalis PWM4, MXM3 pin 8 */
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ #pwm-cells = <3>;
+};
+
+/* Apalis PWM1, MXM3 pin 2 */
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ #pwm-cells = <3>;
+};
+
+/* Apalis PWM2, MXM3 pin 4 */
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ #pwm-cells = <3>;
+};
+
+&rpmsg0{
+ /*
+ * 64K for one rpmsg instance:
+ */
+ vdev-nums = <2>;
+ reg = <0x0 0x90000000 0x0 0x20000>;
+ memory-region = <&vdevbuffer>;
+};
+
+&rpmsg1{
+ /*
+ * 64K for one rpmsg instance:
+ */
+ vdev-nums = <2>;
+ reg = <0x0 0x90100000 0x0 0x20000>;
+ memory-region = <&vdevbuffer>;
+};
+
+&sai1 {
+ #sound-dai-cells = <0>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai1_lpcg 0>; /* FIXME: should be sai1, original code is 0 */
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+};
+
+/* Apalis SATA1 */
+&sata {
+ clocks = <&sata_lpcg 0>,
+ <&phyx1_lpcg 0>,
+ <&phyx1_lpcg 1>,
+ <&phyx1_lpcg 2>,
+ <&phyx2_crr0_lpcg 0>,
+ <&phyx1_crr1_lpcg 0>,
+ <&pciea_crr2_lpcg 0>,
+ <&pcieb_crr3_lpcg 0>,
+ <&sata_crr4_lpcg 0>,
+ <&misc_crr5_lpcg 0>,
+ <&phyx2_lpcg 0>,
+ <&phyx2_lpcg 1>,
+ <&phyx1_lpcg 3>,
+ <&pcie_sata_refclk_gate>;
+ clock-names = "sata", "sata_ref", "epcs_tx", "epcs_rx",
+ "per_clk0", "per_clk1", "per_clk2",
+ "per_clk3", "per_clk4", "per_clk5",
+ "phy_pclk0", "phy_pclk1", "phy_apbclk",
+ "sata_ext";
+ ext_osc = <1>;
+};
+
+/* Apalis SPDIF1 */
+&spdif0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif0>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>;
+ assigned-clock-rates = <786432000>, <49152000>, <24576000>;
+ status = "okay";
+};
+
+&thermal_zones {
+ pmic-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&tsens IMX_SC_R_PMIC_0>;
+ trips {
+ pmic_alert0: trip0 {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ pmic_crit0: trip1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ cooling_maps_map0: map0 {
+ trip = <&pmic_alert0>;
+ };
+ };
+ };
+};
+
+&usb3phynop1 {
+ status = "okay";
+};
+
+/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
+&usbh1 {
+ pinctrl-names = "idle", "active";
+ pinctrl-0 = <&pinctrl_usb_hsic_idle>;
+ pinctrl-1 = <&pinctrl_usb_hsic_active>;
+ adp-disable;
+ disable-over-current;
+ hnp-disable;
+ srp-disable;
+};
+
+&usbphynop2 {
+ status = "okay";
+};
+
+&usbphy1 {
+ status = "okay";
+};
+
+/* Apalis USBO1 */
+&usbotg1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ adp-disable;
+ ci-disable-lpm;
+ hnp-disable;
+ over-current-active-low;
+ power-active-high;
+ srp-disable;
+};
+
+/* On-module eMMC */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+/* Apalis MMC1 */
+&usdhc2 {
+ bus-width = <8>;
+ cd-gpios = <&lsio_gpio2 9 GPIO_ACTIVE_LOW>; /* Apalis MMC1_CD# */
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_mmc1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_mmc1_cd>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_mmc1_cd>;
+};
+
+/* Apalis SD1 */
+&usdhc3 {
+ bus-width = <4>;
+ cd-gpios = <&lsio_gpio4 12 GPIO_ACTIVE_LOW>; /* Apalis SD1_CD# */
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_sd1_cd>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>, <&pinctrl_sd1_cd>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>, <&pinctrl_sd1_cd>;
+};
+
+&vpu_decoder {
+ compatible = "nxp,imx8qm-b0-vpudec";
+ boot-region = <&decoder_boot>;
+ rpc-region = <&decoder_rpc>;
+ reg-csr = <0x2d080000>;
+ core_type = <2>;
+ status = "okay";
+};
+
+&vpu_ts {
+ compatible = "nxp,imx8qm-b0-vpu-ts";
+ boot-region = <&ts_boot>;
+ reg-csr = <0x2d0b0000>;
+ status = "okay";
+};
+
+&vpu_encoder {
+ compatible = "nxp,imx8qm-b0-vpuenc";
+ boot-region = <&encoder_boot>;
+ rpc-region = <&encoder_rpc>;
+ reserved-region = <&encoder_reserved>;
+ reg-rpc-system = <0x40000000>;
+ resolution-max = <1920 1920>;
+ power-domains = <&pd IMX_SC_R_VPU_ENC_0>, <&pd IMX_SC_R_VPU_ENC_1>,
+ <&pd IMX_SC_R_VPU>;
+ power-domain-names = "vpuenc1", "vpuenc2", "vpu";
+ mbox-names = "enc1_tx0", "enc1_tx1", "enc1_rx",
+ "enc2_tx0", "enc2_tx1", "enc2_rx";
+ mboxes = <&mu1_m0 0 0
+ &mu1_m0 0 1
+ &mu1_m0 1 0
+ &mu2_m0 0 0
+ &mu2_m0 0 1
+ &mu2_m0 1 0>;
+ status = "okay";
+
+ vpu_enc_core0: core0@1020000 {
+ compatible = "fsl,imx8-mu1-vpu-m0";
+ reg = <0x1020000 0x20000>;
+ reg-csr = <0x1090000 0x10000>;
+ interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,vpu_ap_mu_id = <17>;
+ fw-buf-size = <0x200000>;
+ rpc-buf-size = <0x80000>;
+ print-buf-size = <0x80000>;
+ };
+
+ vpu_enc_core1: core1@1040000 {
+ compatible = "fsl,imx8-mu2-vpu-m0";
+ reg = <0x1040000 0x20000>;
+ reg-csr = <0x10A0000 0x10000>;
+ interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,vpu_ap_mu_id = <18>;
+ fw-buf-size = <0x200000>;
+ rpc-buf-size = <0x80000>;
+ print-buf-size = <0x80000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
index 4eb51cad186d..9badc2bfa915 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
@@ -62,6 +62,31 @@ conn_subsys: bus@5b000000 {
reg = <0x5b0d0200 0x200>;
};
+ usbh1: usb@5b0e0000 {
+ compatible = "fsl,imx8qm-usb", "fsl,imx7ulp-usb",
+ "fsl,imx27-usb";
+ reg = <0x5b0e0000 0x200>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
+ phy_type = "hsic";
+ dr_mode = "host";
+ fsl,usbphy = <&usbphynop2>;
+ fsl,usbmisc = <&usbmisc2 0>;
+ clocks = <&usb2_lpcg 0>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ #stream-id-cells = <1>;
+ power-domains = <&pd IMX_SC_R_USB_1>;
+ status = "disabled";
+ };
+
+ usbmisc2: usbmisc@5b0e0200 {
+ #index-cells = <1>;
+ compatible = "fsl,imx7ulp-usbmisc", "fsl,imx6q-usbmisc";
+ reg = <0x5b0e0200 0x200>;
+ };
+
usbphy1: usbphy@0x5b100000 {
compatible = "fsl,imx8qm-usbphy", "fsl,imx7ulp-usbphy",
"fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
@@ -183,6 +208,14 @@ conn_subsys: bus@5b000000 {
status = "disabled";
};
+ usbphynop2: usbphynop2 {
+ compatible = "usb-nop-xceiv";
+ clocks = <&usb2_lpcg 1>;
+ clock-names = "main_clk";
+ power-domains = <&pd IMX_SC_R_USB_0_PHY>;
+ status = "okay";
+ };
+
usbotg3: usb3@5b110000 {
compatible = "Cadence,usb3";
reg = <0x5B110000 0x10000>,
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
index 5e2cc2787716..fcf6fd415950 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
@@ -30,7 +30,7 @@ dma_subsys: bus@5a000000 {
<&spi0_lpcg 1>;
clock-names = "per", "ipg";
assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>;
- assigned-clock-rates = <20000000>;
+ assigned-clock-rates = <60000000>;
power-domains = <&pd IMX_SC_R_SPI_0>;
dma-names = "tx","rx";
dmas = <&edma2 1 0 0>, <&edma2 0 0 1>;
@@ -329,6 +329,7 @@ dma_subsys: bus@5a000000 {
adc0: adc@5a880000 {
compatible = "fsl,imx8qxp-adc";
+ #io-channel-cells = <1>;
reg = <0x5a880000 0x10000>;
interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
@@ -343,6 +344,7 @@ dma_subsys: bus@5a000000 {
adc1: adc@5a890000 {
compatible = "fsl,imx8qxp-adc";
+ #io-channel-cells = <1>;
reg = <0x5a890000 0x10000>;
interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
index f406f6adce31..83bb00300d47 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
@@ -27,6 +27,54 @@ lsio_subsys: bus@5d000000 {
clock-output-names = "lsio_bus_clk";
};
+ pwm0: pwm@5d000000 {
+ compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
+ reg = <0x5d000000 0x10000>;
+ clock-names = "ipg", "per";
+ clocks = <&pwm0_lpcg 4>,
+ <&pwm0_lpcg 1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@5d010000 {
+ compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
+ reg = <0x5d010000 0x10000>;
+ clock-names = "ipg", "per";
+ clocks = <&pwm1_lpcg 4>,
+ <&pwm1_lpcg 1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@5d020000 {
+ compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
+ reg = <0x5d020000 0x10000>;
+ clock-names = "ipg", "per";
+ clocks = <&pwm2_lpcg 4>,
+ <&pwm2_lpcg 1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@5d030000 {
+ compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
+ reg = <0x5d030000 0x10000>;
+ clock-names = "ipg", "per";
+ clocks = <&pwm3_lpcg 4>,
+ <&pwm3_lpcg 1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
lsio_gpio0: gpio@5d080000 {
reg = <0x5d080000 0x10000>;
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h b/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
index cffa8991880d..e7fac56db320 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
+++ b/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
@@ -430,18 +430,26 @@
#define MX8MM_IOMUXC_SAI1_MCLK_SIM_M_HRESP 0x1AC 0x414 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI2_RXFS_SAI2_RX_SYNC 0x1B0 0x418 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI2_RXFS_SAI5_TX_SYNC 0x1B0 0x418 0x4EC 0x1 0x2
+#define MX8MM_IOMUXC_SAI2_RXFS_UART1_TX 0x1B0 0x418 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI2_RXFS_UART1_RX 0x1B0 0x418 0x4F4 0x4 0x2
#define MX8MM_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x1B0 0x418 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI2_RXFS_SIM_M_HSIZE0 0x1B0 0x418 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI2_RXC_SAI2_RX_BCLK 0x1B4 0x41C 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI2_RXC_SAI5_TX_BCLK 0x1B4 0x41C 0x4E8 0x1 0x2
+#define MX8MM_IOMUXC_SAI2_RXC_UART1_RX 0x1B4 0x41C 0x4F4 0x4 0x3
+#define MX8MM_IOMUXC_SAI2_RXC_UART1_TX 0x1B4 0x41C 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x1B4 0x41C 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI2_RXC_SIM_M_HSIZE1 0x1B4 0x41C 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0x1B8 0x420 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI2_RXD0_SAI5_TX_DATA0 0x1B8 0x420 0x000 0x1 0x0
+#define MX8MM_IOMUXC_SAI2_RXD0_UART1_RTS_B 0x1B8 0x420 0x4F0 0x4 0x2
+#define MX8MM_IOMUXC_SAI2_RXD0_UART1_CTS_B 0x1B8 0x420 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI2_RXD0_GPIO4_IO23 0x1B8 0x420 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI2_RXD0_SIM_M_HSIZE2 0x1B8 0x420 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0x1BC 0x424 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI2_TXFS_SAI5_TX_DATA1 0x1BC 0x424 0x000 0x1 0x0
+#define MX8MM_IOMUXC_SAI2_TXFS_UART1_CTS_B 0x1BC 0x424 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI2_TXFS_UART1_RTS_B 0x1BC 0x424 0x4F0 0x4 0x3
#define MX8MM_IOMUXC_SAI2_TXFS_GPIO4_IO24 0x1BC 0x424 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI2_TXFS_SIM_M_HWRITE 0x1BC 0x424 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0x1C0 0x428 0x000 0x0 0x0
@@ -464,21 +472,37 @@
#define MX8MM_IOMUXC_SAI3_RXC_SAI3_RX_BCLK 0x1D0 0x438 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI3_RXC_GPT1_CLK 0x1D0 0x438 0x000 0x1 0x0
#define MX8MM_IOMUXC_SAI3_RXC_SAI5_RX_BCLK 0x1D0 0x438 0x4D0 0x2 0x2
+#define MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_CTS_B 0x1D0 0x438 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_RTS_B 0x1D0 0x438 0x4F8 0x4 0x2
+#define MX8MM_IOMUXC_SAI3_RXC_UART2_DTE_CTS_B 0x1D0 0x438 0x4F8 0x4 0x2
+#define MX8MM_IOMUXC_SAI3_RXC_UART2_DTE_RTS_B 0x1D0 0x438 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x1D0 0x438 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_RXC_TPSMP_HTRANS1 0x1D0 0x438 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0x1D4 0x43C 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI3_RXD_GPT1_COMPARE1 0x1D4 0x43C 0x000 0x1 0x0
#define MX8MM_IOMUXC_SAI3_RXD_SAI5_RX_DATA0 0x1D4 0x43C 0x4D4 0x2 0x2
+#define MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x1D4 0x43C 0x4F8 0x4 0x3
+#define MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_CTS_B 0x1D4 0x43C 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI3_RXD_UART2_DTE_RTS_B 0x1D4 0x43C 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI3_RXD_UART2_DTE_CTS_B 0x1D4 0x43C 0x4F8 0x4 0x3
#define MX8MM_IOMUXC_SAI3_RXD_GPIO4_IO30 0x1D4 0x43C 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_RXD_TPSMP_HDATA0 0x1D4 0x43C 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0x1D8 0x440 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_GPT1_CAPTURE2 0x1D8 0x440 0x000 0x1 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_SAI5_RX_DATA1 0x1D8 0x440 0x4D8 0x2 0x2
+#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX 0x1D8 0x440 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_TX 0x1D8 0x440 0x4FC 0x4 0x2
+#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DTE_RX 0x1D8 0x440 0x4FC 0x4 0x2
+#define MX8MM_IOMUXC_SAI3_TXFS_UART2_DTE_TX 0x1D8 0x440 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_GPIO4_IO31 0x1D8 0x440 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_TXFS_TPSMP_HDATA1 0x1D8 0x440 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0x1DC 0x444 0x000 0x0 0x0
#define MX8MM_IOMUXC_SAI3_TXC_GPT1_COMPARE2 0x1DC 0x444 0x000 0x1 0x0
#define MX8MM_IOMUXC_SAI3_TXC_SAI5_RX_DATA2 0x1DC 0x444 0x4DC 0x2 0x2
+#define MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_RX 0x1DC 0x444 0x000 0x4 0x0
+#define MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX 0x1DC 0x444 0x4FC 0x4 0x3
+#define MX8MM_IOMUXC_SAI3_TXC_UART2_DTE_RX 0x1DC 0x444 0x4FC 0x4 0x3
+#define MX8MM_IOMUXC_SAI3_TXC_UART2_DTE_TX 0x1DC 0x444 0x000 0x4 0x0
#define MX8MM_IOMUXC_SAI3_TXC_GPIO5_IO0 0x1DC 0x444 0x000 0x5 0x0
#define MX8MM_IOMUXC_SAI3_TXC_TPSMP_HDATA2 0x1DC 0x444 0x000 0x7 0x0
#define MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0x1E0 0x448 0x000 0x0 0x0
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-dahlia.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-dahlia.dtsi
new file mode 100755
index 000000000000..78bec5e3c94b
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-dahlia.dtsi
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+#include "imx8mm-verdin-dev.dtsi"
+
+&gpio_expander_21 {
+ status = "disabled";
+};
+
+&sound_card {
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "Headphone Jack", "MICBIAS",
+ "IN1L", "Headphone Jack";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
new file mode 100755
index 000000000000..2c3872f3a8f3
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+/* Verdin SPI_1 */
+&ecspi2 {
+ status = "okay";
+
+ spidev20: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ status = "okay";
+ };
+};
+
+/* EEPROM on display adapter boards */
+&eeprom_display_adapter {
+ status = "okay";
+};
+
+/* EEPROM on Verdin Development board */
+&eeprom_carrier_board {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+/* Verdin QSPI_1 */
+&flexspi {
+ status = "okay";
+};
+
+&gpio_expander_21 {
+ status = "okay";
+};
+
+/* Current measurement into module VCC */
+&hwmon {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+/* Verdin PCIE_1 */
+&pcie0 {
+ status = "okay";
+};
+
+/* Verdin PWM_1 */
+&pwm2 {
+ status = "okay";
+};
+
+/* Verdin PWM_2 */
+&pwm3 {
+ status = "okay";
+};
+
+/* VERDIN I2S_1 */
+&sai2 {
+ status = "okay";
+};
+
+/* Verdin UART_3 */
+&uart1 {
+ status = "okay";
+};
+
+/* Verdin UART_1 */
+&uart2 {
+ status = "okay";
+};
+
+/* Verdin UART_2 */
+&uart3 {
+ status = "okay";
+};
+
+/* Verdin USB_1 */
+&usbotg1 {
+ status = "okay";
+};
+
+/* Verdin USB_2 */
+&usbotg2 {
+ status = "okay";
+};
+
+/* Verdin SD_1 */
+&usdhc2 {
+ status = "okay";
+};
+
+/* Audio Codec */
+&wm8904_1a {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dahlia.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dahlia.dts
new file mode 100755
index 000000000000..8bfcac726dd3
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dahlia.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin.dtsi"
+#include "imx8mm-verdin-nonwifi.dtsi"
+#include "imx8mm-verdin-dahlia.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini on Dahlia Board";
+ compatible = "toradex,verdin-imx8mm-nonwifi-dahlia",
+ "toradex,verdin-imx8mm-nonwifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dev.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dev.dts
new file mode 100755
index 000000000000..6f3e76283e54
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dev.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin.dtsi"
+#include "imx8mm-verdin-nonwifi.dtsi"
+#include "imx8mm-verdin-dev.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini on Verdin Development Board";
+ compatible = "toradex,verdin-imx8mm-nonwifi-dev",
+ "toradex,verdin-imx8mm-nonwifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dahlia.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dahlia.dts
new file mode 100755
index 000000000000..7c5c319737b7
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dahlia.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin-v1.1.dtsi"
+#include "imx8mm-verdin-nonwifi.dtsi"
+#include "imx8mm-verdin-dahlia.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini V1.1 on Dahlia Board";
+ compatible = "toradex,verdin-imx8mm-nonwifi-v1.1-dahlia",
+ "toradex,verdin-imx8mm-nonwifi-dahlia",
+ "toradex,verdin-imx8mm-nonwifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dev.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dev.dts
new file mode 100755
index 000000000000..0ec570e098fd
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-v1.1-dev.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin-v1.1.dtsi"
+#include "imx8mm-verdin-nonwifi.dtsi"
+#include "imx8mm-verdin-dev.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini V1.1 on Verdin Development Board";
+ compatible = "toradex,verdin-imx8mm-nonwifi-v1.1-dev",
+ "toradex,verdin-imx8mm-nonwifi-dev",
+ "toradex,verdin-imx8mm-nonwifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi.dtsi
new file mode 100755
index 000000000000..c488a4111cdb
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi.dtsi
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+&gpio3 {
+ gpio-line-names = "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_64",
+ "SODIMM_21",
+ "SODIMM_206",
+ "SODIMM_76",
+ "SODIMM_56",
+ "SODIMM_58",
+ "SODIMM_60",
+ "SODIMM_62",
+ "SODIMM_162",
+ "SODIMM_164",
+ "SODIMM_166",
+ "SODIMM_168",
+ "SODIMM_66",
+ "SODIMM_17",
+ "",
+ "SODIMM_156",
+ "SODIMM_160",
+ "SODIMM_244",
+ "SODIMM_250",
+ "SODIMM_48",
+ "SODIMM_44",
+ "SODIMM_42",
+ "SODIMM_46";
+};
+
+&gpio4 {
+ gpio-line-names = "SODIMM_102",
+ "SODIMM_90",
+ "SODIMM_92",
+ "SODIMM_94",
+ "SODIMM_96",
+ "SODIMM_100",
+ "SODIMM_148",
+ "SODIMM_152",
+ "SODIMM_154",
+ "SODIMM_174",
+ "SODIMM_120",
+ "SODIMM_104",
+ "SODIMM_106",
+ "SODIMM_108",
+ "SODIMM_112",
+ "SODIMM_114",
+ "SODIMM_116",
+ "SODIMM_150",
+ "SODIMM_118",
+ "",
+ "SODIMM_88",
+ "SODIMM_149",
+ "SODIMM_147",
+ "SODIMM_36",
+ "SODIMM_32",
+ "SODIMM_30",
+ "SODIMM_34",
+ "SODIMM_38",
+ "SODIMM_252",
+ "SODIMM_133",
+ "SODIMM_135",
+ "SODIMM_129";
+};
+
+&usdhc3 {
+ bus-width = <4>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-v1.1.dtsi
new file mode 100755
index 000000000000..12d05b137a7c
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-v1.1.dtsi
@@ -0,0 +1,1310 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2019-2020 Toradex
+ */
+
+#include "dt-bindings/pwm/pwm.h"
+#include "imx8mm.dtsi"
+
+/ {
+ chosen {
+ bootargs = "console=ttymxc0,115200 earlycon";
+ stdout-path = &uart1;
+ };
+
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &snvs_rtc;
+ };
+
+ /* fixed clock dedicated to SPI CAN controller */
+ clk20m: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ wakeup {
+ debounce-interval = <10>;
+ gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
+ label = "Wake-Up";
+ linux,code = <KEY_WAKEUP>;
+ wakeup-source;
+ };
+ };
+
+ /* Carrier Board Supply */
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "REG_3P3V";
+ };
+
+ reg_aux_usb: regulator-aux-usb {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "REG_AUX_USB";
+ };
+
+ reg_mipi_phy: regulator-mipi-phy {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <1000000>;
+ regulator-min-microvolt = <1000000>;
+ regulator-name = "REG_MIPI_PHY";
+ };
+
+ reg_ethphy: regulator-ethphy {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+ off-on-delay = <500000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_eth>;
+ regulator-boot-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "V3.3_ETH";
+ startup-delay-us = <200000>;
+ };
+
+ reg_usb_otg1_vbus: regulator-usb-otg1 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ /* Verdin USB1_EN */
+ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb1_en>;
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb_otg1_vbus";
+ };
+
+ reg_usb_otg2_vbus: regulator-usb-otg2 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ /* Verdin USB2_EN */
+ gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb2_en>;
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb_otg2_vbus";
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_pwr_en>;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "V3.3_SD";
+ startup-delay-us = <2000>;
+ off-on-delay = <100000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ rpmsg_reserved: rpmsg@b8000000 {
+ no-map;
+ reg = <0 0xb8000000 0 0x400000>;
+ };
+ };
+
+ sound_card: sound-card {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,name = "imx8mm-wm8904";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "Microphone Jack", "MICBIAS",
+ "IN1L", "Microphone Jack",
+ "IN1R", "Microphone Jack";
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Headphone", "Headphone Jack",
+ "Line", "Line In Jack";
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&wm8904_1a>;
+ clocks = <&clk IMX8MM_CLK_SAI2_ROOT>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai2>;
+ };
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&buck2_reg>;
+};
+
+/* Verdin SPI_1 */
+&ecspi2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+};
+
+/* On-module CAN controller 1 & 2 */
+&ecspi3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>,
+ <&gpio1 5 GPIO_ACTIVE_LOW>;
+ /* This property is required, even if marked as obsolete in the doku */
+ fsl,spi-num-chipselects = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ status = "okay";
+
+ can1: can@0 {
+ compatible = "microchip,mcp2517fd";
+ clocks = <&clk20m>;
+ gpio-controller;
+ interrupt-parent = <&gpio1>;
+ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
+ microchip,clock-allways-on;
+ microchip,clock-out-div = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1_int>;
+ reg = <0>;
+ spi-max-frequency = <2000000>;
+ };
+
+ can2: can@1 {
+ compatible = "microchip,mcp2517fd";
+ clocks = <&clk20m>;
+ gpio-controller;
+ interrupt-parent = <&gpio1>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can2_int>;
+ reg = <1>;
+ spi-max-frequency = <2000000>;
+ /* not assembled */
+ status = "disabled";
+ };
+};
+
+&fec1 {
+ fsl,magic-packet;
+ phy-handle = <&ethphy0>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&reg_ethphy>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_fec1>;
+ pinctrl-1 = <&pinctrl_fec1_sleep>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@7 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ interrupt-parent = <&gpio1>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ micrel,led-mode = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+/* Verdin QSPI_1 */
+&flexspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexspi0>;
+#if 0
+ flash0: mt25qu256aba@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,mt25qu256aba";
+ reg = <0>;
+ spi-max-frequency = <80000000>;
+ spi-nor,ddr-quad-read-dummy = <6>;
+ };
+#endif
+};
+
+&gpio1 {
+ gpio-line-names = "SODIMM_216",
+ "SODIMM_19",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_220",
+ "SODIMM_222",
+ "",
+ "SODIMM_218",
+ "SODIMM_155",
+ "SODIMM_157",
+ "SODIMM_185",
+ "SODIMM_187";
+};
+
+&gpio2 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_84",
+ "SODIMM_78",
+ "SODIMM_74",
+ "SODIMM_80",
+ "SODIMM_82",
+ "SODIMM_70",
+ "SODIMM_72";
+};
+
+&gpio5 {
+ gpio-line-names = "SODIMM_131",
+ "",
+ "SODIMM_91",
+ "SODIMM_16",
+ "SODIMM_15",
+ "SODIMM_208",
+ "SODIMM_137",
+ "SODIMM_139",
+ "SODIMM_141",
+ "SODIMM_143",
+ "SODIMM_196",
+ "SODIMM_200",
+ "SODIMM_198",
+ "SODIMM_202",
+ "",
+ "",
+ "SODIMM_55",
+ "SODIMM_53",
+ "SODIMM_95",
+ "SODIMM_93",
+ "SODIMM_14",
+ "SODIMM_12",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_210",
+ "SODIMM_212",
+ "SODIMM_151",
+ "SODIMM_153";
+
+ ctrl_sleep_moci {
+ gpio-hog;
+ gpios = <1 GPIO_ACTIVE_HIGH>;
+ line-name = "CTRL_SLEEP_MOCI#";
+ output-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
+ };
+};
+
+/* On-module I2C */
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ pmic: pca9450@25 {
+ reg = <0x25>;
+ compatible = "nxp,pca9450";
+ /* PMIC PCA9450 PMIC_nINT GPIO1_IO3 */
+ pinctrl-0 = <&pinctrl_pmic>;
+ gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;
+ i2c-lt-en = <0x101>;
+
+ regulators {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pca9450,pmic-buck2-uses-i2c-dvs;
+ /* Run/Standby voltage */
+ pca9450,pmic-buck2-dvs-voltage = <950000>, <850000>;
+
+ buck1_reg: regulator@0 {
+ reg = <0>;
+ regulator-compatible = "buck1";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <2187500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ };
+
+ buck2_reg: regulator@1 {
+ reg = <1>;
+ regulator-compatible = "buck2";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <2187500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ };
+
+ buck3_reg: regulator@2 {
+ reg = <2>;
+ regulator-compatible = "buck3";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <2187500>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck4_reg: regulator@3 {
+ reg = <3>;
+ regulator-compatible = "buck4";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5_reg: regulator@4 {
+ reg = <4>;
+ regulator-compatible = "buck5";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6_reg: regulator@5 {
+ reg = <5>;
+ regulator-compatible = "buck6";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: regulator@6 {
+ reg = <6>;
+ regulator-compatible = "ldo1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@7 {
+ reg = <7>;
+ regulator-compatible = "ldo2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3_reg: regulator@8 {
+ reg = <8>;
+ regulator-compatible = "ldo3";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4_reg: regulator@9 {
+ reg = <9>;
+ regulator-compatible = "ldo4";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo5_reg: regulator@10 {
+ reg = <10>;
+ regulator-compatible = "ldo5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+
+ rtc_i2c: rtc@32 {
+ compatible = "epson,rx8130";
+ reg = <0x32>;
+ };
+
+ adc@49 {
+ compatible = "ti,ads1015";
+ reg = <0x49>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Verdin I2C_1 (ADC_4 - ADC_3) */
+ channel@0 {
+ reg = <0>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 (ADC_4 - ADC_1) */
+ channel@1 {
+ reg = <1>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 (ADC_3 - ADC_1) */
+ channel@2 {
+ reg = <2>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 (ADC_2 - ADC_1) */
+ channel@3 {
+ reg = <3>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 ADC_4 */
+ channel@4 {
+ reg = <4>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 ADC_3 */
+ channel@5 {
+ reg = <5>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 ADC_2 */
+ channel@6 {
+ reg = <6>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+
+ /* Verdin I2C_1 ADC_1 */
+ channel@7 {
+ reg = <7>;
+ ti,gain = <2>;
+ ti,datarate = <4>;
+ };
+ };
+
+ eeprom@50 {
+ compatible = "st,24c02";
+ pagesize = <16>;
+ reg = <0x50>;
+ };
+};
+
+/* Verdin I2C_3_HDMI N/A */
+
+/* Verdin I2C_4_CSI */
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+/* Verdin I2C_1 */
+&i2c4 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
+ /* Audio Codec */
+ wm8904_1a: codec@1a {
+ compatible = "wlf,wm8904";
+ #sound-dai-cells = <0>;
+ clocks = <&clk IMX8MM_CLK_SAI2_ROOT>;
+ clock-names = "mclk";
+ reg = <0x1a>;
+ status = "disabled";
+ DCVDD-supply = <&reg_3p3v>;
+ DBVDD-supply = <&reg_3p3v>;
+ AVDD-supply = <&reg_3p3v>;
+ CPVDD-supply = <&reg_3p3v>;
+ MICVDD-supply = <&reg_3p3v>;
+ };
+
+ gpio_expander_21: gpio-expander@21 {
+ compatible = "nxp,pcal6416";
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0x21>;
+ status = "disabled";
+ vcc-supply = <&reg_3p3v>;
+ };
+
+ /* Current measurement into module VCC */
+ hwmon: hwmon@40 {
+ compatible = "ti,ina219";
+ reg = <0x40>;
+ shunt-resistor = <10000>;
+ status = "disabled";
+ };
+
+ /* EEPROM on display adapter (MIPI DSI Display Adapter) */
+ eeprom_display_adapter: eeprom@50 {
+ compatible = "st,24c02";
+ pagesize = <16>;
+ reg = <0x50>;
+ status = "disabled";
+ };
+
+ /* EEPROM on carrier board */
+ eeprom_carrier_board: eeprom@57 {
+ compatible = "st,24c02";
+ pagesize = <16>;
+ reg = <0x57>;
+ status = "disabled";
+ };
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&mu {
+ status = "okay";
+};
+
+/* Verdin PCIE_1 */
+&pcie0 {
+ clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>,
+ <&clk IMX8MM_CLK_PCIE1_AUX>,
+ <&clk IMX8MM_CLK_PCIE1_PHY>,
+ <&clk IMX8MM_CLK_PCIE1_PHY>;
+ clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
+ epdev_on-supply = <&reg_3p3v>;
+ ext_osc = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie0>;
+ reserved-region = <&rpmsg_reserved>;
+ reset-gpio = <&gpio3 19 GPIO_ACTIVE_LOW>;
+};
+
+/* Verdin PWM_1 */
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_2>;
+ #pwm-cells = <3>;
+};
+
+/* Verdin PWM_2 */
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_3>;
+ #pwm-cells = <3>;
+};
+
+/* VERDIN I2S_1 */
+&sai2 {
+ #sound-dai-cells = <0>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ assigned-clocks = <&clk IMX8MM_CLK_SAI2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+/* Verdin UART_3 */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+};
+
+/* Verdin UART_1 */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ fsl,uart-has-rtscts;
+};
+
+/* Verdin UART_2 */
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ fsl,uart-has-rtscts;
+};
+
+/* Verdin UART_4 */
+/*
+ * resource allocated to M4 by default, must not be accessed from A-35 or you
+ * get an OOPS
+ */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+};
+
+&usbmisc1 {
+ vbus-wakeup-supply = <&reg_aux_usb>;
+};
+
+&usbmisc2 {
+ vbus-wakeup-supply = <&reg_aux_usb>;
+};
+
+/* Verdin USB_1 */
+&usbotg1 {
+ adp-disable;
+ dr_mode = "otg";
+ hnp-disable;
+ over-current-active-low;
+ picophy,dc-vol-level-adjust = <7>;
+ picophy,pre-emp-curr-control = <3>;
+ srp-disable;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+};
+
+/* Verdin USB_2 */
+&usbotg2 {
+ dr_mode = "host";
+ over-current-active-low;
+ picophy,dc-vol-level-adjust = <7>;
+ picophy,pre-emp-curr-control = <3>;
+ vbus-supply = <&reg_usb_otg2_vbus>;
+};
+
+&usbphynop1 {
+ vcc-supply = <&reg_aux_usb>;
+};
+
+&usbphynop2 {
+ vcc-supply = <&reg_aux_usb>;
+};
+
+/* On-module eMMC */
+&usdhc1 {
+ bus-width = <8>;
+ keep-power-in-suspend;
+ non-removable;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ pm-ignore-notify;
+ status = "okay";
+ /* TODO Strobe */
+};
+
+/* Verdin SD_1 */
+&usdhc2 {
+ bus-width = <4>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_cd>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_cd>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_cd>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+};
+
+&vpu_g1 {
+ status = "okay";
+};
+
+&vpu_g2 {
+ status = "okay";
+};
+
+&vpu_h1 {
+ status = "okay";
+};
+
+&wdog1 {
+ fsl,ext-reset-output;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio7>,
+ <&pinctrl_gpio8>, <&pinctrl_gpio_hog1>,
+ <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>,
+ <&pinctrl_sai5>, <&pinctrl_pmic_tpm_ena>;
+
+ pinctrl_can1_int: can1intgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x1c4 /* CAN_1_SPI_INT#_1.8V */
+ >;
+ };
+
+ pinctrl_can2_int: can2intgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x1c4 /* CAN_2_SPI_INT#_1.8V */
+ >;
+ };
+
+ pinctrl_ctrl_sleep_moci: ctrlsleepmocigrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_TXD_GPIO5_IO1 0x1c4 /* CTRL_SLEEP_MOCI */
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x4 /* SODIMM 196 */
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x4 /* SODIMM 200 */
+ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x1c4 /* SODIMM 198 */
+ MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x1c4 /* SODIMM 202 */
+ >;
+ };
+
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART1_RXD_ECSPI3_SCLK 0x4
+ MX8MM_IOMUXC_UART1_TXD_ECSPI3_MOSI 0x4
+ MX8MM_IOMUXC_UART2_RXD_ECSPI3_MISO 0x1c4
+ MX8MM_IOMUXC_UART2_TXD_GPIO5_IO25 0x1c4
+ MX8MM_IOMUXC_GPIO1_IO05_GPIO1_IO5 0x1c4
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x1c4
+ >;
+ };
+
+ pinctrl_fec1_sleep: fec1-sleepgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MM_IOMUXC_ENET_TD3_GPIO1_IO18 0x1f
+ MX8MM_IOMUXC_ENET_TD2_GPIO1_IO19 0x1f
+ MX8MM_IOMUXC_ENET_TD1_GPIO1_IO20 0x1f
+ MX8MM_IOMUXC_ENET_TD0_GPIO1_IO21 0x1f
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MM_IOMUXC_ENET_TXC_GPIO1_IO23 0x1f
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MM_IOMUXC_ENET_TX_CTL_GPIO1_IO22 0x1f
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x184
+ >;
+ };
+
+ pinctrl_flexspi0: flexspi0grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_ALE_QSPI_A_SCLK 0x1c2 /* SODIMM 52 */
+ MX8MM_IOMUXC_NAND_CE0_B_QSPI_A_SS0_B 0x82 /* SODIMM 54 */
+ MX8MM_IOMUXC_NAND_CE1_B_QSPI_A_SS1_B 0x82 /* SODIMM 64 */
+ MX8MM_IOMUXC_NAND_DQS_QSPI_A_DQS 0x82 /* SODIMM 66 */
+ MX8MM_IOMUXC_NAND_DATA00_QSPI_A_DATA0 0x82 /* SODIMM 56 */
+ MX8MM_IOMUXC_NAND_DATA01_QSPI_A_DATA1 0x82 /* SODIMM 58 */
+ MX8MM_IOMUXC_NAND_DATA02_QSPI_A_DATA2 0x82 /* SODIMM 60 */
+ MX8MM_IOMUXC_NAND_DATA03_QSPI_A_DATA3 0x82 /* SODIMM 62 */
+ >;
+ };
+
+ pinctrl_gpio3: gpio3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART3_RXD_GPIO5_IO26 0x184 /* SODIMM 210 */
+ >;
+ };
+
+ pinctrl_gpio4: gpio4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART3_TXD_GPIO5_IO27 0x184 /* SODIMM 212 */
+ >;
+ };
+
+ pinctrl_gpio5: gpio5grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x184 /* SODIMM 216 */
+ >;
+ };
+
+ pinctrl_gpio6: gpio6grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x184 /* SODIMM 218 */
+ >;
+ };
+
+ pinctrl_gpio7: gpio7grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x184 /* SODIMM 220 */
+ >;
+ };
+
+ pinctrl_gpio8: gpio8grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x184 /* SODIMM 222 */
+ >;
+ };
+
+ pinctrl_gpio_hog1: gpiohog1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x1c4 /* SODIMM 88 */
+ MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x1c4 /* SODIMM 90 */
+ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x1c4 /* SODIMM 92 */
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x1c4 /* SODIMM 94 */
+ MX8MM_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x1c4 /* SODIMM 96 */
+ MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x1c4 /* SODIMM 100 */
+ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x1c4 /* SODIMM 102 */
+ MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x1c4 /* SODIMM 104 */
+ MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x1c4 /* SODIMM 106 */
+ MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x1c4 /* SODIMM 108 */
+ MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x1c4 /* SODIMM 112 */
+ MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x1c4 /* SODIMM 114 */
+ MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x1c4 /* SODIMM 116 */
+ MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x1c4 /* SODIMM 118 */
+ MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10 0x1c4 /* SODIMM 120 */
+ >;
+ };
+
+ pinctrl_gpio_hog2: gpiohog2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2 0x1c4 /* SODIMM 91 */
+ >;
+ };
+
+ pinctrl_gpio_hog3: gpiohog3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x1c4 /* SODIMM 157 */
+ MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x1c4 /* SODIMM 187 */
+ >;
+ };
+
+ pinctrl_gpio_keys: gpiokeysgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x1c4 /* SODIMM 252 */
+ >;
+ };
+
+ /* On-module I2C */
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c6 /* PMIC_I2C_SCL */
+ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c6 /* PMIC_I2C_SDA */
+ >;
+ };
+
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c6 /* PMIC_I2C_SCL */
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c6 /* PMIC_I2C_SDA */
+ >;
+ };
+
+ /* Verdin I2C_4_CSI */
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c6 /* SODIMM 55 */
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c6 /* SODIMM 53 */
+ >;
+ };
+
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c6 /* SODIMM 55 */
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c6 /* SODIMM 53 */
+ >;
+ };
+
+ /* Verdin I2C_2_DSI */
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c6 /* SODIMM 95 */
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c6 /* SODIMM 93 */
+ >;
+ };
+
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c6 /* SODIMM 95 */
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c6 /* SODIMM 93 */
+ >;
+ };
+
+ /* Verdin I2C_1 */
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c6 /* SODIMM 14 */
+ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c6 /* SODIMM 12 */
+ >;
+ };
+
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_GPIO5_IO20 0x400001c6 /* SODIMM 14 */
+ MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21 0x400001c6 /* SODIMM 12 */
+ >;
+ };
+
+ /* Verdin MEZ_DSI_1_BKL_EN */
+ pinctrl_mez_dsi_1_bkl_en: mezdsi1bklengrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_CE2_B_GPIO3_IO3 0x1c4 /* SODIMM 21 */
+ >;
+ };
+
+ /* Verdin MEZ_DSI_1_INT HPD (pulled-down as active-high) */
+ pinctrl_mez_dsi_1_int_hpd: mezdsi1inthpdgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_RE_B_GPIO3_IO15 0x184 /* SODIMM 17 */
+ >;
+ };
+
+ /* Verdin MEZ_DSI_1_INT# (pulled-up as active-low) */
+ pinctrl_mez_dsi_1_int_n: mezdsi1intngrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_RE_B_GPIO3_IO15 0x1c4 /* SODIMM 17 */
+ >;
+ };
+
+ /* MEZ_GPIO_1 shared with MEZ_DSI_1_INT on Verdin DSI to HDMI Display Adapter */
+ pinctrl_mez_gpio1: mezgpio1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_CE3_B_GPIO3_IO4 0x184 /* SODIMM 206 */
+ >;
+ };
+
+ pinctrl_mez_gpio2: mezgpio2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x1c4 /* SODIMM 208 */
+ >;
+ };
+
+ pinctrl_pcie0: pcie0grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXFS_GPIO3_IO19 0x6 /* SODIMM 244 */
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x6 /* PMIC_EN_PCIe_CLK */
+ >;
+ };
+
+ pinctrl_pmic: pmicirqgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41 /* PMIC_INT# */
+ >;
+ };
+
+ pinctrl_pwm_1: pwm1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO01_PWM1_OUT 0x6 /* SODIMM 19 */
+ >;
+ };
+
+ pinctrl_pwm_2: pwm2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SPDIF_RX_PWM2_OUT 0x6 /* SODIMM 15 */
+ >;
+ };
+
+ pinctrl_pwm_3: pwm3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SPDIF_TX_PWM3_OUT 0x6 /* SODIMM 16 */
+ >;
+ };
+
+ pinctrl_reg_eth: regethgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_WP_GPIO2_IO20 0x184 /* PMIC_EN_ETH */
+ >;
+ };
+
+ pinctrl_reg_usb1_en: regusb1engrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x184 /* SODIMM 155 */
+ >;
+ };
+
+ pinctrl_reg_usb2_en: regusb2engrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x184 /* SODIMM 185 */
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0xd6 /* SODIMM 32 */
+ MX8MM_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0xd6 /* SODIMM 30 */
+ MX8MM_IOMUXC_SAI2_MCLK_SAI2_MCLK 0xd6 /* SODIMM 38 */
+ MX8MM_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0xd6 /* SODIMM 36 */
+ MX8MM_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0xd6 /* SODIMM 34 */
+ >;
+ };
+
+ pinctrl_sai5: sai5grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXD0_SAI5_RX_DATA0 0xd6 /* SODIMM 48 */
+ MX8MM_IOMUXC_SAI5_RXD1_SAI5_TX_SYNC 0xd6 /* SODIMM 44 */
+ MX8MM_IOMUXC_SAI5_RXD2_SAI5_TX_BCLK 0xd6 /* SODIMM 42 */
+ MX8MM_IOMUXC_SAI5_RXD3_SAI5_TX_DATA0 0xd6 /* SODIMM 46 */
+ >;
+ };
+
+ /* currently unused ctrl signal for SE050 or ATTPM20P */
+ pinctrl_pmic_tpm_ena: pmictpmenagrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x1c4 /* PMIC_TPM_ENA */
+ >;
+ };
+
+ pinctrl_tsp: tspgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x140 /* SODIMM 148 */
+ MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x140 /* SODIMM 152 */
+ MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x140 /* SODIMM 154 */
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x140 /* SODIMM 179 */
+ MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x140 /* SODIMM 150 */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI2_RXFS_UART1_TX 0x1c4 /* SODIMM 149 */
+ MX8MM_IOMUXC_SAI2_RXC_UART1_RX 0x1c4 /* SODIMM 147 */
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_TX 0x1c4 /* SODIMM 129 */
+ MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_RX 0x1c4 /* SODIMM 131 */
+ MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_CTS_B 0x1c4 /* SODIMM 133 */
+ MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x1c4 /* SODIMM 135 */
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_SCLK_UART3_DCE_RX 0x1c4 /* SODIMM 137 */
+ MX8MM_IOMUXC_ECSPI1_MOSI_UART3_DCE_TX 0x1c4 /* SODIMM 139 */
+ MX8MM_IOMUXC_ECSPI1_MISO_UART3_DCE_CTS_B 0x1c4 /* SODIMM 141 */
+ MX8MM_IOMUXC_ECSPI1_SS0_UART3_DCE_RTS_B 0x1c4 /* SODIMM 143 */
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x1c4 /* SODIMM 151 */
+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x1c4 /* SODIMM 153 */
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x190
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d0
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d0
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d0
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d0
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d0
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d0
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d0
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d0
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d0
+ MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0x1d1
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x194
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d4
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d4
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d4
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d4
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d4
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d4
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d4
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d4
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d4
+ MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0x1d1
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x196
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d6
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d6
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d6
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d6
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d6
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d6
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d6
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d6
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d6
+ MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0x1d1
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x196
+ >;
+ };
+
+ pinctrl_usdhc2_cd: usdhc2cdgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x1c4 /* SODIMM 84 */
+ >;
+ };
+
+ pinctrl_usdhc2_pwr_en: usdhc2pwrengrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_CLE_GPIO3_IO5 0x184 /* SODIMM 76 */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190 /* SODIMM 78 */
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0 /* SODIMM 74 */
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0 /* SODIMM 80 */
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0 /* SODIMM 82 */
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0 /* SODIMM 70 */
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0 /* SODIMM 72 */
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ /* On-module Wi-Fi/BT or SDHC interface on the X52 extention slot */
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x190
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x194
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x196
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 /* PMIC_WDI */
+ >;
+ };
+
+ pinctrl_wifi_ctrl: wifictrlgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16 0x1c4 /* WIFI_WKUP_BT */
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x1c4 /* WIFI_WKUP_WLAN */
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x1c4 /* WIFI_W_WKUP_HOST */
+ >;
+ };
+
+ pinctrl_wifi_i2s: bti2sgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_RXD4_SAI6_TX_BCLK 0xd6 /* WIFI_TX_BCLK */
+ MX8MM_IOMUXC_SAI1_RXD5_SAI6_TX_DATA0 0xd6 /* WIFI_TX_DATA0 */
+ MX8MM_IOMUXC_SAI1_RXD6_SAI6_TX_SYNC 0xd6 /* WIFI_TX_SYNC */
+ MX8MM_IOMUXC_SAI1_TXD5_SAI6_RX_DATA0 0xd6 /* WIFI_RX_DATA0 */
+ >;
+ };
+
+ pinctrl_wifi_pwr_en: wifipwrengrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x184 /* PMIC_EN_WIFI */
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dahlia.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dahlia.dts
new file mode 100755
index 000000000000..452c06e44a21
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dahlia.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin.dtsi"
+#include "imx8mm-verdin-wifi.dtsi"
+#include "imx8mm-verdin-dahlia.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini WB on Dahlia Board";
+ compatible = "toradex,verdin-imx8mm-wifi-dahlia",
+ "toradex,verdin-imx8mm-wifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dev.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dev.dts
new file mode 100755
index 000000000000..c9df17fa48c5
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-dev.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin.dtsi"
+#include "imx8mm-verdin-wifi.dtsi"
+#include "imx8mm-verdin-dev.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini WB on Verdin Development Board";
+ compatible = "toradex,verdin-imx8mm-wifi-dev",
+ "toradex,verdin-imx8mm-wifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dahlia.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dahlia.dts
new file mode 100755
index 000000000000..dbc1b4b15c37
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dahlia.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin-v1.1.dtsi"
+#include "imx8mm-verdin-wifi.dtsi"
+#include "imx8mm-verdin-dahlia.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini WB V1.1 on Dahlia Board";
+ compatible = "toradex,verdin-imx8mm-wifi-v1.1-dahlia",
+ "toradex,verdin-imx8mm-wifi-dahlia",
+ "toradex,verdin-imx8mm-wifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dev.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dev.dts
new file mode 100755
index 000000000000..0aec23ac9806
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-v1.1-dev.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin-v1.1.dtsi"
+#include "imx8mm-verdin-wifi.dtsi"
+#include "imx8mm-verdin-dev.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini WB V1.1 on Verdin Development Board";
+ compatible = "toradex,verdin-imx8mm-wifi-v1.1-dev",
+ "toradex,verdin-imx8mm-wifi-dev",
+ "toradex,verdin-imx8mm-wifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi.dtsi
new file mode 100755
index 000000000000..75c44efe8ac8
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi.dtsi
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2020 Toradex
+ */
+
+/ {
+ reg_wifi_en: regulator-wifi-en {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 25 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi_pwr_en>;
+ regulator-name = "V3.3_WI-FI";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <2000>;
+ };
+};
+
+/* On-module Wi-Fi */
+&usdhc3 {
+ bus-width = <4>;
+ cap-power-off-card;
+ keep-power-in-suspend;
+ non-removable;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_wifi_ctrl>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>, <&pinctrl_wifi_ctrl>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>, <&pinctrl_wifi_ctrl>;
+ vmmc-supply = <&reg_wifi_en>;
+ wifi-host;
+ status = "okay";
+};
+
+&gpio3 {
+ gpio-line-names = "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_64",
+ "SODIMM_21",
+ "SODIMM_206",
+ "SODIMM_76",
+ "SODIMM_56",
+ "SODIMM_58",
+ "SODIMM_60",
+ "SODIMM_62",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_66",
+ "SODIMM_17",
+ "",
+ "",
+ "",
+ "SODIMM_244",
+ "SODIMM_250",
+ "SODIMM_48",
+ "SODIMM_44",
+ "SODIMM_42",
+ "SODIMM_46";
+};
+
+&gpio4 {
+ gpio-line-names = "SODIMM_102",
+ "SODIMM_90",
+ "SODIMM_92",
+ "SODIMM_94",
+ "SODIMM_96",
+ "SODIMM_100",
+ "",
+ "",
+ "",
+ "SODIMM_174",
+ "SODIMM_120",
+ "SODIMM_104",
+ "SODIMM_106",
+ "SODIMM_108",
+ "SODIMM_112",
+ "SODIMM_114",
+ "SODIMM_116",
+ "",
+ "SODIMM_118",
+ "",
+ "SODIMM_88",
+ "SODIMM_149",
+ "SODIMM_147",
+ "SODIMM_36",
+ "SODIMM_32",
+ "SODIMM_30",
+ "SODIMM_34",
+ "SODIMM_38",
+ "SODIMM_252",
+ "SODIMM_133",
+ "SODIMM_135",
+ "SODIMM_129";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
new file mode 100644
index 000000000000..464b85291db0
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+#include "imx8mm-verdin-v1.1.dtsi"
+
+/ {
+ pcie0_refclk: pcie0-refclk {
+ compatible = "gpio-gate-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ /* on-module ext oscillator */
+ enable-gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&i2c1 {
+ /delete-node/ pca9450@25;
+
+ pmic_v10: bd71837@4b {
+ compatible = "rohm,bd71837";
+ interrupt-parent = <&gpio1>;
+ /* PMIC BD71837 PMIC_nINT GPIO1_IO3 */
+ interrupts = <3 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&pinctrl_pmic>;
+ reg = <0x4b>;
+ rohm,reset-snvs-powered;
+
+ gpo {
+ rohm,drv = <0x0C>; /* 0b0000_1100 all gpos with cmos output mode */
+ };
+
+ regulators {
+ buck1_reg: BUCK1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1300000>;
+ regulator-min-microvolt = <700000>;
+ regulator-name = "BUCK1";
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1300000>;
+ regulator-min-microvolt = <700000>;
+ regulator-name = "BUCK2";
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck5_reg: BUCK5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1350000>;
+ regulator-min-microvolt = <700000>;
+ regulator-name = "BUCK5";
+ };
+
+ buck6_reg: BUCK6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3000000>;
+ regulator-name = "BUCK6";
+ };
+
+ buck7_reg: BUCK7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1995000>;
+ regulator-min-microvolt = <1605000>;
+ regulator-name = "BUCK7";
+ };
+
+ buck8_reg: BUCK8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1400000>;
+ regulator-min-microvolt = <800000>;
+ regulator-name = "BUCK8";
+ };
+
+ ldo1_reg: LDO1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1900000>;
+ regulator-min-microvolt = <1600000>;
+ regulator-name = "LDO1";
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <900000>;
+ regulator-min-microvolt = <800000>;
+ regulator-name = "LDO2";
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-name = "LDO3";
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1800000>;
+ regulator-min-microvolt = <900000>;
+ regulator-name = "LDO4";
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "LDO5";
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1800000>;
+ regulator-min-microvolt = <900000>;
+ regulator-name = "LDO6";
+ };
+ };
+ };
+
+ adc: adc@34 {
+ compatible = "maxim,max11607";
+ reg = <0x34>;
+ vcc-supply = <&ldo5_reg>;
+ };
+};
+
+/* Verdin PCIE_1 */
+&pcie0 {
+ clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>,
+ <&clk IMX8MM_CLK_PCIE1_AUX>,
+ <&clk IMX8MM_CLK_PCIE1_PHY>,
+ <&pcie0_refclk>;
+ ext_osc = <1>;
+};
+
+&iomuxc {
+ pinctrl_ctrl_force_off_moci: ctrlforceoffgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x1c4 /* SODIMM 250 */
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x190
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d0
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d0
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d0
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d0
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d0
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d0
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d0
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d0
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d0
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x194
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d4
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d4
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d4
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d4
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d4
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d4
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d4
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d4
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d4
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x196
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d6
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d6
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d6
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d6
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d6
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d6
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d6
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d6
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d6
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x196
+ >;
+ };
+
+ pinctrl_wifi_ctrl: wifictrlgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16 0x1c4 /* WIFI_WKUP_BT */
+ MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x1c4 /* WIFI_WKUP_WLAN */
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x1c4 /* WIFI_W_WKUP_HOST */
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis-eval.dts b/arch/arm64/boot/dts/freescale/imx8qm-apalis-eval.dts
new file mode 100644
index 000000000000..ebff51c16c03
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis-eval.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019-2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qm-apalis.dtsi"
+#include "imx8-apalis-eval.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QM/QP on Apalis Evaluation Board";
+ compatible = "toradex,apalis-imx8-eval",
+ "toradex,apalis-imx8",
+ "fsl,imx8qm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis-ixora-v1.1.dts b/arch/arm64/boot/dts/freescale/imx8qm-apalis-ixora-v1.1.dts
new file mode 100644
index 000000000000..91bc4435fb49
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis-ixora-v1.1.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019-2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qm-apalis.dtsi"
+#include "imx8-apalis-ixora-v1.1.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QM/QP on Apalis Ixora V1.1 Carrier Board";
+ compatible = "toradex,apalis-imx8qp-ixora-v1.1",
+ "toradex,apalis-imx8-ixora-v1.1",
+ "toradex,apalis-imx8qp-ixora",
+ "toradex,apalis-imx8-ixora",
+ "toradex,apalis-imx8qp",
+ "toradex,apalis-imx8",
+ "fsl,imx8qm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-eval.dts b/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-eval.dts
new file mode 100644
index 000000000000..6589cdb2251b
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-eval.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qm-apalis-v1.1.dtsi"
+#include "imx8-apalis-eval.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QM V1.1 on Apalis Evaluation Board";
+ compatible = "toradex,apalis-imx8-v1.1-eval",
+ "toradex,apalis-imx8-eval",
+ "toradex,apalis-imx8",
+ "fsl,imx8qm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-ixora-v1.1.dts b/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-ixora-v1.1.dts
new file mode 100644
index 000000000000..579a27fb5662
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1-ixora-v1.1.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019-2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qm-apalis-v1.1.dtsi"
+#include "imx8-apalis-ixora-v1.1.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QM V1.1 on Apalis Ixora V1.1 Carrier Board";
+ compatible = "toradex,apalis-imx8-v1.1-ixora-v1.1",
+ "toradex,apalis-imx8-v1.1-ixora",
+ "toradex,apalis-imx8-v1.1",
+ "toradex,apalis-imx8",
+ "fsl,imx8qm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1.dtsi
new file mode 100644
index 000000000000..65188f479d03
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis-v1.1.dtsi
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+#include <dt-bindings/pwm/pwm.h>
+#include "imx8qm.dtsi"
+#include "imx8-apalis-v1.1.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QM V1.1";
+ compatible = "toradex,apalis-imx8-v1.1",
+ "toradex,apalis-imx8",
+ "fsl,imx8qm";
+};
+
+&cooling_maps_map0 {
+ cooling-device =
+ <&A53_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A72_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A72_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+};
+
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi
new file mode 100644
index 000000000000..1612e4bae594
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-apalis.dtsi
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2017-2020 Toradex
+ */
+
+#include "imx8qm-apalis-v1.1.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QM";
+ compatible = "toradex,apalis-imx8",
+ "fsl,imx8qm";
+};
+
+/delete-node/ &pcie_wifi_refclk;
+/delete-node/ &pcie_wifi_refclk_gate;
+
+&ethphy0 {
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+};
+
+&lsio_gpio0 {
+ gpio-line-names = "MXM3_279",
+ "MXM3_277",
+ "MXM3_135",
+ "MXM3_203",
+ "MXM3_201",
+ "MXM3_275",
+ "MXM3_110",
+ "MXM3_120",
+ "MXM3_1/GPIO1",
+ "MXM3_3/GPIO2",
+ "MXM3_124",
+ "MXM3_122",
+ "MXM3_5/GPIO3",
+ "MXM3_7/GPIO4",
+ "",
+ "",
+ "MXM3_4",
+ "MXM3_211",
+ "MXM3_209",
+ "MXM3_2",
+ "MXM3_136",
+ "MXM3_134",
+ "MXM3_6",
+ "MXM3_8",
+ "MXM3_112",
+ "MXM3_118",
+ "MXM3_114",
+ "MXM3_116";
+};
+
+&lsio_gpio1 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "MXM3_286",
+ "",
+ "MXM3_87",
+ "MXM3_99",
+ "MXM3_138",
+ "MXM3_140",
+ "MXM3_239",
+ "",
+ "MXM3_281",
+ "MXM3_283",
+ "MXM3_126",
+ "MXM3_132",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_173",
+ "MXM3_175",
+ "MXM3_123";
+};
+
+&lsio_gpio2 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_198",
+ "MXM3_35",
+ "MXM3_164",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_217",
+ "MXM3_215",
+ "",
+ "",
+ "MXM3_193",
+ "MXM3_194",
+ "MXM3_37",
+ "",
+ "MXM3_271",
+ "MXM3_273",
+ "MXM3_195",
+ "MXM3_197",
+ "MXM3_177",
+ "MXM3_179",
+ "MXM3_181",
+ "MXM3_183",
+ "MXM3_185",
+ "MXM3_187";
+};
+
+&lsio_gpio3 {
+ gpio-line-names = "MXM3_191",
+ "",
+ "MXM3_221",
+ "MXM3_225",
+ "MXM3_223",
+ "MXM3_227",
+ "MXM3_200",
+ "MXM3_235",
+ "MXM3_231",
+ "MXM3_229",
+ "MXM3_233",
+ "MXM3_204",
+ "MXM3_196",
+ "",
+ "MXM3_202",
+ "",
+ "",
+ "",
+ "MXM3_305",
+ "MXM3_307",
+ "MXM3_309",
+ "MXM3_311",
+ "MXM3_315",
+ "MXM3_317",
+ "MXM3_319",
+ "MXM3_321",
+ "MXM3_15/GPIO7",
+ "MXM3_63",
+ "MXM3_17/GPIO8",
+ "MXM3_12",
+ "MXM3_14",
+ "MXM3_16";
+};
+
+&lsio_gpio4 {
+ gpio-line-names = "MXM3_18",
+ "MXM3_11/GPIO5",
+ "MXM3_13/GPIO6",
+ "MXM3_274",
+ "MXM3_84",
+ "MXM3_262",
+ "MXM3_96",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_190",
+ "",
+ "",
+ "",
+ "MXM3_269",
+ "MXM3_251",
+ "MXM3_253",
+ "MXM3_295",
+ "MXM3_299",
+ "MXM3_301",
+ "MXM3_297",
+ "MXM3_293",
+ "MXM3_291",
+ "MXM3_289",
+ "MXM3_287";
+};
+
+&lsio_gpio5 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_150",
+ "MXM3_160",
+ "MXM3_162",
+ "MXM3_144",
+ "MXM3_146",
+ "MXM3_148",
+ "MXM3_152",
+ "MXM3_156",
+ "MXM3_158",
+ "MXM3_159",
+ "MXM3_184",
+ "MXM3_180",
+ "MXM3_186",
+ "MXM3_188",
+ "MXM3_176",
+ "MXM3_178";
+};
+
+&lsio_gpio6 {
+ gpio-line-names = "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_261",
+ "MXM3_263",
+ "MXM3_259",
+ "MXM3_257",
+ "MXM3_255",
+ "MXM3_128",
+ "MXM3_130",
+ "MXM3_265",
+ "MXM3_249",
+ "MXM3_247",
+ "MXM3_245",
+ "MXM3_243";
+};
+
+/* Apalis I2C2 (DDC) */
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c0>;
+};
+
+&pinctrl_fec1 {
+ fsl,pins = <
+ IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB_PAD 0x000014a0 /* Use pads in 1.8V mode */
+ IMX8QM_ENET0_MDC_CONN_ENET0_MDC 0x06000020
+ IMX8QM_ENET0_MDIO_CONN_ENET0_MDIO 0x06000020
+ IMX8QM_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x06000020
+ IMX8QM_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC 0x06000020
+ IMX8QM_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x06000020
+ IMX8QM_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x06000020
+ IMX8QM_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2 0x06000020
+ IMX8QM_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3 0x06000020
+ IMX8QM_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC 0x06000020
+ IMX8QM_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x06000020
+ IMX8QM_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x06000020
+ IMX8QM_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x06000020
+ IMX8QM_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2 0x06000020
+ IMX8QM_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3 0x06000020
+ IMX8QM_ENET0_REFCLK_125M_25M_CONN_ENET0_REFCLK_125M_25M 0x06000020
+ /* On-module ETH_RESET# */
+ IMX8QM_LVDS1_GPIO01_LSIO_GPIO1_IO11 0x06000020
+ /* On-module ETH_INT# */
+ IMX8QM_LVDS0_GPIO01_LSIO_GPIO1_IO05 0x04000060
+ >;
+};
+
+&pinctrl_fec1_sleep {
+ fsl,pins = <
+ IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB_PAD 0x000014a0
+ IMX8QM_ENET0_MDC_LSIO_GPIO4_IO14 0x04000040
+ IMX8QM_ENET0_MDIO_LSIO_GPIO4_IO13 0x04000040
+ IMX8QM_ENET0_RGMII_TX_CTL_LSIO_GPIO5_IO31 0x04000040
+ IMX8QM_ENET0_RGMII_TXC_LSIO_GPIO5_IO30 0x04000040
+ IMX8QM_ENET0_RGMII_TXD0_LSIO_GPIO6_IO00 0x04000040
+ IMX8QM_ENET0_RGMII_TXD1_LSIO_GPIO6_IO01 0x04000040
+ IMX8QM_ENET0_RGMII_TXD2_LSIO_GPIO6_IO02 0x04000040
+ IMX8QM_ENET0_RGMII_TXD3_LSIO_GPIO6_IO03 0x04000040
+ IMX8QM_ENET0_RGMII_RXC_LSIO_GPIO6_IO04 0x04000040
+ IMX8QM_ENET0_RGMII_RX_CTL_LSIO_GPIO6_IO05 0x04000040
+ IMX8QM_ENET0_RGMII_RXD0_LSIO_GPIO6_IO06 0x04000040
+ IMX8QM_ENET0_RGMII_RXD1_LSIO_GPIO6_IO07 0x04000040
+ IMX8QM_ENET0_RGMII_RXD2_LSIO_GPIO6_IO08 0x04000040
+ IMX8QM_ENET0_RGMII_RXD3_LSIO_GPIO6_IO09 0x04000040
+ IMX8QM_ENET0_REFCLK_125M_25M_LSIO_GPIO4_IO15 0x04000040
+ IMX8QM_LVDS1_GPIO01_LSIO_GPIO1_IO11 0x04000040
+ IMX8QM_LVDS0_GPIO01_LSIO_GPIO1_IO05 0x04000040
+ >;
+};
+
+&iomuxc {
+ apalis-imx8qm {
+ /* Apalis I2C2 (DDC) */
+ pinctrl_lpi2c0: lpi2c0grp {
+ fsl,pins = <
+ IMX8QM_HDMI_TX0_TS_SCL_DMA_I2C0_SCL 0x04000022
+ IMX8QM_HDMI_TX0_TS_SDA_DMA_I2C0_SDA 0x04000022
+ >;
+ };
+ };
+};
+
+/* On-module PCIe_CTRL0_CLKREQ */
+&pinctrl_pcie_sata_refclk {
+ fsl,pins = <
+ IMX8QM_PCIE_CTRL0_CLKREQ_B_LSIO_GPIO4_IO27 0x00000021
+ >;
+};
+
+&pcie_sata_refclk_gate {
+ enable-gpios = <&lsio_gpio4 27 GPIO_ACTIVE_HIGH>;
+};
+
+/* On-module Wi-Fi */
+&pcieb {
+ clocks = <&pcieb_lpcg 0>,
+ <&pcieb_lpcg 1>,
+ <&pcieb_lpcg 2>,
+ <&phyx2_lpcg 1>,
+ <&phyx2_lpcg 0>,
+ <&phyx2_crr0_lpcg 0>,
+ <&pcieb_crr3_lpcg 0>,
+ <&pciea_crr2_lpcg 0>,
+ <&misc_crr5_lpcg 0>,
+ <&pcie_sata_refclk_gate>;
+ clock-names = "pcie", "pcie_bus", "pcie_inbound_axi",
+ "pcie_phy", "pcie_phy_pclk", "phy_per",
+ "pcie_per", "pciex2_per", "misc_per",
+ "pcie_ext";
+};
+
+/* Apalis MMC1 */
+&usdhc2 {
+ /*
+ * The PMIC on V1.0A HW generates 1.6V instead of 1.8V which creates
+ * issues with certain SD cards, disable 1.8V signaling for now.
+ */
+ no-1-8-v;
+};
+
+/* Apalis SD1 */
+&usdhc3 {
+ /*
+ * The PMIC on V1.0A HW generates 1.6V instead of 1.8V which creates
+ * issues with certain SD cards, disable 1.8V signaling for now.
+ */
+ no-1-8-v;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-eval.dts b/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-eval.dts
new file mode 100644
index 000000000000..80de879b15a1
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-eval.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qp-apalis-v1.1.dtsi"
+#include "imx8-apalis-eval.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QP V1.1 on Apalis Evaluation Board";
+ compatible = "toradex,apalis-imx8qp-v1.1-eval",
+ "toradex,apalis-imx8qp-v1.1",
+ "toradex,apalis-imx8-v1.1",
+ "toradex,apalis-imx8",
+ "fsl,imx8qp",
+ "fsl,imx8qm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-ixora-v1.1.dts b/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-ixora-v1.1.dts
new file mode 100644
index 000000000000..b57e9caccb42
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1-ixora-v1.1.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2020 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qp-apalis-v1.1.dtsi"
+#include "imx8-apalis-ixora-v1.1.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QP V1.1 on Apalis Ixora V1.1 Carrier Board";
+ compatible = "toradex,apalis-imx8qp-v1.1-ixora-v1.1",
+ "toradex,apalis-imx8qp-v1.1-ixora",
+ "toradex,apalis-imx8qp-v1.1",
+ "toradex,apalis-imx8-v1.1",
+ "toradex,apalis-imx8",
+ "fsl,imx8qp",
+ "fsl,imx8qm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1.dtsi
new file mode 100644
index 000000000000..b40a9a4425c3
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qp-apalis-v1.1.dtsi
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2020 Toradex
+ */
+
+#include "imx8qp.dtsi"
+#include "imx8-apalis-v1.1.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QP V1.1";
+ compatible = "toradex,apalis-imx8qp-v1.1",
+ "toradex,apalis-imx8qp",
+ "toradex,apalis-imx8",
+ "fsl,imx8qp",
+ "fsl,imx8qm";
+};
+
+&cooling_maps_map0 {
+ cooling-device =
+ <&A53_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A72_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dts b/arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dts
new file mode 100644
index 000000000000..420a628794c0
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qxp-apalis.dtsi"
+#include "imx8qxp-apalis-eval.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QXP/DX on Apalis Evaluation Board";
+ compatible = "toradex,apalis-imx8x-eval",
+ "toradex,apalis-imx8x",
+ "fsl,imx8qxp";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dtsi
new file mode 100644
index 000000000000..d1ae7e18bee8
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-apalis-eval.dtsi
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2019 Toradex
+ */
+
+/ {
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &rtc;
+ };
+
+ /* TODO: Move this panel to the overlay */
+ panel_dpi: panel-dpi {
+ /*
+ * edt,et057090dhu: EDT 5.7" LCD TFT
+ * edt,et070080dh6: EDT 7.0" LCD TFT
+ * logictechno,lt161010-2nhc: Cap. Touch Display 7" Parallel
+ * logictechno,lt161010-2nhr: Res. Touch Display 7" Paralle
+ * logictechno,lt170410-2whc: Cap. Touch Display 10.1" LVDS
+ * tpk,f07a-0102: Capacitive Multi-Touch Display Fusion 7"
+ * tpk,f10a-0102: Capacitive Multi-Touch Display Fusion 10"
+ */
+ compatible = "panel-dpi";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3>;
+
+ width-mm = <217>;
+ height-mm = <136>;
+
+ data-mapping = "bgr666";
+ status = "disabled";
+
+ panel-timing {
+ /* Default VESA VGA display timings */
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ hback-porch = <48>;
+ hfront-porch = <16>;
+ hsync-len = <96>;
+ vactive = <480>;
+ vback-porch = <31>;
+ vfront-porch = <11>;
+ vsync-len = <2>;
+ pixelclk-active = <0>;
+ };
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usb_otg1_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbo1_en>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ /* Apalis USBO1_EN */
+ gpio = <&lsio_gpio3 16 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_usb_host_vbus: regulator-usb-host-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh_en>;
+ regulator-name = "usb_host_vbus_hub";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ /* Apalis USBH_EN */
+ gpio = <&lsio_gpio4 4 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&adc0 {
+ status = "okay";
+};
+
+&fec1 {
+ status = "okay";
+};
+
+/* Apalis CAN1 */
+&flexcan2 {
+ /* define the following property to disable CAN-FD mode */
+ /* disable-fd-mode; */
+ status = "okay";
+};
+
+/* Apalis CAN2 */
+&flexcan3 {
+ /* define the following property to disable CAN-FD mode */
+ /* disable-fd-mode; */
+ status = "okay";
+};
+
+/* Apalis I2C1 */
+&i2c1 {
+ status = "okay";
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&isi_0 {
+ interface = <2 0 2>;
+ /**
+ * interface = <Input MIPI_VCx Output>
+ * Input: 0-DC0, 1-DC1, 2-MIPI CSI0, 3-MIPI CSI1, 4-HDMI, 5-MEM, INPUT: 6-PARALLEL CSI
+ * MIPI_VCx: 0-VC0, 1-VC1, 2-VC2, 3-VC3, MIPI CSI only
+ * Output: 0-DC0, 1-DC1, 2-MEM
+ */
+ status = "okay";
+
+ cap_device {
+ status = "okay";
+ };
+
+ m2m_device {
+ status = "okay";
+ };
+};
+
+&isi_1 {
+ interface = <6 0 2>;
+ parallel_csi;
+ status = "disabled";
+};
+
+&isi_2 {
+ status = "disabled";
+};
+
+&isi_3 {
+ status = "disabled";
+};
+
+&isi_4 {
+ status = "disabled";
+};
+
+&isi_5 {
+ status = "disabled";
+};
+
+&isi_6 {
+ status = "disabled";
+};
+
+&isi_7 {
+ status = "disabled";
+};
+
+&jpegdec {
+ status = "okay";
+};
+
+&jpegenc {
+ status = "okay";
+};
+
+&ldb1 {
+ status = "okay";
+};
+
+&ldb1_phy {
+ status = "okay";
+};
+
+&ldb2 {
+ status = "okay";
+};
+
+&ldb2_phy {
+ status = "okay";
+};
+
+/* Apalis SPI1 */
+&lpspi0 {
+ status = "okay";
+
+ spidev0: spi@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <4000000>;
+ };
+};
+
+/* Apalis SPI2 */
+&lpspi2 {
+ status = "okay";
+
+ spidev1: spi@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <4000000>;
+ };
+};
+
+/* Apalis UART1 */
+&lpuart1 {
+ status = "okay";
+};
+
+/* Apalis UART2 */
+&lpuart0 {
+ status = "okay";
+};
+
+/* Apalis UART3 */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Apalis UART4 */
+&lpuart3 {
+ status = "okay";
+};
+
+&lsio_gpio1 {
+ /**
+ * Add GPIO1_26 as a wakeup source:
+ * Pin: SC_P_MIPI_DSI0_I2C0_SDA (MXM3_37)
+ * Type: SC_PAD_WAKEUP_FALL_EDGE
+ * Line: GPIO1_IO26
+ */
+ pad-wakeup = <117 5 26>;
+ pad-wakeup-num = <1>;
+};
+
+/* On-module GPIO Expander */
+&pcal6416_1 {
+ /*
+ * This gpio-hog drives a muxing device. With that we can choose
+ * if LVDS1_B pins are active or if DVI signals are active. Those
+ * signals are then muxed to MIPI_DSI1 PADs.
+ *
+ * output-high; muxes to DVI signals
+ * output-low; muxes to LVDS1_B signals
+ */
+ LVDS_HDMI_MUX {
+ gpio-hog;
+ gpios = <14 0>;
+ output-high;
+ line-name = "LVDS_HDMI_MUX";
+ };
+};
+
+/* Apalis PCIE1 */
+&pcieb {
+ status = "okay";
+};
+
+/* Apalis PWM2 */
+&pwm_mipi_lvds0 {
+ status = "okay";
+};
+
+/* Apalis PWM1 */
+&pwm2 {
+ status = "okay";
+};
+
+&usbh1 {
+ status = "okay";
+};
+
+/* Apalis USBO1 */
+&usbotg1 {
+ adp-disable;
+ ci-disable-lpm;
+ hnp-disable;
+ over-current-active-low;
+ srp-disable;
+ status = "okay";
+ vbus-supply = <&reg_usb_otg1_vbus>;
+};
+
+&usbotg3 {
+ vbus-regulator = <&reg_usb_host_vbus>;
+};
+
+&usbphy1 {
+ status = "okay";
+};
+
+/* Apalis MMC1 */
+&usdhc2 {
+ status = "okay";
+};
+
+&vpu_decoder {
+ status = "okay";
+};
+
+&vpu_encoder {
+ status = "okay";
+};
+
+&vpu_lpcg {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-apalis.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-apalis.dtsi
new file mode 100644
index 000000000000..eceee543e6c6
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-apalis.dtsi
@@ -0,0 +1,1388 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include "dt-bindings/pwm/pwm.h"
+#include "imx8qxp.dtsi"
+
+/ {
+ model = "Toradex Apalis iMX8QXP/DX Module";
+ compatible = "toradex,apalis-imx8x",
+ "fsl,imx8qxp";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_bkl_on>;
+ enable-gpios = <&lsio_gpio3 13 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+ };
+
+ chosen {
+ stdout-path = &lpuart1;
+ };
+
+ display_lcdif: display@disp1 {
+ compatible = "fsl,imx-lcdif-mux-display";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif>;
+ clocks = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_BYPASS>,
+ <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_MISC0>;
+ clock-names = "bypass_div", "pixel";
+ assigned-clocks = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_MISC0>;
+ assigned-clock-parents = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_BYPASS>;
+ fsl,lcdif-mux-regs = <&lcdif_mux_regs>;
+ fsl,interface-pix-fmt = "rgb666";
+ power-domains = <&pd IMX_SC_R_LCD_0>;
+ status = "disabled";
+
+ port@0 {
+ reg = <0>;
+
+ lcd_display_in: endpoint {
+ remote-endpoint = <&dpu_disp1_lcdif>;
+ };
+ };
+ };
+
+ gpio-fan {
+ compatible = "gpio-fan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio8>;
+ gpios = <&lsio_gpio3 20 GPIO_ACTIVE_HIGH>;
+ gpio-fan,speed-map = < 0 0
+ 3000 1>;
+ };
+
+ /* Apalis WAKE1_MICO */
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+ status = "disabled";
+
+ wakeup_key: wakeup-key {
+ label = "Wake-Up";
+ gpios = <&lsio_gpio1 26 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ wakeup-source;
+ };
+ };
+
+ imx8x_cm4: imx8x_cm4@0 {
+ compatible = "fsl,imx8qxp-cm4";
+ rsc-da = <0x90000000>;
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&lsio_mu5 0 1
+ &lsio_mu5 1 1
+ &lsio_mu5 3 1>;
+ mub-partition = <3>;
+ memory-region = <&vdev0vring0>, <&vdev0vring1>, <&vdevbuffer>,
+ <&vdev1vring0>, <&vdev1vring1>;
+ core-index = <0>;
+ core-id = <IMX_SC_R_M4_0_PID0>;
+ status = "okay";
+ power-domains = <&pd IMX_SC_R_M4_0_PID0>,
+ <&pd IMX_SC_R_M4_0_MU_1A>;
+ };
+
+ panel_lvds: panel-lvds {
+ compatible = "panel-lvds";
+ backlight = <&backlight>;
+
+ status = "disabled";
+
+ port {
+ panel_lvds_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+ };
+
+ reg_module_3v3: regulator-module-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "+V3.3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_module_3v3_avdd: regulator-module-3v3-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "+V3.3_AVDD_AUDIO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_module_vref_1v8: regulator-vref-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_pcie_switch: regulator-pcie-switch {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio7>;
+ enable-active-high;
+ gpio = <&lsio_gpio3 19 GPIO_ACTIVE_HIGH>;
+ regulator-name = "pcie_switch";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us = <100000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /*
+ * 0x8800_0000 ~ 0x8FFF_FFFF is reserved for M4
+ * Shouldn't be used at A core and Linux side.
+ *
+ */
+ m4_reserved: m4@0x88000000 {
+ no-map;
+ reg = <0 0x88000000 0 0x8000000>;
+ };
+
+ rpmsg_reserved: rpmsg@0x90000000 {
+ no-map;
+ reg = <0 0x90200000 0 0x200000>;
+ };
+
+ decoder_boot: decoder-boot@84000000 {
+ reg = <0 0x84000000 0 0x2000000>;
+ no-map;
+ };
+
+ encoder_boot: encoder-boot@86000000 {
+ reg = <0 0x86000000 0 0x200000>;
+ no-map;
+ };
+
+ decoder_rpc: decoder-rpc@0x92000000 {
+ reg = <0 0x92000000 0 0x200000>;
+ no-map;
+ };
+
+ encoder_rpc: encoder-rpc@0x92200000 {
+ reg = <0 0x92200000 0 0x200000>;
+ no-map;
+ };
+
+ encoder_reserved: encoder_reserved@94400000 {
+ no-map;
+ reg = <0 0x94400000 0 0x800000>;
+ };
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x3c000000>;
+ alloc-ranges = <0 0x96000000 0 0x3c000000>;
+ linux,cma-default;
+ };
+
+ vdev0vring0: vdev0vring0@90000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90000000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@90008000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90008000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: vdev1vring0@90010000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90010000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: vdev1vring1@90018000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90018000 0 0x8000>;
+ no-map;
+ };
+
+ vdevbuffer: vdevbuffer {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90400000 0 0x100000>;
+ no-map;
+ };
+ };
+
+ sound_card: sound-card {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,name = "imx8qxp-sgtl5000";
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&sgtl5000_a>;
+ clocks = <&mclkout0_lpcg 0>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai1>;
+ };
+ };
+};
+
+/* Apalis AN1_ADC */
+&adc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0>;
+ vref-supply = <&reg_module_vref_1v8>;
+};
+
+/* Display Prefetch Resolve, (Tiling) */
+&dc0_dpr1_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel3 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel3 {
+ status = "okay";
+};
+
+&dc0_pc {
+ status = "okay";
+};
+
+&dc0_prg1 {
+ status = "okay";
+};
+
+&dc0_prg2 {
+ status = "okay";
+};
+
+&dc0_prg3 {
+ status = "okay";
+};
+
+&dc0_prg4 {
+ status = "okay";
+};
+
+&dc0_prg5 {
+ status = "okay";
+};
+
+&dc0_prg6 {
+ status = "okay";
+};
+
+&dc0_prg7 {
+ status = "okay";
+};
+
+&dc0_prg8 {
+ status = "okay";
+};
+
+&dc0_prg9 {
+ status = "okay";
+};
+
+&dpu1 {
+ status = "okay";
+};
+
+&dpu_disp1_lcdif {
+ remote-endpoint = <&lcd_display_in>;
+};
+
+/* Apalis Gigabit Ethernet */
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ fsl,magic-packet;
+ fsl,rgmii_rxc_dly;
+ fsl,rgmii_txc_dly;
+ phy-handle = <&ethphy0>;
+ phy-mode = "rgmii";
+ phy-reset-duration = <10>;
+ phy-reset-gpios = <&lsio_gpio3 4 GPIO_ACTIVE_LOW>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ interrupt-parent = <&lsio_gpio1>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ micrel,led-mode = <0>;
+ reg = <4>;
+ };
+ };
+};
+
+/* Apalis CAN1 */
+&flexcan2 {
+ /* define the following property to disable CAN-FD mode */
+ /* disable-fd-mode; */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+};
+
+/* Apalis CAN2 */
+&flexcan3 {
+ /* define the following property to disable CAN-FD mode */
+ /* disable-fd-mode; */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan3>;
+};
+
+&gpu_3d0 {
+ status = "okay";
+};
+
+/* On-module I2C */
+&i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c0>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ /* On-Module EEPROM */
+ eeprom: eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+
+ /* PCAL6416A GPIO Expander */
+ pcal6416_1: gpio@20 {
+ compatible = "nxp,pcal6416";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c_exp1_int>;
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&lsio_gpio4>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ vcc-supply = <&reg_module_3v3>;
+ ngpios = <16>;
+ gpio-line-names = "HDMI1_CEC", "SPDIF1_IN", "SPDIF1_OUT",
+ "UART4_TXD", "UART1_DCD", "UART1_RI", "UART1_DSR",
+ "UART1_DTR", "PWM1", "Wi-Fi_WKUP_WLAN",
+ "Wi-Fi_W_DISABLE", "Wi-Fi_WKUP_BT", "Wi-Fi_PDn",
+ "Wi-Fi_WKUP_HOST", "DSI_SW_SEL", "HDMI1_HPD";
+ };
+
+ /* PCAL6416A GPIO Expander */
+ pcal6416_2: gpio@21 {
+ compatible = "nxp,pcal6416";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c_exp2_int>;
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&lsio_gpio4>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ vcc-supply = <&reg_module_3v3>;
+ };
+
+ sgtl5000_a: sgtl5000@a {
+ compatible = "fsl,sgtl5000";
+ #sound-dai-cells = <0>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&aud_pll_div0_lpcg 0>,
+ <&aud_rec0_lpcg 0>,
+ <&mclkout0_lpcg 0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <12288000>;
+ clocks = <&mclkout0_lpcg 0>;
+ clock-names = "mclk";
+ reg = <0xa>;
+ VDDA-supply = <&reg_module_3v3_avdd>;
+ VDDIO-supply = <&reg_module_3v3>;
+ VDDD-supply = <&reg_module_vref_1v8>;
+ };
+};
+
+/* Apalis I2C2 (DDC) */
+&i2c0_mipi_lvds1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c0_mipi_lvds1>;
+ clock-frequency = <100000>;
+};
+
+/* Apalis I2C1 */
+&i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c1>;
+ clock-frequency = <100000>;
+};
+
+/* Apalis I2C3 (CAM) */
+&i2c3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c3>;
+ clock-frequency = <100000>;
+};
+
+&imx8_gpu_ss {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dap1_gpios>, <&pinctrl_gpio3>, <&pinctrl_gpio4>,
+ <&pinctrl_mmc1_gpios>, <&pinctrl_qspi0a_gpios>, <&pinctrl_sata1_act>,
+ <&pinctrl_gpio_usbh_oc_n>, <&pinctrl_usbo1oc>, <&pinctrl_wifi_sclk>;
+
+ apalis-imx8qxp {
+ /* Apalis AN1_ADC */
+ pinctrl_adc0: adc0grp {
+ fsl,pins = <
+ /* Apalis AN1_ADC0 */
+ IMX8QXP_ADC_IN0_ADMA_ADC_IN0 0x60 /* MXM3 305 */
+ /* Apalis AN1_ADC1 */
+ IMX8QXP_ADC_IN1_ADMA_ADC_IN1 0x60 /* MXM3 307 */
+ /* Apalis AN1_ADC2 */
+ IMX8QXP_ADC_IN4_ADMA_ADC_IN4 0x60 /* MXM3 309 */
+ /* Apalis AN1_TSWIP_ADC3 */
+ IMX8QXP_ADC_IN5_ADMA_ADC_IN5 0x60 /* MXM3 311 */
+ >;
+ };
+
+ /* Apalis BKL1_ON */
+ pinctrl_gpio_bkl_on: gpio-bkl-on {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DQS_LSIO_GPIO3_IO13 0x21 /* MXM3 286 */
+ >;
+ };
+
+ /* Apalis BKL1_PWM */
+ pinctrl_pwm_mipi_lvds1: pwmmipilvds1grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_GPIO0_00_MIPI_DSI1_PWM0_OUT 0x60 /* MXM3 239 */
+ >;
+ };
+
+ /* Apalis CAN1 */
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN1_TX_ADMA_FLEXCAN1_TX 0x21 /* MXM3 14 */
+ IMX8QXP_FLEXCAN1_RX_ADMA_FLEXCAN1_RX 0x21 /* MXM3 12 */
+ >;
+ };
+
+ /* Apalis CAN2 */
+ pinctrl_flexcan3: flexcan3grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN2_TX_ADMA_FLEXCAN2_TX 0x21 /* MXM3 18 */
+ IMX8QXP_FLEXCAN2_RX_ADMA_FLEXCAN2_RX 0x21 /* MXM3 16 */
+ >;
+ };
+
+ /* Apalis DAP1 */
+ pinctrl_dap1_gpios: dap1gpiosgrp {
+ fsl,pins = <
+ /* Apalis DAP1_D_OUT */
+ IMX8QXP_SAI0_TXD_LSIO_GPIO0_IO25 0x21 /* MXM3 196 */
+ /* Apalis DAP1_RESET */
+ IMX8QXP_QSPI0A_SS1_B_LSIO_GPIO3_IO15 0x21 /* MXM3 198 */
+ /* Apalis DAP1_BIT_CLK */
+ IMX8QXP_SAI0_TXC_LSIO_GPIO0_IO26 0x21 /* MXM3 200 */
+ /* Apalis DAP1_D_IN */
+ IMX8QXP_SAI0_RXD_LSIO_GPIO0_IO27 0x21 /* MXM3 202 */
+ /* Apalis DAP1_SYNC */
+ IMX8QXP_SAI0_TXFS_LSIO_GPIO0_IO28 0x21 /* MXM3 204 */
+ >;
+ };
+
+ /* Apalis GPIO1 */
+ pinctrl_gpio1: gpio1grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_DATA3_LSIO_GPIO3_IO21 0x21 /* MXM3 1 */
+ >;
+ };
+
+ /* Apalis GPIO2 */
+ pinctrl_gpio2: gpio2grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_DQS_LSIO_GPIO3_IO22 0x21 /* MXM3 3 */
+ >;
+ };
+
+ /* Apalis GPIO3 */
+ pinctrl_gpio3: gpio3grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_SS0_B_LSIO_GPIO3_IO23 0x21 /* MXM3 5 */
+ >;
+ };
+
+ /* Apalis GPIO4 */
+ pinctrl_gpio4: gpio4grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_SS1_B_LSIO_GPIO3_IO24 0x21 /* MXM3 7 */
+ >;
+ };
+
+ /* Apalis GPIO5 */
+ pinctrl_gpio5: gpio5grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_SCLK_LSIO_GPIO3_IO17 0x21 /* MXM3 11 */
+ >;
+ };
+
+ /* Apalis GPIO6 */
+ pinctrl_gpio6: gpio6grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_DATA0_LSIO_GPIO3_IO18 0x21 /* MXM3 13 */
+ >;
+ };
+
+ /* Apalis GPIO7 */
+ pinctrl_gpio7: gpio7grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_DATA1_LSIO_GPIO3_IO19 0x21 /* MXM3 15 */
+ >;
+ };
+
+ /* Apalis GPIO8 */
+ pinctrl_gpio8: gpio8grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0B_DATA2_LSIO_GPIO3_IO20 0x21 /* MXM3 17 */
+ >;
+ };
+
+ /* Apalis I2C1 */
+ pinctrl_lpi2c1: lpi2c1grp {
+ fsl,pins = <
+ IMX8QXP_USB_SS3_TC0_ADMA_I2C1_SCL 0x06000021 /* MXM3 211 */
+ IMX8QXP_USB_SS3_TC3_ADMA_I2C1_SDA 0x06000021 /* MXM3 209 */
+ >;
+ };
+
+ /* Apalis I2C2 (DDC) */
+ pinctrl_i2c0_mipi_lvds1: mipilvds1i2c0grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_I2C0_SCL_MIPI_DSI1_I2C0_SCL 0xc6000020 /* MXM3 205 */
+ IMX8QXP_MIPI_DSI1_I2C0_SDA_MIPI_DSI1_I2C0_SDA 0xc6000020 /* MXM3 207 */
+ >;
+ };
+
+ /* Apalis I2C3 (CAM) */
+ pinctrl_lpi2c3: lpi2c3grp {
+ fsl,pins = <
+ IMX8QXP_CSI_EN_ADMA_I2C3_SCL 0xc6000020 /* MXM3 203 */
+ IMX8QXP_CSI_RESET_ADMA_I2C3_SDA 0xc6000020 /* MXM3 201 */
+ >;
+ };
+
+ /* Apalis MMC1_ */
+ pinctrl_mmc1_gpios: mmc1gpiosgrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA1_LSIO_GPIO3_IO10 0x21 /* MXM3 148 */
+ IMX8QXP_QSPI0A_SS0_B_LSIO_GPIO3_IO14 0x21 /* MXM3 158 */
+ IMX8QXP_USDHC1_WP_LSIO_GPIO4_IO21 0x21 /* MXM3 156 */
+ IMX8QXP_USDHC1_RESET_B_LSIO_GPIO4_IO19 0x21 /* MXM3 152 */
+ >;
+ };
+
+ /* Apalis MMC1_CD# */
+ pinctrl_usdhc2_gpio: mmc1gpiogrp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CD_B_LSIO_GPIO4_IO22 0x06000021 /* MXM3 164 */
+ >;
+ };
+
+ pinctrl_usdhc2_gpio_sleep: usdhc1gpioslpgrp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CD_B_LSIO_GPIO4_IO22 0x60 /* MXM3 164 */
+ >;
+ };
+
+ /* Apalis MMC1 */
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 /* MXM3 154 */
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x21 /* MXM3 150 */
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x21 /* MXM3 160 */
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x21 /* MXM3 162 */
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x21 /* MXM3 144 */
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x21 /* MXM3 146 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 /* MXM3 154 */
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x21 /* MXM3 150 */
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x21 /* MXM3 160 */
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x21 /* MXM3 162 */
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x21 /* MXM3 144 */
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x21 /* MXM3 146 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 /* MXM3 154 */
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x21 /* MXM3 150 */
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x21 /* MXM3 160 */
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x21 /* MXM3 162 */
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x21 /* MXM3 144 */
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x21 /* MXM3 146 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ pinctrl_usdhc2_sleep: usdhc2slpgrp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_LSIO_GPIO4_IO23 0x60 /* MXM3 154 */
+ IMX8QXP_USDHC1_CMD_LSIO_GPIO4_IO24 0x60 /* MXM3 150 */
+ IMX8QXP_USDHC1_DATA0_LSIO_GPIO4_IO25 0x60 /* MXM3 160 */
+ IMX8QXP_USDHC1_DATA1_LSIO_GPIO4_IO26 0x60 /* MXM3 162 */
+ IMX8QXP_USDHC1_DATA2_LSIO_GPIO4_IO27 0x60 /* MXM3 144 */
+ IMX8QXP_USDHC1_DATA3_LSIO_GPIO4_IO28 0x60 /* MXM3 146 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ /* Apalis Parallel Camera */
+ pinctrl_parallel_csi: parallelcsigrp {
+ fsl,pins = <
+ IMX8QXP_CSI_D00_CI_PI_D02 0xC0000041 /* MXM3 187 */
+ IMX8QXP_CSI_D01_CI_PI_D03 0xC0000041 /* MXM3 185 */
+ IMX8QXP_CSI_D02_CI_PI_D04 0xC0000041 /* MXM3 183 */
+ IMX8QXP_CSI_D03_CI_PI_D05 0xC0000041 /* MXM3 181 */
+ IMX8QXP_CSI_D04_CI_PI_D06 0xC0000041 /* MXM3 179 */
+ IMX8QXP_CSI_D05_CI_PI_D07 0xC0000041 /* MXM3 177 */
+ IMX8QXP_CSI_D06_CI_PI_D08 0xC0000041 /* MXM3 175 */
+ IMX8QXP_CSI_D07_CI_PI_D09 0xC0000041 /* MXM3 173 */
+ IMX8QXP_CSI_MCLK_CI_PI_MCLK 0xC0000041 /* MXM3 193 */
+ IMX8QXP_CSI_PCLK_CI_PI_PCLK 0xC0000041 /* MXM3 191 */
+ IMX8QXP_CSI_HSYNC_CI_PI_HSYNC 0xC0000041 /* MXM3 197 */
+ IMX8QXP_CSI_VSYNC_CI_PI_VSYNC 0xC0000041 /* MXM3 195 */
+ >;
+ };
+
+ /* Apalis Parallel RGB LCD Interface */
+ pinctrl_hog0: hog0grp {
+ fsl,pins = <
+ IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB_PAD 0x000514a0 /* Use pads in 3.3V mode */
+ >;
+ };
+
+ pinctrl_lcdif: lcdif-pins {
+ fsl,pins = <
+ IMX8QXP_MCLK_OUT0_ADMA_LCDIF_CLK 0x60 /* MXM3 243 */
+ IMX8QXP_MCLK_IN0_ADMA_LCDIF_VSYNC 0x60 /* MXM3 245 */
+ IMX8QXP_SPI3_CS0_ADMA_LCDIF_HSYNC 0x60 /* MXM3 247 */
+ IMX8QXP_MCLK_IN1_ADMA_LCDIF_EN 0x60 /* MXM3 249 */
+ IMX8QXP_SPDIF0_EXT_CLK_ADMA_LCDIF_D12 0x60 /* MXM3 255 */
+ IMX8QXP_SPI3_SCK_ADMA_LCDIF_D13 0x60 /* MXM3 257 */
+ IMX8QXP_SPI3_SDO_ADMA_LCDIF_D14 0x60 /* MXM3 259 */
+ IMX8QXP_SPI3_SDI_ADMA_LCDIF_D15 0x60 /* MXM3 261 */
+ IMX8QXP_SPI3_CS1_ADMA_LCDIF_D16 0x60 /* MXM3 263 */
+ IMX8QXP_UART1_CTS_B_ADMA_LCDIF_D17 0x60 /* MXM3 265 */
+ IMX8QXP_ESAI0_TX2_RX3_ADMA_LCDIF_D06 0x60 /* MXM3 273 */
+ IMX8QXP_ESAI0_TX3_RX2_ADMA_LCDIF_D07 0x60 /* MXM3 275 */
+ IMX8QXP_ESAI0_TX4_RX1_ADMA_LCDIF_D08 0x60 /* MXM3 277 */
+ IMX8QXP_ESAI0_TX5_RX0_ADMA_LCDIF_D09 0x60 /* MXM3 279 */
+ IMX8QXP_SPDIF0_RX_ADMA_LCDIF_D10 0x60 /* MXM3 281 */
+ IMX8QXP_SPDIF0_TX_ADMA_LCDIF_D11 0x60 /* MXM3 283 */
+ IMX8QXP_ESAI0_FSR_ADMA_LCDIF_D00 0x60 /* MXM3 291 */
+ IMX8QXP_ESAI0_FST_ADMA_LCDIF_D01 0x60 /* MXM3 293 */
+ IMX8QXP_ESAI0_SCKR_ADMA_LCDIF_D02 0x60 /* MXM3 295 */
+ IMX8QXP_ESAI0_SCKT_ADMA_LCDIF_D03 0x60 /* MXM3 297 */
+ IMX8QXP_ESAI0_TX0_ADMA_LCDIF_D04 0x60 /* MXM3 299 */
+ IMX8QXP_ESAI0_TX1_ADMA_LCDIF_D05 0x60 /* MXM3 301 */
+ >;
+ };
+
+ /* Apalis PWM1 */
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ IMX8QXP_UART1_RTS_B_LSIO_PWM2_OUT 0x60 /* MXM3 2 */
+ >;
+ };
+
+ /* Apalis PWM2 */
+ pinctrl_pwm_mipi_lvds0: pwmmipilvds0grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI0_GPIO0_00_MIPI_DSI0_PWM0_OUT 0x60 /* MXM3 4 */
+ >;
+ };
+
+ /* Apalis PWM_ */
+ pinctrl_pwm_gpios: gpiospwmgrp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI0_GPIO0_01_LSIO_GPIO1_IO28 0x21 /* MXM3 6 */
+ IMX8QXP_MIPI_DSI1_GPIO0_01_LSIO_GPIO2_IO00 0x21 /* MXM3 8 */
+ >;
+ };
+
+ /* Apalis SATA1_ACT# */
+ pinctrl_sata1_act: sata1actgrp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI0_I2C0_SCL_LSIO_GPIO1_IO25 0x21 /* MXM3 35 */
+ >;
+ };
+
+ /* Apalis SPI1 */
+ pinctrl_lpspi0: lpspi0grp {
+ fsl,pins = <
+ IMX8QXP_SPI0_CS0_LSIO_GPIO1_IO08 0x06000040 /* MXM3 227 */
+ IMX8QXP_SPI0_SDI_ADMA_SPI0_SDI 0x06000040 /* MXM3 223 */
+ IMX8QXP_SPI0_SDO_ADMA_SPI0_SDO 0x06000040 /* MXM3 225 */
+ IMX8QXP_SPI0_SCK_ADMA_SPI0_SCK 0x06000040 /* MXM3 221 */
+ >;
+ };
+
+ /* Apalis SPI2 */
+ pinctrl_lpspi2: lpspi2grp {
+ fsl,pins = <
+ IMX8QXP_SPI2_CS0_LSIO_GPIO1_IO00 0x21 /* MXM3 233 */
+ IMX8QXP_SPI2_SDI_ADMA_SPI2_SDI 0x06000040 /* MXM3 229 */
+ IMX8QXP_SPI2_SDO_ADMA_SPI2_SDO 0x06000040 /* MXM3 231 */
+ IMX8QXP_SPI2_SCK_ADMA_SPI2_SCK 0x06000040 /* MXM3 235 */
+ >;
+ };
+
+ /* Apalis UART1 */
+ pinctrl_lpuart1: lpuart1grp {
+ fsl,pins = <
+ IMX8QXP_UART1_RX_ADMA_UART1_RX 0x06000020 /* MXM3 118 */
+ IMX8QXP_UART1_TX_ADMA_UART1_TX 0x06000020 /* MXM3 112 */
+ >;
+ };
+
+ /* Apalis UART1_ */
+ pinctrl_qspi0a_gpios: qspi0agpiosgrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA2_LSIO_GPIO3_IO11 0x21 /* MXM3 114 */
+ IMX8QXP_QSPI0A_DATA3_LSIO_GPIO3_IO12 0x21 /* MXM3 116 */
+ >;
+ };
+
+ /* Apalis UART2 */
+ pinctrl_lpuart0: lpuart0grp {
+ fsl,pins = <
+ IMX8QXP_UART0_TX_ADMA_UART0_TX 0x06000020 /* MXM3 126 */
+ IMX8QXP_UART0_RX_ADMA_UART0_RX 0x06000020 /* MXM3 132 */
+ IMX8QXP_FLEXCAN0_RX_ADMA_UART0_RTS_B 0x06000020 /* MXM3 128 */
+ IMX8QXP_FLEXCAN0_TX_ADMA_UART0_CTS_B 0x06000020 /* MXM3 130 */
+ >;
+ };
+
+ /* Apalis UART3 */
+ pinctrl_lpuart2: lpuart2grp {
+ fsl,pins = <
+ IMX8QXP_UART2_TX_ADMA_UART2_TX 0x06000020 /* MXM3 134 */
+ IMX8QXP_UART2_RX_ADMA_UART2_RX 0x06000020 /* MXM3 136 */
+ >;
+ };
+
+ /* Apalis UART4 */
+ pinctrl_lpuart3: lpuart3grp {
+ fsl,pins = <
+ IMX8QXP_SCU_GPIO0_01_ADMA_UART3_TX 0x06000020 /* MXM3 138 */
+ IMX8QXP_SCU_GPIO0_00_ADMA_UART3_RX 0x06000020 /* MXM3 140 */
+ >;
+ };
+
+ /* Apalis USBH_EN */
+ pinctrl_usbh_en: usbhen {
+ fsl,pins = <
+ IMX8QXP_USB_SS3_TC1_LSIO_GPIO4_IO04 0x21 /* MXM3 84 */
+ >;
+ };
+
+ /* Apalis USBH_OC# */
+ pinctrl_gpio_usbh_oc_n: gpiousbhocn {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA0_LSIO_GPIO3_IO09 0x04000020 /* MXM3 96 */
+ >;
+ };
+
+ /* Apalis USBO1_EN */
+ pinctrl_usbo1_en: usbo1en {
+ fsl,pins = <
+ /* Apalis USBO1_EN */
+ IMX8QXP_QSPI0A_SCLK_LSIO_GPIO3_IO16 0x21 /* MXM3 274 */
+ >;
+ };
+
+ /* Apalis USBO1 */
+ pinctrl_usbo1oc: usbo1oc {
+ fsl,pins = <
+ /* Apalis USBO1_OC# */
+ IMX8QXP_USB_SS3_TC2_LSIO_GPIO4_IO05 0x04000020 /* MXM3 262 */
+ >;
+ };
+
+ /* Apalis WAKE1_MICO */
+ pinctrl_gpio_keys: gpio-keys {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI0_I2C0_SDA_LSIO_GPIO1_IO26 0x06680021 /* MXM3 37 */
+ >;
+ };
+
+ /* On-module Gigabit Ethernet PHY Micrel KSZ9031 */
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ IMX8QXP_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0_PAD 0x14a0 /* Use pads in 3.3V mode */
+ IMX8QXP_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB1_PAD 0x14a0 /* Use pads in 3.3V mode */
+ IMX8QXP_ENET0_MDC_CONN_ENET0_MDC 0x06000020
+ IMX8QXP_ENET0_MDIO_CONN_ENET0_MDIO 0x06000020
+ IMX8QXP_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x61
+ IMX8QXP_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC 0x61
+ IMX8QXP_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x61
+ IMX8QXP_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x61
+ IMX8QXP_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2 0x61
+ IMX8QXP_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3 0x61
+ IMX8QXP_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC 0x61
+ IMX8QXP_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x61
+ IMX8QXP_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x61
+ IMX8QXP_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x61
+ IMX8QXP_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2 0x61
+ IMX8QXP_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3 0x61
+ /* On-module ETH_RESET# */
+ IMX8QXP_MIPI_CSI0_MCLK_OUT_LSIO_GPIO3_IO04 0x21
+ /* On-module ETH_INT# */
+ IMX8QXP_ADC_IN2_LSIO_GPIO1_IO12 0x21
+ >;
+ };
+
+ /* On-module GPIO expanders */
+ pinctrl_i2c_exp1_int: i2cexp1int {
+ fsl,pins = <
+ IMX8QXP_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO02 0x21
+ >;
+ };
+
+ pinctrl_i2c_exp2_int: i2cexp2int {
+ fsl,pins = <
+ IMX8QXP_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO00 0x21
+ >;
+ };
+
+ /* On-module eMMC */
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x21
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x21
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x21
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x21
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x21
+ IMX8QXP_EMMC0_DATA4_CONN_EMMC0_DATA4 0x21
+ IMX8QXP_EMMC0_DATA5_CONN_EMMC0_DATA5 0x21
+ IMX8QXP_EMMC0_DATA6_CONN_EMMC0_DATA6 0x21
+ IMX8QXP_EMMC0_DATA7_CONN_EMMC0_DATA7 0x21
+ IMX8QXP_EMMC0_STROBE_CONN_EMMC0_STROBE 0x41
+ IMX8QXP_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x21
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x21
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x21
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x21
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x21
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x21
+ IMX8QXP_EMMC0_DATA4_CONN_EMMC0_DATA4 0x21
+ IMX8QXP_EMMC0_DATA5_CONN_EMMC0_DATA5 0x21
+ IMX8QXP_EMMC0_DATA6_CONN_EMMC0_DATA6 0x21
+ IMX8QXP_EMMC0_DATA7_CONN_EMMC0_DATA7 0x21
+ IMX8QXP_EMMC0_STROBE_CONN_EMMC0_STROBE 0x41
+ IMX8QXP_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x21
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x21
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x21
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x21
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x21
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x21
+ IMX8QXP_EMMC0_DATA4_CONN_EMMC0_DATA4 0x21
+ IMX8QXP_EMMC0_DATA5_CONN_EMMC0_DATA5 0x21
+ IMX8QXP_EMMC0_DATA6_CONN_EMMC0_DATA6 0x21
+ IMX8QXP_EMMC0_DATA7_CONN_EMMC0_DATA7 0x21
+ IMX8QXP_EMMC0_STROBE_CONN_EMMC0_STROBE 0x41
+ IMX8QXP_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x21
+ >;
+ };
+
+ /* On-module I2C */
+ pinctrl_lpi2c0: i2c0csi0grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_CSI0_GPIO0_00_ADMA_I2C0_SCL 0xc6000020 /* MXM3 140 */
+ IMX8QXP_MIPI_CSI0_GPIO0_01_ADMA_I2C0_SDA 0xc6000020 /* MXM3 142 */
+ >;
+ };
+
+ /* On-module I2S SGTL5000 for Apalis Analogue Audio */
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ IMX8QXP_SAI1_RXD_ADMA_SAI1_RXD 0x06000040
+ IMX8QXP_SPI0_CS1_ADMA_SAI1_TXD 0x06000040
+ IMX8QXP_SAI1_RXC_ADMA_SAI1_TXC 0x06000040
+ IMX8QXP_SAI1_RXFS_ADMA_SAI1_TXFS 0x06000040
+ >;
+ };
+
+ /* On-module I2S SGTL5000 SYS_MCLK */
+ pinctrl_sgtl5000: sgtl5000grp {
+ fsl,pins = <
+ IMX8QXP_ADC_IN3_ADMA_ACM_MCLK_OUT0 0x21
+ >;
+ };
+
+ /* On-module RESET_MOCI#_DRV */
+ pinctrl_reset_moci: gpioresetmocigrp {
+ fsl,pins = <
+ IMX8QXP_PCIE_CTRL0_CLKREQ_B_LSIO_GPIO4_IO01 0x11
+ >;
+ };
+
+ pinctrl_wifi_sclk: wifigrp {
+ fsl,pins = <
+ IMX8QXP_SCU_BOOT_MODE3_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0x20 /* WiFi Sleep clock */
+ >;
+ };
+ };
+};
+
+&ldb1_phy {
+ status = "disabled";
+};
+
+&ldb1 {
+ status = "disabled";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "okay";
+
+ port@1 {
+ reg = <1>;
+
+ lvds0_out: endpoint {
+ remote-endpoint = <&panel_lvds_in>;
+ };
+ };
+ };
+};
+
+/* Apalis SPI1 */
+&lpspi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ fsl,spi-num-chipselects = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi0>;
+ cs-gpios = <&lsio_gpio1 8 GPIO_ACTIVE_LOW>;
+};
+
+/* Apalis SPI2 */
+&lpspi2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ fsl,spi-num-chipselects = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi2>;
+ cs-gpios = <&lsio_gpio1 0 GPIO_ACTIVE_LOW>;
+};
+
+/* Apalis UART2 */
+&lpuart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart0>;
+};
+
+/* Apalis UART1 */
+&lpuart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart1>;
+};
+
+/* Apalis UART3 */
+&lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart2>;
+};
+
+/* Apalis UART4 */
+&lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart3>;
+};
+
+&lsio_gpio0 {
+ gpio-line-names = "",
+ "MXM3_293",
+ "MXM3_295",
+ "MXM3_297",
+ "MXM3_299",
+ "MXM3_301",
+ "MXM3_273",
+ "MXM3_275",
+ "MXM3_277",
+ "MXM3_279",
+ "MXM3_281",
+ "MXM3_283",
+ "MXM3_255",
+ "MXM3_257",
+ "MXM3_259",
+ "MXM3_261",
+ "MXM3_247",
+ "",
+ "",
+ "MXM3_245",
+ "MXM3_243",
+ "MXM3_112",
+ "MXM3_118",
+ "",
+ "MXM3_265",
+ "MXM3_196",
+ "MXM3_200",
+ "MXM3_202",
+ "MXM3_204",
+ "MXM3_310",
+ "MXM3_312",
+ "MXM3_318";
+};
+
+&lsio_gpio1 {
+ gpio-line-names = "MXM3_235",
+ "MXM3_233",
+ "MXM3_231",
+ "MXM3_229",
+ "MXM3_221",
+ "MXM3_223",
+ "MXM3_225",
+ "MXM3_316",
+ "MXM3_227",
+ "MXM3_307",
+ "MXM3_305",
+ "MXM3_194",
+ "",
+ "MXM3_311",
+ "MXM3_309",
+ "MXM3_128",
+ "MXM3_130",
+ "MXM3_12",
+ "MXM3_14",
+ "MXM3_16",
+ "MXM3_18",
+ "MXM3_132",
+ "MXM3_126",
+ "MXM3_134",
+ "MXM3_136",
+ "MXM3_35",
+ "MXM3_37",
+ "MXM3_4",
+ "MXM3_6",
+ "MXM3_207",
+ "MXM3_205",
+ "MXM3_239";
+};
+
+&lsio_gpio2 {
+ gpio-line-names = "MXM3_8",
+ "",
+ "",
+ "MXM3_140";
+};
+
+&lsio_gpio3 {
+ gpio-line-names = "MXM3_191",
+ "MXM3_193",
+ "MXM3_203",
+ "MXM3_201",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_96",
+ "MXM3_110",
+ "MXM3_114",
+ "MXM3_116",
+ "MXM3_286",
+ "MXM3_158",
+ "MXM3_198",
+ "MXM3_274",
+ "MXM3_11",
+ "MXM3_13",
+ "MXM3_15",
+ "MXM3_17",
+ "MXM3_1",
+ "MXM3_3",
+ "MXM3_5",
+ "MXM3_7";
+};
+
+&lsio_gpio4 {
+ gpio-line-names = "",
+ "",
+ "",
+ "MXM3_211",
+ "MXM3_84",
+ "MXM3_262",
+ "MXM3_209",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "MXM3_152",
+ "MXM3_148",
+ "MXM3_156",
+ "MXM3_164",
+ "MXM3_154",
+ "MXM3_150",
+ "MXM3_160",
+ "MXM3_162",
+ "MXM3_144",
+ "MXM3_146",
+ "MXM3_77",
+ "MXM3_79",
+ "MXM3_65";
+
+ reset {
+ gpio-hog;
+ gpios = <&lsio_gpio4 1 GPIO_ACTIVE_LOW>;
+ output-high;
+ };
+};
+
+&lsio_gpio5 {
+ gpio-line-names = "MXM3_67",
+ "MXM3_71",
+ "MXM3_73",
+ "MXM3_113",
+ "MXM3_115",
+ "MXM3_119",
+ "MXM3_121",
+ "MXM3_125",
+ "MXM3_127",
+ "MXM3_131",
+ "MXM3_59",
+ "MXM3_61";
+};
+
+&mipi_csi_0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /delete-property/virtual-channel;
+};
+
+&mipi0_dsi_host {
+ pwr-delay = <10>;
+};
+
+&mipi1_dsi_host {
+ pwr-delay = <10>;
+};
+
+/* Apalis PCIE1 */
+&pcieb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reset_moci>;
+ bus-range = <0x00 0xff>;
+ ext_osc = <0>;
+ fsl,max-link-speed = <2>;
+ reserved-region = <&rpmsg_reserved>;
+ /*
+ * Workaround: Handle reset as a gpio-hog in &lsio_gpio4
+ * reset-gpio = <&lsio_gpio4 1 GPIO_ACTIVE_LOW>;
+ */
+ vpcie-supply = <&reg_pcie_switch>;
+};
+
+/* Apalis PWM2 */
+&pwm_mipi_lvds0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_mipi_lvds0>;
+ #pwm-cells = <3>;
+};
+
+/* Apalis BKL1_PWM */
+&pwm_mipi_lvds1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_mipi_lvds1>;
+ #pwm-cells = <3>;
+};
+
+/* Apalis PWM1 */
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ #pwm-cells = <3>;
+};
+
+&rpmsg{
+ /*
+ * 64K for one rpmsg instance:
+ */
+ vdev-nums = <2>;
+ reg = <0x0 0x90000000 0x0 0x20000>;
+ memory-region = <&vdevbuffer>;
+ status = "okay";
+};
+
+/* On-module I2S */
+&sai1 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ status = "okay";
+};
+
+&thermal_zones {
+ pmic-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&tsens IMX_SC_R_PMIC_0>;
+ trips {
+ pmic_alert0: trip0 {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ pmic_crit0: trip1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&pmic_alert0>;
+ cooling-device =
+ <&A35_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A35_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A35_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A35_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+};
+
+/* Manage on-module USB WiFi */
+&usb3phynop1 {
+ status = "okay";
+ reset-on-resume;
+};
+
+/*
+ * Apalis USB 3.0 Host. Serves USB 3.0 4-port hub on module and
+ * USB 3.0 ports on-board
+ */
+&usbotg3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* On-module eMMC */
+&usdhc1 {
+ bus-width = <8>;
+ non-removable;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ status = "okay";
+};
+
+/* Apalis MMC1 */
+&usdhc2 {
+ bus-width = <4>;
+ cd-gpios = <&lsio_gpio4 22 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>;
+ vmmc-supply = <&reg_module_3v3>;
+};
+
+&vpu_decoder {
+ boot-region = <&decoder_boot>;
+ rpc-region = <&decoder_rpc>;
+ reg-csr = <0x2d040000>;
+ core_type = <1>;
+};
+
+&vpu_encoder {
+ boot-region = <&encoder_boot>;
+ rpc-region = <&encoder_rpc>;
+ reserved-region = <&encoder_reserved>;
+ reg-rpc-system = <0x40000000>;
+ resolution-max = <1920 1920>;
+ mbox-names = "enc1_tx0", "enc1_tx1", "enc1_rx";
+ mboxes = <&mu1_m0 0 0
+ &mu1_m0 0 1
+ &mu1_m0 1 0>;
+
+ core0@1020000 {
+ compatible = "fsl,imx8-mu1-vpu-m0";
+ reg = <0x1020000 0x20000>;
+ reg-csr = <0x1050000 0x10000>;
+ interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,vpu_ap_mu_id = <17>;
+ fw-buf-size = <0x200000>;
+ rpc-buf-size = <0x80000>;
+ print-buf-size = <0x80000>;
+ };
+};
+
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-aster.dts b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-aster.dts
new file mode 100644
index 000000000000..06eb4f9e929d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-aster.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qxp-colibri.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX8QXP/DX on Aster Board";
+ compatible = "toradex,colibri-imx8x-aster",
+ "toradex,colibri-imx8x",
+ "fsl,imx8qxp";
+};
+
+/* Colibri Ethernet */
+&fec1 {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog0>, <&pinctrl_hog2>;
+};
+
+/* Colibri UART_B */
+&lpuart0 {
+ status = "okay";
+};
+
+/* Colibri UART_C */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Colibri UART_A */
+&lpuart3 {
+ status= "okay";
+};
+
+/* Colibri SDCard */
+&usdhc2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-dsihdmi-eval-v3.dts b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-dsihdmi-eval-v3.dts
new file mode 100644
index 000000000000..7cfdadb02b57
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-dsihdmi-eval-v3.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qxp-colibri.dtsi"
+#include "imx8qxp-colibri-eval-v3.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX8QXP/DX with LT8912 MIPI-DSI 2 HDMI bridge";
+ compatible = "toradex,colibri-imx8x-dsihdmi-eval-v3",
+ "toradex,colibri-imx8x",
+ "fsl,imx8qxp";
+
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+
+ colibri-imx8qxp {
+ /* DSI/LVDS Hot Plug Detect on FFC (X2) */
+ pinctrl_gpio_hpd: gpio-hpd {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_GPIO0_00_LSIO_GPIO1_IO31 0x20 /* SODIMM 138 */
+ >;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dts b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dts
new file mode 100644
index 000000000000..0824887773c9
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8qxp-colibri.dtsi"
+#include "imx8qxp-colibri-eval-v3.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX8QXP/DX on Colibri Evaluation Board V3";
+ compatible = "toradex,colibri-imx8x-eval-v3",
+ "toradex,colibri-imx8x",
+ "fsl,imx8qxp";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi
new file mode 100644
index 000000000000..302356d1e33e
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2020 Toradex
+ */
+
+/ {
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &rtc;
+ };
+
+ /* fixed crystal dedicated to mcp25xx */
+ clk16m: clock-16mhz-fixed {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <16000000>;
+ };
+
+ extcon_usbc_det: usbc_det {
+ compatible = "linux,extcon-usb-gpio";
+ debounce = <25>;
+ id-gpio = <&lsio_gpio5 9 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
+ panel_dpi: panel-dpi {
+ /*
+ * edt,et057090dhu: EDT 5.7" LCD TFT
+ * edt,et070080dh6: EDT 7.0" LCD TFT
+ * logictechno,lt161010-2nhc: Cap. Touch Display 7" Parallel
+ * logictechno,lt161010-2nhr: Res. Touch Display 7" Paralle
+ * logictechno,lt170410-2whc: Cap. Touch Display 10.1" LVDS
+ * tpk,f07a-0102: Capacitive Multi-Touch Display Fusion 7"
+ * tpk,f10a-0102: Capacitive Multi-Touch Display Fusion 10"
+ */
+ compatible = "panel-dpi";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3>;
+
+ width-mm = <217>;
+ height-mm = <136>;
+
+ data-mapping = "bgr666";
+ status = "disabled";
+
+ panel-timing {
+ /* Default VESA VGA display timings */
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ hback-porch = <48>;
+ hfront-porch = <16>;
+ hsync-len = <96>;
+ vactive = <480>;
+ vback-porch = <31>;
+ vfront-porch = <11>;
+ vsync-len = <2>;
+ pixelclk-active = <0>;
+ };
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_usbh_vbus: regulator-usbh-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1_reg>;
+ regulator-name = "usbh_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
+ regulator-always-on;
+ };
+};
+
+/* Colibri Analogue Inputs */
+&adc0 {
+ status = "okay";
+};
+
+/* Colibri PWM_A */
+&adma_pwm {
+ status = "okay";
+};
+
+/* Colibri Ethernet */
+&fec1 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc_i2c: rtc@68 {
+ compatible = "st,m41t0";
+ reg = <0x68>;
+ };
+};
+
+&jpegdec {
+ status = "okay";
+};
+
+&jpegenc {
+ status = "okay";
+};
+
+/* Colibri SPI */
+&lpspi2 {
+ status = "okay";
+
+ mcp2515: can@0 {
+ compatible = "microchip,mcp2515";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can_int>;
+ reg = <0>;
+ clocks = <&clk16m>;
+ interrupt-parent = <&lsio_gpio3>;
+ interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+ spi-max-frequency = <10000000>;
+ status = "okay";
+ };
+
+ spidev0: spidev@0 {
+ compatible = "toradex,evalspi";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ status = "disabled";
+ };
+};
+
+/* Colibri UART_B */
+&lpuart0 {
+ status = "okay";
+};
+
+/* Colibri UART_C */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Colibri UART_A */
+&lpuart3 {
+ status= "okay";
+};
+
+&lsio_gpio3 {
+ /*
+ * Add GPIO3_10 as a wakeup source:
+ * Pin: 157 SC_P_QSPI0A_DATA1 (SODIMM_45)
+ * Type: 6 SC_PAD_WAKEUP_RISE_EDGE
+ * Line: 10 GPIO3_IO10
+ */
+ pad-wakeup = <IMX8QXP_QSPI0A_DATA1 6 10>;
+ pad-wakeup-num = <1>;
+ };
+
+/* Colibri PWM_B */
+&pwm0 {
+ status = "okay";
+};
+
+/* Colibri PWM_C */
+&pwm1 {
+ status = "okay";
+};
+
+/* Colibri PWM_D */
+&pwm2 {
+ status = "okay";
+};
+
+/* USB PHY for &usbotg3 */
+&usb3phynop1 {
+ status = "okay";
+};
+
+&usbotg1 {
+ extcon = <&extcon_usbc_det &extcon_usbc_det>;
+ vbus-supply = <&reg_usbh_vbus>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ power-active-high;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* USB PHY for &usbotg1 */
+&usbphy1 {
+ status = "okay";
+};
+
+/* Colibri SDCard */
+&usdhc2 {
+ status = "okay";
+};
+
+&vpu_encoder {
+ status = "okay";
+};
+
+&vpu_decoder {
+ status = "okay";
+};
+
+&vpu_lpcg {
+ status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-dual-eval-v3.dts b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-dual-eval-v3.dts
new file mode 100644
index 000000000000..84ee70779f81
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-dual-eval-v3.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "dt-bindings/pwm/pwm.h"
+#include "imx8qxp-colibri.dtsi"
+#include "imx8qxp-colibri-eval-v3.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX8QXP/DX with dual channel lvds";
+ compatible = "toradex,colibri-imx8x-lvds-dual-eval-v3",
+ "toradex,colibri-imx8x",
+ "fsl,imx8qxp";
+
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+
+ colibri-imx8qxp {
+ pinctrl_gpio_bklght_on: gpio-bl-on {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_GPIO0_00_LSIO_GPIO1_IO31 0x00000020
+ >;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-single-eval-v3.dts b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-single-eval-v3.dts
new file mode 100644
index 000000000000..4dbc5f378dd0
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-lvds-single-eval-v3.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2019 Toradex
+ */
+
+/dts-v1/;
+
+#include "dt-bindings/pwm/pwm.h"
+#include "imx8qxp-colibri.dtsi"
+#include "imx8qxp-colibri-eval-v3.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX8QXP/DX with single channel lvds";
+ compatible = "toradex,colibri-imx8x-lvds-single-eval-v3",
+ "toradex,colibri-imx8x",
+ "fsl,imx8qxp";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+
+ colibri-imx8qxp {
+ pinctrl_touch: touchgrp {
+ fsl,pins = <
+ IMX8QXP_UART1_TX_LSIO_GPIO0_IO21 0x06000040 /* SODIMM 28 */
+ IMX8QXP_UART1_RX_LSIO_GPIO0_IO22 0x06000020 /* SODIMM 30 */
+ >;
+ };
+
+ pinctrl_gpio_bklght_on: gpio-bl-on {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_GPIO0_00_LSIO_GPIO1_IO31 0x00000020
+ >;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-colibri.dtsi
new file mode 100644
index 000000000000..97a5fc44fd57
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri.dtsi
@@ -0,0 +1,1302 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * Copyright 2018-2020 Toradex
+ */
+
+#include "dt-bindings/pwm/pwm.h"
+#include "imx8qxp.dtsi"
+
+/ {
+ model = "Toradex Colibri iMX8QXP/DX Module";
+ compatible = "toradex,colibri-imx8x",
+ "fsl,imx8qxp";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_bl_on>;
+ enable-gpios = <&lsio_gpio3 12 GPIO_ACTIVE_HIGH>; /* Colibri BL_ON */
+ status = "disabled";
+ };
+
+ chosen {
+ bootargs = "console=ttyLP3,115200";
+ stdout-path = &lpuart3;
+ };
+
+ /* Colibri Parallel RGB */
+ display_lcdif: display@disp1 {
+ compatible = "fsl,imx-lcdif-mux-display";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif>;
+ clocks = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_BYPASS>,
+ <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_MISC0>;
+ clock-names = "bypass_div", "pixel";
+ assigned-clocks = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_MISC0>;
+ assigned-clock-parents = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_BYPASS>;
+ fsl,lcdif-mux-regs = <&lcdif_mux_regs>;
+ fsl,interface-pix-fmt = "rgb666";
+ power-domains = <&pd IMX_SC_R_LCD_0>;
+ status = "disabled";
+
+ port@0 {
+ reg = <0>;
+
+ lcd_display_in: endpoint {
+ remote-endpoint = <&dpu_disp1_lcdif>;
+ };
+ };
+ };
+
+ pcie_refclk: pcie-clock-generator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
+
+ pcie_refclk_gate: pcie-ref-clock {
+ compatible = "gpio-gate-clock";
+ #clock-cells = <0>;
+ clocks = <&pcie_refclk>;
+ enable-gpios = <&gpio_expander_43 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_module_3v3: regulator-module-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "+V3.3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_module_3v3_avdd: regulator-module-3v3-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "+V3.3_AVDD_AUDIO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_module_vref_1v8: regulator-module-vref-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vref-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /*
+ * 0x8800_0000 ~ 0x8FFF_FFFF is reserved for M4
+ * Shouldn't be used at A core and Linux side.
+ *
+ */
+ m4_reserved: m4@0x88000000 {
+ no-map;
+ reg = <0 0x88000000 0 0x8000000>;
+ };
+
+ rpmsg_reserved: rpmsg@0x90000000 {
+ no-map;
+ reg = <0 0x90200000 0 0x200000>;
+ };
+
+ decoder_boot: decoder-boot@84000000 {
+ reg = <0 0x84000000 0 0x2000000>;
+ no-map;
+ };
+
+ encoder_boot: encoder-boot@86000000 {
+ reg = <0 0x86000000 0 0x200000>;
+ no-map;
+ };
+
+ decoder_rpc: decoder-rpc@0x92000000 {
+ reg = <0 0x92000000 0 0x200000>;
+ no-map;
+ };
+
+ encoder_rpc: encoder-rpc@0x92200000 {
+ reg = <0 0x92200000 0 0x200000>;
+ no-map;
+ };
+
+ encoder_reserved: encoder_reserved@94400000 {
+ no-map;
+ reg = <0 0x94400000 0 0x800000>;
+ };
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x3c000000>;
+ alloc-ranges = <0 0x96000000 0 0x3c000000>;
+ };
+
+ vdev0vring0: vdev0vring0@90000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90000000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@90008000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90008000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: vdev1vring0@90010000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90010000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: vdev1vring1@90018000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90018000 0 0x8000>;
+ no-map;
+ };
+
+ vdevbuffer: vdevbuffer {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90400000 0 0x100000>;
+ no-map;
+ };
+ };
+
+ sound_card: sound-card {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,name = "imx8qxp-sgtl5000";
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&sgtl5000_a>;
+ clocks = <&mclkout0_lpcg 0>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai0>;
+ };
+ };
+
+ vdd_3v3_vga: regulator-vga-avcc {
+ compatible = "regulator-fixed";
+ regulator-name = "+3.3V_AVCC_VGA";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+/* Colibri Analogue Inputs */
+&adc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0>;
+ status = "okay";
+ vref-supply = <&reg_module_vref_1v8>;
+};
+
+/* Colibri PWM_A */
+&adma_pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_a>;
+ #pwm-cells = <3>;
+};
+
+&cameradev {
+ status = "disabled";
+};
+
+/* Display Prefetch Resolve, (Tiling) */
+&dc0_dpr1_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr1_channel3 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel1 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel2 {
+ status = "okay";
+};
+
+&dc0_dpr2_channel3 {
+ status = "okay";
+};
+
+&dc0_pc {
+ status = "okay";
+};
+
+&dc0_prg1 {
+ status = "okay";
+};
+
+&dc0_prg2 {
+ status = "okay";
+};
+
+&dc0_prg3 {
+ status = "okay";
+};
+
+&dc0_prg4 {
+ status = "okay";
+};
+
+&dc0_prg5 {
+ status = "okay";
+};
+
+&dc0_prg6 {
+ status = "okay";
+};
+
+&dc0_prg7 {
+ status = "okay";
+};
+
+&dc0_prg8 {
+ status = "okay";
+};
+
+&dc0_prg9 {
+ status = "okay";
+};
+
+&dpu1 {
+ status = "okay";
+};
+
+&dpu_disp1_lcdif {
+ remote-endpoint = <&lcd_display_in>;
+};
+
+&enet0_lpcg {
+ clocks = <&clk IMX_SC_R_ENET_0 IMX_SC_PM_CLK_PER>,
+ <&clk IMX_SC_R_ENET_0 IMX_SC_PM_CLK_PER>,
+ <&conn_axi_clk>,
+ <&clk IMX_SC_R_ENET_0 IMX_SC_C_DISABLE_50>,
+ <&conn_ipg_clk>,
+ <&conn_ipg_clk>;
+ clock-output-names = "enet0_lpcg_timer_clk",
+ "enet0_lpcg_txc_sampling_clk",
+ "enet0_lpcg_ahb_clk",
+ "enet0_lpcg_ref_50mhz_clk",
+ "enet0_lpcg_ipg_clk",
+ "enet0_lpcg_ipg_s_clk";
+};
+
+/* Colibri Ethernet */
+&fec1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_fec1>;
+ pinctrl-1 = <&pinctrl_fec1_sleep>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ fsl,wakeup_irq = <0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@2 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ max-speed = <100>;
+ reg = <2>;
+ };
+ };
+};
+
+/* Colibri optional CAN on UART_B RTS/CTS */
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_module_3v3>;
+};
+
+/* Colibri optional CAN on PS2 */
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_module_3v3>;
+};
+
+/* Colibri optional CAN on UART_A TXD/RXD */
+&flexcan3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan3>;
+ xceiver-supply = <&reg_module_3v3>;
+};
+
+&gpu_3d0 {
+ status = "okay";
+};
+
+&hsio_refb_clk {
+ status = "disabled";
+};
+
+/* On-module I2C */
+&i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ /*
+ * There is a shared clock between SGTL5000 and on-module USB hub,
+ * so it is a good way to handle pinmuxing for this clock on a parent
+ * device i2c0
+ */
+ pinctrl-0 = <&pinctrl_i2c0>, <&pinctrl_sgtl5000_usb_clk>;
+ status = "okay";
+
+ /* GPIO expander */
+ gpio_expander_43: gpio-expander@43 {
+ compatible = "fcs,fxl6408";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x43>;
+ inital_io_dir = <0xff>;
+ inital_output = <0x05>;
+ gpio-line-names = "Wi-Fi_W_DISABLE", "Wi-Fi_WKUP_WLAN",
+ "PWR_EN_+V3.3_WiFi_N", "PCIe_REF_CLK_EN",
+ "USB_RESET_N", "USB_BYPASS_N", "Wi-Fi_PDn",
+ "Wi-Fi_WKUP_BT";
+ };
+
+ sgtl5000_a: sgtl5000@a {
+ compatible = "fsl,sgtl5000";
+ #sound-dai-cells = <0>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&mclkout0_lpcg 0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12000000>, <12000000>;
+ clocks = <&mclkout0_lpcg 0>;
+ clock-names = "mclk";
+ reg = <0xa>;
+ VDDA-supply = <&reg_module_3v3_avdd>;
+ VDDIO-supply = <&reg_module_3v3>;
+ VDDD-supply = <&reg_module_vref_1v8>;
+ };
+
+ /* USB3503A */
+ usb3803@8 {
+ compatible = "smsc,usb3803";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb3503a>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&mclkout0_lpcg 0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12000000>, <12000000>;
+ bypass-gpios = <&gpio_expander_43 5 GPIO_ACTIVE_LOW>;
+ clocks = <&mclkout0_lpcg 0>;
+ clock-names = "refclk";
+ disabled-ports = <2>;
+ initial-mode = <1>;
+ intn-gpios = <&lsio_gpio3 4 GPIO_ACTIVE_LOW>;
+ non-removable-devices = <1>;
+ reg = <0x8>;
+ reset-gpios = <&gpio_expander_43 4 GPIO_ACTIVE_LOW>;
+ };
+};
+
+/* MIPI DSI accessible on FFC (X2) */
+&i2c0_mipi_lvds0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c0_mipi_lvds0>;
+ clock-frequency = <100000>;
+};
+
+/* On-module MIPI CSI I2C accessible on FFC (X3) */
+&i2c0_mipi_lvds1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c0_mipi_lvds1>;
+};
+
+/* Colibri I2C */
+&i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+};
+
+&imx8_gpu_ss {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog0>, <&pinctrl_hog1>, <&pinctrl_hog2>,
+ <&pinctrl_ext_io0>;
+
+ colibri-imx8qxp {
+ /* Colibri Analogue Inputs */
+ pinctrl_adc0: adc0grp {
+ fsl,pins = <
+ IMX8QXP_ADC_IN0_ADMA_ADC_IN0 0x60 /* SODIMM 8 */
+ IMX8QXP_ADC_IN1_ADMA_ADC_IN1 0x60 /* SODIMM 6 */
+ IMX8QXP_ADC_IN4_ADMA_ADC_IN4 0x60 /* SODIMM 4 */
+ IMX8QXP_ADC_IN5_ADMA_ADC_IN5 0x60 /* SODIMM 2 */
+ >;
+ };
+
+ pinctrl_can_int: can-int-grp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DQS_LSIO_GPIO3_IO13 0x40 /* SODIMM 73 */
+ >;
+ };
+
+ pinctrl_csi_ctl: csictlgrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_SS0_B_LSIO_GPIO3_IO14 0x20 /* SODIMM 77 */
+ IMX8QXP_QSPI0A_SS1_B_LSIO_GPIO3_IO15 0x20 /* SODIMM 89 */
+ >;
+ };
+
+ pinctrl_gpiokeys: gpiokeysgrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA1_LSIO_GPIO3_IO10 0x06700041 /* SODIMM 45 */
+ >;
+ };
+
+ /* Colibri UART_B */
+ pinctrl_lpuart0: lpuart0grp {
+ fsl,pins = <
+ IMX8QXP_UART0_RX_ADMA_UART0_RX 0x06000020 /* SODIMM 36 */
+ IMX8QXP_UART0_TX_ADMA_UART0_TX 0x06000020 /* SODIMM 38 */
+ IMX8QXP_FLEXCAN0_RX_ADMA_UART0_RTS_B 0x06000020 /* SODIMM 34 */
+ IMX8QXP_FLEXCAN0_TX_ADMA_UART0_CTS_B 0x06000020 /* SODIMM 32 */
+ >;
+ };
+
+ /* Colibri UART_C */
+ pinctrl_lpuart2: lpuart2grp {
+ fsl,pins = <
+ IMX8QXP_UART2_RX_ADMA_UART2_RX 0x06000020 /* SODIMM 19 */
+ IMX8QXP_UART2_TX_ADMA_UART2_TX 0x06000020 /* SODIMM 21 */
+ >;
+ };
+
+ /* Colibri UART_A */
+ pinctrl_lpuart3: lpuart3grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN2_RX_ADMA_UART3_RX 0x06000020 /* SODIMM 33 */
+ IMX8QXP_FLEXCAN2_TX_ADMA_UART3_TX 0x06000020 /* SODIMM 35 */
+ >;
+ };
+
+ /* Colibri UART_A Control */
+ pinctrl_lpuart3_ctrl: lpuart3ctrlgrp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_GPIO0_01_LSIO_GPIO2_IO00 0x20 /* SODIMM 23 */
+ IMX8QXP_SAI1_RXD_LSIO_GPIO0_IO29 0x20 /* SODIMM 25 */
+ IMX8QXP_SAI1_RXC_LSIO_GPIO0_IO30 0x20 /* SODIMM 27 */
+ IMX8QXP_CSI_RESET_LSIO_GPIO3_IO03 0x20 /* SODIMM 29 */
+ IMX8QXP_USDHC1_CD_B_LSIO_GPIO4_IO22 0x20 /* SODIMM 31 */
+ IMX8QXP_CSI_EN_LSIO_GPIO3_IO02 0x20 /* SODIMM 37 */
+ >;
+ };
+
+ /* Colibri Ethernet: On-module 100Mbps PHY Micrel KSZ8041 */
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ IMX8QXP_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0_PAD 0x000014a0 /* Use pads in 3.3V mode */
+ IMX8QXP_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB1_PAD 0x000014a0 /* Use pads in 3.3V mode */
+ IMX8QXP_ENET0_MDC_CONN_ENET0_MDC 0x06000020
+ IMX8QXP_ENET0_MDIO_CONN_ENET0_MDIO 0x06000020
+ IMX8QXP_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x61
+ IMX8QXP_ENET0_RGMII_TXC_CONN_ENET0_RCLK50M_OUT 0x06000061
+ IMX8QXP_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x61
+ IMX8QXP_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x61
+ IMX8QXP_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x61
+ IMX8QXP_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x61
+ IMX8QXP_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x61
+ IMX8QXP_ENET0_RGMII_RXD2_CONN_ENET0_RMII_RX_ER 0x61
+ >;
+ };
+
+ pinctrl_fec1_sleep: fec1-sleep-grp {
+ fsl,pins = <
+ IMX8QXP_ENET0_MDC_LSIO_GPIO5_IO11 0x06000041
+ IMX8QXP_ENET0_MDIO_LSIO_GPIO5_IO10 0x06000041
+ IMX8QXP_ENET0_RGMII_TX_CTL_LSIO_GPIO4_IO30 0x41
+ IMX8QXP_ENET0_RGMII_TXC_LSIO_GPIO4_IO29 0x41
+ IMX8QXP_ENET0_RGMII_TXD0_LSIO_GPIO4_IO31 0x41
+ IMX8QXP_ENET0_RGMII_TXD1_LSIO_GPIO5_IO00 0x41
+ IMX8QXP_ENET0_RGMII_RX_CTL_LSIO_GPIO5_IO04 0x41
+ IMX8QXP_ENET0_RGMII_RXD0_LSIO_GPIO5_IO05 0x41
+ IMX8QXP_ENET0_RGMII_RXD1_LSIO_GPIO5_IO06 0x41
+ IMX8QXP_ENET0_RGMII_RXD2_LSIO_GPIO5_IO07 0x41
+ >;
+ };
+
+ /* Colibri LCD Back-Light GPIO */
+ pinctrl_gpio_bl_on: gpio-bl-on {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA3_LSIO_GPIO3_IO12 0x60 /* SODIMM 71 */
+ >;
+ };
+
+ pinctrl_hog0: hog0grp {
+ fsl,pins = <
+ IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB_PAD 0x000514a0 /* Use pads in 3.3V mode */
+ >;
+ };
+
+ pinctrl_hog1: hog1grp {
+ fsl,pins = <
+ IMX8QXP_ENET0_RGMII_TXD3_LSIO_GPIO5_IO02 0x06000020 /* SODIMM 65 */
+ IMX8QXP_CSI_D07_CI_PI_D09 0x61 /* SODIMM 65 */
+ IMX8QXP_QSPI0A_DATA2_LSIO_GPIO3_IO11 0x20 /* SODIMM 69 */
+ IMX8QXP_SAI0_TXC_LSIO_GPIO0_IO26 0x20 /* SODIMM 79 */
+ IMX8QXP_CSI_D02_CI_PI_D04 0x61 /* SODIMM 79 */
+ IMX8QXP_ENET0_RGMII_RXC_LSIO_GPIO5_IO03 0x06000020 /* SODIMM 85 */
+ IMX8QXP_CSI_D06_CI_PI_D08 0x61 /* SODIMM 85 */
+ IMX8QXP_QSPI0B_SCLK_LSIO_GPIO3_IO17 0x20 /* SODIMM 95 */
+ IMX8QXP_SAI0_RXD_LSIO_GPIO0_IO27 0x20 /* SODIMM 97 */
+ IMX8QXP_CSI_D03_CI_PI_D05 0x61 /* SODIMM 97 */
+ IMX8QXP_QSPI0B_DATA0_LSIO_GPIO3_IO18 0x20 /* SODIMM 99 */
+ IMX8QXP_SAI0_TXFS_LSIO_GPIO0_IO28 0x20 /* SODIMM 101 */
+ IMX8QXP_CSI_D00_CI_PI_D02 0x61 /* SODIMM 101 */
+ IMX8QXP_SAI0_TXD_LSIO_GPIO0_IO25 0x20 /* SODIMM 103 */
+ IMX8QXP_CSI_D01_CI_PI_D03 0x61 /* SODIMM 103 */
+ IMX8QXP_QSPI0B_DATA1_LSIO_GPIO3_IO19 0x20 /* SODIMM 105 */
+ IMX8QXP_USB_SS3_TC2_LSIO_GPIO4_IO05 0x20 /* SODIMM 127 */
+ IMX8QXP_USB_SS3_TC3_LSIO_GPIO4_IO06 0x20 /* SODIMM 131 */
+ IMX8QXP_USB_SS3_TC1_LSIO_GPIO4_IO04 0x20 /* SODIMM 133 */
+ IMX8QXP_CSI_PCLK_LSIO_GPIO3_IO00 0x20 /* SODIMM 96 */
+ IMX8QXP_QSPI0B_DATA3_LSIO_GPIO3_IO21 0x20 /* SODIMM 98 */
+ IMX8QXP_SAI1_RXFS_LSIO_GPIO0_IO31 0x20 /* SODIMM 100 */
+ IMX8QXP_QSPI0B_DQS_LSIO_GPIO3_IO22 0x20 /* SODIMM 102 */
+ IMX8QXP_QSPI0B_SS0_B_LSIO_GPIO3_IO23 0x20 /* SODIMM 104 */
+ >;
+ };
+
+ pinctrl_hog2: hog2grp {
+ fsl,pins = <
+ IMX8QXP_CSI_MCLK_LSIO_GPIO3_IO01 0x20 /* SODIMM 75 */
+ IMX8QXP_QSPI0A_SCLK_LSIO_GPIO3_IO16 0x20 /* SODIMM 93 */
+ >;
+ };
+
+ /*
+ * This pin is used in the SCFW as a UART. Using it from
+ * Linux would require rewritting the SCFW board file.
+ */
+ pinctrl_hog_scfw: hogscfwgrp {
+ fsl,pins = <
+ IMX8QXP_SCU_GPIO0_00_LSIO_GPIO2_IO03 0x20 /* SODIMM 144 */
+ >;
+ };
+
+ /* On Module I2C */
+ pinctrl_i2c0: i2c0grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_CSI0_GPIO0_00_ADMA_I2C0_SCL 0x06000021
+ IMX8QXP_MIPI_CSI0_GPIO0_01_ADMA_I2C0_SDA 0x06000021
+ >;
+ };
+
+ /* Colibri I2C */
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI0_GPIO0_00_ADMA_I2C1_SCL 0x06000021 /* SODIMM 196 */
+ IMX8QXP_MIPI_DSI0_GPIO0_01_ADMA_I2C1_SDA 0x06000021 /* SODIMM 194 */
+ >;
+ };
+
+ /* Colibri optional CAN on UART_B RTS/CTS */
+ pinctrl_flexcan1: flexcan0grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN0_TX_ADMA_FLEXCAN0_TX 0x21 /* SODIMM 32 */
+ IMX8QXP_FLEXCAN0_RX_ADMA_FLEXCAN0_RX 0x21 /* SODIMM 34 */
+ >;
+ };
+
+ /* Colibri optional CAN on PS2 */
+ pinctrl_flexcan2: flexcan1grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN1_TX_ADMA_FLEXCAN1_TX 0x21 /* SODIMM 55 */
+ IMX8QXP_FLEXCAN1_RX_ADMA_FLEXCAN1_RX 0x21 /* SODIMM 63 */
+ >;
+ };
+
+ /* Colibri optional CAN on UART_A TXD/RXD */
+ pinctrl_flexcan3: flexcan2grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN2_TX_ADMA_FLEXCAN2_TX 0x21 /* SODIMM 35 */
+ IMX8QXP_FLEXCAN2_RX_ADMA_FLEXCAN2_RX 0x21 /* SODIMM 33 */
+ >;
+ };
+
+ /* On module wifi module */
+ pinctrl_pcieb: pciebgrp {
+ fsl,pins = <
+ IMX8QXP_PCIE_CTRL0_CLKREQ_B_LSIO_GPIO4_IO01 0x04000061 /* SODIMM 178 */
+ IMX8QXP_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO02 0x04000061 /* SODIMM 94 */
+ IMX8QXP_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO00 0x60 /* SODIMM 81 */
+ >;
+ };
+
+ /* Colibri PWM_A */
+ pinctrl_pwm_a: pwma {
+ /* both pins are connected together, reserve the unused CSI_D05 */
+ fsl,pins = <
+ IMX8QXP_CSI_D05_CI_PI_D07 0x61 /* SODIMM 59 */
+ IMX8QXP_SPI0_CS1_ADMA_LCD_PWM0_OUT 0x60 /* SODIMM 59 */
+ >;
+ };
+
+ /* Colibri PWM_B */
+ pinctrl_pwm_b: pwmb {
+ fsl,pins = <
+ IMX8QXP_UART1_TX_LSIO_PWM0_OUT 0x60 /* SODIMM 28 */
+ >;
+ };
+
+ /* Colibri PWM_C */
+ pinctrl_pwm_c: pwmc {
+ fsl,pins = <
+ IMX8QXP_UART1_RX_LSIO_PWM1_OUT 0x60 /* SODIMM 30 */
+ >;
+ };
+
+ /* Colibri PWM_D */
+ pinctrl_pwm_d: pwmd {
+ /* both pins are connected together, reserve the unused CSI_D04 */
+ fsl,pins = <
+ IMX8QXP_CSI_D04_CI_PI_D06 0x61 /* SODIMM 67 */
+ IMX8QXP_UART1_RTS_B_LSIO_PWM2_OUT 0x60 /* SODIMM 67 */
+ >;
+ };
+
+ /* On-module I2S */
+ pinctrl_sai0: sai0grp {
+ fsl,pins = <
+ IMX8QXP_SPI0_SDI_ADMA_SAI0_TXD 0x06000040
+ IMX8QXP_SPI0_CS0_ADMA_SAI0_RXD 0x06000040
+ IMX8QXP_SPI0_SCK_ADMA_SAI0_TXC 0x06000040
+ IMX8QXP_SPI0_SDO_ADMA_SAI0_TXFS 0x06000040
+ >;
+ };
+
+ /* Colibri Audio Analogue Microphone GND */
+ pinctrl_sgtl5000: sgtl5000 {
+ fsl,pins = <
+ /* MIC GND EN */
+ IMX8QXP_MIPI_CSI0_I2C0_SDA_LSIO_GPIO3_IO06 0x41
+ >;
+ };
+
+ /* On-module SGTL5000 clock */
+ pinctrl_sgtl5000_usb_clk: sgtl5000-usb-clk {
+ fsl,pins = <
+ IMX8QXP_ADC_IN3_ADMA_ACM_MCLK_OUT0 0x21
+ >;
+ };
+
+ /* On-module USB interrupt */
+ pinctrl_usb3503a: usb3503a-grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_CSI0_MCLK_OUT_LSIO_GPIO3_IO04 0x61
+ >;
+ };
+
+ /* Colibri USB Client Cable Detect */
+ pinctrl_usbc_det: usbc-det {
+ fsl,pins = <
+ IMX8QXP_ENET0_REFCLK_125M_25M_LSIO_GPIO5_IO09 0x06000040 /* SODIMM 137 */
+ >;
+ };
+
+ pinctrl_ext_io0: ext-io0 {
+ fsl,pins = <
+ IMX8QXP_ENET0_RGMII_RXD3_LSIO_GPIO5_IO08 0x06000040 /* SODIMM 135 */
+ >;
+ };
+
+ /* Colibri Parallel RGB LCD Interface */
+ pinctrl_lcdif: lcdif-pins {
+ fsl,pins = <
+ IMX8QXP_USDHC1_RESET_B_LSIO_GPIO4_IO19 0x40 /* SODIMM 44 */
+ IMX8QXP_MCLK_IN1_ADMA_LCDIF_EN 0x40 /* SODIMM 44 */
+ IMX8QXP_MCLK_OUT0_ADMA_LCDIF_CLK 0x60 /* SODIMM 56 */
+ IMX8QXP_SPI3_CS0_ADMA_LCDIF_HSYNC 0x60 /* SODIMM 68 */
+ IMX8QXP_MCLK_IN0_ADMA_LCDIF_VSYNC 0x60 /* SODIMM 82 */
+ IMX8QXP_ESAI0_FSR_ADMA_LCDIF_D00 0x60 /* SODIMM 76 */
+ IMX8QXP_USDHC1_WP_LSIO_GPIO4_IO21 0x60 /* SODIMM 76 */
+ IMX8QXP_ESAI0_FST_ADMA_LCDIF_D01 0x60 /* SODIMM 70 */
+ IMX8QXP_ESAI0_SCKR_ADMA_LCDIF_D02 0x60 /* SODIMM 60 */
+ IMX8QXP_ESAI0_SCKT_ADMA_LCDIF_D03 0x60 /* SODIMM 58 */
+ IMX8QXP_ESAI0_TX0_ADMA_LCDIF_D04 0x60 /* SODIMM 78 */
+ IMX8QXP_ESAI0_TX1_ADMA_LCDIF_D05 0x60 /* SODIMM 72 */
+ IMX8QXP_ESAI0_TX2_RX3_ADMA_LCDIF_D06 0x60 /* SODIMM 80 */
+ IMX8QXP_ESAI0_TX3_RX2_ADMA_LCDIF_D07 0x60 /* SODIMM 46 */
+ IMX8QXP_ESAI0_TX4_RX1_ADMA_LCDIF_D08 0x60 /* SODIMM 62 */
+ IMX8QXP_ESAI0_TX5_RX0_ADMA_LCDIF_D09 0x60 /* SODIMM 48 */
+ IMX8QXP_SPDIF0_RX_ADMA_LCDIF_D10 0x60 /* SODIMM 74 */
+ IMX8QXP_SPDIF0_TX_ADMA_LCDIF_D11 0x60 /* SODIMM 50 */
+ IMX8QXP_SPDIF0_EXT_CLK_ADMA_LCDIF_D12 0x60 /* SODIMM 52 */
+ IMX8QXP_SPI3_SCK_ADMA_LCDIF_D13 0x60 /* SODIMM 54 */
+ IMX8QXP_SPI3_SDO_ADMA_LCDIF_D14 0x60 /* SODIMM 66 */
+ IMX8QXP_SPI3_SDI_ADMA_LCDIF_D15 0x60 /* SODIMM 64 */
+ IMX8QXP_SPI3_CS1_ADMA_LCDIF_D16 0x60 /* SODIMM 57 */
+ IMX8QXP_ENET0_RGMII_TXD2_LSIO_GPIO5_IO01 0x60 /* SODIMM 57 */
+ IMX8QXP_UART1_CTS_B_ADMA_LCDIF_D17 0x60 /* SODIMM 61 */
+ >;
+ };
+
+ /* USB Host Power Enable */
+ pinctrl_usbh1_reg: usbh1-reg {
+ fsl,pins = <
+ IMX8QXP_USB_SS3_TC0_LSIO_GPIO4_IO03 0x06000040 /* SODIMM 129 */
+ >;
+ };
+
+ /* On-module eMMC */
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x21
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x21
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x21
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x21
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x21
+ IMX8QXP_EMMC0_DATA4_CONN_EMMC0_DATA4 0x21
+ IMX8QXP_EMMC0_DATA5_CONN_EMMC0_DATA5 0x21
+ IMX8QXP_EMMC0_DATA6_CONN_EMMC0_DATA6 0x21
+ IMX8QXP_EMMC0_DATA7_CONN_EMMC0_DATA7 0x21
+ IMX8QXP_EMMC0_STROBE_CONN_EMMC0_STROBE 0x41
+ IMX8QXP_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x21
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x21
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x21
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x21
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x21
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x21
+ IMX8QXP_EMMC0_DATA4_CONN_EMMC0_DATA4 0x21
+ IMX8QXP_EMMC0_DATA5_CONN_EMMC0_DATA5 0x21
+ IMX8QXP_EMMC0_DATA6_CONN_EMMC0_DATA6 0x21
+ IMX8QXP_EMMC0_DATA7_CONN_EMMC0_DATA7 0x21
+ IMX8QXP_EMMC0_STROBE_CONN_EMMC0_STROBE 0x41
+ IMX8QXP_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x21
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ IMX8QXP_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QXP_EMMC0_CMD_CONN_EMMC0_CMD 0x21
+ IMX8QXP_EMMC0_DATA0_CONN_EMMC0_DATA0 0x21
+ IMX8QXP_EMMC0_DATA1_CONN_EMMC0_DATA1 0x21
+ IMX8QXP_EMMC0_DATA2_CONN_EMMC0_DATA2 0x21
+ IMX8QXP_EMMC0_DATA3_CONN_EMMC0_DATA3 0x21
+ IMX8QXP_EMMC0_DATA4_CONN_EMMC0_DATA4 0x21
+ IMX8QXP_EMMC0_DATA5_CONN_EMMC0_DATA5 0x21
+ IMX8QXP_EMMC0_DATA6_CONN_EMMC0_DATA6 0x21
+ IMX8QXP_EMMC0_DATA7_CONN_EMMC0_DATA7 0x21
+ IMX8QXP_EMMC0_STROBE_CONN_EMMC0_STROBE 0x41
+ IMX8QXP_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x21
+ >;
+ };
+
+ /* Colibri SDCard CardDetect */
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA0_LSIO_GPIO3_IO09 0x06000021 /* SODIMM 43 */
+ >;
+ };
+
+ pinctrl_usdhc2_gpio_sleep: usdhc2gpioslpgrp {
+ fsl,pins = <
+ IMX8QXP_QSPI0A_DATA0_LSIO_GPIO3_IO09 0x60 /* SODIMM 43 */
+ >;
+ };
+
+ /* Colibri SDCard */
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 /* SODIMM 47 */
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x21 /* SODIMM 190 */
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x21 /* SODIMM 192 */
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x21 /* SODIMM 49 */
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x21 /* SODIMM 51 */
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x21 /* SODIMM 53 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 /* SODIMM 47 */
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x21 /* SODIMM 190 */
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x21 /* SODIMM 192 */
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x21 /* SODIMM 49 */
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x21 /* SODIMM 51 */
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x21 /* SODIMM 53 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_CONN_USDHC1_CLK 0x06000041 /* SODIMM 47 */
+ IMX8QXP_USDHC1_CMD_CONN_USDHC1_CMD 0x21 /* SODIMM 190 */
+ IMX8QXP_USDHC1_DATA0_CONN_USDHC1_DATA0 0x21 /* SODIMM 192 */
+ IMX8QXP_USDHC1_DATA1_CONN_USDHC1_DATA1 0x21 /* SODIMM 49 */
+ IMX8QXP_USDHC1_DATA2_CONN_USDHC1_DATA2 0x21 /* SODIMM 51 */
+ IMX8QXP_USDHC1_DATA3_CONN_USDHC1_DATA3 0x21 /* SODIMM 53 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ pinctrl_usdhc2_sleep: usdhc2slpgrp {
+ fsl,pins = <
+ IMX8QXP_USDHC1_CLK_LSIO_GPIO4_IO23 0x60 /* SODIMM 47 */
+ IMX8QXP_USDHC1_CMD_LSIO_GPIO4_IO24 0x60 /* SODIMM 190 */
+ IMX8QXP_USDHC1_DATA0_LSIO_GPIO4_IO25 0x60 /* SODIMM 192 */
+ IMX8QXP_USDHC1_DATA1_LSIO_GPIO4_IO26 0x60 /* SODIMM 49 */
+ IMX8QXP_USDHC1_DATA2_LSIO_GPIO4_IO27 0x60 /* SODIMM 51 */
+ IMX8QXP_USDHC1_DATA3_LSIO_GPIO4_IO28 0x60 /* SODIMM 53 */
+ IMX8QXP_USDHC1_VSELECT_CONN_USDHC1_VSELECT 0x21
+ >;
+ };
+
+ /* MIPI DSI I2C accessible on SODIMM (X1) and FFC (X2) */
+ pinctrl_i2c0_mipi_lvds0: mipi_lvds0_i2c0_grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI0_I2C0_SCL_MIPI_DSI0_I2C0_SCL 0xc6000020 /* SODIMM 140 */
+ IMX8QXP_MIPI_DSI0_I2C0_SDA_MIPI_DSI0_I2C0_SDA 0xc6000020 /* SODIMM 142 */
+ >;
+ };
+
+ /* MIPI CSI I2C accessible on SODIMM (X1) and FFC (X3) */
+ pinctrl_i2c0_mipi_lvds1: mipi_lvds1_i2c0_grp {
+ fsl,pins = <
+ IMX8QXP_MIPI_DSI1_I2C0_SCL_MIPI_DSI1_I2C0_SCL 0xc6000020 /* SODIMM 186 */
+ IMX8QXP_MIPI_DSI1_I2C0_SDA_MIPI_DSI1_I2C0_SDA 0xc6000020 /* SODIMM 188 */
+ >;
+ };
+
+ /* Colibri SPI */
+ pinctrl_lpspi2: lpspi2 {
+ fsl,pins = <
+ IMX8QXP_SPI2_CS0_LSIO_GPIO1_IO00 0x21 /* SODIMM 86 */
+ IMX8QXP_SPI2_SDO_ADMA_SPI2_SDO 0x06000040 /* SODIMM 92 */
+ IMX8QXP_SPI2_SDI_ADMA_SPI2_SDI 0x06000040 /* SODIMM 90 */
+ IMX8QXP_SPI2_SCK_ADMA_SPI2_SCK 0x06000040 /* SODIMM 88 */
+ >;
+ };
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ IMX8QXP_SCU_BOOT_MODE3_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0x20
+ >;
+ };
+ };
+};
+
+&isi_0 {
+ interface = <2 0 2>;
+ /**
+ * interface = <Input MIPI_VCx Output>
+ * Input: 0-DC0, 1-DC1, 2-MIPI CSI0, 3-MIPI CSI1, 4-HDMI, 5-MEM, INPUT: 6-PARALLEL CSI
+ * MIPI_VCx: 0-VC0, 1-VC1, 2-VC2, 3-VC3, MIPI CSI only
+ * Output: 0-DC0, 1-DC1, 2-MEM
+ */
+};
+
+&isi_1 {
+ interface = <6 0 2>;
+ parallel_csi;
+};
+
+/* Colibri SPI */
+&lpspi2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ fsl,spi-num-chipselects = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi2>;
+ cs-gpios = <&lsio_gpio1 0 GPIO_ACTIVE_LOW>;
+};
+
+/* Colibri UART_B */
+&lpuart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart0>;
+};
+
+/* Colibri UART_C */
+&lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart2>;
+};
+
+/* Colibri UART_A */
+&lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart3>, <&pinctrl_lpuart3_ctrl>;
+};
+
+&lsio_gpio0 {
+ gpio-line-names = "",
+ "SODIMM_70",
+ "SODIMM_60",
+ "SODIMM_58",
+ "SODIMM_78",
+ "SODIMM_72",
+ "SODIMM_80",
+ "SODIMM_46",
+ "SODIMM_62",
+ "SODIMM_48",
+ "SODIMM_74",
+ "SODIMM_50",
+ "SODIMM_52",
+ "SODIMM_54",
+ "SODIMM_66",
+ "SODIMM_64",
+ "SODIMM_68",
+ "",
+ "",
+ "SODIMM_82",
+ "SODIMM_56",
+ "SODIMM_28",
+ "SODIMM_30",
+ "",
+ "SODIMM_61",
+ "SODIMM_103",
+ "",
+ "",
+ "",
+ "SODIMM_25",
+ "SODIMM_27",
+ "SODIMM_100";
+ status = "okay";
+};
+
+&lsio_gpio1 {
+ gpio-line-names = "SODIMM_86",
+ "SODIMM_92",
+ "SODIMM_90",
+ "SODIMM_88",
+ "",
+ "",
+ "",
+ "SODIMM_59",
+ "",
+ "SODIMM_6",
+ "SODIMM_8",
+ "",
+ "",
+ "SODIMM_2",
+ "SODIMM_4",
+ "SODIMM_34",
+ "SODIMM_32",
+ "SODIMM_63",
+ "SODIMM_55",
+ "SODIMM_33",
+ "SODIMM_35",
+ "SODIMM_36",
+ "SODIMM_38",
+ "SODIMM_21",
+ "SODIMM_19",
+ "SODIMM_140",
+ "SODIMM_142",
+ "SODIMM_196",
+ "SODIMM_194",
+ "SODIMM_186",
+ "SODIMM_188",
+ "SODIMM_138";
+ status = "okay";
+};
+
+&lsio_gpio2 {
+ gpio-line-names = "SODIMM_23",
+ "",
+ "",
+ "SODIMM_144";
+ status = "okay";
+};
+
+&lsio_gpio3 {
+ gpio-line-names = "SODIMM_96",
+ "SODIMM_75",
+ "SODIMM_37",
+ "SODIMM_29",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_43",
+ "SODIMM_45",
+ "SODIMM_69",
+ "SODIMM_71",
+ "SODIMM_73",
+ "SODIMM_77",
+ "SODIMM_89",
+ "SODIMM_93",
+ "SODIMM_95",
+ "SODIMM_99",
+ "SODIMM_105",
+ "SODIMM_107",
+ "SODIMM_98",
+ "SODIMM_102",
+ "SODIMM_104",
+ "SODIMM_106";
+ status = "okay";
+};
+
+&lsio_gpio4 {
+ gpio-line-names = "",
+ "",
+ "",
+ "SODIMM_129",
+ "SODIMM_133",
+ "SODIMM_127",
+ "SODIMM_131",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_44",
+ "",
+ "SODIMM_76",
+ "SODIMM_31",
+ "SODIMM_47",
+ "SODIMM_190",
+ "SODIMM_192",
+ "SODIMM_49",
+ "SODIMM_51",
+ "SODIMM_53";
+ status = "okay";
+};
+
+&lsio_gpio5 {
+ gpio-line-names = "",
+ "SODIMM_57",
+ "SODIMM_65",
+ "SODIMM_85",
+ "",
+ "",
+ "",
+ "",
+ "SODIMM_135",
+ "SODIMM_137",
+ "UNUSABLE_SODIMM_180",
+ "UNUSABLE_SODIMM_184";
+ status = "okay";
+};
+
+/* MIPI CSI accessible via FFC (X3) */
+&mipi_csi_0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /delete-property/virtual-channel;
+};
+
+&mipi0_dsi_host {
+ pwr-delay = <10>;
+};
+
+&mipi1_dsi_host {
+ pwr-delay = <10>;
+};
+
+/* On-module PCIe for wifi */
+&pcieb{
+ compatible = "fsl,imx8qxp-pcie","snps,dw-pcie";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcieb &pinctrl_wifi>;
+ clocks = <&pcieb_lpcg 0>,
+ <&pcieb_lpcg 1>,
+ <&pcieb_lpcg 2>,
+ <&phyx1_lpcg 0>,
+ <&phyx1_crr1_lpcg 0>,
+ <&pcieb_crr3_lpcg 0>,
+ <&misc_crr5_lpcg 0>,
+ <&pcie_refclk_gate>;
+ clock-names = "pcie", "pcie_bus", "pcie_inbound_axi",
+ "pcie_phy", "phy_per", "pcie_per", "misc_per",
+ "pcie_ext";
+
+ clkreq-gpio = <&lsio_gpio4 1 GPIO_ACTIVE_LOW>;
+ ext_osc = <1>;
+ fsl,max-link-speed = <1>;
+ hard-wired = <1>;
+ disable-gpio = <&gpio_expander_43 6 GPIO_ACTIVE_LOW>;
+ power-on-gpio = <&gpio_expander_43 2 GPIO_ACTIVE_LOW>;
+ reserved-region = <&rpmsg_reserved>;
+ reset-gpio = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+/* Colibri PWM_B */
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_b>;
+ #pwm-cells = <3>;
+};
+
+/* Colibri PWM_C */
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_c>;
+ #pwm-cells = <3>;
+};
+
+/* Colibri PWM_D */
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_d>;
+ #pwm-cells = <3>;
+};
+
+&rpmsg{
+ /*
+ * 64K for one rpmsg instance:
+ */
+ vdev-nums = <2>;
+ reg = <0x0 0x90000000 0x0 0x20000>;
+ memory-region = <&vdevbuffer>;
+ status = "okay";
+};
+
+/* On-module I2S */
+&sai0 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai0>;
+ status = "okay";
+};
+
+&thermal_zones {
+ pmic-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&tsens IMX_SC_R_PMIC_0>;
+
+ trips {
+ pmic_alert0: trip0 {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ pmic_crit0: trip1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&pmic_alert0>;
+ cooling-device =
+ <&A35_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A35_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A35_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A35_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+};
+
+/* On-module eMMC */
+&usdhc1 {
+ bus-width = <8>;
+ no-sd;
+ no-sdio;
+ non-removable;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ status = "okay";
+};
+
+/* Colibri SDCard */
+&usdhc2 {
+ bus-width = <4>;
+ cd-gpios = <&lsio_gpio3 9 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>;
+ disable-wp;
+ vmmc-supply = <&reg_module_3v3>;
+};
+
+&vpu_decoder {
+ boot-region = <&decoder_boot>;
+ rpc-region = <&decoder_rpc>;
+ reg-csr = <0x2d040000>;
+ core_type = <1>;
+ status = "okay";
+};
+
+&vpu_encoder {
+ boot-region = <&encoder_boot>;
+ rpc-region = <&encoder_rpc>;
+ reserved-region = <&encoder_reserved>;
+ reg-rpc-system = <0x40000000>;
+ resolution-max = <1920 1920>;
+ mbox-names = "enc1_tx0", "enc1_tx1", "enc1_rx";
+ mboxes = <&mu1_m0 0 0
+ &mu1_m0 0 1
+ &mu1_m0 1 0>;
+ status = "okay";
+
+ core0@1020000 {
+ compatible = "fsl,imx8-mu1-vpu-m0";
+ reg = <0x1020000 0x20000>;
+ reg-csr = <0x1050000 0x10000>;
+ interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,vpu_ap_mu_id = <17>;
+ fw-buf-size = <0x200000>;
+ rpc-buf-size = <0x80000>;
+ print-buf-size = <0x80000>;
+ };
+};
+
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 12309e8a6237..882429442ae0 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -23,46 +23,16 @@ CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
-CONFIG_ARCH_AGILEX=y
-CONFIG_ARCH_SUNXI=y
-CONFIG_ARCH_ALPINE=y
-CONFIG_ARCH_BCM2835=y
-CONFIG_ARCH_BCM_IPROC=y
-CONFIG_ARCH_BERLIN=y
-CONFIG_ARCH_BRCMSTB=y
-CONFIG_ARCH_EXYNOS=y
-CONFIG_ARCH_K3=y
-CONFIG_ARCH_LAYERSCAPE=y
-CONFIG_ARCH_LG1K=y
-CONFIG_ARCH_HISI=y
-CONFIG_ARCH_MEDIATEK=y
-CONFIG_ARCH_MESON=y
-CONFIG_ARCH_MVEBU=y
CONFIG_ARCH_MXC=y
-CONFIG_ARCH_QCOM=y
-CONFIG_ARCH_RENESAS=y
-CONFIG_ARCH_ROCKCHIP=y
-CONFIG_ARCH_S32=y
-CONFIG_SOC_S32V234=y
-CONFIG_ARCH_SEATTLE=y
-CONFIG_ARCH_STRATIX10=y
-CONFIG_ARCH_SYNQUACER=y
-CONFIG_ARCH_TEGRA=y
-CONFIG_ARCH_SPRD=y
-CONFIG_ARCH_THUNDER=y
-CONFIG_ARCH_THUNDER2=y
-CONFIG_ARCH_UNIPHIER=y
-CONFIG_ARCH_VEXPRESS=y
-CONFIG_ARCH_XGENE=y
-CONFIG_ARCH_ZX=y
-CONFIG_ARCH_ZYNQMP=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_NUMA=y
@@ -70,7 +40,7 @@ CONFIG_SECCOMP=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
-CONFIG_COMPAT=y
+CONFIG_FORCE_MAX_ZONEORDER=14
CONFIG_RANDOMIZE_BASE=y
CONFIG_PM_DEBUG=y
CONFIG_PM_TEST_SUSPEND=y
@@ -80,25 +50,20 @@ CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPUFREQ_DT=y
CONFIG_ACPI_CPPC_CPUFREQ=m
-CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_IMX_CPUFREQ_DT=y
-CONFIG_ARM_RASPBERRYPI_CPUFREQ=m
-CONFIG_ARM_TEGRA186_CPUFREQ=y
-CONFIG_QORIQ_CPUFREQ=y
CONFIG_ARM_SCPI_PROTOCOL=y
-CONFIG_RASPBERRYPI_FIRMWARE=y
-CONFIG_INTEL_STRATIX10_SERVICE=y
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_IMX_DSP=y
CONFIG_IMX_SCU=y
CONFIG_IMX_SCU_PD=y
+CONFIG_IMX_SECO_MU=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
@@ -113,15 +78,18 @@ CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_SHA3_ARM64=m
CONFIG_CRYPTO_SM3_ARM64_CE=m
+CONFIG_CRYPTO_SM4_ARM64_CE=m
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_CHACHA20_NEON=m
+CONFIG_CRYPTO_NHPOLY1305_NEON=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
@@ -155,19 +123,26 @@ CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
-CONFIG_BRIDGE_VLAN_FILTERING=y
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_VLAN_8021Q_MVRP=y
CONFIG_LLC2=y
-CONFIG_TSN=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_CBS=y
+CONFIG_NET_SCH_TAPRIO=y
+CONFIG_NET_SCH_MQPRIO=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
CONFIG_NET_SWITCHDEV=y
-CONFIG_QRTR=m
-CONFIG_QRTR_SMD=m
-CONFIG_QRTR_TUN=m
CONFIG_BPF_JIT=y
+CONFIG_NET_PKTGEN=y
CONFIG_CAN=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_VXCAN=m
+CONFIG_CAN_SLCAN=m
CONFIG_CAN_FLEXCAN=m
-CONFIG_BT=y
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_MCP25XXFD=m
+CONFIG_BT=m
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=y
@@ -179,53 +154,40 @@ CONFIG_BT_HIDP=y
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIBTUSB=m
-CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_ATH3K=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_HCIUART_QCA=y
-CONFIG_BT_HCIVHCI=y
-CONFIG_CFG80211=y
+CONFIG_BT_HCIUART_MRVL=y
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=m
CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_WEXT=y
-CONFIG_MAC80211=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
CONFIG_MAC80211_LEDS=y
-CONFIG_NET_9P=y
-CONFIG_NET_9P_VIRTIO=y
+CONFIG_RFKILL=m
+CONFIG_RFKILL_GPIO=m
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=y
CONFIG_PCI_IOV=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
-CONFIG_PCI_AARDVARK=y
-CONFIG_PCI_TEGRA=y
-CONFIG_PCIE_RCAR=y
CONFIG_PCI_HOST_GENERIC=y
-CONFIG_PCI_XGENE=y
-CONFIG_PCIE_ALTERA=y
-CONFIG_PCIE_ALTERA_MSI=y
-CONFIG_PCI_HOST_THUNDER_PEM=y
-CONFIG_PCI_HOST_THUNDER_ECAM=y
-CONFIG_PCIE_ROCKCHIP_HOST=m
CONFIG_PCI_IMX6=y
-CONFIG_PCI_LAYERSCAPE=y
-CONFIG_PCI_HISI=y
-CONFIG_PCIE_QCOM=y
-CONFIG_PCIE_ARMADA_8K=y
-CONFIG_PCIE_KIRIN=y
-CONFIG_PCIE_HISI_STB=y
-CONFIG_PCIE_TEGRA194=m
-CONFIG_PCIE_LAYERSCAPE_GEN4=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_FW_LOADER_USER_HELPER=y
-CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
-CONFIG_HISILICON_LPC=y
+CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_SIMPLE_PM_BUS=y
-CONFIG_FSL_MC_BUS=y
-CONFIG_FSL_MC_UAPI_SUPPORT=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
@@ -240,19 +202,17 @@ CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
-CONFIG_MTD_NAND_MARVELL=y
-CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_MTD_NAND_GPMI_NAND=y
-CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_SPI_NOR=y
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
+CONFIG_XEN_BLKDEV_BACKEND=m
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=y
-CONFIG_SENSORS_FXOS8700=y
-CONFIG_SENSORS_FXAS2100X=y
+CONFIG_SENSORS_FXOS8700=m
+CONFIG_SENSORS_FXAS2100X=m
CONFIG_SRAM=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=m
@@ -264,18 +224,12 @@ CONFIG_SCSI_HISI_SAS_PCI=y
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
-CONFIG_SCSI_UFS_QCOM=m
-CONFIG_SCSI_UFS_HISI=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_IMX=y
CONFIG_AHCI_CEVA=y
-CONFIG_AHCI_MVEBU=y
-CONFIG_AHCI_XGENE=y
-CONFIG_AHCI_QORIQ=y
CONFIG_SATA_SIL24=y
-CONFIG_SATA_RCAR=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_MD=y
@@ -289,216 +243,164 @@ CONFIG_MACVTAP=m
CONFIG_TUN=y
CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
-CONFIG_AMD_XGBE=y
-CONFIG_NET_XGENE=y
-CONFIG_ATL1C=m
-CONFIG_BNX2X=m
-CONFIG_MACB=y
-CONFIG_THUNDER_NIC_PF=y
CONFIG_FEC=y
-CONFIG_FSL_SDK_DPAA_ETH=y
-CONFIG_FSL_DPAA2_ETH=y
-CONFIG_FSL_ENETC=y
-CONFIG_FSL_ENETC_VF=y
-CONFIG_FSL_ENETC_MDIO=y
-CONFIG_ENETC_TSN=y
-CONFIG_HIX5HD2_GMAC=y
-CONFIG_HNS_DSAF=y
-CONFIG_HNS_ENET=y
-CONFIG_HNS3=y
-CONFIG_HNS3_HCLGE=y
-CONFIG_HNS3_ENET=y
-CONFIG_E1000=y
-CONFIG_E1000E=y
-CONFIG_IGB=y
-CONFIG_IGBVF=y
-CONFIG_MVNETA=y
-CONFIG_MVPP2=y
-CONFIG_SKY2=y
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IGB=m
+CONFIG_IGBVF=m
+CONFIG_SKY2=m
CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y
-CONFIG_MSCC_OCELOT_SWITCH=y
-CONFIG_QCOM_EMAC=m
-CONFIG_RAVB=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-CONFIG_SNI_AVE=y
-CONFIG_SNI_NETSEC=y
-CONFIG_STMMAC_ETH=m
+CONFIG_SMC91X=m
+CONFIG_SMSC911X=m
+CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
-CONFIG_AQUANTIA_PHY=y
-CONFIG_AT803X_PHY=y
-CONFIG_INPHI_PHY=y
+CONFIG_AT803X_PHY=m
+CONFIG_INPHI_PHY=m
CONFIG_MARVELL_PHY=m
-CONFIG_MARVELL_10G_PHY=m
-CONFIG_MESON_GXL_PHY=m
CONFIG_MICREL_PHY=y
-CONFIG_MICROSEMI_PHY=y
-CONFIG_NXP_TJA11XX_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_ROCKCHIP_PHY=y
-CONFIG_VITESSE_PHY=y
+CONFIG_MICROSEMI_PHY=m
+CONFIG_NXP_TJA11XX_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_PPP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_ASYNC=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
-CONFIG_USB_USBNET=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9800=m
CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
-CONFIG_BRCMFMAC=m
-CONFIG_BRCMFMAC_PCIE=y
-CONFIG_HOSTAP=y
-CONFIG_WL18XX=m
-CONFIG_WLCORE_SDIO=m
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_MWIFIEX_PCIE=m
+CONFIG_MWIFIEX_USB=m
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_NXP is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_RTL_CARDS is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_IVSHMEM_NET=m
+CONFIG_INPUT_MATRIXKMAP=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_SNVS_PWRKEY=y
CONFIG_KEYBOARD_IMX_SC_PWRKEY=y
-CONFIG_KEYBOARD_CROS_EC=y
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_COLIBRI_VF50=m
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C=m
CONFIG_INPUT_MISC=y
-CONFIG_INPUT_PM8941_PWRKEY=y
-CONFIG_INPUT_HISI_POWERKEY=y
-CONFIG_INPUT_MPL3115=y
-CONFIG_INPUT_ISL29023=y
+CONFIG_INPUT_MPL3115=m
+CONFIG_INPUT_ISL29023=m
# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIO_AMBAKMI=m
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_8250_DW=y
-CONFIG_SERIAL_8250_OMAP=y
-CONFIG_SERIAL_8250_MT6577=y
-CONFIG_SERIAL_8250_UNIPHIER=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_SERIAL_MESON=y
-CONFIG_SERIAL_MESON_CONSOLE=y
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_SERIAL_TEGRA=y
-CONFIG_SERIAL_TEGRA_TCU=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_MSM_CONSOLE=y
-CONFIG_SERIAL_QCOM_GENI=y
-CONFIG_SERIAL_QCOM_GENI_CONSOLE=y
-CONFIG_SERIAL_XILINX_PS_UART=y
-CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_FSL_LINFLEXUART=y
CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
-CONFIG_SERIAL_MVEBU_UART=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_TCG_TPM=y
-CONFIG_TCG_TIS_I2C_INFINEON=y
+CONFIG_TCG_TIS_I2C_INFINEON=m
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
-CONFIG_I2C_BCM2835=m
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_GPIO=m
CONFIG_I2C_IMX=y
CONFIG_I2C_IMX_LPI2C=y
-CONFIG_I2C_MESON=y
-CONFIG_I2C_MV64XXX=y
-CONFIG_I2C_PXA=y
-CONFIG_I2C_QCOM_GENI=m
-CONFIG_I2C_QUP=y
CONFIG_I2C_RK3X=y
CONFIG_I2C_RPBUS=y
-CONFIG_I2C_SH_MOBILE=y
-CONFIG_I2C_TEGRA=y
-CONFIG_I2C_UNIPHIER_F=y
-CONFIG_I2C_RCAR=y
-CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_XEN_I2C_BACKEND=y
+CONFIG_I2C_SLAVE=y
CONFIG_SPI=y
-CONFIG_SPI_ARMADA_3700=y
-CONFIG_SPI_BCM2835=m
-CONFIG_SPI_BCM2835AUX=m
CONFIG_SPI_FSL_LPSPI=y
CONFIG_SPI_FSL_QUADSPI=y
CONFIG_SPI_NXP_FLEXSPI=y
+CONFIG_SPI_GPIO=y
CONFIG_SPI_IMX=y
-CONFIG_SPI_FSL_DSPI=y
-CONFIG_SPI_MESON_SPICC=m
-CONFIG_SPI_MESON_SPIFC=m
-CONFIG_SPI_ORION=y
+CONFIG_SPI_FSL_SPI=y
CONFIG_SPI_PL022=y
-CONFIG_SPI_ROCKCHIP=y
-CONFIG_SPI_QUP=y
-CONFIG_SPI_S3C64XX=y
-CONFIG_SPI_SUN6I=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=y
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y
CONFIG_SPMI=y
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_IMX8MM=y
CONFIG_PINCTRL_IMX8MN=y
+CONFIG_PINCTRL_IMX8MP=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_PINCTRL_IMX8QM=y
CONFIG_PINCTRL_IMX8QXP=y
CONFIG_PINCTRL_IMX8DXL=y
-CONFIG_PINCTRL_IPQ8074=y
-CONFIG_PINCTRL_MSM8916=y
-CONFIG_PINCTRL_S32V234=y
-CONFIG_PINCTRL_MSM8994=y
-CONFIG_PINCTRL_MSM8996=y
-CONFIG_PINCTRL_MSM8998=y
-CONFIG_PINCTRL_QCS404=y
-CONFIG_PINCTRL_QDF2XXX=y
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
-CONFIG_PINCTRL_SDM845=y
-CONFIG_PINCTRL_SM8150=y
+CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_GPIO_MB86S7X=y
-CONFIG_GPIO_MPC8XXX=y
CONFIG_GPIO_PL061=y
-CONFIG_GPIO_RCAR=y
-CONFIG_GPIO_UNIPHIER=y
-CONFIG_GPIO_XGENE=y
-CONFIG_GPIO_XGENE_SB=y
+CONFIG_GPIO_FXL6408=y
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
CONFIG_POWER_AVS=y
-CONFIG_ROCKCHIP_IODOMAIN=y
-CONFIG_POWER_RESET_MSM=y
-CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_BRCMSTB=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_BATTERY_SBS=m
-CONFIG_BATTERY_BQ27XXX=y
+CONFIG_BATTERY_BQ27XXX=m
+CONFIG_SENSORS_ADT7410=m
CONFIG_SENSORS_ARM_SCPI=y
+CONFIG_SENSORS_GPIO_FAN=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_PWM_FAN=m
-CONFIG_SENSORS_RASPBERRYPI_HWMON=m
+CONFIG_SENSORS_SHT3x=m
CONFIG_SENSORS_INA2XX=m
CONFIG_SENSORS_INA3221=m
+CONFIG_SENSORS_TMP102=m
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
@@ -506,68 +408,31 @@ CONFIG_THERMAL_EMULATION=y
CONFIG_IMX_SC_THERMAL=y
CONFIG_DEVICE_THERMAL=y
CONFIG_IMX8MM_THERMAL=y
-CONFIG_QORIQ_THERMAL=y
-CONFIG_ROCKCHIP_THERMAL=m
-CONFIG_RCAR_THERMAL=y
-CONFIG_RCAR_GEN3_THERMAL=y
-CONFIG_ARMADA_THERMAL=y
-CONFIG_BCM2835_THERMAL=m
-CONFIG_BRCMSTB_THERMAL=m
-CONFIG_EXYNOS_THERMAL=y
-CONFIG_TEGRA_BPMP_THERMAL=m
-CONFIG_QCOM_TSENS=y
-CONFIG_UNIPHIER_THERMAL=y
CONFIG_WATCHDOG=y
-CONFIG_ARM_SBSA_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
-CONFIG_S3C2410_WATCHDOG=y
+CONFIG_ARM_SBSA_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
-CONFIG_SUNXI_WATCHDOG=m
CONFIG_IMX2_WDT=y
CONFIG_IMX_SC_WDT=y
-CONFIG_MESON_GXBB_WATCHDOG=m
-CONFIG_MESON_WATCHDOG=m
-CONFIG_RENESAS_WDT=y
-CONFIG_UNIPHIER_WATCHDOG=y
-CONFIG_BCM2835_WDT=y
-CONFIG_MFD_ALTERA_SYSMGR=y
-CONFIG_MFD_BD9571MWV=y
-CONFIG_MFD_AXP20X_I2C=y
-CONFIG_MFD_AXP20X_RSB=y
-CONFIG_MFD_EXYNOS_LPASS=m
+CONFIG_XEN_WDT=y
CONFIG_MFD_IMX_AUDIOMIX=y
CONFIG_MFD_HI6421_PMIC=y
-CONFIG_MFD_HI655X_PMIC=y
CONFIG_MFD_MAX77620=y
-CONFIG_MFD_SPMI_PMIC=y
-CONFIG_MFD_RK808=y
-CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_ROHM_BD718XX=y
CONFIG_MFD_PCA9450=y
+CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_AXP20X=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
CONFIG_REGULATOR_BD718XX=y
-CONFIG_REGULATOR_BD9571MWV=y
-CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
-CONFIG_REGULATOR_HI6421V530=y
-CONFIG_REGULATOR_HI655X=y
-CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PCA9450=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
-CONFIG_REGULATOR_QCOM_RPMH=y
-CONFIG_REGULATOR_QCOM_SMD_RPM=y
-CONFIG_REGULATOR_QCOM_SPMI=y
-CONFIG_REGULATOR_RK808=y
-CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_VCTRL=m
CONFIG_RC_CORE=m
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
-CONFIG_IR_MESON=m
-CONFIG_IR_SUNXI=m
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
@@ -582,83 +447,75 @@ CONFIG_VIDEO_MX8_CAPTURE=y
CONFIG_VIDEO_MXC_CAPTURE=y
CONFIG_VIDEO_MXC_CSI_CAMERA=y
CONFIG_MXC_MIPI_CSI=y
-CONFIG_MXC_CAMERA_OV5640_MIPI_V2=y
-CONFIG_VIDEO_SUN6I_CSI=m
+CONFIG_MXC_CAMERA_OV5640_MIPI_V2=m
CONFIG_V4L_MEM2MEM_DRIVERS=y
-CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
-CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
-CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
-CONFIG_VIDEO_RENESAS_FCP=m
-CONFIG_VIDEO_RENESAS_VSP1=m
-CONFIG_VIDEO_OV5640=y
+CONFIG_VIDEO_OV5640=m
CONFIG_IMX_DPU_CORE=y
CONFIG_IMX_LCDIF_CORE=y
+CONFIG_IMX_LCDIFV3_CORE=y
CONFIG_DRM=y
+CONFIG_DRM_DP_AUX_CHARDEV=y
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_DRM_I2C_CH7006=m
+CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
+CONFIG_DRM_I2C_NXP_TDA9950=m
CONFIG_DRM_MALI_DISPLAY=m
-CONFIG_DRM_NOUVEAU=m
-CONFIG_DRM_EXYNOS=m
-CONFIG_DRM_EXYNOS5433_DECON=y
-CONFIG_DRM_EXYNOS7_DECON=y
-CONFIG_DRM_EXYNOS_DSI=y
-# CONFIG_DRM_EXYNOS_DP is not set
-CONFIG_DRM_EXYNOS_HDMI=y
-CONFIG_DRM_EXYNOS_MIC=y
-CONFIG_DRM_ROCKCHIP=m
-CONFIG_ROCKCHIP_ANALOGIX_DP=y
-CONFIG_ROCKCHIP_CDN_DP=y
-CONFIG_ROCKCHIP_DW_HDMI=y
-CONFIG_ROCKCHIP_DW_MIPI_DSI=y
-CONFIG_ROCKCHIP_INNO_HDMI=y
-CONFIG_DRM_RCAR_DU=m
-CONFIG_DRM_SUN4I=m
-CONFIG_DRM_SUN8I_DW_HDMI=m
-CONFIG_DRM_SUN8I_MIXER=m
-CONFIG_DRM_MSM=m
-CONFIG_DRM_TEGRA=m
+CONFIG_DRM_VGEM=m
+CONFIG_DRM_VIRTIO_GPU=m
+CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_RAYDIUM_RM67191=y
CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
+CONFIG_DRM_DUMB_VGA_DAC=m
+CONFIG_DRM_FSL_IMX_LVDS_BRIDGE=y
+CONFIG_DRM_LVDS_ENCODER=y
+CONFIG_DRM_LONTIUM_LT8912=y
CONFIG_DRM_SII902X=m
CONFIG_DRM_I2C_ADV7511=y
CONFIG_DRM_NWL_MIPI_DSI=y
+CONFIG_DRM_CDNS_MHDP=y
+CONFIG_DRM_CDNS_HDMI=y
+CONFIG_DRM_CDNS_DP=y
+CONFIG_DRM_CDNS_AUDIO=y
CONFIG_DRM_CDNS_HDMI_CEC=y
+CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
+CONFIG_DRM_DW_HDMI_I2S_AUDIO=m
+CONFIG_DRM_DW_HDMI_GP_AUDIO=y
+CONFIG_DRM_DW_HDMI_CEC=y
CONFIG_DRM_ITE_IT6263=y
CONFIG_DRM_IMX=y
CONFIG_DRM_IMX_LCDIF_MUX_DISPLAY=y
CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
CONFIG_DRM_IMX_TVE=y
CONFIG_DRM_IMX_LDB=y
+CONFIG_DRM_IMX8QM_LDB=y
+CONFIG_DRM_IMX8QXP_LDB=y
+CONFIG_DRM_IMX8MP_LDB=y
CONFIG_DRM_IMX_HDMI=y
CONFIG_DRM_IMX_SEC_DSIM=y
-CONFIG_DRM_IMX_CDNS_MHDP=y
+CONFIG_DRM_IMX_CDNS_MHDP=m
CONFIG_DRM_IMX_DCSS=y
-CONFIG_DRM_VC4=m
CONFIG_DRM_ETNAVIV=m
-CONFIG_DRM_HISI_HIBMC=m
-CONFIG_DRM_HISI_KIRIN=m
CONFIG_DRM_MXSFB=y
-CONFIG_DRM_MESON=m
-CONFIG_DRM_PL111=m
-CONFIG_DRM_LIMA=m
-CONFIG_DRM_PANFROST=m
-CONFIG_FB_ARMCLCD=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_TILEBLITTING=y
CONFIG_FB_EFI=y
CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PWM=y
CONFIG_BACKLIGHT_LP855X=m
+CONFIG_BACKLIGHT_GPIO=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
-CONFIG_SND_HDA_TEGRA=m
-CONFIG_SND_HDA_CODEC_HDMI=m
+CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_SOC=y
-CONFIG_SND_BCM2835_SOC_I2S=m
-CONFIG_SND_SOC_FSL_EASRC=y
CONFIG_SND_SOC_FSL_DAI=m
+CONFIG_SND_SOC_FSL_EASRC=y
+CONFIG_SND_SOC_FSL_AUD2HTX=y
CONFIG_SND_IMX_SOC=y
CONFIG_SND_SOC_IMX_AK4458=y
CONFIG_SND_SOC_IMX_AK5558=y
@@ -673,62 +530,75 @@ CONFIG_SND_SOC_IMX_SPDIF=y
CONFIG_SND_SOC_IMX_AUDMIX=y
CONFIG_SND_SOC_IMX_PDM_MIC=y
CONFIG_SND_SOC_IMX_DSP=y
-CONFIG_SND_SOC_IMX_CDNHDMI=y
-CONFIG_SND_MESON_AXG_SOUND_CARD=m
-CONFIG_SND_SOC_ROCKCHIP=m
-CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
-CONFIG_SND_SOC_ROCKCHIP_RT5645=m
-CONFIG_SND_SOC_RK3399_GRU_SOUND=m
-CONFIG_SND_SOC_SAMSUNG=y
-CONFIG_SND_SOC_RCAR=m
+CONFIG_SND_SOC_IMX_CDNHDMI=m
+CONFIG_SND_SOC_IMX_XCVR=y
CONFIG_SND_SOC_SOF_TOPLEVEL=y
CONFIG_SND_SOC_SOF_OF=m
CONFIG_SND_SOC_SOF_IMX_TOPLEVEL=y
-CONFIG_SND_SOC_SOF_IMX8_SUPPORT=y
-CONFIG_SND_SUN4I_SPDIF=m
-CONFIG_SND_SOC_AK4613=m
-CONFIG_SND_SOC_ES7134=m
-CONFIG_SND_SOC_ES7241=m
-CONFIG_SND_SOC_PCM3168A_I2C=m
-CONFIG_SND_SOC_SGTL5000=m
+CONFIG_SND_SOC_SOF_IMX8_SUPPORT=m
+CONFIG_SND_SOC_SOF_IMX8M_SUPPORT=m
+CONFIG_SND_SOC_BT_SCO=y
+CONFIG_SND_SOC_SGTL5000=y
+CONFIG_SND_SOC_SPDIF=m
CONFIG_SND_SOC_TAS571X=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_WM8904=m
CONFIG_SND_SIMPLE_CARD=y
CONFIG_SND_AUDIO_GRAPH_CARD=y
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
CONFIG_I2C_HID=m
CONFIG_USB=y
CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_TEGRA=y
CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EXYNOS=y
-CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_EXYNOS=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
-CONFIG_USB_RENESAS_USBHS=m
+CONFIG_USB_EHCI_HCD_PLATFORM=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PLATFORM=m
+CONFIG_USB_HCD_TEST_MODE=y
CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
CONFIG_USB_STORAGE=y
CONFIG_USB_CDNS3=y
CONFIG_USB_CDNS3_GADGET=y
CONFIG_USB_CDNS3_HOST=y
CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC2=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760=m
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=y
+CONFIG_USB_SERIAL_CP210X=y
+CONFIG_USB_SERIAL_FTDI_SIO=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_TEST=m
CONFIG_USB_EHSET_TEST_FIXTURE=m
+CONFIG_USB_HUB_USB251XB=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MXS_PHY=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
-CONFIG_USB_RENESAS_USBHS_UDC=m
-CONFIG_USB_RENESAS_USB3=m
-CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
@@ -749,6 +619,7 @@ CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_ZERO=m
CONFIG_USB_AUDIO=m
CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_TYPEC=y
@@ -765,20 +636,12 @@ CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
-CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_MMC_SDHCI_F_SDH30=y
-CONFIG_MMC_MESON_GX=y
-CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SPI=y
-CONFIG_MMC_SDHI=y
-CONFIG_MMC_UNIPHIER=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_HI3798CV200=y
CONFIG_MMC_DW_K3=y
-CONFIG_MMC_DW_ROCKCHIP=y
-CONFIG_MMC_SUNXI=y
-CONFIG_MMC_BCM2835=y
CONFIG_MMC_SDHCI_XENON=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
@@ -792,194 +655,103 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_EDAC=y
CONFIG_EDAC_GHES=y
+CONFIG_EDAC_SYNOPSYS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_MAX77686=y
-CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_PCF85363=y
CONFIG_RTC_DRV_RX8581=m
-CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_PCF2127=y
CONFIG_RTC_DRV_EFI=y
-CONFIG_RTC_DRV_CROS_EC=y
-CONFIG_RTC_DRV_S3C=y
CONFIG_RTC_DRV_PL031=y
-CONFIG_RTC_DRV_SUN6I=y
-CONFIG_RTC_DRV_ARMADA38X=y
-CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_SNVS=y
CONFIG_RTC_DRV_IMX_SC=y
-CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y
-CONFIG_DMA_BCM2835=m
-CONFIG_DMA_SUN6I=m
+CONFIG_BCM_SBA_RAID=m
CONFIG_FSL_EDMA=y
CONFIG_FSL_EDMA_V3=y
-CONFIG_IMX_SDMA=y
-CONFIG_K3_DMA=y
-CONFIG_MV_XOR=y
+CONFIG_IMX_SDMA=m
CONFIG_MV_XOR_V2=y
CONFIG_MXS_DMA=y
CONFIG_PL330_DMA=y
-CONFIG_TEGRA20_APB_DMA=y
-CONFIG_QCOM_BAM_DMA=y
-CONFIG_QCOM_HIDMA_MGMT=y
-CONFIG_QCOM_HIDMA=y
-CONFIG_RCAR_DMAC=y
-CONFIG_RENESAS_USB_DMAC=m
CONFIG_DMATEST=y
CONFIG_UIO=y
CONFIG_UIO_PCI_GENERIC=y
+CONFIG_UIO_IVSHMEM=y
CONFIG_VFIO=y
CONFIG_VFIO_PCI=y
-CONFIG_VFIO_FSL_MC=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_STAGING=y
+CONFIG_R8188EU=m
CONFIG_STAGING_MEDIA=y
CONFIG_VIDEO_IMX_CAPTURE=y
CONFIG_ION=y
CONFIG_ION_SYSTEM_HEAP=y
CONFIG_ION_CMA_HEAP=y
-CONFIG_FSL_DPAA2=y
-CONFIG_FSL_DPAA2_ETHSW=y
-CONFIG_FSL_DPAA2_MAC=y
CONFIG_FSL_SDK_DPA=y
CONFIG_FSL_PPFE=y
CONFIG_FSL_PPFE_UTIL_DISABLED=y
-CONFIG_MFD_CROS_EC=y
-CONFIG_CROS_EC_I2C=y
-CONFIG_CROS_EC_SPI=y
-CONFIG_COMMON_CLK_RK808=y
+CONFIG_COMMON_CLK_VERSATILE=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
-CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_COMMON_CLK_PWM=y
-CONFIG_CLK_RASPBERRYPI=m
CONFIG_CLK_IMX8MM=y
CONFIG_CLK_IMX8MN=y
+CONFIG_CLK_IMX8MP=y
CONFIG_CLK_IMX8MQ=y
CONFIG_CLK_IMX8QXP=y
-CONFIG_TI_SCI_CLK=y
-CONFIG_COMMON_CLK_QCOM=y
-CONFIG_QCOM_A53PLL=y
-CONFIG_QCOM_CLK_APCS_MSM8916=y
-CONFIG_QCOM_CLK_SMD_RPM=y
-CONFIG_QCOM_CLK_RPMH=y
-CONFIG_IPQ_GCC_8074=y
-CONFIG_MSM_GCC_8916=y
-CONFIG_MSM_GCC_8994=y
-CONFIG_MSM_MMCC_8996=y
-CONFIG_MSM_GCC_8998=y
-CONFIG_QCS_GCC_404=y
-CONFIG_SDM_GCC_845=y
-CONFIG_SM_GCC_8150=y
CONFIG_HWSPINLOCK=y
-CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
CONFIG_IMX_MBOX=y
CONFIG_PLATFORM_MHU=y
-CONFIG_BCM2835_MBOX=y
-CONFIG_QCOM_APCS_IPC=y
-CONFIG_ROCKCHIP_IOMMU=y
-CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_V3=y
-CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=y
-CONFIG_QCOM_Q6V5_MSS=m
-CONFIG_QCOM_Q6V5_PAS=m
-CONFIG_QCOM_SYSMON=m
+CONFIG_IMX_REMOTEPROC=y
CONFIG_RPMSG_QCOM_GLINK_RPM=y
-CONFIG_RPMSG_QCOM_GLINK_SMEM=m
-CONFIG_RPMSG_QCOM_SMD=y
-CONFIG_RASPBERRYPI_POWER=y
-CONFIG_FSL_MC_DPIO=y
+CONFIG_SOC_BRCMSTB=y
CONFIG_FSL_QIXIS=y
CONFIG_IMX_SCU_SOC=y
-CONFIG_QCOM_GENI_SE=y
-CONFIG_QCOM_GLINK_SSR=m
-CONFIG_QCOM_RPMH=y
-CONFIG_QCOM_SMEM=y
-CONFIG_QCOM_SMD_RPM=y
-CONFIG_QCOM_SMP2P=y
-CONFIG_QCOM_SMSM=y
-CONFIG_ARCH_R8A774A1=y
-CONFIG_ARCH_R8A774C0=y
-CONFIG_ARCH_R8A7795=y
-CONFIG_ARCH_R8A7796=y
-CONFIG_ARCH_R8A77965=y
-CONFIG_ARCH_R8A77970=y
-CONFIG_ARCH_R8A77980=y
-CONFIG_ARCH_R8A77990=y
-CONFIG_ARCH_R8A77995=y
-CONFIG_ROCKCHIP_PM_DOMAINS=y
-CONFIG_ARCH_TEGRA_132_SOC=y
-CONFIG_ARCH_TEGRA_210_SOC=y
-CONFIG_ARCH_TEGRA_186_SOC=y
-CONFIG_ARCH_TEGRA_194_SOC=y
-CONFIG_ARCH_K3_AM6_SOC=y
-CONFIG_ARCH_K3_J721E_SOC=y
-CONFIG_TI_SCI_PM_DOMAINS=y
+CONFIG_SECVIO_SC=y
+CONFIG_SOC_TI=y
+CONFIG_EXTCON_GPIO=y
CONFIG_EXTCON_USB_GPIO=y
-CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_IIO=y
-CONFIG_EXYNOS_ADC=y
+CONFIG_BMC150_ACCEL=m
+CONFIG_IIO_ST_ACCEL_3AXIS=m
CONFIG_IMX8QXP_ADC=y
-CONFIG_ROCKCHIP_SARADC=m
-CONFIG_IIO_CROS_EC_SENSORS_CORE=m
-CONFIG_IIO_CROS_EC_SENSORS=m
-CONFIG_IIO_CROS_EC_LIGHT_PROX=m
-CONFIG_IIO_CROS_EC_BARO=m
+CONFIG_MAX1363=y
+CONFIG_TI_ADS1015=y
+CONFIG_BMG160=m
+CONFIG_IIO_ST_GYRO_3AXIS=m
+CONFIG_HTU21=m
+CONFIG_SI7020=m
+CONFIG_BMI160_I2C=m
+CONFIG_BMI160_SPI=m
+CONFIG_ISL29125=m
+CONFIG_SI1145=m
+CONFIG_VEML6070=m
+CONFIG_BMC150_MAGN_I2C=m
+CONFIG_BMC150_MAGN_SPI=m
+CONFIG_IIO_ST_MAGN_3AXIS=m
+CONFIG_MS5611=m
+CONFIG_MS5611_I2C=m
+CONFIG_MS5611_SPI=m
CONFIG_PWM=y
-CONFIG_PWM_BCM2835=m
-CONFIG_PWM_CROS_EC=m
CONFIG_PWM_IMX27=y
-CONFIG_PWM_MESON=m
-CONFIG_PWM_RCAR=m
-CONFIG_PWM_ROCKCHIP=y
-CONFIG_PWM_SAMSUNG=y
-CONFIG_PWM_SUN4I=m
-CONFIG_PWM_TEGRA=m
-CONFIG_RESET_TI_SCI=y
-CONFIG_PHY_XGENE=y
-CONFIG_PHY_SUN4I_USB=y
+CONFIG_PHY_MIXEL_LVDS=y
+CONFIG_PHY_MIXEL_LVDS_COMBO=y
+CONFIG_PHY_FSL_IMX8MP_LVDS=y
CONFIG_PHY_MIXEL_MIPI_DPHY=y
-CONFIG_PHY_HI6220_USB=y
-CONFIG_PHY_HISTB_COMBPHY=y
-CONFIG_PHY_HISI_INNO_USB2=y
-CONFIG_PHY_MVEBU_CP110_COMPHY=y
-CONFIG_PHY_QCOM_QMP=m
-CONFIG_PHY_QCOM_QUSB2=m
-CONFIG_PHY_QCOM_USB_HS=y
-CONFIG_PHY_RCAR_GEN3_PCIE=y
-CONFIG_PHY_RCAR_GEN3_USB2=y
-CONFIG_PHY_RCAR_GEN3_USB3=m
-CONFIG_PHY_ROCKCHIP_EMMC=y
-CONFIG_PHY_ROCKCHIP_INNO_HDMI=m
-CONFIG_PHY_ROCKCHIP_INNO_USB2=y
-CONFIG_PHY_ROCKCHIP_PCIE=m
-CONFIG_PHY_ROCKCHIP_TYPEC=y
-CONFIG_PHY_UNIPHIER_USB2=y
-CONFIG_PHY_UNIPHIER_USB3=y
-CONFIG_PHY_TEGRA_XUSB=y
CONFIG_FSL_IMX8_DDR_PMU=y
-CONFIG_HISI_PMU=y
-CONFIG_QCOM_L2_PMU=y
-CONFIG_QCOM_L3_PMU=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_IMX_OCOTP_SCU=y
-CONFIG_QCOM_QFPROM=y
-CONFIG_ROCKCHIP_EFUSE=y
-CONFIG_NVMEM_SUNXI_SID=y
-CONFIG_UNIPHIER_EFUSE=y
-CONFIG_MESON_EFUSE=m
CONFIG_FPGA=y
-CONFIG_FPGA_MGR_STRATIX10_SOC=m
CONFIG_FPGA_BRIDGE=m
CONFIG_ALTERA_FREEZE_BRIDGE=m
CONFIG_FPGA_REGION=m
@@ -988,11 +760,13 @@ CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_MUX_MMIO=y
CONFIG_MXC_SIM=y
+CONFIG_MXC_SIMv2=y
CONFIG_MXC_EMVSIM=y
CONFIG_MXC_MLB150=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
@@ -1003,52 +777,84 @@ CONFIG_FUSE_FS=m
CONFIG_CUSE=m
CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_EFIVAR_FS=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
-CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
-CONFIG_9P_FS=y
+CONFIG_CIFS=m
+CONFIG_9P_FS=m
+CONFIG_NLS_DEFAULT="cp437"
CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_ECHAINIV=y
-CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_TLS=m
CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CFB=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_RMD128=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_RMD256=m
CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_STREEBOG=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
CONFIG_CRYPTO_DEV_FSL_CAAM=y
CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y
CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=m
-CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y
-CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=y
+# CONFIG_RAID6_PQ_BENCHMARK is not set
+CONFIG_INDIRECT_PIO=y
+CONFIG_CRC_CCITT=y
CONFIG_CMA_SIZE_MBYTES=320
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
@@ -1058,3 +864,6 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SOURCE_ETM4X=y
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index e69af4d2c303..00ddc2302108 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -144,6 +144,7 @@ struct imx_ahci_priv {
struct clk *per_clk4;
struct clk *per_clk5;
void __iomem *phy_base;
+ struct clk *sata_ext;
int clkreq_gpio;
struct regmap *gpr;
bool no_device;
@@ -910,10 +911,14 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
if (ret)
return ret;
- ret = clk_prepare_enable(imxpriv->sata_ref_clk);
+ ret = clk_prepare_enable(imxpriv->sata_ext);
if (ret < 0)
goto disable_regulator;
+ ret = clk_prepare_enable(imxpriv->sata_ref_clk);
+ if (ret < 0)
+ goto disable_ext;
+
if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
/*
* set PHY Paremeters, two steps to configure the GPR13,
@@ -957,6 +962,8 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
disable_clk:
clk_disable_unprepare(imxpriv->sata_ref_clk);
+disable_ext:
+ clk_disable_unprepare(imxpriv->sata_ext);
disable_regulator:
ahci_platform_disable_regulators(hpriv);
@@ -996,6 +1003,8 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv)
clk_disable_unprepare(imxpriv->sata_ref_clk);
+ clk_disable_unprepare(imxpriv->sata_ext);
+
ahci_platform_disable_regulators(hpriv);
}
@@ -1479,6 +1488,12 @@ static int imx_ahci_probe(struct platform_device *pdev)
return PTR_ERR(imxpriv->sata_clk);
}
+ imxpriv->sata_ext = devm_clk_get(dev, "sata_ext");
+ if (IS_ERR(imxpriv->sata_ext)) {
+ dev_err(dev, "can't get sata_ext clock.\n");
+ return PTR_ERR(imxpriv->sata_ext);
+ }
+
imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
if (IS_ERR(imxpriv->sata_ref_clk)) {
dev_err(dev, "can't get sata_ref clock.\n");
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index 7c0c5ca5953d..87318ec34702 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -35,6 +35,7 @@ static DEVICE_ATTR(machine, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(family, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(serial_number, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(soc_id, S_IRUGO, soc_info_get, NULL);
+static DEVICE_ATTR(unique_id, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(revision, S_IRUGO, soc_info_get, NULL);
struct device *soc_device_to_device(struct soc_device *soc_dev)
@@ -64,6 +65,9 @@ static umode_t soc_attribute_mode(struct kobject *kobj,
if ((attr == &dev_attr_soc_id.attr)
&& (soc_dev->attr->soc_id != NULL))
return attr->mode;
+ if ((attr == &dev_attr_unique_id.attr)
+ && (soc_dev->attr->unique_id != NULL))
+ return attr->mode;
/* Unknown or unfilled attribute. */
return 0;
@@ -85,6 +89,8 @@ static ssize_t soc_info_get(struct device *dev,
return sprintf(buf, "%s\n", soc_dev->attr->serial_number);
if (attr == &dev_attr_soc_id)
return sprintf(buf, "%s\n", soc_dev->attr->soc_id);
+ if (attr == &dev_attr_unique_id)
+ return sprintf(buf, "%s\n", soc_dev->attr->unique_id);
return -EINVAL;
@@ -95,6 +101,7 @@ static struct attribute *soc_attr[] = {
&dev_attr_family.attr,
&dev_attr_serial_number.attr,
&dev_attr_soc_id.attr,
+ &dev_attr_unique_id.attr,
&dev_attr_revision.attr,
NULL,
};
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index d9a4487dd384..76633512e7cb 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -78,6 +78,8 @@ static void clk_gate2_do_shared_clks(struct clk_hw *hw, bool enable)
clk_gate2_do_hardware(gate, enable);
imx_sema4_mutex_unlock(amp_power_mutex);
+#else
+ clk_gate2_do_hardware(gate, enable);
#endif
} else {
clk_gate2_do_hardware(gate, enable);
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index ed70a57e2e6d..e288a1b2d269 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -704,7 +704,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
hws[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_hw_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
hws[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_hw_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
hws[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_hw_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
- hws[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_hw_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
+ hws[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_hw_divider2_flags("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
hws[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_hw_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
hws[IMX7D_IPG_ROOT_CLK] = imx_clk_hw_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
hws[IMX7D_DRAM_ROOT_DIV] = imx_clk_hw_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
@@ -878,12 +878,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clk_set_parent(hws[IMX7D_MIPI_CSI_ROOT_SRC]->clk, hws[IMX7D_PLL_SYS_PFD3_CLK]->clk);
- if (imx_src_is_m4_enabled()) {
- clk_set_parent(hws[IMX7D_ARM_M4_ROOT_SRC]->clk, hws[IMX7D_PLL_SYS_MAIN_240M_CLK]->clk);
- clk_prepare_enable(hws[IMX7D_ARM_M4_ROOT_CLK]->clk);
- clk_prepare_enable(hws[IMX7D_UART2_ROOT_CLK]->clk);
- }
-
/* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */
clk_set_parent(hws[IMX7D_GPT1_ROOT_SRC]->clk, hws[IMX7D_OSC_24M_CLK]->clk);
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
index 6e8afaa9d229..ae83aad62fe9 100644
--- a/drivers/clk/imx/clk-imx8qxp.c
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -136,6 +136,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
+ imx_clk_scu("adc1_clk", IMX_SC_R_ADC_1, IMX_SC_PM_CLK_PER);
imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0);
diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c
index fc2e0fe03bdd..ad76fbe9ad62 100644
--- a/drivers/clk/imx/clk-pfd.c
+++ b/drivers/clk/imx/clk-pfd.c
@@ -69,6 +69,8 @@ static void clk_pfd_do_shared_clks(struct clk_hw *hw, bool enable)
clk_pfd_do_hardware(pfd, enable);
imx_sema4_mutex_unlock(amp_power_mutex);
+#else
+ clk_pfd_do_hardware(pfd, enable);
#endif
} else {
clk_pfd_do_hardware(pfd, enable);
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index fd4d4d809d61..b90ae869ed0a 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -128,6 +128,8 @@ static void clk_pllv3_do_shared_clks(struct clk_hw *hw, bool enable)
clk_pllv3_do_hardware(hw, enable);
imx_sema4_mutex_unlock(amp_power_mutex);
+#else
+ clk_pllv3_do_hardware(hw, enable);
#endif
} else {
clk_pllv3_do_hardware(hw, enable);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index b940f68c978c..6acd41c29c9a 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -300,6 +300,14 @@ static inline struct clk_hw *imx_clk_hw_divider2(const char *name, const char *p
reg, shift, width, 0, &imx_ccm_lock);
}
+static inline struct clk_hw *imx_clk_hw_divider2_flags(const char *name,
+ const char *parent,
+ void __iomem *reg, u8 shift, u8 width, unsigned long flags)
+{
+ return clk_hw_register_divider(NULL, name, parent,
+ flags, reg, shift, width, 0, &imx_ccm_lock);
+}
+
static inline struct clk *imx_clk_divider2_flags(const char *name,
const char *parent, void __iomem *reg, u8 shift, u8 width,
unsigned long flags)
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index fbf52fbebd9b..aef90044ed43 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -107,6 +107,8 @@ static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "calxeda,ecx-2000", },
{ .compatible = "fsl,imx7d", },
+ { .compatible = "fsl,imx7s", },
+
{ .compatible = "fsl,imx8mq", },
{ .compatible = "fsl,imx8mm", },
{ .compatible = "fsl,imx8mn", },
diff --git a/drivers/crypto/caam/secvio.c b/drivers/crypto/caam/secvio.c
index 237017ada217..5a57e2112240 100644
--- a/drivers/crypto/caam/secvio.c
+++ b/drivers/crypto/caam/secvio.c
@@ -276,7 +276,7 @@ static int snvs_secvio_probe(struct platform_device *pdev)
svpriv->clk = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(svpriv->clk)) {
- dev_err(&pdev->dev, "can't get snvs clock\n");
+ dev_info(&pdev->dev, "can't get snvs clock\n");
svpriv->clk = NULL;
}
diff --git a/drivers/dma/pxp/pxp_dma_v3.c b/drivers/dma/pxp/pxp_dma_v3.c
index 0b6afe03c1fa..b9642af626a8 100644
--- a/drivers/dma/pxp/pxp_dma_v3.c
+++ b/drivers/dma/pxp/pxp_dma_v3.c
@@ -7974,14 +7974,14 @@ static int pxp_probe(struct platform_device *pdev)
goto exit;
}
+ pxp_clk_enable(pxp);
+
pxp_soft_reset(pxp);
pxp_writel(0x0, HW_PXP_CTRL);
/* Initialize DMA engine */
err = pxp_dma_init(pxp);
if (err < 0)
goto exit;
-
- pxp_clk_enable(pxp);
pxp_soft_reset(pxp);
/* Initialize PXP Interrupt */
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index 98b5afa5b615..b5435b341553 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -20,7 +20,7 @@
#include <linux/workqueue.h>
#include <linux/pinctrl/consumer.h>
-#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
+#define USB_GPIO_DEBOUNCE_MS 100 /* ms */
struct usb_extcon_info {
struct device *dev;
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index e737f2540bed..0e088452f23a 100755
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -156,10 +156,10 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "can", IMX_SC_R_CAN_0, 3, true, 0 },
{ "ftm", IMX_SC_R_FTM_0, 2, true, 0 },
{ "lpi2c", IMX_SC_R_I2C_0, 4, true, 0 },
- { "adc", IMX_SC_R_ADC_0, 1, true, 0 },
+ { "adc", IMX_SC_R_ADC_0, 2, true, 0 },
{ "lcd", IMX_SC_R_LCD_0, 1, true, 0 },
{ "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
- { "lpuart", IMX_SC_R_UART_0, 4, true, 0 },
+ { "lpuart", IMX_SC_R_UART_0, 5, true, 0 },
{ "sim", IMX_SC_R_EMVSIM_0, 2, true, 0 },
{ "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
{ "irqstr_dsp", IMX_SC_R_IRQSTR_DSP, 1, false, 0 },
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b7176ce6f7e0..dcf4871d4633 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -862,6 +862,12 @@ config GPIO_ADNP
enough to represent all pins, but the driver will assume a
register layout for 64 pins (8 registers).
+config GPIO_FXL6408
+ tristate "FXL6408 I2C GPIO expander"
+ help
+ This option enables support for 8 GPIOs found
+ on the Fairchild Semiconductor FXL6408.
+
config GPIO_GW_PLD
tristate "Gateworks PLD GPIO Expander"
depends on OF_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 30e93c76995d..d62218ba921a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
+obj-$(CONFIG_GPIO_FXL6408) += gpio-fxl6408.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c
new file mode 100644
index 000000000000..22d193c4d9d5
--- /dev/null
+++ b/drivers/gpio/gpio-fxl6408.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2016 Broadcom Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/**
+ * DOC: FXL6408 I2C to GPIO expander.
+ *
+ * This chip has has 8 GPIO lines out of it, and is controlled by an
+ * I2C bus (a pair of lines), providing 4x expansion of GPIO lines.
+ * It also provides an interrupt line out for notifying of
+ * statechanges.
+ *
+ * Any preconfigured state will be left in place until the GPIO lines
+ * get activated. At power on, everything is treated as an input.
+ *
+ * Documentation can be found at:
+ * https://www.fairchildsemi.com/datasheets/FX/FXL6408.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/of_platform.h>
+
+#define FXL6408_DEVICE_ID 0x01
+# define FXL6408_RST_INT BIT(1)
+# define FXL6408_SW_RST BIT(0)
+
+/* Bits set here indicate that the GPIO is an output. */
+#define FXL6408_IO_DIR 0x03
+/* Bits set here, when the corresponding bit of IO_DIR is set, drive
+ * the output high instead of low.
+ */
+#define FXL6408_OUTPUT 0x05
+/* Bits here make the output High-Z, instead of the OUTPUT value. */
+#define FXL6408_OUTPUT_HIGH_Z 0x07
+/* Bits here define the expected input state of the GPIO.
+ * INTERRUPT_STAT bits will be set when the INPUT transitions away
+ * from this value.
+ */
+#define FXL6408_INPUT_DEFAULT_STATE 0x09
+/* Bits here enable either pull up or pull down according to
+ * FXL6408_PULL_DOWN.
+ */
+#define FXL6408_PULL_ENABLE 0x0b
+/* Bits set here (when the corresponding PULL_ENABLE is set) enable a
+ * pull-up instead of a pull-down.
+ */
+#define FXL6408_PULL_UP 0x0d
+/* Returns the current status (1 = HIGH) of the input pins. */
+#define FXL6408_INPUT_STATUS 0x0f
+/* Mask of pins which can generate interrupts. */
+#define FXL6408_INTERRUPT_MASK 0x11
+/* Mask of pins which have generated an interrupt. Cleared on read. */
+#define FXL6408_INTERRUPT_STAT 0x13
+
+struct fxl6408_chip {
+ struct gpio_chip gpio_chip;
+ struct i2c_client *client;
+ struct mutex i2c_lock;
+
+ /* Caches of register values so we don't have to read-modify-write. */
+ u8 reg_io_dir;
+ u8 reg_output;
+};
+
+static int fxl6408_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+ struct fxl6408_chip *chip = gpiochip_get_data(gc);
+
+ mutex_lock(&chip->i2c_lock);
+ chip->reg_io_dir &= ~BIT(off);
+ i2c_smbus_write_byte_data(chip->client, FXL6408_IO_DIR,
+ chip->reg_io_dir);
+ mutex_unlock(&chip->i2c_lock);
+
+ return 0;
+}
+
+static int fxl6408_gpio_direction_output(struct gpio_chip *gc,
+ unsigned off, int val)
+{
+ struct fxl6408_chip *chip = gpiochip_get_data(gc);
+
+ mutex_lock(&chip->i2c_lock);
+ chip->reg_io_dir |= BIT(off);
+ i2c_smbus_write_byte_data(chip->client, FXL6408_IO_DIR,
+ chip->reg_io_dir);
+ mutex_unlock(&chip->i2c_lock);
+
+ return 0;
+}
+
+static int fxl6408_gpio_get_direction(struct gpio_chip *gc, unsigned off)
+{
+ struct fxl6408_chip *chip = gpiochip_get_data(gc);
+
+ return (chip->reg_io_dir & BIT(off)) == 0;
+}
+
+static int fxl6408_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+ struct fxl6408_chip *chip = gpiochip_get_data(gc);
+ u8 reg;
+
+ if (fxl6408_gpio_get_direction(gc, off) == 0)
+ {
+ reg = chip->reg_output;
+ } else {
+ mutex_lock(&chip->i2c_lock);
+ reg = i2c_smbus_read_byte_data(chip->client, FXL6408_INPUT_STATUS);
+ mutex_unlock(&chip->i2c_lock);
+ }
+ return (reg & BIT(off)) != 0;
+}
+
+static void fxl6408_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct fxl6408_chip *chip = gpiochip_get_data(gc);
+
+ mutex_lock(&chip->i2c_lock);
+
+ if (val)
+ chip->reg_output |= BIT(off);
+ else
+ chip->reg_output &= ~BIT(off);
+
+ i2c_smbus_write_byte_data(chip->client, FXL6408_OUTPUT,
+ chip->reg_output);
+ mutex_unlock(&chip->i2c_lock);
+}
+
+
+static void fxl6408_gpio_set_multiple(struct gpio_chip *gc,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct fxl6408_chip *chip = gpiochip_get_data(gc);
+ mutex_lock(&chip->i2c_lock);
+ chip->reg_output = (chip->reg_output & ~mask[0]) | bits[0];
+ i2c_smbus_write_byte_data(chip->client, FXL6408_OUTPUT,
+ chip->reg_output);
+ mutex_unlock(&chip->i2c_lock);
+}
+
+static int fxl6408_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct fxl6408_chip *chip;
+ struct gpio_chip *gc;
+ unsigned int val;
+ int ret;
+ u8 device_id;
+
+ /* Check the device ID register to see if it's responding.
+ * This also clears RST_INT as a side effect, so we won't get
+ * the "we've been power cycled" interrupt once we enable
+ * interrupts.
+ */
+ device_id = i2c_smbus_read_byte_data(client, FXL6408_DEVICE_ID);
+ if (device_id < 0) {
+ dev_err(dev, "FXL6408 probe returned %d\n", device_id);
+ return device_id;
+ } else if (device_id >> 5 != 5) {
+ dev_err(dev, "FXL6408 probe returned DID: 0x%02x\n", device_id);
+ return -ENODEV;
+ }
+
+ /* Disable High-Z of outputs, so that our OUTPUT updates
+ * actually take effect.
+ */
+ i2c_smbus_write_byte_data(client, FXL6408_OUTPUT_HIGH_Z, 0);
+
+ chip = devm_kzalloc(dev, sizeof(struct fxl6408_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ chip->client = client;
+ mutex_init(&chip->i2c_lock);
+
+ /* if configured, set initial output state and direction,
+ * otherwise read them from the chip */
+ if (of_property_read_u32(dev->of_node, "inital_io_dir", &val)) {
+ chip->reg_io_dir = i2c_smbus_read_byte_data(client, FXL6408_IO_DIR);
+ } else {
+ chip->reg_io_dir = val & 0xff;
+ i2c_smbus_write_byte_data(client, FXL6408_IO_DIR, chip->reg_io_dir);
+ }
+ if (of_property_read_u32(dev->of_node, "inital_output", &val)) {
+ chip->reg_output = i2c_smbus_read_byte_data(client, FXL6408_OUTPUT);
+ } else {
+ chip->reg_output = val & 0xff;
+ i2c_smbus_write_byte_data(client, FXL6408_OUTPUT, chip->reg_output);
+ }
+
+ gc = &chip->gpio_chip;
+ gc->direction_input = fxl6408_gpio_direction_input;
+ gc->direction_output = fxl6408_gpio_direction_output;
+ gc->get_direction = fxl6408_gpio_get_direction;
+ gc->get = fxl6408_gpio_get_value;
+ gc->set = fxl6408_gpio_set_value;
+ gc->set_multiple = fxl6408_gpio_set_multiple;
+ gc->can_sleep = true;
+
+ gc->base =-1;
+ gc->ngpio = 8;
+ gc->label = chip->client->name;
+ gc->parent = dev;
+ gc->owner = THIS_MODULE;
+
+ ret = gpiochip_add_data(gc, chip);
+ if (ret)
+ return ret;
+
+ i2c_set_clientdata(client, chip);
+ return 0;
+}
+
+static int fxl6408_remove(struct i2c_client *client)
+{
+ struct fxl6408_chip *chip = i2c_get_clientdata(client);
+
+ gpiochip_remove(&chip->gpio_chip);
+
+ return 0;
+}
+
+static const struct of_device_id fxl6408_dt_ids[] = {
+ { .compatible = "fcs,fxl6408" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, fxl6408_dt_ids);
+
+static const struct i2c_device_id fxl6408_id[] = {
+ { "fxl6408", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, fxl6408_id);
+
+static struct i2c_driver fxl6408_driver = {
+ .driver = {
+ .name = "fxl6408",
+ .of_match_table = fxl6408_dt_ids,
+ },
+ .probe = fxl6408_probe,
+ .remove = fxl6408_remove,
+ .id_table = fxl6408_id,
+};
+
+module_i2c_driver(fxl6408_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("GPIO expander driver for FXL6408");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 8beb0bdb4b38..8235f63c33d5 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -7,6 +7,7 @@
// Authors: Daniel Mack, Juergen Beisert.
// Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+#include <linux/moduleparam.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -32,6 +33,10 @@
#define IMX_SC_IRQ_PAD (1 << 1)
#endif
+static bool noclearirq = false;
+module_param(noclearirq, bool, 0);
+MODULE_PARM_DESC(noclearirq, "do not clear IRQ mask/status on probe");
+
enum mxc_gpio_hwtype {
IMX1_GPIO, /* runs on i.mx1 */
IMX21_GPIO, /* runs on i.mx21 and i.mx27 */
@@ -583,6 +588,37 @@ static void mxc_gpio_free(struct gpio_chip *chip, unsigned offset)
pm_runtime_put(chip->parent);
}
+#ifdef CONFIG_GPIO_MXC_PAD_WAKEUP
+/*
+ * parse pad wakeup info from dtb, each pad has to provide
+ * <pin_id, type, line>, these info should be put in each
+ * gpio node and with a "pad-wakeup-num" to indicate the
+ * total lines are with pad wakeup enabled.
+ */
+static int setup_pad_wakeup(struct mxc_gpio_port *port,
+ struct device_node *np)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < port->pad_wakeup_num; i++) {
+ if ((err = of_property_read_u32_index(np, "pad-wakeup",
+ i * 3 + 0, &port->pad_wakeup[i].pin_id)))
+ return err;
+ if ((err = of_property_read_u32_index(np, "pad-wakeup",
+ i * 3 + 1, &port->pad_wakeup[i].type)))
+ return err;
+ if ((err = of_property_read_u32_index(np, "pad-wakeup",
+ i * 3 + 2, &port->pad_wakeup[i].line)))
+ return err;
+ }
+ err = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_WAKE, IMX_SC_IRQ_PAD, true);
+
+
+ return err;
+}
+#endif
+
static int mxc_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -590,9 +626,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
int irq_count;
int irq_base = 0;
int err;
-#ifdef CONFIG_GPIO_MXC_PAD_WAKEUP
- int i;
-#endif
mxc_gpio_get_hw(pdev);
@@ -632,30 +665,18 @@ static int mxc_gpio_probe(struct platform_device *pdev)
}
#ifdef CONFIG_GPIO_MXC_PAD_WAKEUP
- /*
- * parse pad wakeup info from dtb, each pad has to provide
- * <pin_id, type, line>, these info should be put in each
- * gpio node and with a "pad-wakeup-num" to indicate the
- * total lines are with pad wakeup enabled.
- */
- if (!of_property_read_u32(np, "pad-wakeup-num", &port->pad_wakeup_num)) {
- if (port->pad_wakeup_num != 0) {
- if (!gpio_ipc_handle) {
- err = imx_scu_get_handle(&gpio_ipc_handle);
- if (err)
- return err;
- }
- for (i = 0; i < port->pad_wakeup_num; i++) {
- of_property_read_u32_index(np, "pad-wakeup",
- i * 3 + 0, &port->pad_wakeup[i].pin_id);
- of_property_read_u32_index(np, "pad-wakeup",
- i * 3 + 1, &port->pad_wakeup[i].type);
- of_property_read_u32_index(np, "pad-wakeup",
- i * 3 + 2, &port->pad_wakeup[i].line);
- }
- err = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_WAKE, IMX_SC_IRQ_PAD, true);
+ if (!of_property_read_u32(np, "pad-wakeup-num", &port->pad_wakeup_num)
+ && port->pad_wakeup_num != 0) {
+ if (!gpio_ipc_handle) {
+ err = imx_scu_get_handle(&gpio_ipc_handle);
if (err)
- dev_warn(&pdev->dev, "Enable irq failed, GPIO pad wakeup NOT supported\n");
+ goto out_clk_disable;
+ }
+
+ err = setup_pad_wakeup(port, np);
+ if (err) {
+ dev_warn(&pdev->dev, "Enable irq failed, GPIO pad wakeup NOT supported\n");
+ goto out_clk_disable;
}
}
#endif
@@ -667,11 +688,13 @@ static int mxc_gpio_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
err = pm_runtime_get_sync(&pdev->dev);
if (err < 0)
- goto out_pm_dis;
+ goto out_pm_disable;
/* disable the interrupt and clear the status */
- writel(0, port->base + GPIO_IMR);
- writel(~0, port->base + GPIO_ISR);
+ if (!noclearirq) {
+ writel(0, port->base + GPIO_IMR);
+ writel(~0, port->base + GPIO_ISR);
+ }
if (mxc_gpio_hwtype == IMX21_GPIO) {
/*
@@ -697,7 +720,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
port->base + GPIO_GDIR, NULL,
BGPIOF_READ_OUTPUT_REG_SET);
if (err)
- goto out_bgio;
+ goto out_pm_put;
if (of_property_read_bool(np, "gpio-ranges")) {
port->gc.request = gpiochip_generic_request;
@@ -718,19 +741,19 @@ static int mxc_gpio_probe(struct platform_device *pdev)
err = devm_gpiochip_add_data(&pdev->dev, &port->gc, port);
if (err)
- goto out_bgio;
+ goto out_pm_put;
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
if (irq_base < 0) {
err = irq_base;
- goto out_bgio;
+ goto out_pm_put;
}
port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
&irq_domain_simple_ops, NULL);
if (!port->domain) {
err = -ENODEV;
- goto out_bgio;
+ goto out_pm_put;
}
/* gpio-mxc can be a generic irq chip */
@@ -745,12 +768,15 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return 0;
-out_pm_dis:
- pm_runtime_disable(&pdev->dev);
- clk_disable_unprepare(port->clk);
out_irqdomain_remove:
irq_domain_remove(port->domain);
-out_bgio:
+out_pm_put:
+ pm_runtime_put(&pdev->dev);
+out_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+#ifdef CONFIG_GPIO_MXC_PAD_WAKEUP
+out_clk_disable:
+#endif
clk_disable_unprepare(port->clk);
dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
return err;
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 8b2e5d975590..02aef36b5dde 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -74,6 +74,14 @@ config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW
to DP++. This is used with the i.MX6 imx-ldb
driver. You are likely to say N here.
+config DRM_LONTIUM_LT8912
+ tristate "Lontium LT8912 MIPI-DSI to LVDS and HDMI/MHL bridge"
+ depends on OF
+ select DRM_KMS_HELPER
+ select REGMAP_I2C
+ help
+ Lontium LT8912 MIPI-DSI to LVDS and HDMI/MHL bridge chip driver.
+
config DRM_SEC_MIPI_DSIM
tristate "Samsung MIPI DSIM Bridge"
depends on OF
@@ -178,6 +186,8 @@ source "drivers/gpu/drm/bridge/cadence/Kconfig"
source "drivers/gpu/drm/bridge/synopsys/Kconfig"
+source "drivers/gpu/drm/bridge/sn65dsi83/Kconfig"
+
config DRM_ITE_IT6263
tristate "ITE IT6263 LVDS/HDMI bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 7c755b93a3c5..59b755e690af 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
obj-$(CONFIG_DRM_FSL_IMX_LVDS_BRIDGE) += fsl-imx-ldb.o
obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
+obj-$(CONFIG_DRM_LONTIUM_LT8912) += lt8912.o
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
@@ -22,3 +23,4 @@ obj-y += cadence/
obj-y += synopsys/
obj-$(CONFIG_DRM_ITE_IT6263) += it6263.o
obj-$(CONFIG_DRM_SEC_MIPI_DSIM) += sec-dsim.o
+obj-$(CONFIG_DRM_I2C_SN65DSI83) += sn65dsi83/
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
index 73a7d0a04f21..067290b3b3ad 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
@@ -226,6 +226,7 @@ void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp)
static enum drm_connector_status
cdns_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
+ struct edid *edid;
struct cdns_mhdp_device *mhdp =
container_of(connector, struct cdns_mhdp_device, connector.base);
@@ -233,15 +234,21 @@ cdns_hdmi_connector_detect(struct drm_connector *connector, bool force)
hpd = cdns_mhdp_read_hpd(mhdp);
- if (hpd == 1)
+ if (hpd == 1) {
/* Cable Connected */
return connector_status_connected;
- else if (hpd == 0)
+ } else if (hpd == 0) {
/* Cable Disconnedted */
return connector_status_disconnected;
- else {
+ } else if (mhdp->ddc) {
+ edid = drm_get_edid(connector, mhdp->ddc);
+ if (drm_edid_is_valid(edid))
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+ } else {
/* Cable status unknown */
- DRM_INFO("Unknow cable status, hdp=%u\n", hpd);
+ DRM_INFO("Unknow cable status, hpd=%u\n", hpd);
return connector_status_unknown;
}
}
@@ -253,8 +260,15 @@ static int cdns_hdmi_connector_get_modes(struct drm_connector *connector)
int num_modes = 0;
struct edid *edid;
- edid = drm_do_get_edid(&mhdp->connector.base,
- cdns_hdmi_get_edid_block, mhdp);
+ /*
+ * Check if optional regular DDC I2C bus should be used.
+ * Fall-back to using IP/firmware integrated one.
+ */
+ if (mhdp->ddc)
+ edid = drm_get_edid(&mhdp->connector.base, mhdp->ddc);
+ else
+ edid = drm_do_get_edid(&mhdp->connector.base,
+ cdns_hdmi_get_edid_block, mhdp);
if (edid) {
dev_info(mhdp->dev, "%x,%x,%x,%x,%x,%x,%x,%x\n",
edid->header[0], edid->header[1],
@@ -374,9 +388,12 @@ cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
if (mode->hdisplay > 3840 || mode->vdisplay > 2160)
return MODE_BAD_HVALUE;
- vic = drm_match_cea_mode(mode);
- if (vic == 0)
- return MODE_BAD;
+ /* imx8mq-hdmi does not support non CEA modes */
+ if (!strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) {
+ vic = drm_match_cea_mode(mode);
+ if (vic == 0)
+ return MODE_BAD;
+ }
mhdp->valid_mode = mode;
ret = cdns_mhdp_plat_call(mhdp, phy_video_valid);
@@ -503,6 +520,7 @@ static irqreturn_t cdns_hdmi_irq_thread(int irq, void *data)
static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp)
{
struct device_node *of_node = mhdp->dev->of_node;
+ struct device_node *ddc_phandle;
int ret;
ret = of_property_read_u32(of_node, "lane-mapping", &mhdp->lane_mapping);
@@ -511,6 +529,17 @@ static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp)
dev_warn(mhdp->dev, "Failed to get lane_mapping - using default 0xc6\n");
}
dev_info(mhdp->dev, "lane-mapping 0x%02x\n", mhdp->lane_mapping);
+
+ /* get optional regular DDC I2C bus */
+ ddc_phandle = of_parse_phandle(of_node, "ddc-i2c-bus", 0);
+ if (ddc_phandle) {
+ mhdp->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
+ if (mhdp->ddc)
+ dev_info(mhdp->dev, "Connector's ddc i2c bus found\n");
+ else
+ ret = -EPROBE_DEFER;
+ of_node_put(ddc_phandle);
+ }
}
static int __cdns_hdmi_probe(struct platform_device *pdev,
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index 7aa789c35882..83ba7ba78f35 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -79,6 +79,13 @@ dumb_vga_connector_detect(struct drm_connector *connector, bool force)
struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
/*
+ * If I2C bus for DDC is not defined, asume that the cable
+ * is always connected.
+ */
+ if (PTR_ERR(vga->ddc) == -ENODEV)
+ return connector_status_connected;
+
+ /*
* Even if we have an I2C bus, we can't assume that the cable
* is disconnected if drm_probe_ddc fails. Some cables don't
* wire the DDC pins, or the I2C bus might not be working at
diff --git a/drivers/gpu/drm/bridge/lt8912.c b/drivers/gpu/drm/bridge/lt8912.c
new file mode 100644
index 000000000000..aa407d09d319
--- /dev/null
+++ b/drivers/gpu/drm/bridge/lt8912.c
@@ -0,0 +1,684 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
+ * Copyright 2019 Toradex AG
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_graph.h>
+#include <linux/regmap.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_of.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_mipi_dsi.h>
+
+struct lt8912 {
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+ struct drm_display_mode mode;
+ struct device *dev;
+ struct mipi_dsi_device *dsi;
+ struct device_node *host_node;
+ u8 num_dsi_lanes;
+ u8 channel_id;
+ unsigned int irq;
+ u8 sink_is_hdmi;
+ struct regmap *regmap[3];
+ struct gpio_desc *hpd_gpio;
+ struct gpio_desc *reset_n;
+ struct i2c_adapter *ddc; /* optional regular DDC I2C bus */
+};
+
+static int lt8912_attach_dsi(struct lt8912 *lt);
+
+static inline struct lt8912 *bridge_to_lt8912(struct drm_bridge *b)
+{
+ return container_of(b, struct lt8912, bridge);
+}
+
+static inline struct lt8912 *connector_to_lt8912(struct drm_connector *c)
+{
+ return container_of(c, struct lt8912, connector);
+}
+
+/* LT8912 MIPI to HDMI & LVDS REG setting - 20180115.txt */
+static void lt8912_init(struct lt8912 *lt)
+{
+ u8 lanes = lt->dsi->lanes;
+ const struct drm_display_mode *mode = &lt->mode;
+ u32 hactive, hfp, hsync, hbp, vfp, vsync, vbp, htotal, vtotal;
+ unsigned int hsync_activehigh, vsync_activehigh, reg;
+ unsigned int version[2];
+
+ dev_info(lt->dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
+ /* TODO: lvds output init */
+
+ hactive = mode->hdisplay;
+ hfp = mode->hsync_start - mode->hdisplay;
+ hsync = mode->hsync_end - mode->hsync_start;
+ hsync_activehigh = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
+ hbp = mode->htotal - mode->hsync_end;
+ vfp = mode->vsync_start - mode->vdisplay;
+ vsync = mode->vsync_end - mode->vsync_start;
+ vsync_activehigh = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
+ vbp = mode->vtotal - mode->vsync_end;
+ htotal = mode->htotal;
+ vtotal = mode->vtotal;
+
+ regmap_read(lt->regmap[0], 0x00, &version[0]);
+ regmap_read(lt->regmap[0], 0x01, &version[1]);
+
+ dev_info(lt->dev, "LT8912 ID: %02x, %02x\n",
+ version[0], version[1]);
+
+ /* DigitalClockEn */
+ regmap_write(lt->regmap[0], 0x08, 0xff);
+ regmap_write(lt->regmap[0], 0x09, 0xff);
+ regmap_write(lt->regmap[0], 0x0a, 0xff);
+ regmap_write(lt->regmap[0], 0x0b, 0x7c);
+ regmap_write(lt->regmap[0], 0x0c, 0xff);
+
+ /* TxAnalog */
+ regmap_write(lt->regmap[0], 0x31, 0xa1);
+ regmap_write(lt->regmap[0], 0x32, 0xa1);
+ regmap_write(lt->regmap[0], 0x33, 0x03);
+ regmap_write(lt->regmap[0], 0x37, 0x00);
+ regmap_write(lt->regmap[0], 0x38, 0x22);
+ regmap_write(lt->regmap[0], 0x60, 0x82);
+
+ /* CbusAnalog */
+ regmap_write(lt->regmap[0], 0x39, 0x45);
+ regmap_write(lt->regmap[0], 0x3a, 0x00);
+ regmap_write(lt->regmap[0], 0x3b, 0x00);
+
+ /* HDMIPllAnalog */
+ regmap_write(lt->regmap[0], 0x44, 0x31);
+ regmap_write(lt->regmap[0], 0x55, 0x44);
+ regmap_write(lt->regmap[0], 0x57, 0x01);
+ regmap_write(lt->regmap[0], 0x5a, 0x02);
+
+ /* MIPIAnalog */
+ regmap_write(lt->regmap[0], 0x3e, 0xce);
+ regmap_write(lt->regmap[0], 0x3f, 0xd4);
+ regmap_write(lt->regmap[0], 0x41, 0x3c);
+
+ /* MipiBasicSet */
+ regmap_write(lt->regmap[1], 0x12, 0x04);
+ regmap_write(lt->regmap[1], 0x13, lanes % 4);
+ regmap_write(lt->regmap[1], 0x14, 0x00);
+
+ regmap_write(lt->regmap[1], 0x15, 0x00);
+ regmap_write(lt->regmap[1], 0x1a, 0x03);
+ regmap_write(lt->regmap[1], 0x1b, 0x03);
+
+ /* MIPIDig */
+ regmap_write(lt->regmap[1], 0x10, 0x01);
+ regmap_write(lt->regmap[1], 0x11, 0x0a);
+ regmap_write(lt->regmap[1], 0x18, hsync);
+ regmap_write(lt->regmap[1], 0x19, vsync);
+ regmap_write(lt->regmap[1], 0x1c, hactive % 0x100);
+ regmap_write(lt->regmap[1], 0x1d, hactive >> 8);
+
+ regmap_write(lt->regmap[1], 0x2f, 0x0c);
+
+ regmap_write(lt->regmap[1], 0x34, htotal % 0x100);
+ regmap_write(lt->regmap[1], 0x35, htotal >> 8);
+ regmap_write(lt->regmap[1], 0x36, vtotal % 0x100);
+ regmap_write(lt->regmap[1], 0x37, vtotal >> 8);
+ regmap_write(lt->regmap[1], 0x38, vbp % 0x100);
+ regmap_write(lt->regmap[1], 0x39, vbp >> 8);
+ regmap_write(lt->regmap[1], 0x3a, vfp % 0x100);
+ regmap_write(lt->regmap[1], 0x3b, vfp >> 8);
+ regmap_write(lt->regmap[1], 0x3c, hbp % 0x100);
+ regmap_write(lt->regmap[1], 0x3d, hbp >> 8);
+ regmap_write(lt->regmap[1], 0x3e, hfp % 0x100);
+ regmap_write(lt->regmap[1], 0x3f, hfp >> 8);
+ regmap_read(lt->regmap[0], 0xab, &reg);
+ reg &= 0xfc;
+ reg |= (hsync_activehigh < 1) | vsync_activehigh;
+ regmap_write(lt->regmap[0], 0xab, reg);
+
+ /* DDSConfig */
+ regmap_write(lt->regmap[1], 0x4e, 0x6a);
+ regmap_write(lt->regmap[1], 0x4f, 0xad);
+ regmap_write(lt->regmap[1], 0x50, 0xf3);
+ regmap_write(lt->regmap[1], 0x51, 0x80);
+
+ regmap_write(lt->regmap[1], 0x1f, 0x5e);
+ regmap_write(lt->regmap[1], 0x20, 0x01);
+ regmap_write(lt->regmap[1], 0x21, 0x2c);
+ regmap_write(lt->regmap[1], 0x22, 0x01);
+ regmap_write(lt->regmap[1], 0x23, 0xfa);
+ regmap_write(lt->regmap[1], 0x24, 0x00);
+ regmap_write(lt->regmap[1], 0x25, 0xc8);
+ regmap_write(lt->regmap[1], 0x26, 0x00);
+ regmap_write(lt->regmap[1], 0x27, 0x5e);
+ regmap_write(lt->regmap[1], 0x28, 0x01);
+ regmap_write(lt->regmap[1], 0x29, 0x2c);
+ regmap_write(lt->regmap[1], 0x2a, 0x01);
+ regmap_write(lt->regmap[1], 0x2b, 0xfa);
+ regmap_write(lt->regmap[1], 0x2c, 0x00);
+ regmap_write(lt->regmap[1], 0x2d, 0xc8);
+ regmap_write(lt->regmap[1], 0x2e, 0x00);
+ regmap_write(lt->regmap[1], 0x42, 0x64);
+ regmap_write(lt->regmap[1], 0x43, 0x00);
+ regmap_write(lt->regmap[1], 0x44, 0x04);
+ regmap_write(lt->regmap[1], 0x45, 0x00);
+ regmap_write(lt->regmap[1], 0x46, 0x59);
+ regmap_write(lt->regmap[1], 0x47, 0x00);
+ regmap_write(lt->regmap[1], 0x48, 0xf2);
+ regmap_write(lt->regmap[1], 0x49, 0x06);
+ regmap_write(lt->regmap[1], 0x4a, 0x00);
+ regmap_write(lt->regmap[1], 0x4b, 0x72);
+ regmap_write(lt->regmap[1], 0x4c, 0x45);
+ regmap_write(lt->regmap[1], 0x4d, 0x00);
+ regmap_write(lt->regmap[1], 0x52, 0x08);
+ regmap_write(lt->regmap[1], 0x53, 0x00);
+ regmap_write(lt->regmap[1], 0x54, 0xb2);
+ regmap_write(lt->regmap[1], 0x55, 0x00);
+ regmap_write(lt->regmap[1], 0x56, 0xe4);
+ regmap_write(lt->regmap[1], 0x57, 0x0d);
+ regmap_write(lt->regmap[1], 0x58, 0x00);
+ regmap_write(lt->regmap[1], 0x59, 0xe4);
+ regmap_write(lt->regmap[1], 0x5a, 0x8a);
+ regmap_write(lt->regmap[1], 0x5b, 0x00);
+ regmap_write(lt->regmap[1], 0x5c, 0x34);
+ regmap_write(lt->regmap[1], 0x1e, 0x4f);
+ regmap_write(lt->regmap[1], 0x51, 0x00);
+
+ regmap_write(lt->regmap[0], 0xb2, lt->sink_is_hdmi);
+
+ /* Audio Disable */
+ regmap_write(lt->regmap[2], 0x06, 0x00);
+ regmap_write(lt->regmap[2], 0x07, 0x00);
+
+ regmap_write(lt->regmap[2], 0x34, 0xd2);
+
+ regmap_write(lt->regmap[2], 0x3c, 0x41);
+
+ /* MIPIRxLogicRes */
+ regmap_write(lt->regmap[0], 0x03, 0x7f);
+ usleep_range(10000, 20000);
+ regmap_write(lt->regmap[0], 0x03, 0xff);
+
+ regmap_write(lt->regmap[1], 0x51, 0x80);
+ usleep_range(10000, 20000);
+ regmap_write(lt->regmap[1], 0x51, 0x00);
+}
+
+static void lt8912_wakeup(struct lt8912 *lt)
+{
+ gpiod_direction_output(lt->reset_n, 1);
+ msleep(120);
+ gpiod_direction_output(lt->reset_n, 0);
+
+ regmap_write(lt->regmap[0], 0x08,0xff); /* enable clk gating */
+ regmap_write(lt->regmap[0], 0x41,0x3c); /* MIPI Rx Power On */
+ regmap_write(lt->regmap[0], 0x05,0xfb); /* DDS logical reset */
+ regmap_write(lt->regmap[0], 0x05,0xff);
+ regmap_write(lt->regmap[0], 0x03,0x7f); /* MIPI RX logical reset */
+ usleep_range(10000, 20000);
+ regmap_write(lt->regmap[0], 0x03,0xff);
+ regmap_write(lt->regmap[0], 0x32,0xa1);
+ regmap_write(lt->regmap[0], 0x33,0x03);
+}
+
+static void lt8912_sleep(struct lt8912 *lt)
+{
+ regmap_write(lt->regmap[0], 0x32,0xa0);
+ regmap_write(lt->regmap[0], 0x33,0x00); /* Disable HDMI output. */
+ regmap_write(lt->regmap[0], 0x41,0x3d); /* MIPI Rx Power Down. */
+ regmap_write(lt->regmap[0], 0x08,0x00); /* diable DDS clk. */
+
+ gpiod_direction_output(lt->reset_n, 1);
+}
+
+static enum drm_connector_status
+lt8912_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct lt8912 *lt = connector_to_lt8912(connector);
+ enum drm_connector_status hpd, hpd_last;
+ int timeout = 0;
+
+ hpd = connector_status_unknown;
+ do {
+ hpd_last = hpd;
+ hpd = gpiod_get_value_cansleep(lt->hpd_gpio) ?
+ connector_status_connected : connector_status_disconnected;
+ msleep(20);
+ timeout += 20;
+ } while((hpd_last != hpd) && (timeout < 500));
+
+ return hpd;
+}
+
+static const struct drm_connector_funcs lt8912_connector_funcs = {
+ .detect = lt8912_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static irqreturn_t lt8912_hpd_irq_thread(int irq, void *arg)
+{
+ struct lt8912 *lt = arg;
+ struct drm_connector *connector = &lt->connector;
+
+ drm_helper_hpd_irq_event(connector->dev);
+
+ return IRQ_HANDLED;
+}
+
+static struct drm_encoder *
+lt8912_connector_best_encoder(struct drm_connector *connector)
+{
+ struct lt8912 *lt = connector_to_lt8912(connector);
+
+ return lt->bridge.encoder;
+}
+
+static int lt8912_connector_get_modes(struct drm_connector *connector)
+{
+ struct lt8912 *lt = connector_to_lt8912(connector);
+ struct edid *edid;
+ struct display_timings *timings;
+ u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ int i, ret, num_modes = 0;
+
+ /* Check if optional DDC I2C bus should be used. */
+ if (lt->ddc) {
+ edid = drm_get_edid(connector, lt->ddc);
+ if (edid) {
+ drm_connector_update_edid_property(connector,
+ edid);
+ num_modes = drm_add_edid_modes(connector, edid);
+ lt->sink_is_hdmi = !!drm_detect_hdmi_monitor(edid);
+ kfree(edid);
+ }
+ if (num_modes == 0) {
+ dev_warn(lt->dev, "failed to get display timings from EDID\n");
+ return 0;
+ }
+ } else { /* if not EDID, use dtb timings */
+ timings = of_get_display_timings(lt->dev->of_node);
+
+ if (timings->num_timings == 0) {
+ dev_err(lt->dev, "failed to get display timings from dtb\n");
+ return 0;
+ }
+
+ for (i = 0; i < timings->num_timings; i++) {
+ struct drm_display_mode *mode;
+ struct videomode vm;
+
+ if (videomode_from_timings(timings, &vm, i)) {
+ continue;
+ }
+
+ mode = drm_mode_create(connector->dev);
+ drm_display_mode_from_videomode(&vm, mode);
+ mode->type = DRM_MODE_TYPE_DRIVER;
+
+ if (timings->native_mode == i)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+ num_modes++;
+ }
+ if (num_modes == 0) {
+ dev_err(lt->dev, "failed to get display modes from dtb\n");
+ return 0;
+ }
+ }
+
+ connector->display_info.bus_flags = DRM_BUS_FLAG_DE_LOW |
+ DRM_BUS_FLAG_PIXDATA_NEGEDGE;
+ ret = drm_display_info_set_bus_formats(&connector->display_info,
+ &bus_format, 1);
+
+ if (ret)
+ return ret;
+
+ return num_modes;
+}
+
+static enum drm_mode_status lt8912_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ if (mode->clock > 150000)
+ return MODE_CLOCK_HIGH;
+
+ if (mode->hdisplay > 1920)
+ return MODE_BAD_HVALUE;
+
+ if (mode->vdisplay > 1080)
+ return MODE_BAD_VVALUE;
+
+ return MODE_OK;
+}
+
+static const struct drm_connector_helper_funcs lt8912_connector_helper_funcs = {
+ .get_modes = lt8912_connector_get_modes,
+ .best_encoder = lt8912_connector_best_encoder,
+ .mode_valid = lt8912_connector_mode_valid,
+};
+
+static void lt8912_bridge_post_disable(struct drm_bridge *bridge)
+{
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+ lt8912_sleep(lt);
+}
+
+static void lt8912_bridge_enable(struct drm_bridge *bridge)
+{
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+ lt8912_init(lt);
+}
+
+static void lt8912_bridge_pre_enable(struct drm_bridge *bridge)
+{
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+ lt8912_wakeup(lt);
+}
+
+static void lt8912_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adj)
+{
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+
+ drm_mode_copy(&lt->mode, adj);
+}
+
+static int lt8912_bridge_attach(struct drm_bridge *bridge)
+{
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+ struct drm_connector *connector = &lt->connector;
+ int ret;
+
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+ ret = drm_connector_init(bridge->dev, connector,
+ &lt8912_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ if (ret) {
+ dev_err(lt->dev, "failed to initialize connector\n");
+ return ret;
+ }
+
+ drm_connector_helper_add(connector, &lt8912_connector_helper_funcs);
+ drm_connector_attach_encoder(connector, bridge->encoder);
+
+ ret = lt8912_attach_dsi(lt);
+
+ enable_irq(lt->irq);
+
+ return ret;
+}
+
+static const struct drm_bridge_funcs lt8912_bridge_funcs = {
+ .attach = lt8912_bridge_attach,
+ .mode_set = lt8912_bridge_mode_set,
+ .pre_enable = lt8912_bridge_pre_enable,
+ .enable = lt8912_bridge_enable,
+ .post_disable = lt8912_bridge_post_disable,
+};
+
+static const struct regmap_config lt8912_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+};
+
+static int lt8912_i2c_init(struct lt8912 *lt,
+ struct i2c_client *client)
+{
+ struct i2c_board_info info[] = {
+ { I2C_BOARD_INFO("lt8912p0", 0x48), },
+ { I2C_BOARD_INFO("lt8912p1", 0x49), },
+ { I2C_BOARD_INFO("lt8912p2", 0x4a), }
+ };
+ struct regmap *regmap;
+ unsigned int i;
+ int ret;
+
+ if (!lt || !client)
+ return -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(info); i++) {
+ if (i > 0 ) {
+ client = i2c_new_dummy(client->adapter, info[i].addr);
+ if (!client)
+ return -ENODEV;
+ }
+ regmap = devm_regmap_init_i2c(client, &lt8912_regmap_config);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(lt->dev,
+ "Failed to initialize regmap: %d\n", ret);
+ return ret;
+ }
+
+ lt->regmap[i] = regmap;
+ }
+
+ return 0;
+}
+
+int lt8912_attach_dsi(struct lt8912 *lt)
+{
+ struct device *dev = lt->dev;
+ struct mipi_dsi_host *host;
+ struct mipi_dsi_device *dsi;
+ int ret = 0;
+ const struct mipi_dsi_device_info info = { .type = "lt8912",
+ .channel = lt->channel_id,
+ .node = NULL,
+ };
+
+ host = of_find_mipi_dsi_host_by_node(lt->host_node);
+ if (!host) {
+ dev_err(dev, "failed to find dsi host\n");
+ return -EPROBE_DEFER;
+ }
+
+ dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(dsi)) {
+ dev_err(dev, "failed to create dsi device\n");
+ ret = PTR_ERR(dsi);
+ goto err_dsi_device;
+ }
+
+ lt->dsi = dsi;
+
+ dsi->lanes = lt->num_dsi_lanes;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "failed to attach dsi to host\n");
+ goto err_dsi_attach;
+ }
+
+ return 0;
+
+err_dsi_attach:
+ mipi_dsi_device_unregister(dsi);
+err_dsi_device:
+ return ret;
+}
+
+void lt8912_detach_dsi(struct lt8912 *lt)
+{
+ mipi_dsi_detach(lt->dsi);
+ mipi_dsi_device_unregister(lt->dsi);
+}
+
+
+static int lt8912_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c->dev;
+ struct lt8912 *lt;
+ struct device_node *ddc_phandle;
+ struct device_node *endpoint;
+ unsigned int irq_flags;
+ int ret;
+
+ static int initialize_it = 1;
+
+ if(!initialize_it) {
+ initialize_it = 1;
+ return -EPROBE_DEFER;
+ }
+
+ lt = devm_kzalloc(dev, sizeof(*lt), GFP_KERNEL);
+ if (!lt)
+ return -ENOMEM;
+
+ lt->dev = dev;
+
+ /* get optional regular DDC I2C bus */
+ ddc_phandle = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
+ if (ddc_phandle) {
+ lt->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
+ if (!(lt->ddc))
+ ret = -EPROBE_DEFER;
+ of_node_put(ddc_phandle);
+ }
+
+ lt->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
+ if (IS_ERR(lt->hpd_gpio)) {
+ dev_err(dev, "failed to get hpd gpio\n");
+ return ret;
+ }
+
+ lt->irq = gpiod_to_irq(lt->hpd_gpio);
+ if (lt->irq == -ENXIO) {
+ dev_err(dev, "failed to get hpd irq\n");
+ return -ENODEV;
+ }
+ if (lt->irq < 0) {
+ dev_err(dev, "failed to get hpd irq, %i\n", lt->irq);
+ return lt->irq;
+ }
+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ ret = devm_request_threaded_irq(dev, lt->irq,
+ NULL,
+ lt8912_hpd_irq_thread,
+ irq_flags, "lt8912_hpd", lt);
+ if (ret) {
+ dev_err(dev, "failed to request irq\n");
+ return -ENODEV;
+ }
+
+ disable_irq(lt->irq);
+
+ lt->reset_n = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
+ if (IS_ERR(lt->reset_n)) {
+ ret = PTR_ERR(lt->reset_n);
+ dev_err(dev, "failed to request reset GPIO: %d\n", ret);
+ return ret;
+ }
+
+ ret = lt8912_i2c_init(lt, i2c);
+ if (ret)
+ return ret;
+
+ /* TODO: interrupt handing */
+
+ lt->num_dsi_lanes = 4;
+ lt->channel_id = 1;
+
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!endpoint)
+ return -ENODEV;
+
+ lt->host_node = of_graph_get_remote_port_parent(endpoint);
+ if (!lt->host_node) {
+ of_node_put(endpoint);
+ return -ENODEV;
+ }
+
+ of_node_put(endpoint);
+ of_node_put(lt->host_node);
+
+ lt->bridge.funcs = &lt8912_bridge_funcs;
+ lt->bridge.of_node = dev->of_node;
+ drm_bridge_add(&lt->bridge);
+
+ return 0;
+}
+
+static int lt8912_remove(struct i2c_client *i2c)
+{
+ struct lt8912 *lt = i2c_get_clientdata(i2c);
+
+ lt8912_sleep(lt);
+ mipi_dsi_detach(lt->dsi);
+ drm_bridge_remove(&lt->bridge);
+
+ return 0;
+}
+
+static const struct i2c_device_id lt8912_i2c_ids[] = {
+ { "lt8912", 0 },
+ { }
+};
+
+static const struct of_device_id lt8912_of_match[] = {
+ { .compatible = "lontium,lt8912" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, lt8912_of_match);
+
+static struct mipi_dsi_driver lt8912_driver = {
+ .driver.name = "lt8912",
+};
+
+static struct i2c_driver lt8912_i2c_driver = {
+ .driver = {
+ .name = "lt8912",
+ .of_match_table = lt8912_of_match,
+ },
+ .id_table = lt8912_i2c_ids,
+ .probe = lt8912_probe,
+ .remove = lt8912_remove,
+};
+
+static int __init lt8912_i2c_drv_init(void)
+{
+ mipi_dsi_driver_register(&lt8912_driver);
+
+ return i2c_add_driver(&lt8912_i2c_driver);
+}
+module_init(lt8912_i2c_drv_init);
+
+static void __exit lt8912_i2c_exit(void)
+{
+ i2c_del_driver(&lt8912_i2c_driver);
+
+ mipi_dsi_driver_unregister(&lt8912_driver);
+}
+module_exit(lt8912_i2c_exit);
+
+MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
+MODULE_DESCRIPTION("Lontium LT8912 MIPI-DSI to LVDS and HDMI/MHL bridge");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/Kconfig b/drivers/gpu/drm/bridge/sn65dsi83/Kconfig
new file mode 100644
index 000000000000..1d8f37f689d3
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/Kconfig
@@ -0,0 +1,7 @@
+config DRM_I2C_SN65DSI83
+ bool "SN65DSI83 mipi dsi to lvds bridge"
+ depends on OF
+ select DRM_MIPI_DSI
+ default y
+ help
+ Support for the sn65dsi83 MIPI DSI to LVDS bridge
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/Makefile b/drivers/gpu/drm/bridge/sn65dsi83/Makefile
new file mode 100644
index 000000000000..dee7f493b323
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/Makefile
@@ -0,0 +1,2 @@
+sn65dsi83-objs := sn65dsi83_drv.o sn65dsi83_brg.o
+obj-$(CONFIG_DRM_I2C_SN65DSI83) := sn65dsi83.o
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c
new file mode 100644
index 000000000000..f4a7713635d6
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2018 CopuLab Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_connector.h>
+#include <video/mipi_display.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include "sn65dsi83_brg.h"
+
+/* Register addresses */
+
+#define SN65DSI83_SOFT_RESET 0x09
+#define SN65DSI83_CORE_PLL 0x0A
+ #define LVDS_CLK_RANGE_SHIFT 1
+ #define HS_CLK_SRC_SHIFT 0
+
+#define SN65DSI83_PLL_DIV 0x0B
+ #define DSI_CLK_DIV_SHIFT 3
+
+#define SN65DSI83_PLL_EN 0x0D
+#define SN65DSI83_DSI_CFG 0x10
+ #define CHA_DSI_LANES_SHIFT 3
+
+#define SN65DSI83_DSI_EQ 0x11
+#define SN65DSI83_CHA_DSI_CLK_RNG 0x12
+#define SN65DSI83_CHB_DSI_CLK_RNG 0x13
+#define SN65DSI83_LVDS_MODE 0x18
+ #define DE_NEG_POLARITY_SHIFT 7
+ #define HS_NEG_POLARITY_SHIFT 6
+ #define VS_NEG_POLARITY_SHIFT 5
+ #define LVDS_LINK_CFG_SHIFT 4
+ #define CHA_24BPP_MODE_SHIFT 3
+ #define CHA_24BPP_FMT1_SHIFT 1
+
+#define SN65DSI83_LVDS_SIGN 0x19
+#define SN65DSI83_LVDS_TERM 0x1A
+#define SN65DSI83_LVDS_CM_ADJ 0x1B
+#define SN65DSI83_CHA_LINE_LEN_LO 0x20
+#define SN65DSI83_CHA_LINE_LEN_HI 0x21
+#define SN65DSI83_CHB_LINE_LEN_LO 0x22
+#define SN65DSI83_CHB_LINE_LEN_HI 0x23
+#define SN65DSI83_CHA_VERT_LINES_LO 0x24
+#define SN65DSI83_CHA_VERT_LINES_HI 0x25
+#define SN65DSI83_CHB_VERT_LINES_LO 0x26
+#define SN65DSI83_CHB_VERT_LINES_HI 0x27
+#define SN65DSI83_CHA_SYNC_DELAY_LO 0x28
+#define SN65DSI83_CHA_SYNC_DELAY_HI 0x29
+#define SN65DSI83_CHB_SYNC_DELAY_LO 0x2A
+#define SN65DSI83_CHB_SYNC_DELAY_HI 0x2B
+#define SN65DSI83_CHA_HSYNC_WIDTH_LO 0x2C
+#define SN65DSI83_CHA_HSYNC_WIDTH_HI 0x2D
+#define SN65DSI83_CHB_HSYNC_WIDTH_LO 0x2E
+#define SN65DSI83_CHB_HSYNC_WIDTH_HI 0x2F
+#define SN65DSI83_CHA_VSYNC_WIDTH_LO 0x30
+#define SN65DSI83_CHA_VSYNC_WIDTH_HI 0x31
+#define SN65DSI83_CHB_VSYNC_WIDTH_LO 0x32
+#define SN65DSI83_CHB_VSYNC_WIDTH_HI 0x33
+#define SN65DSI83_CHA_HORZ_BACKPORCH 0x34
+#define SN65DSI83_CHB_HORZ_BACKPORCH 0x35
+#define SN65DSI83_CHA_VERT_BACKPORCH 0x36
+#define SN65DSI83_CHB_VERT_BACKPORCH 0x37
+#define SN65DSI83_CHA_HORZ_FRONTPORCH 0x38
+#define SN65DSI83_CHB_HORZ_FRONTPORCH 0x39
+#define SN65DSI83_CHA_VERT_FRONTPORCH 0x3A
+#define SN65DSI83_CHB_VERT_FRONTPORCH 0x3B
+#define SN65DSI83_CHA_ERR 0xE5
+#define SN65DSI83_TEST_PATTERN 0x3C
+#define SN65DSI83_REG_3D 0x3D
+#define SN65DSI83_REG_3E 0x3E
+
+static int sn65dsi83_brg_power_on(struct sn65dsi83_brg *brg)
+{
+ dev_info(&brg->client->dev,"%s\n",__func__);
+ gpiod_set_value_cansleep(brg->gpio_enable, 1);
+ /* Wait for 1ms for the internal voltage regulator to stabilize */
+ msleep(1);
+
+ return 0;
+}
+
+static void sn65dsi83_brg_power_off(struct sn65dsi83_brg *brg)
+{
+ dev_info(&brg->client->dev,"%s\n",__func__);
+ gpiod_set_value_cansleep(brg->gpio_enable, 0);
+ /*
+ * The EN pin must be held low for at least 10 ms
+ * before being asserted high
+ */
+ msleep(10);
+}
+
+static int sn65dsi83_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+
+ if (ret)
+ dev_err(&client->dev, "failed to write at 0x%02x", reg);
+
+ dev_dbg(&client->dev, "%s: write reg 0x%02x data 0x%02x", __func__, reg, val);
+
+ return ret;
+}
+#define SN65DSI83_WRITE(reg,val) sn65dsi83_write(client, (reg) , (val))
+
+static int sn65dsi83_read(struct i2c_client *client, u8 reg)
+{
+ int ret;
+
+ dev_info(&client->dev, "client 0x%p", client);
+ ret = i2c_smbus_read_byte_data(client, reg);
+
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading at 0x%02x", reg);
+ return ret;
+ }
+
+ dev_dbg(&client->dev, "%s: read reg 0x%02x data 0x%02x", __func__, reg, ret);
+
+ return ret;
+}
+#define SN65DSI83_READ(reg) sn65dsi83_read(client, (reg))
+
+static int sn65dsi83_brg_start_stream(struct sn65dsi83_brg *brg)
+{
+ int regval;
+ struct i2c_client *client = I2C_CLIENT(brg);
+
+ dev_info(&client->dev,"%s\n",__func__);
+ /* Set the PLL_EN bit (CSR 0x0D.0) */
+ SN65DSI83_WRITE(SN65DSI83_PLL_EN, 0x1);
+ /* Wait for the PLL_LOCK bit to be set (CSR 0x0A.7) */
+ msleep(200);
+
+ /* Perform SW reset to apply changes */
+ SN65DSI83_WRITE(SN65DSI83_SOFT_RESET, 0x01);
+
+ /* Read CHA Error register */
+ regval = SN65DSI83_READ(SN65DSI83_CHA_ERR);
+ dev_info(&client->dev, "CHA (0x%02x) = 0x%02x",
+ SN65DSI83_CHA_ERR, regval);
+
+ return 0;
+}
+
+static void sn65dsi83_brg_stop_stream(struct sn65dsi83_brg *brg)
+{
+ struct i2c_client *client = I2C_CLIENT(brg);
+ dev_info(&client->dev,"%s\n",__func__);
+ /* Clear the PLL_EN bit (CSR 0x0D.0) */
+ SN65DSI83_WRITE(SN65DSI83_PLL_EN, 0x00);
+}
+
+static int sn65dsi83_calk_clk_range(int min_regval, int max_regval,
+ unsigned long min_clk, unsigned long inc,
+ unsigned long target_clk)
+{
+ int regval = min_regval;
+ unsigned long clk = min_clk;
+
+ while (regval <= max_regval) {
+ if ((clk <= target_clk) && (target_clk < (clk + inc)))
+ return regval;
+
+ regval++;
+ clk += inc;
+ }
+
+ return -1;
+}
+
+#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
+static int sn65dsi83_calk_div(int min_regval, int max_regval, int min_div,
+ int inc, unsigned long source_clk,
+ unsigned long target_clk)
+{
+ int regval = min_regval;
+ int div = min_div;
+ unsigned long curr_delta;
+ unsigned long prev_delta = ABS(DIV_ROUND_UP(source_clk, div) -
+ target_clk);
+
+ while (regval <= max_regval) {
+ curr_delta = ABS(DIV_ROUND_UP(source_clk, div) - target_clk);
+ if (curr_delta > prev_delta)
+ return --regval;
+
+ regval++;
+ div += inc;
+ }
+
+ return -1;
+}
+
+static int sn65dsi83_brg_configure(struct sn65dsi83_brg *brg)
+{
+ int regval = 0;
+ struct i2c_client *client = I2C_CLIENT(brg);
+ struct videomode *vm = VM(brg);
+
+ u32 dsi_clk = (((PIXCLK * BPP(brg)) / DSI_LANES(brg)) >> 1);
+
+ dev_info(&client->dev, "DSI clock [ %u ] Hz\n",dsi_clk);
+ dev_info(&client->dev, "GeoMetry [ %d x %d ] Hz\n",HACTIVE,VACTIVE);
+
+ /* Reset PLL_EN and SOFT_RESET registers */
+ SN65DSI83_WRITE(SN65DSI83_SOFT_RESET,0x00);
+ SN65DSI83_WRITE(SN65DSI83_PLL_EN,0x00);
+
+ /* LVDS clock setup */
+ if ((25000000 <= PIXCLK) && (PIXCLK < 37500000))
+ regval = 0;
+ else
+ regval = sn65dsi83_calk_clk_range(0x01, 0x05, 37500000, 25000000,
+ PIXCLK);
+
+ if (regval < 0) {
+ dev_err(&client->dev, "failed to configure LVDS clock");
+ return -EINVAL;
+ }
+
+ regval = (regval << LVDS_CLK_RANGE_SHIFT);
+ regval |= (1 << HS_CLK_SRC_SHIFT); /* Use DSI clock */
+ SN65DSI83_WRITE(SN65DSI83_CORE_PLL,regval);
+
+ /* DSI clock range */
+ regval = sn65dsi83_calk_clk_range(0x08, 0x64, 40000000, 5000000, dsi_clk);
+ if (regval < 0) {
+ dev_err(&client->dev, "failed to configure DSI clock range\n");
+ return -EINVAL;
+ }
+ SN65DSI83_WRITE(SN65DSI83_CHA_DSI_CLK_RNG,regval);
+
+ /* DSI clock divider */
+ regval = sn65dsi83_calk_div(0x0, 0x18, 1, 1, dsi_clk, PIXCLK);
+ if (regval < 0) {
+ dev_err(&client->dev, "failed to calculate DSI clock divider");
+ return -EINVAL;
+ }
+
+ regval = regval << DSI_CLK_DIV_SHIFT;
+ SN65DSI83_WRITE(SN65DSI83_PLL_DIV,regval);
+
+ /* Configure DSI_LANES */
+ regval = SN65DSI83_READ(SN65DSI83_DSI_CFG);
+ regval &= ~(3 << CHA_DSI_LANES_SHIFT);
+ regval |= ((4 - DSI_LANES(brg)) << CHA_DSI_LANES_SHIFT);
+ SN65DSI83_WRITE(SN65DSI83_DSI_CFG,regval);
+
+ /* CHA_DSI_DATA_EQ - No Equalization */
+ /* CHA_DSI_CLK_EQ - No Equalization */
+ SN65DSI83_WRITE(SN65DSI83_DSI_EQ,0x00);
+
+ /* Video formats */
+ regval = 0;
+ if (FLAGS & DISPLAY_FLAGS_HSYNC_LOW)
+ regval |= (1 << HS_NEG_POLARITY_SHIFT);
+
+ if (FLAGS & DISPLAY_FLAGS_VSYNC_LOW)
+ regval |= (1 << VS_NEG_POLARITY_SHIFT);
+
+ if (FLAGS & DISPLAY_FLAGS_DE_LOW)
+ regval |= (1 << DE_NEG_POLARITY_SHIFT);
+
+ if (BPP(brg) == 24)
+ regval |= (1 << CHA_24BPP_MODE_SHIFT);
+
+ if (FORMAT(brg) == 1)
+ regval |= (1 << CHA_24BPP_FMT1_SHIFT);
+
+ regval |= (1 << LVDS_LINK_CFG_SHIFT);
+ SN65DSI83_WRITE(SN65DSI83_LVDS_MODE,regval);
+
+ /* Voltage and pins */
+ SN65DSI83_WRITE(SN65DSI83_LVDS_SIGN,0x00);
+ SN65DSI83_WRITE(SN65DSI83_LVDS_TERM,0x03);
+ SN65DSI83_WRITE(SN65DSI83_LVDS_CM_ADJ,0x00);
+
+ /* Configure sync delay to minimal allowed value */
+ SN65DSI83_WRITE(SN65DSI83_CHA_SYNC_DELAY_LO,0x21);
+ SN65DSI83_WRITE(SN65DSI83_CHA_SYNC_DELAY_HI,0x00);
+
+ /* Geometry */
+ SN65DSI83_WRITE(SN65DSI83_CHA_LINE_LEN_LO,LOW(HACTIVE));
+ SN65DSI83_WRITE(SN65DSI83_CHA_LINE_LEN_HI,HIGH(HACTIVE));
+
+ SN65DSI83_WRITE(SN65DSI83_CHA_VERT_LINES_LO,LOW(VACTIVE));
+ SN65DSI83_WRITE(SN65DSI83_CHA_VERT_LINES_HI,HIGH(VACTIVE));
+
+ SN65DSI83_WRITE(SN65DSI83_CHA_HSYNC_WIDTH_LO,LOW(HPW));
+ SN65DSI83_WRITE(SN65DSI83_CHA_HSYNC_WIDTH_HI,HIGH(HPW));
+
+ SN65DSI83_WRITE(SN65DSI83_CHA_VSYNC_WIDTH_LO,LOW(VPW));
+ SN65DSI83_WRITE(SN65DSI83_CHA_VSYNC_WIDTH_HI,HIGH(VPW));
+
+ SN65DSI83_WRITE(SN65DSI83_CHA_HORZ_BACKPORCH,LOW(HBP));
+ SN65DSI83_WRITE(SN65DSI83_CHA_VERT_BACKPORCH,LOW(VBP));
+
+ SN65DSI83_WRITE(SN65DSI83_CHA_HORZ_FRONTPORCH,LOW(HFP));
+ SN65DSI83_WRITE(SN65DSI83_CHA_VERT_FRONTPORCH,LOW(VFP));
+
+ SN65DSI83_WRITE(SN65DSI83_TEST_PATTERN,0x00);
+ SN65DSI83_WRITE(SN65DSI83_REG_3D,0x00);
+ SN65DSI83_WRITE(SN65DSI83_REG_3E,0x00);
+
+ /* mute channel B */
+ SN65DSI83_WRITE(SN65DSI83_CHB_DSI_CLK_RNG, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_LINE_LEN_LO, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_LINE_LEN_HI, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_VERT_LINES_LO, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_VERT_LINES_HI, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_SYNC_DELAY_LO, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_SYNC_DELAY_HI, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_HSYNC_WIDTH_LO, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_HSYNC_WIDTH_HI, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_VSYNC_WIDTH_LO, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_VSYNC_WIDTH_HI, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_HORZ_BACKPORCH, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_VERT_BACKPORCH, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_HORZ_FRONTPORCH, 0x00);
+ SN65DSI83_WRITE(SN65DSI83_CHB_VERT_FRONTPORCH, 0x00);
+ return 0;
+}
+
+static int sn65dsi83_brg_setup(struct sn65dsi83_brg *brg)
+{
+ struct i2c_client *client = I2C_CLIENT(brg);
+ dev_info(&client->dev,"%s\n",__func__);
+ sn65dsi83_brg_power_on(brg);
+ return sn65dsi83_brg_configure(brg);
+}
+
+static int sn65dsi83_brg_reset(struct sn65dsi83_brg *brg)
+{
+ /* Soft Reset reg value at power on should be 0x00 */
+ struct i2c_client *client = I2C_CLIENT(brg);
+ int ret = SN65DSI83_READ(SN65DSI83_SOFT_RESET);
+ dev_info(&client->dev,"%s\n",__func__);
+ if (ret != 0x00) {
+ dev_err(&client->dev,"Failed to reset the device");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static struct sn65dsi83_brg_funcs brg_func = {
+ .power_on = sn65dsi83_brg_power_on,
+ .power_off = sn65dsi83_brg_power_off,
+ .setup = sn65dsi83_brg_setup,
+ .reset = sn65dsi83_brg_reset,
+ .start_stream = sn65dsi83_brg_start_stream,
+ .stop_stream = sn65dsi83_brg_stop_stream,
+};
+
+static struct sn65dsi83_brg brg = {
+ .funcs = &brg_func,
+};
+
+struct sn65dsi83_brg *sn65dsi83_brg_get(void) {
+ return &brg;
+}
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h
new file mode 100644
index 000000000000..9f23df8afedc
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h
@@ -0,0 +1,55 @@
+#ifndef _SN65DSI83_BRG_H__
+#define _SN65DSI83_BRG_H__
+
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+#include <video/videomode.h>
+
+struct sn65dsi83_brg;
+struct sn65dsi83_brg_funcs {
+ int (*power_on)(struct sn65dsi83_brg *sn65dsi8383_brg);
+ void (*power_off)(struct sn65dsi83_brg *sn65dsi8383_brg);
+ int (*reset)(struct sn65dsi83_brg *sn65dsi8383_brg);
+ int (*setup)(struct sn65dsi83_brg *sn65dsi8383_brg);
+ int (*start_stream)(struct sn65dsi83_brg *sn65dsi8383_brg);
+ void (*stop_stream)(struct sn65dsi83_brg *sn65dsi8383_brg);
+};
+
+struct sn65dsi83_brg {
+ struct i2c_client *client;
+ struct gpio_desc *gpio_enable;
+ /* Bridge Panel Parameters */
+ struct videomode vm;
+ u32 width_mm;
+ u32 height_mm;
+ u32 format;
+ u32 bpp;
+
+ u8 num_dsi_lanes;
+ struct sn65dsi83_brg_funcs *funcs;
+};
+struct sn65dsi83_brg *sn65dsi83_brg_get(void);
+
+#define I2C_DEVICE(A) &(A)->client->dev
+#define I2C_CLIENT(A) (A)->client
+#define VM(A) &(A)->vm
+#define BPP(A) (A)->bpp
+#define FORMAT(A) (A)->format
+#define DSI_LANES(A) (A)->num_dsi_lanes
+
+/* The caller has to have a vm structure defined */
+#define PIXCLK vm->pixelclock
+#define HACTIVE vm->hactive
+#define HFP vm->hfront_porch
+#define HBP vm->hback_porch
+#define HPW vm->hsync_len
+#define VACTIVE vm->vactive
+#define VFP vm->vfront_porch
+#define VBP vm->vback_porch
+#define VPW vm->vsync_len
+#define FLAGS vm->flags
+
+#define HIGH(A) (((A) >> 8) & 0xFF)
+#define LOW(A) ((A) & 0xFF)
+
+#endif /* _SN65DSI83_BRG_H__ */
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c
new file mode 100644
index 000000000000..ec7d62cc3275
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c
@@ -0,0 +1,408 @@
+/*
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <video/mipi_display.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include "sn65dsi83_timing.h"
+#include "sn65dsi83_brg.h"
+
+struct sn65dsi83 {
+ u8 channel_id;
+ enum drm_connector_status status;
+ bool powered;
+ struct drm_display_mode curr_mode;
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+ struct device_node *host_node;
+ struct mipi_dsi_device *dsi;
+ struct sn65dsi83_brg *brg;
+};
+
+static int sn65dsi83_attach_dsi(struct sn65dsi83 *sn65dsi83);
+#define DRM_DEVICE(A) A->dev->dev
+/* Connector funcs */
+static struct sn65dsi83 *connector_to_sn65dsi83(struct drm_connector *connector)
+{
+ return container_of(connector, struct sn65dsi83, connector);
+}
+
+static int sn65dsi83_connector_get_modes(struct drm_connector *connector)
+{
+ struct sn65dsi83 *sn65dsi83 = connector_to_sn65dsi83(connector);
+ struct sn65dsi83_brg *brg = sn65dsi83->brg;
+ struct device *dev = connector->dev->dev;
+ struct drm_display_mode *mode;
+ u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ u32 *bus_flags = &connector->display_info.bus_flags;
+ int ret;
+
+ dev_info(dev, "%s\n",__func__);
+ mode = drm_mode_create(connector->dev);
+ if (!mode) {
+ DRM_DEV_ERROR(dev, "Failed to create display mode!\n");
+ return 0;
+ }
+
+ drm_display_mode_from_videomode(&brg->vm, mode);
+ mode->width_mm = brg->width_mm;
+ mode->height_mm = brg->height_mm;
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, mode);
+ drm_connector_list_update(connector);
+
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+
+ if (brg->vm.flags & DISPLAY_FLAGS_DE_HIGH)
+ *bus_flags |= DRM_BUS_FLAG_DE_HIGH;
+ if (brg->vm.flags & DISPLAY_FLAGS_DE_LOW)
+ *bus_flags |= DRM_BUS_FLAG_DE_LOW;
+ if (brg->vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+ *bus_flags |= DRM_BUS_FLAG_PIXDATA_NEGEDGE;
+ if (brg->vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
+ *bus_flags |= DRM_BUS_FLAG_PIXDATA_POSEDGE;
+
+ ret = drm_display_info_set_bus_formats(&connector->display_info,
+ &bus_format, 1);
+ if (ret)
+ return ret;
+
+ return 1;
+}
+
+static enum drm_mode_status
+sn65dsi83_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct sn65dsi83 *sn65dsi83 = connector_to_sn65dsi83(connector);
+ struct device *dev = connector->dev->dev;
+ if (mode->clock > ( sn65dsi83->brg->vm.pixelclock / 1000 ))
+ return MODE_CLOCK_HIGH;
+
+ dev_info(dev, "%s: mode: %d*%d@%d is valid\n",__func__,
+ mode->hdisplay,mode->vdisplay,mode->clock);
+ return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs sn65dsi83_connector_helper_funcs = {
+ .get_modes = sn65dsi83_connector_get_modes,
+ .mode_valid = sn65dsi83_connector_mode_valid,
+};
+
+static enum drm_connector_status
+sn65dsi83_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct sn65dsi83 *sn65dsi83 = connector_to_sn65dsi83(connector);
+ struct device *dev = connector->dev->dev;
+ enum drm_connector_status status;
+ dev_info(dev, "%s\n",__func__);
+
+ status = connector_status_connected;
+ sn65dsi83->status = status;
+ return status;
+}
+
+int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
+ uint32_t maxX, uint32_t maxY);
+
+static struct drm_connector_funcs sn65dsi83_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = sn65dsi83_connector_detect,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+/* Bridge funcs */
+static struct sn65dsi83 *bridge_to_sn65dsi83(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct sn65dsi83, bridge);
+}
+
+static void sn65dsi83_bridge_enable(struct drm_bridge *bridge)
+{
+ struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+ dev_info(DRM_DEVICE(bridge),"%s\n",__func__);
+ sn65dsi83->brg->funcs->setup(sn65dsi83->brg);
+ sn65dsi83->brg->funcs->start_stream(sn65dsi83->brg);
+}
+
+static void sn65dsi83_bridge_disable(struct drm_bridge *bridge)
+{
+ struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+ dev_info(DRM_DEVICE(bridge),"%s\n",__func__);
+ sn65dsi83->brg->funcs->stop_stream(sn65dsi83->brg);
+ sn65dsi83->brg->funcs->power_off(sn65dsi83->brg);
+}
+
+static void sn65dsi83_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adj_mode)
+{
+ struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+ dev_info(DRM_DEVICE(bridge), "%s: mode: %d*%d@%d\n",__func__,
+ mode->hdisplay,mode->vdisplay,mode->clock);
+ drm_mode_copy(&sn65dsi83->curr_mode, adj_mode);
+}
+
+static int sn65dsi83_bridge_attach(struct drm_bridge *bridge)
+{
+ struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+ int ret;
+
+ dev_info(DRM_DEVICE(bridge),"%s\n",__func__);
+ if (!bridge->encoder) {
+ DRM_ERROR("Parent encoder object not found");
+ return -ENODEV;
+ }
+
+ sn65dsi83->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
+
+ ret = drm_connector_init(bridge->dev, &sn65dsi83->connector,
+ &sn65dsi83_connector_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ if (ret) {
+ DRM_ERROR("Failed to initialize connector with drm\n");
+ return ret;
+ }
+ drm_connector_helper_add(&sn65dsi83->connector,
+ &sn65dsi83_connector_helper_funcs);
+ drm_connector_attach_encoder(&sn65dsi83->connector, bridge->encoder);
+
+ ret = sn65dsi83_attach_dsi(sn65dsi83);
+
+ return ret;
+}
+
+static struct drm_bridge_funcs sn65dsi83_bridge_funcs = {
+ .enable = sn65dsi83_bridge_enable,
+ .disable = sn65dsi83_bridge_disable,
+ .mode_set = sn65dsi83_bridge_mode_set,
+ .attach = sn65dsi83_bridge_attach,
+};
+
+static int sn65dsi83_parse_dt(struct device_node *np,
+ struct sn65dsi83 *sn65dsi83)
+{
+ struct device *dev = &sn65dsi83->brg->client->dev;
+ u32 num_lanes = 2, bpp = 24, format = 2, width = 149, height = 93;
+ struct device_node *endpoint;
+
+ endpoint = of_graph_get_next_endpoint(np, NULL);
+ if (!endpoint)
+ return -ENODEV;
+
+ sn65dsi83->host_node = of_graph_get_remote_port_parent(endpoint);
+ if (!sn65dsi83->host_node) {
+ of_node_put(endpoint);
+ return -ENODEV;
+ }
+
+ of_property_read_u32(np, "ti,dsi-lanes", &num_lanes);
+ of_property_read_u32(np, "ti,lvds-format", &format);
+ of_property_read_u32(np, "ti,lvds-bpp", &bpp);
+ of_property_read_u32(np, "ti,width-mm", &width);
+ of_property_read_u32(np, "ti,height-mm", &height);
+
+ if (num_lanes < 1 || num_lanes > 4) {
+ dev_err(dev, "Invalid dsi-lanes: %d\n", num_lanes);
+ return -EINVAL;
+ }
+ sn65dsi83->brg->num_dsi_lanes = num_lanes;
+
+ sn65dsi83->brg->gpio_enable = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(sn65dsi83->brg->gpio_enable)) {
+ dev_err(dev, "failed to parse enable gpio");
+ return PTR_ERR(sn65dsi83->brg->gpio_enable);
+ }
+
+ sn65dsi83->brg->format = format;
+ sn65dsi83->brg->bpp = bpp;
+
+ sn65dsi83->brg->width_mm = width;
+ sn65dsi83->brg->height_mm = height;
+
+ /* Read default timing if there is not device tree node for */
+ if ((of_get_videomode(np, &sn65dsi83->brg->vm, 0)) < 0)
+ videomode_from_timing(&panel_default_timing, &sn65dsi83->brg->vm);
+
+ of_node_put(endpoint);
+ of_node_put(sn65dsi83->host_node);
+
+ return 0;
+}
+
+static int sn65dsi83_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct sn65dsi83 *sn65dsi83;
+ struct device *dev = &i2c->dev;
+ int ret;
+
+ dev_info(dev,"%s\n",__func__);
+ if (!dev->of_node)
+ return -EINVAL;
+
+ sn65dsi83 = devm_kzalloc(dev, sizeof(*sn65dsi83), GFP_KERNEL);
+ if (!sn65dsi83)
+ return -ENOMEM;
+
+ /* Initialize it before DT parser */
+ sn65dsi83->brg = sn65dsi83_brg_get();
+ sn65dsi83->brg->client = i2c;
+
+ sn65dsi83->powered = false;
+ sn65dsi83->status = connector_status_disconnected;
+
+ i2c_set_clientdata(i2c, sn65dsi83);
+
+ ret = sn65dsi83_parse_dt(dev->of_node, sn65dsi83);
+ if (ret)
+ return ret;
+
+ sn65dsi83->brg->funcs->power_off(sn65dsi83->brg);
+ sn65dsi83->brg->funcs->power_on(sn65dsi83->brg);
+ ret = sn65dsi83->brg->funcs->reset(sn65dsi83->brg);
+ if (ret != 0x00) {
+ dev_err(dev, "Failed to reset the device");
+ return -ENODEV;
+ }
+ sn65dsi83->brg->funcs->power_off(sn65dsi83->brg);
+
+
+ sn65dsi83->bridge.funcs = &sn65dsi83_bridge_funcs;
+ sn65dsi83->bridge.of_node = dev->of_node;
+
+ drm_bridge_add(&sn65dsi83->bridge);
+
+ return ret;
+}
+
+static int sn65dsi83_attach_dsi(struct sn65dsi83 *sn65dsi83)
+{
+ struct device *dev = &sn65dsi83->brg->client->dev;
+ struct mipi_dsi_host *host;
+ struct mipi_dsi_device *dsi;
+ int ret = 0;
+ const struct mipi_dsi_device_info info = { .type = "sn65dsi83",
+ .channel = 0,
+ .node = NULL,
+ };
+
+ dev_info(dev, "%s\n",__func__);
+ host = of_find_mipi_dsi_host_by_node(sn65dsi83->host_node);
+ if (!host) {
+ dev_err(dev, "failed to find dsi host\n");
+ return -EPROBE_DEFER;
+ }
+
+ dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(dsi)) {
+ dev_err(dev, "failed to create dsi device\n");
+ ret = PTR_ERR(dsi);
+ return -ENODEV;
+ }
+
+ sn65dsi83->dsi = dsi;
+
+ dsi->lanes = sn65dsi83->brg->num_dsi_lanes;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "failed to attach dsi to host\n");
+ mipi_dsi_device_unregister(dsi);
+ }
+
+ return ret;
+}
+
+static void sn65dsi83_detach_dsi(struct sn65dsi83 *sn65dsi83)
+{
+ struct device *dev = &sn65dsi83->brg->client->dev;
+ dev_info(dev, "%s\n",__func__);
+ mipi_dsi_detach(sn65dsi83->dsi);
+ mipi_dsi_device_unregister(sn65dsi83->dsi);
+}
+
+static int sn65dsi83_remove(struct i2c_client *i2c)
+{
+ struct sn65dsi83 *sn65dsi83 = i2c_get_clientdata(i2c);
+ struct device *dev = &sn65dsi83->brg->client->dev;
+ dev_info(dev, "%s\n",__func__);
+
+ sn65dsi83_detach_dsi(sn65dsi83);
+ drm_bridge_remove(&sn65dsi83->bridge);
+
+ return 0;
+}
+
+static const struct i2c_device_id sn65dsi83_i2c_ids[] = {
+ { "sn65dsi83", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sn65dsi83_i2c_ids);
+
+static const struct of_device_id sn65dsi83_of_ids[] = {
+ { .compatible = "ti,sn65dsi83" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sn65dsi83_of_ids);
+
+static struct mipi_dsi_driver sn65dsi83_dsi_driver = {
+ .driver.name = "sn65dsi83",
+};
+
+static struct i2c_driver sn65dsi83_driver = {
+ .driver = {
+ .name = "sn65dsi83",
+ .of_match_table = sn65dsi83_of_ids,
+ },
+ .id_table = sn65dsi83_i2c_ids,
+ .probe = sn65dsi83_probe,
+ .remove = sn65dsi83_remove,
+};
+
+static int __init sn65dsi83_init(void)
+{
+ if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
+ mipi_dsi_driver_register(&sn65dsi83_dsi_driver);
+
+ return i2c_add_driver(&sn65dsi83_driver);
+}
+module_init(sn65dsi83_init);
+
+static void __exit sn65dsi83_exit(void)
+{
+ i2c_del_driver(&sn65dsi83_driver);
+
+ if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
+ mipi_dsi_driver_unregister(&sn65dsi83_dsi_driver);
+}
+module_exit(sn65dsi83_exit);
+
+MODULE_AUTHOR("CompuLab <compulab@compula.co.il>");
+MODULE_DESCRIPTION("SN65DSI bridge driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h
new file mode 100644
index 000000000000..e9bb6633c376
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h
@@ -0,0 +1,33 @@
+#ifndef __SN65DSI83_TIMING_H__
+#define __SN65DSI83_TIMING_H__
+
+/* Default Video Parameters */
+#define PIXCLK_INIT 62500000
+
+#define HACTIVE_INIT 1280
+#define HPW_INIT 2
+#define HBP_INIT 6
+#define HFP_INIT 5
+
+#define VACTIVE_INIT 800
+#define VPW_INIT 1
+#define VBP_INIT 2
+#define VFP_INIT 3
+
+static const struct display_timing panel_default_timing = {
+ .pixelclock = { PIXCLK_INIT, PIXCLK_INIT, PIXCLK_INIT },
+ .hactive = { HACTIVE_INIT, HACTIVE_INIT, HACTIVE_INIT },
+ .hfront_porch = { HFP_INIT, HFP_INIT, HFP_INIT },
+ .hsync_len = { HPW_INIT, HPW_INIT, HPW_INIT },
+ .hback_porch = { HBP_INIT, HBP_INIT, HBP_INIT },
+ .vactive = { VACTIVE_INIT, VACTIVE_INIT, VACTIVE_INIT },
+ .vfront_porch = { VFP_INIT, VFP_INIT, VFP_INIT },
+ .vsync_len = { VPW_INIT, VPW_INIT, VPW_INIT },
+ .vback_porch = { VBP_INIT, VBP_INIT, VBP_INIT },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW |
+ DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_LOW |
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+};
+
+#endif /* __SN65DSI83_TIMING_H__ */
diff --git a/drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c b/drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c
index cfc3e12df2fc..b8a7938d2d1a 100644
--- a/drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c
+++ b/drivers/gpu/drm/imx/cdn-mhdp-imx8qm.c
@@ -10,6 +10,7 @@
#include <linux/firmware.h>
#include <linux/pm_domain.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <drm/drmP.h>
#include "cdns-mhdp-imx.h"
@@ -538,13 +539,6 @@ int cdns_mhdp_firmware_write_section(struct imx_mhdp_device *imx_mhdp,
return 0;
}
-static void cdns_mhdp_firmware_load_cont(const struct firmware *fw, void *context)
-{
- struct imx_mhdp_device *imx_mhdp = context;
-
- imx_mhdp->fw = fw;
-}
-
static int cdns_mhdp_firmware_load(struct imx_mhdp_device *imx_mhdp)
{
const u8 *iram;
@@ -564,23 +558,25 @@ static int cdns_mhdp_firmware_load(struct imx_mhdp_device *imx_mhdp)
goto out;
if (!imx_mhdp->fw) {
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ ret = request_firmware_direct(&imx_mhdp->fw,
imx_mhdp->firmware_name,
- imx_mhdp->mhdp.dev, GFP_KERNEL,
- imx_mhdp,
- cdns_mhdp_firmware_load_cont);
+ imx_mhdp->mhdp.dev);
if (ret < 0) {
DRM_ERROR("failed to load firmware\n");
- return -ENOENT;
+ /* Maybe U-Boot loaded the firmware. Therefore, still try to
+ * reset the controller */
+ goto out;
}
- } else {
- iram = imx_mhdp->fw->data + FW_IRAM_OFFSET;
- dram = iram + FW_IRAM_SIZE;
-
- cdns_mhdp_firmware_write_section(imx_mhdp, iram, FW_IRAM_SIZE, ADDR_IMEM);
- cdns_mhdp_firmware_write_section(imx_mhdp, dram, FW_DRAM_SIZE, ADDR_DMEM);
}
+ iram = imx_mhdp->fw->data + FW_IRAM_OFFSET;
+ dram = iram + FW_IRAM_SIZE;
+
+ cdns_mhdp_firmware_write_section(imx_mhdp, iram,
+ FW_IRAM_SIZE, ADDR_IMEM);
+ cdns_mhdp_firmware_write_section(imx_mhdp, dram,
+ FW_DRAM_SIZE, ADDR_DMEM);
+
out:
/* un-reset ucpu */
cdns_mhdp_bus_write(0, &imx_mhdp->mhdp, APB_CTRL);
diff --git a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
index 2515d02fa8d1..af3640713020 100644
--- a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
+++ b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/component.h>
+#include <linux/of_gpio.h>
#include <drm/drm_of.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
@@ -159,6 +160,19 @@ static int cdns_mhdp_imx_bind(struct device *dev, struct device *master,
match = of_match_node(cdns_mhdp_imx_dt_ids, pdev->dev.of_node);
plat_data = match->data;
+
+ imx_mhdp->hdmi_ctrl_gpio = of_get_named_gpio(dev->of_node, "hdmi-ctrl-gpios", 0);
+ if (gpio_is_valid(imx_mhdp->hdmi_ctrl_gpio)) {
+ ret = gpio_request(imx_mhdp->hdmi_ctrl_gpio, "HDMI_CTRL");
+ if (ret < 0) {
+ dev_err(dev, "request HDMI CTRL GPIO failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Set signals depending on HDP device type, 0 DP, 1 HDMI */
+ gpio_direction_output(imx_mhdp->hdmi_ctrl_gpio, !plat_data->is_dp);
+ }
+
encoder = &imx_mhdp->encoder;
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
@@ -171,8 +185,10 @@ static int cdns_mhdp_imx_bind(struct device *dev, struct device *master,
* not been registered yet. Defer probing, and hope that
* the required CRTC is added later.
*/
- if (encoder->possible_crtcs == 0)
- return -EPROBE_DEFER;
+ if (encoder->possible_crtcs == 0) {
+ ret = -EPROBE_DEFER;
+ goto err_free_hdmi_gpio;
+ }
drm_encoder_helper_add(encoder, &cdns_mhdp_imx_encoder_helper_funcs);
drm_encoder_init(drm, encoder, &cdns_mhdp_imx_encoder_funcs,
@@ -188,9 +204,16 @@ static int cdns_mhdp_imx_bind(struct device *dev, struct device *master,
* which would have called the encoder cleanup. Do it manually.
*/
if (ret < 0)
- drm_encoder_cleanup(encoder);
+ goto err_cleanup_encoder;
return ret;
+
+err_cleanup_encoder:
+ drm_encoder_cleanup(encoder);
+err_free_hdmi_gpio:
+ if (gpio_is_valid(imx_mhdp->hdmi_ctrl_gpio))
+ gpio_free(imx_mhdp->hdmi_ctrl_gpio);
+ return ret;
}
static void cdns_mhdp_imx_unbind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/imx/cdns-mhdp-imx.h b/drivers/gpu/drm/imx/cdns-mhdp-imx.h
index b95907ddc578..62c7d9567e3a 100644
--- a/drivers/gpu/drm/imx/cdns-mhdp-imx.h
+++ b/drivers/gpu/drm/imx/cdns-mhdp-imx.h
@@ -52,6 +52,7 @@ struct imx_mhdp_device {
struct imx_hdp_clks clks;
const struct firmware *fw;
const char *firmware_name;
+ int hdmi_ctrl_gpio;
int bus_type;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 5607fc0d61a6..0097fc563c46 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -151,9 +151,9 @@ err:
return -EINVAL;
}
-static u32 get_bus_format_from_bpp(u32 bpp)
+static u32 get_bus_format_from_width(u32 width)
{
- switch (bpp) {
+ switch (width) {
case 16:
return MEDIA_BUS_FMT_RGB565_1X16;
case 18:
@@ -170,7 +170,7 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
struct drm_crtc *crtc = &mxsfb->pipe.crtc;
unsigned int bits_per_pixel = crtc->primary->state->fb->format->depth;
struct drm_device *drm = crtc->dev;
- u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ u32 bus_format = get_bus_format_from_width(mxsfb->bus_width);
int num_bus_formats = mxsfb->connector->display_info.num_bus_formats;
const u32 *bus_formats = mxsfb->connector->display_info.bus_formats;
u32 reg = 0;
@@ -178,7 +178,7 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
/* match the user requested bus_format to one supported by the panel */
if (num_bus_formats) {
- u32 user_bus_format = get_bus_format_from_bpp(bits_per_pixel);
+ u32 user_bus_format = get_bus_format_from_width(bits_per_pixel);
bus_format = bus_formats[0];
for (i = 0; i < num_bus_formats; i++) {
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index bf60a1c52e17..9bec17a6c31e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -44,6 +44,9 @@ enum mxsfb_devtype {
MXSFB_V4,
};
+/* default output bus width */
+#define MXSFB_DEFAULT_BUS_WIDTH 24
+
/*
* When adding new formats, make sure to update the num_formats from
* mxsfb_devdata below.
@@ -88,6 +91,25 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
},
};
+/*
+ * There are non-atomic versions of clk_enable()/clk_disable() callbacks
+ * used in IMX8QM/IMX8QXP, so we can't manage axi clk in interrupt handlers
+ */
+#if defined(CONFIG_ARCH_FSL_IMX8QM) || defined(CONFIG_ARCH_FSL_IMX8QXP)
+# define mxsfb_enable_axi_clk(mxsfb) 0
+# define mxsfb_disable_axi_clk(mxsfb)
+#else
+static inline int mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
+{
+ return clk_prepare_enable(mxsfb->clk_axi);
+}
+
+static inline void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
+{
+ clk_disable_unprepare(mxsfb->clk_axi);
+}
+#endif
+
static struct mxsfb_drm_private *
drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe)
{
@@ -232,9 +254,17 @@ static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
}
pm_runtime_get_sync(drm->dev);
- drm_panel_prepare(mxsfb->panel);
- mxsfb_crtc_enable(mxsfb);
- drm_panel_enable(mxsfb->panel);
+ if (mxsfb->panel) {
+ drm_panel_prepare(mxsfb->panel);
+ mxsfb_crtc_enable(mxsfb);
+ drm_panel_enable(mxsfb->panel);
+ }
+
+ if (mxsfb->bridge) {
+ drm_bridge_pre_enable(mxsfb->bridge);
+ mxsfb_crtc_enable(mxsfb);
+ drm_bridge_enable(mxsfb->bridge);
+ }
}
static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -244,9 +274,18 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
struct drm_crtc *crtc = &pipe->crtc;
struct drm_pending_vblank_event *event;
- drm_panel_disable(mxsfb->panel);
- mxsfb_crtc_disable(mxsfb);
- drm_panel_unprepare(mxsfb->panel);
+ if (mxsfb->bridge) {
+ drm_bridge_disable(mxsfb->bridge);
+ mxsfb_crtc_disable(mxsfb);
+ drm_bridge_post_disable(mxsfb->bridge);
+ }
+
+ if (mxsfb->panel) {
+ drm_panel_disable(mxsfb->panel);
+ mxsfb_crtc_disable(mxsfb);
+ drm_panel_unprepare(mxsfb->panel);
+ }
+
pm_runtime_put_sync(drm->dev);
spin_lock_irq(&drm->event_lock);
@@ -274,14 +313,14 @@ static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
int ret = 0;
- ret = clk_prepare_enable(mxsfb->clk_axi);
+ ret = mxsfb_enable_axi_clk(mxsfb);
if (ret)
return ret;
/* Clear and enable VBLANK IRQ */
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
- clk_disable_unprepare(mxsfb->clk_axi);
+ mxsfb_disable_axi_clk(mxsfb);
return ret;
}
@@ -290,13 +329,13 @@ static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
{
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
- if (clk_prepare_enable(mxsfb->clk_axi))
+ if (mxsfb_enable_axi_clk(mxsfb))
return;
/* Disable and clear VBLANK IRQ */
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
- clk_disable_unprepare(mxsfb->clk_axi);
+ mxsfb_disable_axi_clk(mxsfb);
}
static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
@@ -315,6 +354,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
struct platform_device *pdev = to_platform_device(drm->dev);
struct mxsfb_drm_private *mxsfb;
struct resource *res;
+ u32 bus_width = MXSFB_DEFAULT_BUS_WIDTH;
int ret;
mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL);
@@ -349,6 +389,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
return ret;
pm_runtime_enable(drm->dev);
+ pm_runtime_get_sync(drm->dev);
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) {
@@ -396,6 +437,10 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
}
}
+ /* bus width is needed to set up correct bus format */
+ of_property_read_u32(drm->dev->of_node, "bus-width", &bus_width);
+ mxsfb->bus_width = bus_width;
+
drm->mode_config.min_width = MXSFB_MIN_XRES;
drm->mode_config.min_height = MXSFB_MIN_YRES;
drm->mode_config.max_width = MXSFB_MAX_XRES;
@@ -423,7 +468,8 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
return 0;
err_irq:
- drm_panel_detach(mxsfb->panel);
+ if (mxsfb->panel)
+ drm_panel_detach(mxsfb->panel);
err_vblank:
pm_runtime_disable(drm->dev);
@@ -441,6 +487,7 @@ static void mxsfb_unload(struct drm_device *drm)
drm->dev_private = NULL;
+ pm_runtime_put_sync(drm->dev);
pm_runtime_disable(drm->dev);
}
@@ -457,7 +504,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
struct mxsfb_drm_private *mxsfb = drm->dev_private;
u32 reg;
- clk_prepare_enable(mxsfb->clk_axi);
+ mxsfb_enable_axi_clk(mxsfb);
reg = readl(mxsfb->base + LCDC_CTRL1);
@@ -466,7 +513,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
- clk_disable_unprepare(mxsfb->clk_axi);
+ mxsfb_disable_axi_clk(mxsfb);
return IRQ_HANDLED;
}
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 54c06445be96..dffe4b8f52f7 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -34,6 +34,7 @@ struct mxsfb_drm_private {
struct drm_bridge *bridge;
u32 max_bw;
+ u32 bus_width;
};
int mxsfb_setup_crtc(struct drm_device *dev);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
index 4eb94744c526..582e771cf726 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c
@@ -92,7 +92,7 @@ int mxsfb_create_output(struct drm_device *drm)
&mxsfb_panel_connector_helper_funcs);
ret = drm_connector_init(drm, mxsfb->connector,
&mxsfb_panel_connector_funcs,
- DRM_MODE_CONNECTOR_Unknown);
+ DRM_MODE_CONNECTOR_DPI);
}
return ret;
diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index bf5fcc3e5379..7e7655e002c4 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -23,6 +23,11 @@
#include <drm/drm_crtc.h>
#include <drm/drm_panel.h>
+enum panel_type {
+ PANEL_LVDS,
+ PANEL_DPI
+};
+
struct panel_lvds {
struct drm_panel panel;
struct device *dev;
@@ -124,7 +129,9 @@ static int panel_lvds_get_modes(struct drm_panel *panel)
connector->display_info.height_mm = lvds->height;
drm_display_info_set_bus_formats(&connector->display_info,
&lvds->bus_format, 1);
- connector->display_info.bus_flags = lvds->data_mirror
+ drm_bus_flags_from_videomode(&lvds->video_mode,
+ &connector->display_info.bus_flags);
+ connector->display_info.bus_flags |= lvds->data_mirror
? DRM_BUS_FLAG_DATA_LSB_TO_MSB
: DRM_BUS_FLAG_DATA_MSB_TO_LSB;
@@ -145,6 +152,7 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds)
struct display_timing timing;
const char *mapping;
int ret;
+ enum panel_type type;
ret = of_get_display_timing(np, "panel-timing", &timing);
if (ret < 0) {
@@ -177,13 +185,30 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds)
return -ENODEV;
}
- if (!strcmp(mapping, "jeida-18")) {
- lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
- } else if (!strcmp(mapping, "jeida-24")) {
- lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
- } else if (!strcmp(mapping, "vesa-24")) {
- lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
- } else {
+ type = (enum panel_type)of_device_get_match_data(lvds->dev);
+ switch (type) {
+ case PANEL_LVDS:
+ if (!strcmp(mapping, "jeida-18")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
+ } else if (!strcmp(mapping, "jeida-24")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
+ } else if (!strcmp(mapping, "vesa-24")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
+ }
+ break;
+ case PANEL_DPI:
+ if (!strcmp(mapping, "rgb24")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ } else if (!strcmp(mapping, "rgb565")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB565_1X16;
+ } else if (!strcmp(mapping, "bgr666")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
+ } else if (!strcmp(mapping, "lvds666")) {
+ lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+ }
+ };
+
+ if (!lvds->bus_format) {
dev_err(lvds->dev, "%pOF: invalid or missing %s DT property\n",
np, "data-mapping");
return -EINVAL;
@@ -278,7 +303,8 @@ static int panel_lvds_remove(struct platform_device *pdev)
}
static const struct of_device_id panel_lvds_of_table[] = {
- { .compatible = "panel-lvds", },
+ { .compatible = "panel-lvds", .data = (void *)PANEL_LVDS },
+ { .compatible = "panel-dpi", .data = (void *)PANEL_DPI },
{ /* Sentinel */ },
};
@@ -288,7 +314,7 @@ static struct platform_driver panel_lvds_driver = {
.probe = panel_lvds_probe,
.remove = panel_lvds_remove,
.driver = {
- .name = "panel-lvds",
+ .name = "panel-generic",
.of_match_table = panel_lvds_of_table,
},
};
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 3b30f8624f4d..1a6affc2a966 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2070,6 +2070,85 @@ static const struct panel_desc lg_lp129qe = {
},
};
+static const struct drm_display_mode lg_lp156wf1_mode = {
+ .clock = 138500,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 48,
+ .hsync_end = 1920 + 48 + 32,
+ .htotal = 1920 + 48 + 32 + 80,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 3,
+ .vsync_end = 1080 + 3 + 5,
+ .vtotal = 1080 + 3 + 5 + 23,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc lg_lp156wf1 = {
+ .modes = &lg_lp156wf1_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 345,
+ .height = 194,
+ },
+};
+
+static const struct display_timing logictechno_lt161010_2nh_timing = {
+ .pixelclock = { 26400000, 33300000, 46800000 },
+ .hactive = { 800, 800, 800 },
+ .hfront_porch = { 16, 210, 354 },
+ .hback_porch = { 46, 46, 46 },
+ .hsync_len = { 1, 20, 40 },
+ .vactive = { 480, 480, 480 },
+ .vfront_porch = { 7, 22, 147 },
+ .vback_porch = { 23, 23, 23 },
+ .vsync_len = { 1, 10, 20 },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_POSEDGE,
+};
+
+static const struct panel_desc logictechno_lt161010_2nh = {
+ .timings = &logictechno_lt161010_2nh_timing,
+ .num_timings = 1,
+ .size = {
+ .width = 154,
+ .height = 86,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH |
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
+};
+
+static const struct display_timing logictechno_lt170410_2whc_timing = {
+ .pixelclock = { 68900000, 71100000, 73400000 },
+ .hactive = { 1280, 1280, 1280 },
+ .hfront_porch = { 23, 60, 71 },
+ .hback_porch = { 23, 60, 71 },
+ .hsync_len = { 15, 40, 47 },
+ .vactive = { 800, 800, 800 },
+ .vfront_porch = { 5, 7, 10 },
+ .vback_porch = { 5, 7, 10 },
+ .vsync_len = { 6, 9, 12 },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_POSEDGE,
+};
+
+static const struct panel_desc logictechno_lt170410_2whc = {
+ .timings = &logictechno_lt170410_2whc_timing,
+ .num_timings = 1,
+ .size = {
+ .width = 217,
+ .height = 136,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH |
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
+};
+
static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
@@ -3338,9 +3417,21 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "lg,lp129qe",
.data = &lg_lp129qe,
}, {
+ .compatible = "lg,lp156wf1",
+ .data = &lg_lp156wf1,
+ }, {
.compatible = "logicpd,type28",
.data = &logicpd_type_28,
}, {
+ .compatible = "logictechno,lt161010-2nhc",
+ .data = &logictechno_lt161010_2nh,
+ }, {
+ .compatible = "logictechno,lt161010-2nhr",
+ .data = &logictechno_lt161010_2nh,
+ }, {
+ .compatible = "logictechno,lt170410-2whc",
+ .data = &logictechno_lt170410_2whc,
+ }, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = &mitsubishi_aa070mc01,
}, {
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index 7364764baaeb..b1065c9cb292 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/platform_data/sht3x.h>
+#include <linux/of.h>
/* commands (high precision mode) */
static const unsigned char sht3x_cmd_measure_blocking_hpm[] = { 0x2c, 0x06 };
@@ -671,6 +672,7 @@ static int sht3x_probe(struct i2c_client *client,
struct i2c_adapter *adap = client->adapter;
struct device *dev = &client->dev;
const struct attribute_group **attribute_groups;
+ struct device_node *np = client->dev.of_node;
/*
* we require full i2c support since the sht3x uses multi-byte read and
@@ -696,8 +698,16 @@ static int sht3x_probe(struct i2c_client *client,
data->client = client;
crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
- if (client->dev.platform_data)
- data->setup = *(struct sht3x_platform_data *)dev->platform_data;
+ if (np) {
+ if (of_property_read_bool(np, "sensirion,blocking-io"))
+ data->setup.blocking_io = true;
+ if (of_property_read_bool(np, "sensirion,no-high-precision"))
+ data->setup.high_precision = false;
+ } else {
+ if (client->dev.platform_data)
+ data->setup = *(struct sht3x_platform_data *)
+ dev->platform_data;
+ }
sht3x_select_command(data);
@@ -740,8 +750,20 @@ static const struct i2c_device_id sht3x_ids[] = {
MODULE_DEVICE_TABLE(i2c, sht3x_ids);
+#ifdef CONFIG_OF
+static const struct of_device_id sht3x_dt_match[] = {
+ { .compatible = "sensirion,sht3x" },
+ { .compatible = "sensirion,sts3x" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sht3x_dt_match);
+#endif
+
static struct i2c_driver sht3x_i2c_driver = {
- .driver.name = "sht3x",
+ .driver = {
+ .name = "sht3x",
+ .of_match_table = of_match_ptr(sht3x_dt_match),
+ },
.probe = sht3x_probe,
.id_table = sht3x_ids,
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index f0bcef6aad10..ff37bbaa9503 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -119,6 +119,16 @@ config TOUCHSCREEN_ADC
To compile this driver as a module, choose M here: the
module will be called resistive-adc-touch.ko.
+config TOUCHSCREEN_AR1020_I2C
+ tristate "Microchip AR1020 I2C touchscreen"
+ depends on I2C
+ help
+ Say Y here if you have a Microchip AR1020 I2C Controller and
+ want to enable support for the built-in touchscreen.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ar1020-i2c.
+
config TOUCHSCREEN_AR1021_I2C
tristate "Microchip AR1020/1021 i2c touchscreen"
depends on I2C && OF
@@ -746,6 +756,13 @@ config TOUCHSCREEN_MIGOR
To compile this driver as a module, choose M here: the
module will be called migor_ts.
+config TOUCHSCREEN_FUSION_F0710A
+ tristate "TouchRevolution Fusion F0710A Touchscreens"
+ depends on I2C
+ help
+ Say Y here if you want to support the multi-touch input driver for
+ the TouchRevolution Fusion 7 and 10 panels.
+
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
@@ -1307,11 +1324,11 @@ config TOUCHSCREEN_ZFORCE
config TOUCHSCREEN_COLIBRI_VF50
tristate "Toradex Colibri on board touchscreen driver"
- depends on IIO && VF610_ADC
+ depends on IIO
depends on GPIOLIB || COMPILE_TEST
help
- Say Y here if you have a Colibri VF50 and plan to use
- the on-board provided 4-wire touchscreen driver.
+ Say Y here if you have a Apalis iMX8 or Colibri VF50 and plan
+ to use the on-board provided 4-wire touchscreen controller.
If unsure, say N.
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 28985ca20b7e..e98ea5886300 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADC) += resistive-adc-touch.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_AR1020_I2C) += ar1020-i2c.o
obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
@@ -45,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/
+obj-$(CONFIG_TOUCHSCREEN_FUSION_F0710A) += fusion_F0710A.o
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX) += synaptics_dsx/
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
diff --git a/drivers/input/touchscreen/ar1020-i2c.c b/drivers/input/touchscreen/ar1020-i2c.c
new file mode 100644
index 000000000000..1ecfbecf460d
--- /dev/null
+++ b/drivers/input/touchscreen/ar1020-i2c.c
@@ -0,0 +1,500 @@
+/*
+ * Microchip I2C Touchscreen Driver
+ *
+ * Copyright (c) 2011 Microchip Technology, Inc.
+ *
+ * http://www.microchip.com/mtouch
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+/* The private data structure that is referenced within the I2C bus driver */
+struct ar1020_i2c_priv {
+ struct i2c_client *client;
+ struct input_dev *input;
+ int irq;
+ int testCount;
+ int command_pending;
+ int use_count;
+ int button;
+ struct delayed_work reenable_work;
+};
+
+/*
+ * These are all the sysfs variables used to store and retrieve information
+ * from a user-level application
+ */
+static char sendBuffer[100];
+static char receiveBuffer[100];
+static int commandDataPending;
+
+/*
+ * These variables allows the IRQ to be specified via a module parameter
+ * or kernel parameter. To configuration of these value, please see
+ * driver documentation.
+ */
+static int touchIRQ;
+
+module_param(touchIRQ, int, S_IRUGO);
+
+
+/*
+ * Since the reference to private data is stored within the I2C
+ * bus driver, we will store another reference within this driver
+ * so the sysfs related function may also access this data
+ */
+struct ar1020_i2c_priv *g_priv;
+
+/*
+ * Display value of "commandDataPending" variable to application that is
+ * requesting it's value.
+ */
+static ssize_t commandDataPending_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d", commandDataPending);
+}
+
+/*
+ * Save value to "commandDataPending" variable from application that is
+ * requesting this.
+ */
+static ssize_t commandDataPending_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ sscanf(buf, "%d", &commandDataPending);
+ return count;
+}
+
+static struct kobj_attribute commandDataPending_attribute =
+ __ATTR(commandDataPending, 0666, commandDataPending_show,
+ commandDataPending_store);
+
+
+/*
+ * Display value of "receiveBuffer" variable to application that is
+ * requesting it's value.
+ */
+static ssize_t receiveBuffer_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ /* receive data is no longer pending */
+ commandDataPending = 0;
+ return sprintf(buf, "%s", receiveBuffer);
+}
+
+/*
+ * Save value to "receiveBuffer" variable from application that is
+ * requesting this.
+ */
+static ssize_t receiveBuffer_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ return snprintf(receiveBuffer, sizeof(receiveBuffer), "%s", buf);
+}
+
+static struct kobj_attribute receiveBuffer_attribute =
+ __ATTR(receiveBuffer, 0666, receiveBuffer_show, receiveBuffer_store);
+
+/*
+ * Display value of "sendBuffer" variable to application that is
+ * requesting it's value.
+ */
+static ssize_t sendBuffer_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s", sendBuffer);
+}
+
+/*
+ * Save value to "sendBuffer" variable from application that is
+ * requesting this.
+ */
+static ssize_t sendBuffer_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int data[8];
+ char buff[8];
+ int cnt;
+ int i;
+ struct ar1020_i2c_priv *priv = g_priv;
+
+ commandDataPending = 0;
+
+ cnt = sscanf(buf, "%x %x %x %x %x %x %x %x", &data[0], &data[1],
+ &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]);
+
+ pr_debug("AR1020 I2C: Processed %d bytes.\n", cnt);
+
+ /* Verify command string to send to controller is valid */
+ if (cnt < 3)
+ pr_info("AR1020 I2C: Insufficient command bytes to process.\n");
+ else if (data[0] != 0x0)
+ pr_info("AR1020 I2C: Leading zero required when sending I2C commands.\n");
+ else if (data[1] != 0x55)
+ pr_info("AR1020 I2C: Invalid header byte (0x55 expected).\n");
+ else if (data[2] != (cnt - 3))
+ pr_info("AR1020 I2C: Number of command bytes specified not "
+ "valid for current string.\n");
+
+ strcpy(sendBuffer, "");
+ pr_debug("AR1020 I2C: sending command bytes: ");
+ for (i = 0; i < cnt; i++) {
+ buff[i] = (char)data[i];
+ pr_debug("0x%02x ", data[i]);
+ }
+ pr_debug("\n");
+
+ if (priv) {
+ priv->command_pending = 1;
+ i2c_master_send(priv->client, buff, cnt);
+ }
+
+ return snprintf(sendBuffer, sizeof(sendBuffer), "%s", buf);
+}
+
+static struct kobj_attribute sendBuffer_attribute =
+ __ATTR(sendBuffer, 0666, sendBuffer_show, sendBuffer_store);
+
+/*
+ * Create a group of calibration attributes so we may work with them
+ * as a set.
+ */
+static struct attribute *attrs[] = {
+ &commandDataPending_attribute.attr,
+ &receiveBuffer_attribute.attr,
+ &sendBuffer_attribute.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
+static struct kobject *ar1020_kobj;
+
+static void irq_reenable_work(struct work_struct *work)
+{
+ struct ar1020_i2c_priv *priv = container_of(work,
+ struct ar1020_i2c_priv, reenable_work.work);
+
+ enable_irq(priv->irq);
+}
+
+/*
+ * When the controller interrupt is asserted, this function is scheduled
+ * to be called to read the controller data.
+ */
+static irqreturn_t touch_irq_handler_func(int irq, void *dev_id)
+{
+ struct ar1020_i2c_priv *priv = (struct ar1020_i2c_priv *)dev_id;
+ int i;
+ int cnt;
+ unsigned char packet[9];
+ int x;
+ int y;
+ int button;
+
+ for (i = 0; i < 5; i++)
+ packet[i] = 0;
+
+ /*
+ * We want to ensure we only read packets when we are not in the middle
+ * of command communication. Disable command mode after receiving
+ * command response to resume receiving packets.
+ */
+ cnt = i2c_master_recv(priv->client, packet,
+ (priv->command_pending) ? 9 : 5);
+
+ if (cnt <= 0)
+ goto error;
+
+ if (packet[0] == 0x55) {
+ unsigned char *p = receiveBuffer;
+ unsigned char *pend = p + sizeof(receiveBuffer) - 2;
+ /* process up to 9 bytes */
+ strcpy(receiveBuffer, "");
+
+ priv->command_pending = 0;
+
+ if (packet[1] > 6)
+ pr_info("AR1020 I2C: invalid byte count\n");
+ else if (cnt > packet[1] + 2)
+ cnt = packet[1] + 2;
+
+ for (i = 0; i < cnt; i++) {
+ int ret = snprintf(p, pend - p, " 0x%02x", packet[i]);
+ if (ret <= 0)
+ break;
+ p += ret;
+ if (p >= pend)
+ break;
+ }
+ *p++ = '\n';
+ *p++ = 0;
+ pr_info("AR1020 I2C: command response: %s", receiveBuffer);
+ commandDataPending = 1;
+ return IRQ_HANDLED;
+ }
+
+ /*
+ * Decode packets of data from a device path using AR1XXX protocol.
+ * Data format, 5 bytes: SYNC, DATA1, DATA2, DATA3, DATA4
+ * SYNC [7:0]: 1,0,0,0,0,TOUCHSTATUS[0:0]
+ * DATA1[7:0]: 0,X-LOW[6:0]
+ * DATA2[7:0]: 0,X-HIGH[4:0]
+ * DATA3[7:0]: 0,Y-LOW[6:0]
+ * DATA4[7:0]: 0,Y-HIGH[4:0]
+ *
+ * TOUCHSTATUS: 0 = Touch up, 1 = Touch down
+ */
+ if ((packet[0] & 0xfe) != 0x80) {
+ pr_err("AR1020 I2C: 1st Touch byte not valid. Value: 0x%02x\n",
+ packet[0]);
+ goto error; /* irq line may be shorted high, let's delay */
+ }
+ for (i = 1; i < 5; i++) {
+ /* verify byte is valid for current index */
+ if (0x80 & packet[i]) {
+ pr_err("AR1020 I2C: Touch byte not valid. Value: "
+ "0x%02x Index: 0x%02x\n", packet[i], i);
+ goto error;
+ }
+ }
+ x = ((packet[2] & 0x1f) << 7) | (packet[1] & 0x7f);
+ y = ((packet[4] & 0x1f) << 7) | (packet[3] & 0x7f);
+ button = (packet[0] & 1);
+
+ if (!button && !priv->button)
+ return IRQ_HANDLED;
+
+ priv->button = button;
+ input_report_abs(priv->input, ABS_X, x);
+ input_report_abs(priv->input, ABS_Y, y);
+ input_report_key(priv->input, BTN_TOUCH, button);
+ input_sync(priv->input);
+ return IRQ_HANDLED;
+error:
+ disable_irq_nosync(priv->irq);
+ schedule_delayed_work(&priv->reenable_work, 100);
+ return IRQ_HANDLED;
+}
+
+static int ar1020_i2c_open(struct input_dev *idev)
+{
+ struct ar1020_i2c_priv *priv = input_get_drvdata(idev);
+
+ if (priv->use_count++ == 0)
+ enable_irq(priv->irq);
+ return 0;
+}
+
+static void ar1020_i2c_close(struct input_dev *idev)
+{
+ struct ar1020_i2c_priv *priv = input_get_drvdata(idev);
+
+ if (--priv->use_count == 0)
+ disable_irq(priv->irq);
+}
+
+/*
+ * After the kernel's platform specific source files have been modified to
+ * reference the "ar1020_i2c" driver, this function will then be called.
+ * This function needs to be called to finish registering the driver.
+ */
+static int ar1020_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ar1020_i2c_priv *priv = NULL;
+ struct input_dev *input_dev = NULL;
+ int err = 0;
+ int irq;
+
+ pr_info("%s: begin\n", __func__);
+
+ if (!client) {
+ pr_err("AR1020 I2C: client pointer is NULL\n");
+ err = -EINVAL;
+ goto error;
+ }
+
+ irq = client->irq;
+ if (touchIRQ)
+ irq = touchIRQ;
+
+ if (!irq) {
+ pr_err("AR1020 I2C: no IRQ set for touch controller\n");
+ err = -EINVAL;
+ goto error;
+ }
+
+ priv = kzalloc(sizeof(struct ar1020_i2c_priv), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!priv) {
+ pr_err("AR1020 I2C: kzalloc error\n");
+ err = -ENOMEM;
+ goto error;
+ }
+
+ if (!input_dev) {
+ pr_err("AR1020 I2C: input allocate error\n");
+ err = -ENOMEM;
+ goto error;
+ }
+
+ priv->client = client;
+ priv->irq = irq;
+ priv->input = input_dev;
+ INIT_DELAYED_WORK(&priv->reenable_work, irq_reenable_work);
+
+ input_dev->name = "AR1020 Touchscreen";
+ input_dev->id.bustype = BUS_I2C;
+
+ input_dev->open = ar1020_i2c_open;
+ input_dev->close = ar1020_i2c_close;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(input_dev, ABS_X, 0, 4095, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 4095, 0, 0);
+ input_set_drvdata(input_dev, priv);
+ err = input_register_device(input_dev);
+ if (err) {
+ pr_err("AR1020 I2C: error registering input device\n");
+ goto error;
+ }
+
+ /* set type and register gpio pin as our interrupt */
+ err = request_threaded_irq(priv->irq, NULL, touch_irq_handler_func,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "AR1020 I2C IRQ",
+ priv);
+ if (err < 0)
+ goto error1;
+ disable_irq(priv->irq); /* wait for open */
+ i2c_set_clientdata(client, priv);
+ /*
+ * save pointer so sysfs helper functions may also have access
+ * to private data
+ */
+ g_priv = priv;
+ return 0;
+
+error1:
+ input_unregister_device(input_dev);
+error:
+ if (input_dev)
+ input_free_device(input_dev);
+
+ kfree(priv);
+ return err;
+
+}
+
+/*
+ * Unregister/remove the kernel driver from memory.
+ */
+static int ar1020_i2c_remove(struct i2c_client *client)
+{
+ struct ar1020_i2c_priv *priv =
+ (struct ar1020_i2c_priv *)i2c_get_clientdata(client);
+
+ free_irq(priv->irq, priv);
+ input_unregister_device(priv->input);
+ kfree(priv);
+ g_priv = NULL;
+ return 0;
+}
+
+/* This structure describe a list of supported slave chips */
+static const struct i2c_device_id ar1020_i2c_id[] = {
+ { "ar1020_i2c", 0 },
+ { }
+};
+
+/*
+ * This is the initial set of information the kernel has
+ * before probing drivers on the system
+ */
+static struct i2c_driver ar1020_i2c_driver = {
+ .driver = {
+ .name = "ar1020_i2c",
+ },
+ .probe = ar1020_i2c_probe,
+ .remove = ar1020_i2c_remove,
+ /*
+ * suspend/resume functions not needed since controller automatically
+ * put's itself to sleep mode after configurable short period of time
+ */
+ .suspend = NULL,
+ .resume = NULL,
+ .id_table = ar1020_i2c_id,
+};
+
+/*
+ * This function is called during startup even if the platform specific
+ * files have not been setup yet.
+ */
+static int __init ar1020_i2c_init(void)
+{
+ int retval;
+
+ pr_debug("AR1020 I2C: ar1020_i2c_init: begin\n");
+ strcpy(receiveBuffer, "");
+ strcpy(sendBuffer, "");
+
+ /*
+ * Creates a kobject "ar1020" that appears as a sub-directory
+ * under "/sys/kernel".
+ */
+ ar1020_kobj = kobject_create_and_add("ar1020", kernel_kobj);
+ if (!ar1020_kobj) {
+ pr_err("AR1020 I2C: cannot create kobject\n");
+ return -ENOMEM;
+ }
+
+ /* Create the files associated with this kobject */
+ retval = sysfs_create_group(ar1020_kobj, &attr_group);
+ if (retval) {
+ pr_err("AR1020 I2C: error registering ar1020-i2c driver's sysfs interface\n");
+ kobject_put(ar1020_kobj);
+ }
+
+ return i2c_add_driver(&ar1020_i2c_driver);
+}
+
+/*
+ * This function is called after ar1020_i2c_remove() immediately before
+ * being removed from the kernel.
+ */
+static void __exit ar1020_i2c_exit(void)
+{
+ pr_debug("AR1020 I2C: ar1020_i2c_exit begin\n");
+ kobject_put(ar1020_kobj);
+ i2c_del_driver(&ar1020_i2c_driver);
+}
+
+MODULE_AUTHOR("Steve Grahovac <steve.grahovac@microchip.com>");
+MODULE_DESCRIPTION("AR1020 touchscreen I2C bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(ar1020_i2c_init);
+module_exit(ar1020_i2c_exit);
diff --git a/drivers/input/touchscreen/fusion_F0710A.c b/drivers/input/touchscreen/fusion_F0710A.c
new file mode 100644
index 000000000000..7ee34f86dcd0
--- /dev/null
+++ b/drivers/input/touchscreen/fusion_F0710A.c
@@ -0,0 +1,507 @@
+/*
+ * "fusion_F0710A" touchscreen driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <linux/gpio.h>
+#include <linux/input/fusion_F0710A.h>
+#include <linux/input/mt.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+
+
+#include "fusion_F0710A.h"
+
+#define DRV_NAME "fusion_F0710A"
+#define MAX_TOUCHES 2
+
+static struct fusion_F0710A_data fusion_F0710A;
+
+static unsigned short normal_i2c[] = { fusion_F0710A_I2C_SLAVE_ADDR, I2C_CLIENT_END };
+
+static int fusion_F0710A_write_u8(u8 addr, u8 data)
+{
+ return i2c_smbus_write_byte_data(fusion_F0710A.client, addr, data);
+}
+
+static int fusion_F0710A_read_u8(u8 addr)
+{
+ return i2c_smbus_read_byte_data(fusion_F0710A.client, addr);
+}
+
+static int fusion_F0710A_read_block(u8 addr, u8 len, u8 *data)
+{
+ u8 msgbuf0[1] = { addr };
+ u16 slave = fusion_F0710A.client->addr;
+ u16 flags = fusion_F0710A.client->flags;
+ struct i2c_msg msg[2] = { { slave, flags, 1, msgbuf0 },
+ { slave, flags | I2C_M_RD, len, data }
+ };
+
+ return i2c_transfer(fusion_F0710A.client->adapter, msg, ARRAY_SIZE(msg));
+}
+
+static int fusion_F0710A_register_input(void)
+{
+ int ret;
+ struct input_dev *dev;
+
+ dev = fusion_F0710A.input = input_allocate_device();
+ if (dev == NULL)
+ return -ENOMEM;
+
+ dev->name = "fusion_F0710A";
+
+ set_bit(EV_KEY, dev->evbit);
+ set_bit(EV_ABS, dev->evbit);
+ set_bit(EV_SYN, dev->evbit);
+ set_bit(BTN_TOUCH, dev->keybit);
+
+ input_mt_init_slots(dev, MAX_TOUCHES, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_X, 0, fusion_F0710A.info.xres-1, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, fusion_F0710A.info.yres-1, 0, 0);
+ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ input_set_abs_params(dev, ABS_X, 0, fusion_F0710A.info.xres-1, 0, 0);
+ input_set_abs_params(dev, ABS_Y, 0, fusion_F0710A.info.yres-1, 0, 0);
+ input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
+
+ ret = input_register_device(dev);
+ if (ret < 0)
+ goto bail1;
+
+ return 0;
+
+bail1:
+ input_free_device(dev);
+ return ret;
+}
+
+static void fusion_F0710A_reset(void)
+{
+ /* Generate a 0 => 1 edge explicitly, and wait for startup... */
+ gpio_set_value(fusion_F0710A.gpio_reset, 0);
+ msleep(10);
+ gpio_set_value(fusion_F0710A.gpio_reset, 1);
+ /* Wait for startup (up to 125ms according to datasheet) */
+ msleep(125);
+}
+
+#define WC_RETRY_COUNT 3
+static int fusion_F0710A_write_complete(void)
+{
+ int ret, i;
+
+ for(i=0; i<WC_RETRY_COUNT; i++)
+ {
+ ret = fusion_F0710A_write_u8(fusion_F0710A_SCAN_COMPLETE, 0);
+ if(ret == 0)
+ break;
+ else {
+ dev_warn(&fusion_F0710A.client->dev,
+ "Write complete failed(%d): %d. Resetting controller...\n", i, ret);
+ fusion_F0710A_reset();
+ }
+ }
+
+ return ret;
+}
+
+#define DATA_START fusion_F0710A_DATA_INFO
+#define DATA_END fusion_F0710A_SEC_TIDTS
+#define DATA_LEN (DATA_END - DATA_START + 1)
+#define DATA_OFF(x) ((x) - DATA_START)
+
+static int fusion_F0710A_read_sensor(void)
+{
+ int ret;
+ u8 data[DATA_LEN];
+
+#define DATA(x) (data[DATA_OFF(x)])
+ /* To ensure data coherency, read the sensor with a single transaction. */
+ ret = fusion_F0710A_read_block(DATA_START, DATA_LEN, data);
+ if (ret < 0) {
+ dev_err(&fusion_F0710A.client->dev,
+ "Read block failed: %d\n", ret);
+
+ return ret;
+ }
+
+ fusion_F0710A.f_num = DATA(fusion_F0710A_DATA_INFO)&0x03;
+
+ fusion_F0710A.y1 = DATA(fusion_F0710A_POS_X1_HI) << 8;
+ fusion_F0710A.y1 |= DATA(fusion_F0710A_POS_X1_LO);
+ fusion_F0710A.x1 = DATA(fusion_F0710A_POS_Y1_HI) << 8;
+ fusion_F0710A.x1 |= DATA(fusion_F0710A_POS_Y1_LO);
+ fusion_F0710A.z1 = DATA(fusion_F0710A_FIR_PRESS);
+ fusion_F0710A.tip1 = DATA(fusion_F0710A_FIR_TIDTS)&0x0f;
+ fusion_F0710A.tid1 = (DATA(fusion_F0710A_FIR_TIDTS)&0xf0)>>4;
+
+
+ fusion_F0710A.y2 = DATA(fusion_F0710A_POS_X2_HI) << 8;
+ fusion_F0710A.y2 |= DATA(fusion_F0710A_POS_X2_LO);
+ fusion_F0710A.x2 = DATA(fusion_F0710A_POS_Y2_HI) << 8;
+ fusion_F0710A.x2 |= DATA(fusion_F0710A_POS_Y2_LO);
+ fusion_F0710A.z2 = DATA(fusion_F0710A_SEC_PRESS);
+ fusion_F0710A.tip2 = DATA(fusion_F0710A_SEC_TIDTS)&0x0f;
+ fusion_F0710A.tid2 =(DATA(fusion_F0710A_SEC_TIDTS)&0xf0)>>4;
+#undef DATA
+
+ return 0;
+}
+
+#define val_cut_max(x, max, reverse) \
+do \
+{ \
+ if(x > max) \
+ x = max; \
+ if(reverse) \
+ x = (max) - (x); \
+} \
+while(0)
+
+static void fusion_F0710A_wq(struct work_struct *work)
+{
+ struct input_dev *dev = fusion_F0710A.input;
+
+ if (fusion_F0710A_read_sensor() < 0)
+ goto restore_irq;
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "tip1, tid1, x1, y1, z1 (%x,%x,%d,%d,%d); tip2, tid2, x2, y2, z2 (%x,%x,%d,%d,%d)\n",
+ fusion_F0710A.tip1, fusion_F0710A.tid1, fusion_F0710A.x1, fusion_F0710A.y1, fusion_F0710A.z1,
+ fusion_F0710A.tip2, fusion_F0710A.tid2, fusion_F0710A.x2, fusion_F0710A.y2, fusion_F0710A.z2);
+#endif /* DEBUG */
+
+ val_cut_max(fusion_F0710A.x1, fusion_F0710A.info.xres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.y1, fusion_F0710A.info.yres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.x2, fusion_F0710A.info.xres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.y2, fusion_F0710A.info.yres-1, fusion_F0710A.info.xy_reverse);
+
+ if (fusion_F0710A.tid1) {
+ input_mt_slot(dev, fusion_F0710A.tid1 - 1);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, fusion_F0710A.tip1);
+ if (fusion_F0710A.tip1) {
+ input_report_abs(dev, ABS_MT_POSITION_X, fusion_F0710A.x1);
+ input_report_abs(dev, ABS_MT_POSITION_Y, fusion_F0710A.y1);
+ input_report_abs(dev, ABS_MT_PRESSURE, fusion_F0710A.z1);
+ }
+ }
+
+ if (fusion_F0710A.tid2) {
+ input_mt_slot(dev, fusion_F0710A.tid2 - 1);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, fusion_F0710A.tip2);
+ if (fusion_F0710A.tip2) {
+ input_report_abs(dev, ABS_MT_POSITION_X, fusion_F0710A.x2);
+ input_report_abs(dev, ABS_MT_POSITION_Y, fusion_F0710A.y2);
+ input_report_abs(dev, ABS_MT_PRESSURE, fusion_F0710A.z2);
+ }
+ }
+
+ input_mt_report_pointer_emulation(dev, false);
+ input_sync(dev);
+
+restore_irq:
+ enable_irq(fusion_F0710A.client->irq);
+
+ /* Clear fusion_F0710A interrupt */
+ fusion_F0710A_write_complete();
+}
+static DECLARE_WORK(fusion_F0710A_work, fusion_F0710A_wq);
+
+static irqreturn_t fusion_F0710A_interrupt(int irq, void *dev_id)
+{
+ disable_irq_nosync(fusion_F0710A.client->irq);
+
+ queue_work(fusion_F0710A.workq, &fusion_F0710A_work);
+
+ return IRQ_HANDLED;
+}
+
+const static u8* g_ver_product[4] = {
+ "10Z8", "70Z7", "43Z6", ""
+};
+
+static int of_fusion_F0710A_get_pins(struct device_node *np,
+ unsigned int *int_pin, unsigned int *reset_pin)
+{
+ if (of_gpio_count(np) < 2)
+ return -ENODEV;
+
+ *int_pin = of_get_gpio(np, 0);
+ *reset_pin = of_get_gpio(np, 1);
+
+ if (!gpio_is_valid(*int_pin) || !gpio_is_valid(*reset_pin)) {
+ pr_err("%s: invalid GPIO pins, int=%d/reset=%d\n",
+ np->full_name, *int_pin, *reset_pin);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int fusion_F0710A_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ struct device_node *np = i2c->dev.of_node;
+ struct fusion_f0710a_init_data *pdata = i2c->dev.platform_data;
+ int ret;
+ u8 ver_product, ver_id;
+ u32 version;
+
+ if (np != NULL) {
+ pdata = i2c->dev.platform_data =
+ devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL) {
+ dev_err(&i2c->dev, "No platform data for Fusion driver\n");
+ return -ENODEV;
+ }
+ /* the dtb did the pinmuxing for us */
+ pdata->pinmux_fusion_pins = NULL;
+ ret = of_fusion_F0710A_get_pins(i2c->dev.of_node,
+ &pdata->gpio_int, &pdata->gpio_reset);
+ if (ret)
+ return ret;
+ }
+ else if (pdata == NULL) {
+ dev_err(&i2c->dev, "No platform data for Fusion driver\n");
+ return -ENODEV;
+ }
+
+ /* Request pinmuxing, if necessary */
+ if (pdata->pinmux_fusion_pins != NULL) {
+ ret = pdata->pinmux_fusion_pins();
+ if (ret < 0) {
+ dev_err(&i2c->dev, "muxing GPIOs failed\n");
+ return -ENODEV;
+ }
+ }
+
+ if ((gpio_request(pdata->gpio_int, "Fusion pen down interrupt") == 0) &&
+ (gpio_direction_input(pdata->gpio_int) == 0)) {
+ gpio_export(pdata->gpio_int, 0);
+ } else {
+ dev_warn(&i2c->dev, "Could not obtain GPIO for Fusion pen down\n");
+ return -ENODEV;
+ }
+
+ if ((gpio_request(pdata->gpio_reset, "Fusion reset") == 0) &&
+ (gpio_direction_output(pdata->gpio_reset, 1) == 0)) {
+ fusion_F0710A.gpio_reset = pdata->gpio_reset;
+ fusion_F0710A_reset();
+ gpio_export(pdata->gpio_reset, 0);
+ } else {
+ dev_warn(&i2c->dev, "Could not obtain GPIO for Fusion reset\n");
+ ret = -ENODEV;
+ goto bail0;
+ }
+
+ /* Use Pen Down GPIO as sampling interrupt */
+ i2c->irq = gpio_to_irq(pdata->gpio_int);
+ irq_set_irq_type(i2c->irq, IRQ_TYPE_LEVEL_HIGH);
+
+ if(!i2c->irq)
+ {
+ dev_err(&i2c->dev, "fusion_F0710A irq < 0 \n");
+ ret = -ENOMEM;
+ goto bail1;
+ }
+
+ /* Attach the I2C client */
+ fusion_F0710A.client = i2c;
+ i2c_set_clientdata(i2c, &fusion_F0710A);
+
+ dev_info(&i2c->dev, "Touchscreen registered with bus id (%d) with slave address 0x%x\n",
+ i2c_adapter_id(fusion_F0710A.client->adapter), fusion_F0710A.client->addr);
+
+ /* Read out a lot of registers */
+ ret = fusion_F0710A_read_u8(fusion_F0710A_VIESION_INFO_LO);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "query failed: %d\n", ret);
+ goto bail1;
+ }
+ ver_product = (((u8)ret) & 0xc0) >> 6;
+ version = (10 + ((((u32)ret)&0x30) >> 4)) * 100000;
+ version += (((u32)ret)&0xf) * 1000;
+ /* Read out a lot of registers */
+ ret = fusion_F0710A_read_u8(fusion_F0710A_VIESION_INFO);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "query failed: %d\n", ret);
+ goto bail1;
+ }
+ ver_id = ((u8)(ret) & 0x6) >> 1;
+ version += ((((u32)ret) & 0xf8) >> 3) * 10;
+ version += (((u32)ret) & 0x1) + 1; /* 0 is build 1, 1 is build 2 */
+ dev_info(&i2c->dev, "version product %s(%d)\n", g_ver_product[ver_product] ,ver_product);
+ dev_info(&i2c->dev, "version id %s(%d)\n", ver_id ? "1.4" : "1.0", ver_id);
+ dev_info(&i2c->dev, "version series (%d)\n", version);
+
+ switch(ver_product)
+ {
+ case fusion_F0710A_VIESION_07: /* 7 inch */
+ fusion_F0710A.info.xres = fusion_F0710A07_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A07_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A07_REV;
+ break;
+ case fusion_F0710A_VIESION_43: /* 4.3 inch */
+ fusion_F0710A.info.xres = fusion_F0710A43_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A43_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A43_REV;
+ break;
+ default: /* fusion_F0710A_VIESION_10 10 inch */
+ fusion_F0710A.info.xres = fusion_F0710A10_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A10_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A10_REV;
+ break;
+ }
+
+ /* Register the input device. */
+ ret = fusion_F0710A_register_input();
+ if (ret < 0) {
+ dev_err(&i2c->dev, "can't register input: %d\n", ret);
+ goto bail1;
+ }
+
+ /* Create a worker thread */
+ fusion_F0710A.workq = create_singlethread_workqueue(DRV_NAME);
+ if (fusion_F0710A.workq == NULL) {
+ dev_err(&i2c->dev, "can't create work queue\n");
+ ret = -ENOMEM;
+ goto bail2;
+ }
+
+
+ /* Register for the interrupt and enable it. Our handler will
+ * start getting invoked after this call. */
+ ret = request_irq(i2c->irq, fusion_F0710A_interrupt, IRQF_TRIGGER_RISING,
+ i2c->name, &fusion_F0710A);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "can't get irq %d: %d\n", i2c->irq, ret);
+ goto bail3;
+ }
+ /* clear the irq first */
+ ret = fusion_F0710A_write_u8(fusion_F0710A_SCAN_COMPLETE, 0);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Clear irq failed: %d\n", ret);
+ goto bail4;
+ }
+
+ return 0;
+
+bail4:
+ free_irq(i2c->irq, &fusion_F0710A);
+
+bail3:
+ destroy_workqueue(fusion_F0710A.workq);
+ fusion_F0710A.workq = NULL;
+
+bail2:
+ input_unregister_device(fusion_F0710A.input);
+bail1:
+ gpio_free(pdata->gpio_reset);
+bail0:
+ gpio_free(pdata->gpio_int);
+
+ return ret;
+}
+
+static int __maybe_unused fusion_F0710A_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ disable_irq(i2c->irq);
+ flush_workqueue(fusion_F0710A.workq);
+
+ return 0;
+}
+
+static int __maybe_unused fusion_F0710A_resume(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ enable_irq(i2c->irq);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(fusion_F0710A_pm_ops,
+ fusion_F0710A_suspend, fusion_F0710A_resume);
+
+static int fusion_F0710A_remove(struct i2c_client *i2c)
+{
+ struct fusion_f0710a_init_data *pdata = i2c->dev.platform_data;
+
+ gpio_free(pdata->gpio_int);
+ gpio_free(pdata->gpio_reset);
+ destroy_workqueue(fusion_F0710A.workq);
+ free_irq(i2c->irq, &fusion_F0710A);
+ input_unregister_device(fusion_F0710A.input);
+ i2c_set_clientdata(i2c, NULL);
+
+ dev_info(&i2c->dev, "driver removed\n");
+
+ return 0;
+}
+
+static struct i2c_device_id fusion_F0710A_id[] = {
+ {"fusion_F0710A", 0},
+ {},
+};
+
+static const struct of_device_id fusion_F0710A_dt_ids[] = {
+ {
+ .compatible = "touchrevolution,fusion-f0710a",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, fusion_F0710A_dt_ids);
+
+static struct i2c_driver fusion_F0710A_i2c_drv = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .pm = &fusion_F0710A_pm_ops,
+ .of_match_table = fusion_F0710A_dt_ids,
+ },
+ .probe = fusion_F0710A_probe,
+ .remove = fusion_F0710A_remove,
+ .id_table = fusion_F0710A_id,
+ .address_list = normal_i2c,
+};
+
+
+static int __init fusion_F0710A_init( void )
+{
+ int ret;
+
+ memset(&fusion_F0710A, 0, sizeof(fusion_F0710A));
+
+ /* Probe for fusion_F0710A on I2C. */
+ ret = i2c_add_driver(&fusion_F0710A_i2c_drv);
+ if (ret < 0) {
+ printk(KERN_WARNING DRV_NAME " can't add i2c driver: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static void __exit fusion_F0710A_exit( void )
+{
+ i2c_del_driver(&fusion_F0710A_i2c_drv);
+}
+module_init(fusion_F0710A_init);
+module_exit(fusion_F0710A_exit);
+
+MODULE_DESCRIPTION("fusion_F0710A Touchscreen Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/fusion_F0710A.h b/drivers/input/touchscreen/fusion_F0710A.h
new file mode 100644
index 000000000000..3e5af9e72b78
--- /dev/null
+++ b/drivers/input/touchscreen/fusion_F0710A.h
@@ -0,0 +1,88 @@
+/*
+ * "fusion_F0710A" touchscreen driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* I2C slave address */
+#define fusion_F0710A_I2C_SLAVE_ADDR 0x10
+
+/* I2C registers */
+#define fusion_F0710A_DATA_INFO 0x00
+
+/* First Point*/
+#define fusion_F0710A_POS_X1_HI 0x01 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_X1_LO 0x02 /* 16-bit register, LSB */
+#define fusion_F0710A_POS_Y1_HI 0x03 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_Y1_LO 0x04 /* 16-bit register, LSB */
+#define fusion_F0710A_FIR_PRESS 0X05
+#define fusion_F0710A_FIR_TIDTS 0X06
+
+/* Second Point */
+#define fusion_F0710A_POS_X2_HI 0x07 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_X2_LO 0x08 /* 16-bit register, LSB */
+#define fusion_F0710A_POS_Y2_HI 0x09 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_Y2_LO 0x0A /* 16-bit register, LSB */
+#define fusion_F0710A_SEC_PRESS 0x0B
+#define fusion_F0710A_SEC_TIDTS 0x0C
+
+#define fusion_F0710A_VIESION_INFO_LO 0X0E
+#define fusion_F0710A_VIESION_INFO 0X0F
+
+#define fusion_F0710A_RESET 0x10
+#define fusion_F0710A_SCAN_COMPLETE 0x11
+
+
+#define fusion_F0710A_VIESION_10 0
+#define fusion_F0710A_VIESION_07 1
+#define fusion_F0710A_VIESION_43 2
+
+/* fusion_F0710A 10 inch panel */
+#define fusion_F0710A10_XMAX 2275
+#define fusion_F0710A10_YMAX 1275
+#define fusion_F0710A10_REV 1
+
+/* fusion_F0710A 7 inch panel */
+#define fusion_F0710A07_XMAX 1500
+#define fusion_F0710A07_YMAX 900
+#define fusion_F0710A07_REV 0
+
+/* fusion_F0710A 4.3 inch panel */
+#define fusion_F0710A43_XMAX 900
+#define fusion_F0710A43_YMAX 500
+#define fusion_F0710A43_REV 0
+
+#define fusion_F0710A_SAVE_PT1 0x1
+#define fusion_F0710A_SAVE_PT2 0x2
+
+
+
+/* fusion_F0710A touch screen information */
+struct fusion_F0710A_info {
+ int xres; /* x resolution */
+ int yres; /* y resolution */
+ int xy_reverse; /* if need reverse in the x,y value x=xres-1-x, y=yres-1-y*/
+};
+
+struct fusion_F0710A_data {
+ struct fusion_F0710A_info info;
+ struct i2c_client *client;
+ struct workqueue_struct *workq;
+ struct input_dev *input;
+ int gpio_reset;
+ u16 x1;
+ u16 y1;
+ u8 z1;
+ u8 tip1;
+ u8 tid1;
+ u16 x2;
+ u16 y2;
+ u8 z2;
+ u8 tip2;
+ u8 tid2;
+ u8 f_num;
+ u8 save_points;
+};
+
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 16cbff0e9b0b..c1771f54e801 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -150,6 +150,7 @@ config VIDEO_MX8_CAPTURE
config VIDEO_MXC_CAPTURE
tristate "MXC Video For Linux Video Capture"
depends on VIDEO_V4L2
+ select VIDEOBUF2_DMA_CONTIG
---help---
This is the video4linux2 capture driver based on i.MX video-in module.
diff --git a/drivers/media/platform/mxc/capture/Kconfig b/drivers/media/platform/mxc/capture/Kconfig
index 040f410ff2d4..471afd676a65 100644
--- a/drivers/media/platform/mxc/capture/Kconfig
+++ b/drivers/media/platform/mxc/capture/Kconfig
@@ -61,12 +61,26 @@ config MXC_CAMERA_OV5640_MIPI_V2
help
If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
+config MXC_CAMERA_OV5640_MIPI_NV
+ tristate "OmniVision ov5640 camera support using mipi (based on driver from nVidia)"
+ depends on MXC_MIPI_CSI && I2C
+ ---help---
+ If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here.
+
config MXC_CAMERA_OV5647_MIPI
tristate "OmniVision ov5647 camera support using mipi"
depends on MXC_MIPI_CSI && I2C
help
If you plan to use the ov5647 Camera with mipi interface in your MXC system, say Y here.
+config MXC_HDMI_CSI2_TC358743
+ tristate "Toshiba tc358743 Hdmi to CSI 2 bridge"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+ select MXC_MIPI_CSI2 if ARCH_MX6Q
+ select MXC_CAMERA_SENSOR_CLK
+ ---help---
+ Toshina HDMI to MIPI-CSI2 bridge
+
config MXC_TVIN_ADV7180
tristate "Analog Device adv7180 TV Decoder Input support"
depends on !VIDEO_MXC_EMMA_CAMERA && I2C
@@ -74,6 +88,20 @@ config MXC_TVIN_ADV7180
help
If you plan to use the adv7180 video decoder with your MXC system, say Y here.
+config MXC_TVIN_ADV7280
+ tristate "Analog Device adv7280 TV Decoder Input support"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+ select VIDEO_V4L2_MXC_INT_DEVICE
+ ---help---
+ If you plan to use the adv7280 video decoder with your MXC system, say Y here.
+
+config MXC_TVIN_MAX9526
+ tristate "Maxim Integrated MAX9526 NTSC/PAL Decoder Input support"
+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C
+ select VIDEO_V4L2_MXC_INT_DEVICE
+ ---help---
+ If you plan to use the MAX9526 video decoder with your MXC system, say Y here.
+
choice
prompt "Select Overlay Rounting"
default MXC_IPU_DEVICE_QUEUE_SDC
diff --git a/drivers/media/platform/mxc/capture/Makefile b/drivers/media/platform/mxc/capture/Makefile
index e6e4b99f9435..1abe623d4048 100644
--- a/drivers/media/platform/mxc/capture/Makefile
+++ b/drivers/media/platform/mxc/capture/Makefile
@@ -29,10 +29,22 @@ obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi_int.o
ov5640_camera_mipi_v2-objs := ov5640_mipi_v2.o
obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI_V2) += ov5640_camera_mipi_v2.o
+ov5640_camera_mipi_nv-objs := ov5640_mipi_nv.o
+obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI_NV) += ov5640_camera_mipi_nv.o
+
ov5647_camera_mipi-objs := ov5647_mipi.o
obj-$(CONFIG_MXC_CAMERA_OV5647_MIPI) += ov5647_camera_mipi.o
+tc358743_h2c_bridge-objs := tc358743_h2c.o
+obj-$(CONFIG_MXC_HDMI_CSI2_TC358743) += tc358743_h2c_bridge.o
+
adv7180_tvin-objs := adv7180.o
obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o
+adv7280_tvin-objs := adv7280.o
+obj-$(CONFIG_MXC_TVIN_ADV7280) += adv7280_tvin.o
+
+max9526_tvin-objs := max9526.o
+obj-$(CONFIG_MXC_TVIN_MAX9526) += max9526_tvin.o
+
obj-$(CONFIG_VIDEO_V4L2_MXC_INT_DEVICE) += v4l2-int-device.o
diff --git a/drivers/media/platform/mxc/capture/adv7180.c b/drivers/media/platform/mxc/capture/adv7180.c
index ff75823021b1..8171c1729232 100644
--- a/drivers/media/platform/mxc/capture/adv7180.c
+++ b/drivers/media/platform/mxc/capture/adv7180.c
@@ -34,6 +34,13 @@
#include "v4l2-int-device.h"
#include "mxc_v4l2_capture.h"
+#if 0
+#undef dev_dbg
+#define dev_dbg(dev, format, arg...) {dev_printk(KERN_ERR, dev, format, ##arg);}
+#undef pr_debug
+#define pr_debug(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
#define ADV7180_VOLTAGE_ANALOG 1800000
#define ADV7180_VOLTAGE_DIGITAL_CORE 1800000
#define ADV7180_VOLTAGE_DIGITAL_IO 3300000
@@ -85,6 +92,7 @@ static struct i2c_driver adv7180_i2c_driver = {
struct sensor {
struct sensor_data sen;
v4l2_std_id std_id;
+ int rev_id;
} adv7180_data;
@@ -195,8 +203,10 @@ static struct v4l2_queryctrl adv7180_qctrl[] = {
static inline void adv7180_power_down(int enable)
{
- gpio_set_value_cansleep(pwn_gpio, !enable);
- msleep(2);
+ if (gpio_is_valid(pwn_gpio)) {
+ gpio_set_value_cansleep(pwn_gpio, !enable);
+ msleep(2);
+ }
}
static int adv7180_regulator_enable(struct device *dev)
@@ -292,6 +302,9 @@ static inline int adv7180_read(u8 reg)
"%s:read reg error: reg=%2x\n", __func__, reg);
return -1;
}
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:read reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
+
return val;
}
@@ -305,6 +318,8 @@ static int adv7180_write_reg(u8 reg, u8 val)
{
s32 ret;
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:write reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val);
if (ret < 0) {
dev_dbg(&adv7180_data.sen.i2c_client->dev,
@@ -392,10 +407,16 @@ static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
/* Initialize structure to 0s then set any non-0 values. */
memset(p, 0, sizeof(*p));
p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */
+#if 0
p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
p->u.bt656.nobt_hs_inv = 1;
p->u.bt656.bt_sync_correct = 1;
-
+#else
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.nobt_hs_inv = 0;
+ p->u.bt656.bt_sync_correct = 0;
+ p->u.bt656.clock_curr = 0; //BT656 interlace clock mode
+#endif
/* ADV7180 has a dedicated clock so no clock settings needed. */
return 0;
@@ -429,13 +450,13 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on)
* This is a workaround for preview scrolling issue.
*/
msleep(400);
+
} else if (!on && sensor->sen.on) {
if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0)
return -EIO;
}
sensor->sen.on = on;
-
return 0;
}
@@ -938,8 +959,8 @@ static void adv7180_hard_reset(bool cvbs)
"In adv7180:adv7180_hard_reset\n");
if (cvbs) {
- /* Set CVBS input on AIN1 */
- adv7180_write_reg(ADV7180_INPUT_CTL, 0x00);
+ /* Set CVBS input on AIN4 */
+ adv7180_write_reg(ADV7180_INPUT_CTL, 0x03);
} else {
/*
* Set YPbPr input on AIN1,4,5 and normal
@@ -948,13 +969,12 @@ static void adv7180_hard_reset(bool cvbs)
adv7180_write_reg(ADV7180_INPUT_CTL, 0x09);
}
- /* Datasheet recommends */
+/* The used chip on the Toradex ACM module reacts badly to writes to
+ nonexisting/reserved/read only registers, so reduce the above list to the
+ writable ones in the datasheet sheet */
adv7180_write_reg(0x01, 0xc8);
- adv7180_write_reg(0x02, 0x04);
- adv7180_write_reg(0x03, 0x00);
+ adv7180_write_reg(0x03, 0x0C);
adv7180_write_reg(0x04, 0x45);
- adv7180_write_reg(0x05, 0x00);
- adv7180_write_reg(0x06, 0x02);
adv7180_write_reg(0x07, 0x7F);
adv7180_write_reg(0x08, 0x80);
adv7180_write_reg(0x0A, 0x00);
@@ -962,31 +982,15 @@ static void adv7180_hard_reset(bool cvbs)
adv7180_write_reg(0x0C, 0x36);
adv7180_write_reg(0x0D, 0x7C);
adv7180_write_reg(0x0E, 0x00);
- adv7180_write_reg(0x0F, 0x00);
- adv7180_write_reg(0x13, 0x00);
+ adv7180_write_reg(0x0F, 0x04);//00
+ adv7180_write_reg(0x13, 0x00);//R
adv7180_write_reg(0x14, 0x12);
adv7180_write_reg(0x15, 0x00);
- adv7180_write_reg(0x16, 0x00);
adv7180_write_reg(0x17, 0x01);
adv7180_write_reg(0x18, 0x93);
- adv7180_write_reg(0xF1, 0x19);
- adv7180_write_reg(0x1A, 0x00);
- adv7180_write_reg(0x1B, 0x00);
- adv7180_write_reg(0x1C, 0x00);
+ adv7180_write_reg(0x19, 0xF1);
adv7180_write_reg(0x1D, 0x40);
- adv7180_write_reg(0x1E, 0x00);
- adv7180_write_reg(0x1F, 0x00);
- adv7180_write_reg(0x20, 0x00);
- adv7180_write_reg(0x21, 0x00);
- adv7180_write_reg(0x22, 0x00);
- adv7180_write_reg(0x23, 0xC0);
- adv7180_write_reg(0x24, 0x00);
- adv7180_write_reg(0x25, 0x00);
- adv7180_write_reg(0x26, 0x00);
adv7180_write_reg(0x27, 0x58);
- adv7180_write_reg(0x28, 0x00);
- adv7180_write_reg(0x29, 0x00);
- adv7180_write_reg(0x2A, 0x00);
adv7180_write_reg(0x2B, 0xE1);
adv7180_write_reg(0x2C, 0xAE);
adv7180_write_reg(0x2D, 0xF4);
@@ -1003,18 +1007,8 @@ static void adv7180_hard_reset(bool cvbs)
adv7180_write_reg(0x38, 0x80);
adv7180_write_reg(0x39, 0xC0);
adv7180_write_reg(0x3A, 0x10);
- adv7180_write_reg(0x3B, 0x05);
- adv7180_write_reg(0x3C, 0x58);
adv7180_write_reg(0x3D, 0xB2);
- adv7180_write_reg(0x3E, 0x64);
- adv7180_write_reg(0x3F, 0xE4);
- adv7180_write_reg(0x40, 0x90);
adv7180_write_reg(0x41, 0x01);
- adv7180_write_reg(0x42, 0x7E);
- adv7180_write_reg(0x43, 0xA4);
- adv7180_write_reg(0x44, 0xFF);
- adv7180_write_reg(0x45, 0xB6);
- adv7180_write_reg(0x46, 0x12);
adv7180_write_reg(0x48, 0x00);
adv7180_write_reg(0x49, 0x00);
adv7180_write_reg(0x4A, 0x00);
@@ -1022,171 +1016,34 @@ static void adv7180_hard_reset(bool cvbs)
adv7180_write_reg(0x4C, 0x00);
adv7180_write_reg(0x4D, 0xEF);
adv7180_write_reg(0x4E, 0x08);
- adv7180_write_reg(0x4F, 0x08);
adv7180_write_reg(0x50, 0x08);
adv7180_write_reg(0x51, 0x24);
- adv7180_write_reg(0x52, 0x0B);
- adv7180_write_reg(0x53, 0x4E);
- adv7180_write_reg(0x54, 0x80);
- adv7180_write_reg(0x55, 0x00);
- adv7180_write_reg(0x56, 0x10);
- adv7180_write_reg(0x57, 0x00);
adv7180_write_reg(0x58, 0x00);
adv7180_write_reg(0x59, 0x00);
- adv7180_write_reg(0x5A, 0x00);
- adv7180_write_reg(0x5B, 0x00);
- adv7180_write_reg(0x5C, 0x00);
- adv7180_write_reg(0x5D, 0x00);
- adv7180_write_reg(0x5E, 0x00);
- adv7180_write_reg(0x5F, 0x00);
- adv7180_write_reg(0x60, 0x00);
- adv7180_write_reg(0x61, 0x00);
- adv7180_write_reg(0x62, 0x20);
- adv7180_write_reg(0x63, 0x00);
- adv7180_write_reg(0x64, 0x00);
- adv7180_write_reg(0x65, 0x00);
- adv7180_write_reg(0x66, 0x00);
- adv7180_write_reg(0x67, 0x03);
- adv7180_write_reg(0x68, 0x01);
- adv7180_write_reg(0x69, 0x00);
- adv7180_write_reg(0x6A, 0x00);
- adv7180_write_reg(0x6B, 0xC0);
- adv7180_write_reg(0x6C, 0x00);
- adv7180_write_reg(0x6D, 0x00);
- adv7180_write_reg(0x6E, 0x00);
- adv7180_write_reg(0x6F, 0x00);
- adv7180_write_reg(0x70, 0x00);
- adv7180_write_reg(0x71, 0x00);
- adv7180_write_reg(0x72, 0x00);
- adv7180_write_reg(0x73, 0x10);
- adv7180_write_reg(0x74, 0x04);
- adv7180_write_reg(0x75, 0x01);
- adv7180_write_reg(0x76, 0x00);
- adv7180_write_reg(0x77, 0x3F);
- adv7180_write_reg(0x78, 0xFF);
- adv7180_write_reg(0x79, 0xFF);
- adv7180_write_reg(0x7A, 0xFF);
- adv7180_write_reg(0x7B, 0x1E);
- adv7180_write_reg(0x7C, 0xC0);
- adv7180_write_reg(0x7D, 0x00);
- adv7180_write_reg(0x7E, 0x00);
- adv7180_write_reg(0x7F, 0x00);
- adv7180_write_reg(0x80, 0x00);
- adv7180_write_reg(0x81, 0xC0);
- adv7180_write_reg(0x82, 0x04);
- adv7180_write_reg(0x83, 0x00);
- adv7180_write_reg(0x84, 0x0C);
- adv7180_write_reg(0x85, 0x02);
- adv7180_write_reg(0x86, 0x03);
- adv7180_write_reg(0x87, 0x63);
- adv7180_write_reg(0x88, 0x5A);
- adv7180_write_reg(0x89, 0x08);
- adv7180_write_reg(0x8A, 0x10);
- adv7180_write_reg(0x8B, 0x00);
- adv7180_write_reg(0x8C, 0x40);
- adv7180_write_reg(0x8D, 0x00);
- adv7180_write_reg(0x8E, 0x40);
adv7180_write_reg(0x8F, 0x00);
- adv7180_write_reg(0x90, 0x00);
- adv7180_write_reg(0x91, 0x50);
- adv7180_write_reg(0x92, 0x00);
- adv7180_write_reg(0x93, 0x00);
- adv7180_write_reg(0x94, 0x00);
- adv7180_write_reg(0x95, 0x00);
- adv7180_write_reg(0x96, 0x00);
- adv7180_write_reg(0x97, 0xF0);
- adv7180_write_reg(0x98, 0x00);
- adv7180_write_reg(0x99, 0x00);
- adv7180_write_reg(0x9A, 0x00);
- adv7180_write_reg(0x9B, 0x00);
- adv7180_write_reg(0x9C, 0x00);
- adv7180_write_reg(0x9D, 0x00);
- adv7180_write_reg(0x9E, 0x00);
- adv7180_write_reg(0x9F, 0x00);
- adv7180_write_reg(0xA0, 0x00);
- adv7180_write_reg(0xA1, 0x00);
- adv7180_write_reg(0xA2, 0x00);
- adv7180_write_reg(0xA3, 0x00);
- adv7180_write_reg(0xA4, 0x00);
- adv7180_write_reg(0xA5, 0x00);
- adv7180_write_reg(0xA6, 0x00);
- adv7180_write_reg(0xA7, 0x00);
- adv7180_write_reg(0xA8, 0x00);
- adv7180_write_reg(0xA9, 0x00);
- adv7180_write_reg(0xAA, 0x00);
- adv7180_write_reg(0xAB, 0x00);
- adv7180_write_reg(0xAC, 0x00);
- adv7180_write_reg(0xAD, 0x00);
- adv7180_write_reg(0xAE, 0x60);
- adv7180_write_reg(0xAF, 0x00);
- adv7180_write_reg(0xB0, 0x00);
- adv7180_write_reg(0xB1, 0x60);
adv7180_write_reg(0xB2, 0x1C);
- adv7180_write_reg(0xB3, 0x54);
- adv7180_write_reg(0xB4, 0x00);
- adv7180_write_reg(0xB5, 0x00);
- adv7180_write_reg(0xB6, 0x00);
- adv7180_write_reg(0xB7, 0x13);
- adv7180_write_reg(0xB8, 0x03);
- adv7180_write_reg(0xB9, 0x33);
- adv7180_write_reg(0xBF, 0x02);
- adv7180_write_reg(0xC0, 0x00);
- adv7180_write_reg(0xC1, 0x00);
- adv7180_write_reg(0xC2, 0x00);
adv7180_write_reg(0xC3, 0x00);
adv7180_write_reg(0xC4, 0x00);
- adv7180_write_reg(0xC5, 0x81);
- adv7180_write_reg(0xC6, 0x00);
- adv7180_write_reg(0xC7, 0x00);
- adv7180_write_reg(0xC8, 0x00);
- adv7180_write_reg(0xC9, 0x04);
- adv7180_write_reg(0xCC, 0x69);
- adv7180_write_reg(0xCD, 0x00);
- adv7180_write_reg(0xCE, 0x01);
- adv7180_write_reg(0xCF, 0xB4);
- adv7180_write_reg(0xD0, 0x00);
- adv7180_write_reg(0xD1, 0x10);
- adv7180_write_reg(0xD2, 0xFF);
- adv7180_write_reg(0xD3, 0xFF);
- adv7180_write_reg(0xD4, 0x7F);
- adv7180_write_reg(0xD5, 0x7F);
- adv7180_write_reg(0xD6, 0x3E);
- adv7180_write_reg(0xD7, 0x08);
- adv7180_write_reg(0xD8, 0x3C);
- adv7180_write_reg(0xD9, 0x08);
- adv7180_write_reg(0xDA, 0x3C);
- adv7180_write_reg(0xDB, 0x9B);
adv7180_write_reg(0xDC, 0xAC);
adv7180_write_reg(0xDD, 0x4C);
- adv7180_write_reg(0xDE, 0x00);
- adv7180_write_reg(0xDF, 0x00);
- adv7180_write_reg(0xE0, 0x14);
adv7180_write_reg(0xE1, 0x80);
adv7180_write_reg(0xE2, 0x80);
adv7180_write_reg(0xE3, 0x80);
adv7180_write_reg(0xE4, 0x80);
adv7180_write_reg(0xE5, 0x25);
- adv7180_write_reg(0xE6, 0x44);
+ adv7180_write_reg(0xE6, 0x44);//0x04
adv7180_write_reg(0xE7, 0x63);
adv7180_write_reg(0xE8, 0x65);
adv7180_write_reg(0xE9, 0x14);
adv7180_write_reg(0xEA, 0x63);
adv7180_write_reg(0xEB, 0x55);
adv7180_write_reg(0xEC, 0x55);
- adv7180_write_reg(0xEE, 0x00);
- adv7180_write_reg(0xEF, 0x4A);
- adv7180_write_reg(0xF0, 0x44);
- adv7180_write_reg(0xF1, 0x0C);
- adv7180_write_reg(0xF2, 0x32);
adv7180_write_reg(0xF3, 0x00);
- adv7180_write_reg(0xF4, 0x3F);
- adv7180_write_reg(0xF5, 0xE0);
- adv7180_write_reg(0xF6, 0x69);
- adv7180_write_reg(0xF7, 0x10);
+ adv7180_write_reg(0xF4, 0x15);
adv7180_write_reg(0xF8, 0x00);
adv7180_write_reg(0xF9, 0x03);
- adv7180_write_reg(0xFA, 0xFA);
adv7180_write_reg(0xFB, 0x40);
+ adv7180_write_reg(0xFC, 0x04);//was missing
}
/*! ADV7180 I2C attach function.
@@ -1208,13 +1065,12 @@ static void adv7180_hard_reset(bool cvbs)
static int adv7180_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int rev_id;
int ret = 0;
u32 cvbs = true;
struct pinctrl *pinctrl;
struct device *dev = &client->dev;
- printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data);
+ dev_dbg(dev, "%s sensor data is at %p\n", __func__, &adv7180_data);
pinctrl = devm_pinctrl_get_select_default(dev);
if (IS_ERR(pinctrl)) {
@@ -1224,15 +1080,15 @@ static int adv7180_probe(struct i2c_client *client,
/* request power down pin */
pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- if (!gpio_is_valid(pwn_gpio)) {
- dev_err(dev, "no sensor pwdn pin available\n");
- return -ENODEV;
- }
- ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ if (!gpio_is_valid(pwn_gpio))
+ dev_warn(dev, "no sensor pwdn pin available\n");
+ else {
+ ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
"adv7180_pwdn");
- if (ret < 0) {
- dev_err(dev, "no power pin available!\n");
- return ret;
+ if (ret < 0) {
+ dev_err(dev, "no power pin available!\n");
+ //return ret;
+ }
}
adv7180_regulator_enable(dev);
@@ -1282,6 +1138,9 @@ static int adv7180_probe(struct i2c_client *client,
return ret;
}
+ /* ADV7180 is always parallel IF */
+ adv7180_data.sen.mipi_camera = 0;
+
clk_prepare_enable(adv7180_data.sen.sensor_clk);
dev_dbg(&adv7180_data.sen.i2c_client->dev,
@@ -1289,10 +1148,26 @@ static int adv7180_probe(struct i2c_client *client,
__func__, adv7180_data.sen.i2c_client->addr);
/*! Read the revision ID of the tvin chip */
- rev_id = adv7180_read(ADV7180_IDENT);
- dev_dbg(dev,
- "%s:Analog Device adv7%2X0 detected!\n", __func__,
- rev_id);
+ adv7180_data.rev_id = adv7180_read(ADV7180_IDENT);
+ switch(adv7180_data.rev_id) {
+ case 0x1b:
+ case 0x1c:
+ case 0x1e:
+ dev_dbg(dev,
+ "%s:Analog Device adv7180 ident %2X detected!\n", __func__,
+ adv7180_data.rev_id);
+ break;
+ case 0x40:
+ case 0x41:
+ dev_dbg(dev,
+ "%s:Analog Device adv7182 ident %2X detected!\n", __func__,
+ adv7180_data.rev_id);
+ break;
+ default:
+ dev_dbg(dev,
+ "%s:Analog Device adv7180 not detected!\n", __func__);
+ return -ENODEV;
+ }
ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs));
if (ret) {
diff --git a/drivers/media/platform/mxc/capture/adv7280.c b/drivers/media/platform/mxc/capture/adv7280.c
new file mode 100644
index 000000000000..b31e09ab9414
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/adv7280.c
@@ -0,0 +1,1080 @@
+/*
+ * Copyright 2016 Toradex AG.
+ *
+ * Based on adv7180/max9526 driver for iMX6 and adv7280 driver for Tegra
+ * by Antmicro
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#define ADV7280_VOLTAGE_ANALOG 1800000
+#define ADV7280_VOLTAGE_DIGITAL_CORE 1800000
+#define ADV7280_VOLTAGE_DIGITAL_IO 3300000
+#define ADV7280_VOLTAGE_PLL 1800000
+
+static struct regulator *dvddio_regulator;
+static struct regulator *dvdd_regulator;
+static struct regulator *avdd_regulator;
+static struct regulator *pvdd_regulator;
+static int pwn_gpio;
+
+struct sensor {
+ struct sensor_data sen;
+ v4l2_std_id std_id;
+ int rev_id;
+} adv7280_data;
+
+typedef enum {
+ ADV7280_NTSC = 0, /*!< Locked on (M) NTSC video signal. */
+ ADV7280_PAL, /*!< (B, G, H, I, N)PAL video signal. */
+ ADV7280_NOT_LOCKED, /*!< Not locked on a signal. */
+} video_fmt_idx;
+
+struct video_fmt_t {
+ int v4l2_id;
+ char name[16];
+ u16 raw_width;
+ u16 raw_height;
+ u16 active_width;
+ u16 active_height;
+ int frame_rate;
+};
+
+static const struct video_fmt_t video_fmts[] = {
+ {
+ .v4l2_id = V4L2_STD_NTSC,
+ .name = "NTSC",
+ .raw_width = 720,
+ .raw_height = 525,
+ .active_width = 720,
+ .active_height = 480,
+ .frame_rate = 30,
+ },
+ {
+ .v4l2_id = V4L2_STD_PAL,
+ .name = "PAL",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .frame_rate = 25,
+ },
+ {
+ .v4l2_id = V4L2_STD_ALL,
+ .name = "Autodetect",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ .frame_rate = 0,
+ },
+};
+
+static video_fmt_idx video_idx = ADV7280_PAL;
+
+static DEFINE_MUTEX(mutex);
+
+#define IF_NAME "adv7280"
+
+#define ADV7280_INPUT_CONTROL 0x00
+#define ADV7280_VIDEO_SELECTION_1 0x01
+#define ADV7280_VIDEO_SELECTION_2 0x02
+#define ADV7280_OUTPUT_CONTROL 0x03
+#define ADV7280_EXTENDED_OUTPUT_CONTROL 0x04
+#define ADV7280_AUTODETECT_ENABLE 0x07
+#define ADV7280_BRIGHTNESS 0x0A
+#define ADV7280_ADI_CONTROL_1 0x0E
+#define ADV7280_POWER_MANAGEMENT 0x0F
+#define ADV7280_STATUS_1 0x10
+#define ADV7280_IDENT 0x11
+#define ADV7280_STATUS_3 0x13
+#define ADV7280_SHAPING_FILTER_CONTROL_1 0x17
+#define ADV7280_ADI_CONTROL_2 0x1D
+#define ADV7280_PIXEL_DELAY_CONTROL 0x27
+#define ADV7280_VPP_SLAVE_ADDRESS 0xFD
+#define ADV7280_OUTPUT_SYNC_SELECT_2 0x6B
+#define ADV7280_SD_SATURATION_CB 0xe3
+#define ADV7280_SD_SATURATION_CR 0xe4
+
+#define HW_DEINT /* Enable hardware deinterlacer */
+#define VPP_SLAVE_ADDRESS 0x42
+
+#define VPP_DEINT_RESET 0x41
+#define VPP_I2C_DEINT_ENABLE 0x55
+#define VPP_ADV_TIMING_MODE_EN 0x5B
+
+#define ADV7280_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5
+#define ADV7280_AUTODETECT_DEFAULT 0x7f
+
+#define ADV7280_INPUT_CONTROL_COMPOSITE_IN1 0x00
+#define ADV7280_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00
+
+#define ADV7280_INPUT_CONTROL_NTSC_M 0x50
+#define ADV7280_INPUT_CONTROL_PAL60 0x60
+#define ADV7280_INPUT_CONTROL_NTSC_443 0x70
+#define ADV7280_INPUT_CONTROL_PAL_BG 0x80
+#define ADV7280_INPUT_CONTROL_PAL_N 0x90
+#define ADV7280_INPUT_CONTROL_PAL_M 0xa0
+#define ADV7280_INPUT_CONTROL_PAL_M_PED 0xb0
+#define ADV7280_INPUT_CONTROL_PAL_COMB_N 0xc0
+#define ADV7280_INPUT_CONTROL_PAL_COMB_N_PED 0xd0
+#define ADV7280_INPUT_CONTROL_PAL_SECAM 0xe0
+
+#define ADV7280_STATUS1_IN_LOCK 0x01
+/* Autodetection results */
+#define ADV7280_STATUS1_AUTOD_MASK 0x70
+#define ADV7280_STATUS1_AUTOD_NTSM_M_J 0x00
+#define ADV7280_STATUS1_AUTOD_NTSC_4_43 0x10
+#define ADV7280_STATUS1_AUTOD_PAL_M 0x20
+#define ADV7280_STATUS1_AUTOD_PAL_60 0x30
+#define ADV7280_STATUS1_AUTOD_PAL_B_G 0x40
+#define ADV7280_STATUS1_AUTOD_SECAM 0x50
+#define ADV7280_STATUS1_AUTOD_PAL_COMB 0x60
+#define ADV7280_STATUS1_AUTOD_SECAM_525 0x70
+
+static const struct v4l2_queryctrl adv7280_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 127,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 0x1,
+ .default_value = 127,
+ .flags = 0,
+ }
+};
+
+static inline void adv7280_power_down(int enable)
+{
+ if (gpio_is_valid(pwn_gpio)) {
+ gpio_set_value_cansleep(pwn_gpio, !enable);
+ msleep(2);
+ }
+}
+
+static int adv7280_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ dvddio_regulator = devm_regulator_get(dev, "DOVDD");
+
+ if (!IS_ERR(dvddio_regulator)) {
+ regulator_set_voltage(dvddio_regulator,
+ ADV7280_VOLTAGE_DIGITAL_IO,
+ ADV7280_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(dvddio_regulator);
+ if (ret) {
+ dev_err(dev, "set io voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set io voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get io voltage\n");
+ dvddio_regulator = NULL;
+ }
+
+ dvdd_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(dvdd_regulator)) {
+ regulator_set_voltage(dvdd_regulator,
+ ADV7280_VOLTAGE_DIGITAL_CORE,
+ ADV7280_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(dvdd_regulator);
+ if (ret) {
+ dev_err(dev, "set core voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set core voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get core voltage\n");
+ dvdd_regulator = NULL;
+ }
+
+ avdd_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(avdd_regulator)) {
+ regulator_set_voltage(avdd_regulator,
+ ADV7280_VOLTAGE_ANALOG,
+ ADV7280_VOLTAGE_ANALOG);
+ ret = regulator_enable(avdd_regulator);
+ if (ret) {
+ dev_err(dev, "set analog voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set analog voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get analog voltage\n");
+ avdd_regulator = NULL;
+ }
+
+ pvdd_regulator = devm_regulator_get(dev, "PVDD");
+ if (!IS_ERR(pvdd_regulator)) {
+ regulator_set_voltage(pvdd_regulator,
+ ADV7280_VOLTAGE_PLL,
+ ADV7280_VOLTAGE_PLL);
+ ret = regulator_enable(pvdd_regulator);
+ if (ret) {
+ dev_err(dev, "set pll voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set pll voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get pll voltage\n");
+ pvdd_regulator = NULL;
+ }
+
+ return ret;
+}
+
+static inline int adv7280_read(u8 reg)
+{
+ int val;
+
+ val = i2c_smbus_read_byte_data(adv7280_data.sen.i2c_client, reg);
+ if (val < 0) {
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ "%s:read reg error: reg=%2x\n", __func__, reg);
+ return val;
+ }
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ "%s:read reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
+
+ return val;
+}
+
+static int adv7280_write_reg(u8 reg, u8 val)
+{
+ s32 ret;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ "%s:write reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
+
+ ret = i2c_smbus_write_byte_data(adv7280_data.sen.i2c_client, reg, val);
+ if (ret < 0) {
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ "%s:write reg error:reg=%2x,val=%2x\n", __func__,
+ reg, val);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int adv7280_write_reg_with_client(struct i2c_client *client,
+ u8 reg, u8 val)
+{
+ s32 ret;
+
+ dev_dbg(&client->dev,
+ "%s:write reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+ if (ret < 0) {
+ dev_dbg(&client->dev,
+ "%s:write reg error:reg=%2x,val=%2x\n", __func__,
+ reg, val);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void adv7280_get_std(v4l2_std_id *std)
+{
+ int status_1, standard, idx;
+ bool locked = 0;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "In %s\n", __func__);
+
+ status_1 = adv7280_read(ADV7280_STATUS_1);
+ locked = status_1 & ADV7280_STATUS1_IN_LOCK;
+ standard = status_1 & ADV7280_STATUS1_AUTOD_MASK;
+
+ mutex_lock(&mutex);
+ *std = V4L2_STD_ALL;
+ idx = ADV7280_NOT_LOCKED;
+ if (locked) {
+ if (standard == ADV7280_STATUS1_AUTOD_PAL_B_G) {
+ *std = V4L2_STD_PAL;
+ idx = ADV7280_PAL;
+ } else if (standard == ADV7280_STATUS1_AUTOD_NTSM_M_J) {
+ *std = V4L2_STD_NTSC;
+ idx = ADV7280_NTSC;
+ }
+ }
+ mutex_unlock(&mutex);
+
+ /* This assumes autodetect which this device uses. */
+ if (*std != adv7280_data.std_id) {
+ video_idx = idx;
+ adv7280_data.std_id = *std;
+ adv7280_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ adv7280_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ }
+}
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ struct device *dev = &adv7280_data.sen.i2c_client->dev;
+
+ dev_dbg(dev, "adv7280: %s\n", __func__);
+
+ if (s == NULL) {
+ dev_err(dev, " ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+ p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */
+#if 0
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.nobt_hs_inv = 1;
+ p->u.bt656.bt_sync_correct = 1;
+#else
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.nobt_hs_inv = 0;
+ p->u.bt656.bt_sync_correct = 0;
+#ifdef HW_DEINT
+ p->u.bt656.clock_curr = 1; /* BT656 de-interlace clock mode */
+#endif
+#endif
+ /* ADV7280 has a dedicated clock so no clock settings needed. */
+
+ return 0;
+}
+
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor *sensor = s->priv;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ if (on && !sensor->sen.on) {
+ if (adv7280_write_reg(ADV7280_POWER_MANAGEMENT, 0x04) != 0)
+ return -EIO;
+
+ msleep(400);
+
+ } else if (!on && sensor->sen.on) {
+ if (adv7280_write_reg(ADV7280_POWER_MANAGEMENT, 0x24) != 0)
+ return -EIO;
+ }
+
+ sensor->sen.on = on;
+
+ return 0;
+}
+
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ struct device *dev = &adv7280_data.sen.i2c_client->dev;
+
+ dev_dbg(dev, "adv7280: %s\n", __func__);
+
+ switch (a->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ dev_dbg(dev, " type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->sen.streamcap.capability;
+ cparm->timeperframe = sensor->sen.streamcap.timeperframe;
+ cparm->capturemode = sensor->sen.streamcap.capturemode;
+ break;
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ break;
+
+ default:
+ dev_dbg(dev, "ioctl_g_parm:type is unknown %d\n", a->type);
+ break;
+ }
+
+ return 0;
+}
+
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct device *dev = &adv7280_data.sen.i2c_client->dev;
+
+ dev_dbg(dev, "adv7280: %s\n", __func__);
+
+ switch (a->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ break;
+
+ default:
+ dev_dbg(dev, " type is unknown - %d\n", a->type);
+ break;
+ }
+
+ return 0;
+}
+
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ struct device *dev = &adv7280_data.sen.i2c_client->dev;
+ struct sensor *sensor = s->priv;
+ v4l2_std_id std;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ dev_dbg(dev, " Returning size of %dx%d\n",
+ sensor->sen.pix.width, sensor->sen.pix.height);
+ f->fmt.pix = sensor->sen.pix;
+ break;
+
+ case V4L2_BUF_TYPE_PRIVATE:
+ adv7280_get_std(&std);
+ f->fmt.pix.pixelformat = (u32)std;
+ break;
+
+ default:
+ f->fmt.pix = sensor->sen.pix;
+ break;
+ }
+
+ return 0;
+}
+
+static int ioctl_queryctrl(struct v4l2_int_device *s,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(adv7280_qctrl); i++)
+ if (qc->id && qc->id == adv7280_qctrl[i].id) {
+ *qc = adv7280_qctrl[i];
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+ int sat = 0;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_BRIGHTNESS\n");
+ adv7280_data.sen.brightness = adv7280_read(ADV7280_BRIGHTNESS);
+ vc->value = adv7280_data.sen.brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_CONTRAST\n");
+ vc->value = adv7280_data.sen.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_SATURATION\n");
+ sat = adv7280_read(ADV7280_SD_SATURATION_CB);
+ adv7280_data.sen.saturation = sat;
+ vc->value = adv7280_data.sen.saturation;
+ break;
+ case V4L2_CID_HUE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_HUE\n");
+ vc->value = adv7280_data.sen.hue;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_RED_BALANCE\n");
+ vc->value = adv7280_data.sen.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_BLUE_BALANCE\n");
+ vc->value = adv7280_data.sen.blue;
+ break;
+ case V4L2_CID_GAMMA:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_EXPOSURE\n");
+ vc->value = adv7280_data.sen.ae_mode;
+ break;
+ case V4L2_CID_AUTOGAIN:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_VFLIP\n");
+ break;
+ default:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " Default case\n");
+ vc->value = 0;
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+ u8 tmp;
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_BRIGHTNESS\n");
+ tmp = vc->value;
+ adv7280_write_reg(ADV7280_BRIGHTNESS, tmp);
+ adv7280_data.sen.brightness = vc->value;
+ break;
+ case V4L2_CID_CONTRAST:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_CONTRAST\n");
+ break;
+ case V4L2_CID_SATURATION:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_SATURATION\n");
+ tmp = vc->value;
+ adv7280_write_reg(ADV7280_SD_SATURATION_CB, tmp);
+ adv7280_write_reg(ADV7280_SD_SATURATION_CR, tmp);
+ adv7280_data.sen.saturation = vc->value;
+ break;
+ case V4L2_CID_HUE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_HUE\n");
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_RED_BALANCE\n");
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_BLUE_BALANCE\n");
+ break;
+ case V4L2_CID_GAMMA:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_EXPOSURE\n");
+ break;
+ case V4L2_CID_AUTOGAIN:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " V4L2_CID_VFLIP\n");
+ break;
+ default:
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ " Default case\n");
+ retval = -EINVAL;
+ break;
+ }
+
+ return retval;
+}
+
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index >= 1)
+ return -EINVAL;
+
+ fsize->discrete.width = video_fmts[video_idx].active_width;
+ fsize->discrete.height = video_fmts[video_idx].active_height;
+
+ return 0;
+}
+
+static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
+ struct v4l2_frmivalenum *fival)
+{
+ struct video_fmt_t fmt;
+ int i;
+
+ if (fival->index != 0)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(video_fmts) - 1; i++) {
+ fmt = video_fmts[i];
+ if (fival->width == fmt.active_width &&
+ fival->height == fmt.active_height) {
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+ fival->discrete.denominator = fmt.frame_rate;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+ "adv7280_decoder");
+ ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7280;
+
+ return 0;
+}
+
+static int ioctl_init(struct v4l2_int_device *s)
+{
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ return 0;
+}
+
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ dev_dbg(&adv7280_data.sen.i2c_client->dev, "adv7280: %s\n", __func__);
+
+ return 0;
+}
+
+static struct v4l2_int_ioctl_desc adv7280_ioctl_desc[] = {
+
+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init},
+
+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power},
+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm},
+ {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init},
+
+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap},
+
+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm},
+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm},
+ {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl},
+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl},
+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl},
+ {vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_framesizes},
+ {vidioc_int_enum_frameintervals_num,
+ (v4l2_int_ioctl_func *)
+ ioctl_enum_frameintervals},
+ {vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave adv7280_slave = {
+ .ioctls = adv7280_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(adv7280_ioctl_desc),
+};
+
+static struct v4l2_int_device adv7280_int_device = {
+ .module = THIS_MODULE,
+ .name = "adv7280",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &adv7280_slave,
+ },
+};
+
+static int adv7280_hard_reset(void)
+{
+ int ret;
+
+ struct i2c_client vpp_client = {
+ .flags = adv7280_data.sen.i2c_client->flags,
+ .addr = VPP_SLAVE_ADDRESS,
+ .name = "ADV7280_VPP",
+ .adapter = adv7280_data.sen.i2c_client->adapter,
+ .dev = adv7280_data.sen.i2c_client->dev,
+ };
+
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ "In %s\n", __func__);
+
+ /* Reset */
+ ret = adv7280_write_reg(ADV7280_POWER_MANAGEMENT, 0xA0);
+ if (ret < 0)
+ goto error;
+ msleep(10);
+
+ /* Initialize adv7280 */
+ /* Exit Power Down Mode */
+ ret = adv7280_write_reg(ADV7280_POWER_MANAGEMENT, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(ADV7280_ADI_CONTROL_1, 0x80);
+ if (ret < 0)
+ goto error;
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(0x9C, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(0x9C, 0xFF);
+ if (ret < 0)
+ goto error;
+
+ /* Enter User Sub Map */
+ ret = adv7280_write_reg(ADV7280_ADI_CONTROL_1, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* Enable Pixel & Sync output drivers */
+ ret = adv7280_write_reg(ADV7280_OUTPUT_CONTROL, 0x0C);
+ if (ret < 0)
+ goto error;
+
+ /* Power-up INTRQ, HS & VS pads */
+ ret = adv7280_write_reg(ADV7280_EXTENDED_OUTPUT_CONTROL, 0x07);
+ if (ret < 0)
+ goto error;
+
+ /* Enable SH1 */
+ /*
+ ret = adv7280_write_reg(ADV7280_SHAPING_FILTER_CONTROL_1, 0x41);
+ if (ret < 0)
+ goto error;
+ */
+
+ /* Disable comb filtering */
+ /*
+ ret = adv7280_write_reg(0x39, 0x24);
+ if (ret < 0)
+ goto error;
+ */
+
+ /* Enable LLC output driver */
+ ret = adv7280_write_reg(ADV7280_ADI_CONTROL_2, 0x40);
+ if (ret < 0)
+ goto error;
+
+ /* VSYNC on VS/FIELD/SFL pin */
+ ret = adv7280_write_reg(ADV7280_OUTPUT_SYNC_SELECT_2, 0x01);
+ if (ret < 0)
+ goto error;
+
+ /* Enable autodetection */
+ ret = adv7280_write_reg(ADV7280_INPUT_CONTROL,
+ ADV7280_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM |
+ (ADV7280_INPUT_CONTROL_COMPOSITE_IN1 +
+ 0));
+ if (ret < 0)
+ goto error;
+
+ ret = adv7280_write_reg(ADV7280_AUTODETECT_ENABLE,
+ ADV7280_AUTODETECT_DEFAULT);
+ if (ret < 0)
+ goto error;
+
+ /* ITU-R BT.656-4 compatible */
+ /*ret = adv7280_write_reg(ADV7280_EXTENDED_OUTPUT_CONTROL,
+ ADV7280_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
+ if (ret < 0)
+ goto error;
+ */
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(0x52, 0xCD);
+ if (ret < 0)
+ goto error;
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(0x80, 0x51);
+ if (ret < 0)
+ goto error;
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(0x81, 0x51);
+ if (ret < 0)
+ goto error;
+
+ /* analog devices recommends */
+ ret = adv7280_write_reg(0x82, 0x68);
+ if (ret < 0)
+ goto error;
+
+#ifdef HW_DEINT
+ /* Set VPP Map */
+ ret = adv7280_write_reg(ADV7280_VPP_SLAVE_ADDRESS, (VPP_SLAVE_ADDRESS << 1));
+ if (ret < 0)
+ goto error;
+
+ /* VPP - not documented */
+ ret = adv7280_write_reg_with_client(&vpp_client,
+ 0xA3, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* VPP - Enbable Advanced Timing Mode */
+ ret = adv7280_write_reg_with_client(&vpp_client,
+ VPP_ADV_TIMING_MODE_EN, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* VPP - Enable Deinterlacer */
+ ret = adv7280_write_reg_with_client(&vpp_client,
+ VPP_I2C_DEINT_ENABLE, 0x80);
+ if (ret < 0)
+ goto error;
+#endif
+
+ return 0;
+
+error:
+ return ret;
+}
+
+static int adv7280_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret = 0;
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(dev, "Required functionality not supported by I2C adapter\n");
+ return -EIO;
+ }
+
+ v4l_info(client, "chip found @ 0x%02x (%s)\n",
+ client->addr << 1, client->adapter->name);
+
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(dev, "setup pinctrl failed\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio))
+ dev_warn(dev, "no sensor pwdn pin available\n");
+ else {
+ ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "adv7280_pwdn");
+ if (ret < 0)
+ dev_err(dev, "no power pin available!\n");
+ }
+
+ adv7280_regulator_enable(dev);
+
+ adv7280_power_down(0);
+
+ msleep(1);
+
+ memset(&adv7280_data, 0, sizeof(adv7280_data));
+ adv7280_data.sen.i2c_client = client;
+ adv7280_data.sen.streamcap.timeperframe.denominator = 30;
+ adv7280_data.sen.streamcap.timeperframe.numerator = 1;
+ adv7280_data.std_id = V4L2_STD_ALL;
+ video_idx = ADV7280_NOT_LOCKED;
+ adv7280_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ adv7280_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ adv7280_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */
+ adv7280_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
+ adv7280_data.sen.on = true;
+
+ adv7280_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(adv7280_data.sen.sensor_clk)) {
+ dev_err(dev, "get mclk failed\n");
+ return PTR_ERR(adv7280_data.sen.sensor_clk);
+ }
+
+ ret = of_property_read_u32(dev->of_node, "mclk",
+ &adv7280_data.sen.mclk);
+ if (ret) {
+ dev_err(dev, "mclk frequency is invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(
+ dev->of_node, "mclk_source",
+ (u32 *) &(adv7280_data.sen.mclk_source));
+ if (ret) {
+ dev_err(dev, "mclk_source invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "csi_id",
+ &(adv7280_data.sen.csi));
+ if (ret) {
+ dev_err(dev, "csi_id invalid\n");
+ return ret;
+ }
+
+ /* ADV7280 is always parallel IF */
+ adv7280_data.sen.mipi_camera = 0;
+
+ clk_prepare_enable(adv7280_data.sen.sensor_clk);
+
+ adv7280_data.rev_id = adv7280_read(ADV7280_IDENT);
+ switch (adv7280_data.rev_id) {
+ case 0x42:
+ dev_dbg(dev,
+ "%s:Analog Device adv7280 ident %2X detected!\n",
+ __func__, adv7280_data.rev_id);
+ break;
+ default:
+ dev_err(dev,
+ "%s:Analog Device adv7280 not detected %d!\n", __func__,
+ adv7280_data.rev_id);
+ return -ENODEV;
+
+ }
+
+ dev_dbg(dev, " type is %d (expect %d)\n",
+ adv7280_int_device.type, v4l2_int_type_slave);
+ dev_dbg(dev, " num ioctls is %d\n",
+ adv7280_int_device.u.slave->num_ioctls);
+
+ ret = adv7280_hard_reset();
+ if (ret) {
+ dev_err(dev, "error resetting adv7280\n");
+ return ret;
+ }
+
+ /* This function attaches this structure to the /dev/video0 device.
+ * The pointer in priv points to the adv7280_data structure here.*/
+ adv7280_int_device.priv = &adv7280_data;
+ ret = v4l2_int_device_register(&adv7280_int_device);
+
+ clk_disable_unprepare(adv7280_data.sen.sensor_clk);
+
+ return 0;
+}
+
+static int adv7280_detach(struct i2c_client *client)
+{
+ dev_dbg(&adv7280_data.sen.i2c_client->dev,
+ "%s:Removing %s video decoder @ 0x%02X from adapter %s\n",
+ __func__, IF_NAME, client->addr << 1, client->adapter->name);
+
+ adv7280_write_reg(ADV7280_POWER_MANAGEMENT, 0x24);
+
+ if (dvddio_regulator)
+ regulator_disable(dvddio_regulator);
+
+ if (dvdd_regulator)
+ regulator_disable(dvdd_regulator);
+
+ if (avdd_regulator)
+ regulator_disable(avdd_regulator);
+
+ if (pvdd_regulator)
+ regulator_disable(pvdd_regulator);
+
+ v4l2_int_device_unregister(&adv7280_int_device);
+
+ return 0;
+}
+
+static const struct i2c_device_id adv7280_id[] = {
+ {"adv7280", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, adv7280_id);
+
+static struct i2c_driver adv7280_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "adv7280",
+ },
+ .probe = adv7280_probe,
+ .remove = adv7280_detach,
+ .id_table = adv7280_id,
+};
+module_i2c_driver(adv7280_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Analog Device ADV7280 video decoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/ipu_csi_enc.c b/drivers/media/platform/mxc/capture/ipu_csi_enc.c
index 241c744bfcb0..0b722ed4c3e3 100644
--- a/drivers/media/platform/mxc/capture/ipu_csi_enc.c
+++ b/drivers/media/platform/mxc/capture/ipu_csi_enc.c
@@ -255,7 +255,7 @@ static int csi_enc_enabling_tasks(void *private)
err = ipu_request_irq(
cam->ipu, irq, csi_enc_callback, 0, "Mxc Camera", cam);
if (err != 0) {
- printk(KERN_ERR "Error registering rot irq\n");
+ pr_err("%s: Error requesting IPU_IRQ_CSI0_OUT_EOF\n", __func__);
return err;
}
diff --git a/drivers/media/platform/mxc/capture/ipu_prp_enc.c b/drivers/media/platform/mxc/capture/ipu_prp_enc.c
index d1e1def371e5..8e361dcded08 100644
--- a/drivers/media/platform/mxc/capture/ipu_prp_enc.c
+++ b/drivers/media/platform/mxc/capture/ipu_prp_enc.c
@@ -377,6 +377,7 @@ static int prp_enc_enabling_tasks(void *private)
{
cam_data *cam = (cam_data *) private;
int err = 0;
+ int irq;
CAMERA_TRACE("IPU:In prp_enc_enabling_tasks\n");
cam->dummy_frame.vaddress = dma_alloc_coherent(cam->dev,
@@ -393,15 +394,12 @@ static int prp_enc_enabling_tasks(void *private)
PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
- if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
- err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF,
- prp_enc_callback, 0, "Mxc Camera", cam);
- } else {
- err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF,
- prp_enc_callback, 0, "Mxc Camera", cam);
- }
- if (err != 0) {
- printk(KERN_ERR "Error registering rot irq\n");
+ irq = (cam->rotation >= IPU_ROTATE_90_RIGHT) ?
+ IPU_IRQ_PRP_ENC_ROT_OUT_EOF : IPU_IRQ_PRP_ENC_OUT_EOF;
+ err = ipu_request_irq(cam->ipu, irq,
+ prp_enc_callback, 0, "Mxc Camera", cam);
+ if (err) {
+ pr_err("%s: Error requesting irq=%d\n", __func__, irq);
return err;
}
diff --git a/drivers/media/platform/mxc/capture/max9526.c b/drivers/media/platform/mxc/capture/max9526.c
new file mode 100644
index 000000000000..06242b727ca2
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/max9526.c
@@ -0,0 +1,1153 @@
+/*
+ * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2015 Toradex AG All Rights Reserved.
+ * copied and adapted from adv7180.c
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file max9526.c
+ *
+ * @brief Maxim Integrated MAX9526 video decoder functions
+ *
+ * @ingroup Camera
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-chip-ident.h>
+#include "v4l2-int-device.h"
+#include "mxc_v4l2_capture.h"
+
+#if 0
+#undef dev_dbg
+#define dev_dbg(dev, format, arg...) {dev_printk(KERN_ERR, dev, format, ##arg);}
+#undef pr_debug
+#define pr_debug(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#define MAX9526_VOLTAGE_ANALOG 1800000
+#define MAX9526_VOLTAGE_DIGITAL_CORE 1800000
+#define MAX9526_VOLTAGE_DIGITAL_IO 3300000
+#define MAX9526_VOLTAGE_PLL 1800000
+
+static struct regulator *dvddio_regulator;
+static struct regulator *dvdd_regulator;
+static struct regulator *avdd_regulator;
+
+static int max9526_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *id);
+static int max9526_detach(struct i2c_client *client);
+
+static const struct i2c_device_id max9526_id[] = {
+ {"max9526", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, max9526_id);
+
+static struct i2c_driver max9526_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "max9526",
+ },
+ .probe = max9526_probe,
+ .remove = max9526_detach,
+ .id_table = max9526_id,
+};
+
+/*!
+ * Maintains the information on the current state of the sensor.
+ */
+struct sensor {
+ struct sensor_data sen;
+ v4l2_std_id std_id;
+} max9526_data;
+
+
+/*! List of input video formats supported. The video formats is corresponding
+ * with v4l2 id in video_fmt_t
+ */
+typedef enum {
+ MAX9526_NTSC = 0, /*!< Locked on (M) NTSC video signal. */
+ MAX9526_PAL, /*!< (B, G, H, I, N)PAL video signal. */
+ MAX9526_NOT_LOCKED, /*!< Not locked on a signal. */
+} video_fmt_idx;
+
+/*! Number of video standards supported (including 'not locked' signal). */
+#define MAX9526_STD_MAX (MAX9526_PAL + 1)
+
+/*! Video format structure. */
+typedef struct {
+ int v4l2_id; /*!< Video for linux ID. */
+ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */
+ u16 raw_width; /*!< Raw width. */
+ u16 raw_height; /*!< Raw height. */
+ u16 active_width; /*!< Active width. */
+ u16 active_height; /*!< Active height. */
+} video_fmt_t;
+
+/*! Description of video formats supported.
+ *
+ * PAL: raw=720x625, active=720x576.
+ * NTSC: raw=720x525, active=720x480.
+ */
+static video_fmt_t video_fmts[] = {
+ { /*! NTSC */
+ .v4l2_id = V4L2_STD_NTSC,
+ .name = "NTSC",
+ .raw_width = 720, /* SENS_FRM_WIDTH */
+ .raw_height = 525, /* SENS_FRM_HEIGHT */
+ .active_width = 720, /* ACT_FRM_WIDTH plus 1 */
+ .active_height = 480, /* ACT_FRM_WIDTH plus 1 */
+ },
+ { /*! (B, G, H, I, N) PAL */
+ .v4l2_id = V4L2_STD_PAL,
+ .name = "PAL",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ },
+ { /*! Unlocked standard */
+ .v4l2_id = V4L2_STD_ALL,
+ .name = "Autodetect",
+ .raw_width = 720,
+ .raw_height = 625,
+ .active_width = 720,
+ .active_height = 576,
+ },
+};
+
+/*!* Standard index of MAX9526. */
+static video_fmt_idx video_idx = MAX9526_PAL;
+
+/*! @brief This mutex is used to provide mutual exclusion.
+ *
+ * Create a mutex that can be used to provide mutually exclusive
+ * read/write access to the globally accessible data structures
+ * and variables that were defined above.
+ */
+static DEFINE_MUTEX(mutex);
+
+#define IF_NAME "max9526"
+/* registers */
+#define REG_STATUS_0 0x00
+#define REG_STATUS_1 0x01
+#define REG_IRQMASK_0 0x02
+#define REG_IRQMASK_1 0x03
+#define REG_STANDARD_SELECT_SHUTDOWN_CONTROL 0x04
+#define REG_CONTRAST 0x05
+#define REG_BRIGHTNESS 0x06
+#define REG_HUE 0x07
+#define REG_SATURATION 0x08
+#define REG_VIDEO_INPUT_SELECT_AND_CLAMP 0x09
+#define REG_GAIN_CONTROL 0x0A
+#define REG_COLOR_KILL 0x0B
+#define REG_OUTPUT_TEST_SIGNAL 0x0C
+#define REG_CLOCK_AND_OUTPUT 0x0D
+#define REG_PLL_CONTROL 0x0E
+#define REG_MISCELLANEOUS 0x0F
+
+#define I2C_RETRY_COUNT 5
+
+/* supported controls */
+/* This hasn't been fully implemented yet.
+ * This is how it should work, though. */
+static struct v4l2_queryctrl max9526_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0, /* check this value */
+ .maximum = 255, /* check this value */
+ .step = 1, /* check this value */
+ .default_value = 127, /* check this value */
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0, /* check this value */
+ .maximum = 255, /* check this value */
+ .step = 0x1, /* check this value */
+ .default_value = 127, /* check this value */
+ .flags = 0,
+ }
+};
+
+static inline void max9526_power_down(int enable)
+{
+}
+
+static int max9526_regulator_enable(struct device *dev)
+{
+ int ret = 0;
+
+ dvddio_regulator = devm_regulator_get(dev, "DVDDIO");
+
+ if (!IS_ERR(dvddio_regulator)) {
+ regulator_set_voltage(dvddio_regulator,
+ MAX9526_VOLTAGE_DIGITAL_IO,
+ MAX9526_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(dvddio_regulator);
+ if (ret) {
+ dev_err(dev, "set io voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set io voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get io voltage\n");
+ }
+
+ dvdd_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(dvdd_regulator)) {
+ regulator_set_voltage(dvdd_regulator,
+ MAX9526_VOLTAGE_DIGITAL_CORE,
+ MAX9526_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(dvdd_regulator);
+ if (ret) {
+ dev_err(dev, "set core voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set core voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get core voltage\n");
+ }
+
+ avdd_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(avdd_regulator)) {
+ regulator_set_voltage(avdd_regulator,
+ MAX9526_VOLTAGE_ANALOG,
+ MAX9526_VOLTAGE_ANALOG);
+ ret = regulator_enable(avdd_regulator);
+ if (ret) {
+ dev_err(dev, "set analog voltage failed\n");
+ return ret;
+ } else {
+ dev_dbg(dev, "set analog voltage ok\n");
+ }
+ } else {
+ dev_warn(dev, "cannot get analog voltage\n");
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * I2C transfert.
+ ***********************************************************************/
+
+/*! Read one register from a MAX9526 i2c slave device.
+ *
+ * @param *reg register in the device we wish to access.
+ *
+ * @return 0 if success, an error code otherwise.
+ */
+static inline int __max9526_read__(u8 reg)
+{
+ int val;
+ unsigned retry = 0;
+
+ do {
+ val = i2c_smbus_read_byte_data(max9526_data.sen.i2c_client, reg);
+ if (val < 0) {
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:read reg error: reg=%2x, retry %u\n", __func__, reg, retry);
+ val = -1;
+ i2c_recover_bus(max9526_data.sen.i2c_client->adapter);
+ }
+ } while ((val < 0) && (++retry < I2C_RETRY_COUNT));
+
+ if (val < 0) {
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:read reg ERROR:reg=%2x,val=%2x\n", __func__,
+ reg, val);
+ }
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:read reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
+
+ return val;
+}
+static inline int max9526_read(u8 reg)
+{
+ int val, last_val;
+ unsigned retry = 0;
+
+ last_val = __max9526_read__(reg);
+
+ do {
+ val = __max9526_read__(reg);
+ if (val != last_val) {
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:read reg error: reg=%2x, retry %u\n", __func__, reg, retry);
+ last_val = val;
+ val = -1;
+ msleep(1);
+ }
+ } while ((val == -1) && (++retry < I2C_RETRY_COUNT));
+ return val;
+}
+/*! Write one register of a MAX9526 i2c slave device.
+ *
+ * @param *reg register in the device we wish to access.
+ *
+ * @return 0 if success, an error code otherwise.
+ */
+static int max9526_write_reg(u8 reg, u8 val)
+{
+ s32 ret = 0;
+ unsigned retry = 0;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:write reg 0x%2x, val: 0x%2x\n", __func__, reg, val);
+
+ do {
+ ret = i2c_smbus_write_byte_data(max9526_data.sen.i2c_client, reg, val);
+ if (ret < 0) {
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:write reg error:reg=%2x,val=%2x, retry %u\n", __func__,
+ reg, val, retry+1);
+ ret = -1;
+ i2c_recover_bus(max9526_data.sen.i2c_client->adapter);
+ }
+ } while ((ret < 0) && (++retry < I2C_RETRY_COUNT));
+
+ if (ret < 0) {
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:write reg ERROR:reg=%2x,val=%2x\n", __func__,
+ reg, val);
+ }
+
+ return ret;
+}
+
+/***********************************************************************
+ * mxc_v4l2_capture interface.
+ ***********************************************************************/
+
+/*!
+ * Return attributes of current video standard.
+ * Since this device autodetects the current standard, this function also
+ * sets the values that need to be changed if the standard changes.
+ * There is no set std equivalent function.
+ *
+ * @return None.
+ */
+static void max9526_get_std(v4l2_std_id *std)
+{
+ int tmp = 0;
+ int idx;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526_get_std\n");
+
+ /* reset the status flag to get current state */
+#if 0
+ (void) max9526_read(REG_STATUS_0);
+ msleep(1);
+ tmp = max9526_read(REG_STATUS_0) & 0x1;
+#endif
+ tmp |= max9526_read(REG_STATUS_1) & 0x40;
+
+ mutex_lock(&mutex);
+ if (tmp == 0x0) {
+ /* PAL */
+ *std = V4L2_STD_PAL;
+ idx = MAX9526_PAL;
+ } else if (tmp == 0x40) {
+ /*NTSC*/
+ *std = V4L2_STD_NTSC;
+ idx = MAX9526_NTSC;
+ } else {
+ *std = V4L2_STD_ALL;
+ idx = MAX9526_NOT_LOCKED;
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "Got invalid video standard!\n");
+ }
+ mutex_unlock(&mutex);
+
+ /* This assumes autodetect which this device uses. */
+ if (*std != max9526_data.std_id) {
+ video_idx = idx;
+ max9526_data.std_id = *std;
+ max9526_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ max9526_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ }
+}
+
+/***********************************************************************
+ * IOCTL Functions from v4l2_int_ioctl_desc.
+ ***********************************************************************/
+
+/*!
+ * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
+ * s: pointer to standard V4L2 device structure
+ * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
+ *
+ * Gets slave interface parameters.
+ * Calculates the required xclk value to support the requested
+ * clock parameters in p. This value is returned in the p
+ * parameter.
+ *
+ * vidioc_int_g_ifparm returns platform-specific information about the
+ * interface settings used by the sensor.
+ *
+ * Called on open.
+ */
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "max9526:ioctl_g_ifparm\n");
+
+ if (s == NULL) {
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ /* Initialize structure to 0s then set any non-0 values. */
+ memset(p, 0, sizeof(*p));
+ p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */
+#if 0
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.nobt_hs_inv = 1;
+ p->u.bt656.bt_sync_correct = 1;
+#elif 0
+//working for PAL
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.nobt_hs_inv = 0;
+ p->u.bt656.bt_sync_correct = 0;
+ p->u.bt656.clock_curr = 0; //BT656 interlace clock mode
+#else
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_BT_8BIT;
+ p->u.bt656.nobt_hs_inv = 1;
+ p->u.bt656.nobt_vs_inv = 1;
+ p->u.bt656.bt_sync_correct = 0;
+ p->u.bt656.clock_curr = 0; //BT656 interlace clock mode
+#endif
+ /* MAX9526 has a dedicated clock so no clock settings needed. */
+
+ return 0;
+}
+
+/*!
+ * Sets the camera power.
+ *
+ * s pointer to the camera device
+ * on if 1, power is to be turned on. 0 means power is to be turned off
+ *
+ * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num
+ * @s: pointer to standard V4L2 device structure
+ * @on: power state to which device is to be set
+ *
+ * Sets devices power state to requrested state, if possible.
+ * This is called on open, close, suspend and resume.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor *sensor = s->priv;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "max9526:ioctl_s_power\n");
+
+ if (on && !sensor->sen.on) {
+ if (max9526_write_reg(REG_STANDARD_SELECT_SHUTDOWN_CONTROL, 0x10) != 0)
+ return -EIO;
+
+ /*
+ * FIXME:Additional 400ms to wait the chip to be stable?
+ * This is a workaround for preview scrolling issue.
+ * Taken from ADV7180, really needed on MAX9526??
+ */
+ msleep(400);
+
+ } else if (!on && sensor->sen.on) {
+ if (max9526_write_reg(REG_STANDARD_SELECT_SHUTDOWN_CONTROL, 0x18) != 0)
+ return -EIO;
+ }
+
+ sensor->sen.on = on;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526:ioctl_g_parm\n");
+
+ switch (a->type) {
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->sen.streamcap.capability;
+ cparm->timeperframe = sensor->sen.streamcap.timeperframe;
+ cparm->capturemode = sensor->sen.streamcap.capturemode;
+ break;
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ break;
+
+ default:
+ pr_debug("ioctl_g_parm:type is unknown %d\n", a->type);
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ *
+ * This driver cannot change these settings.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526:ioctl_s_parm\n");
+
+ switch (a->type) {
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ struct sensor *sensor = s->priv;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "max9526:ioctl_g_fmt_cap\n");
+ //dump_stack();
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" Returning size of %dx%d\n",
+ sensor->sen.pix.width, sensor->sen.pix.height);
+ f->fmt.pix = sensor->sen.pix;
+ break;
+
+ case V4L2_BUF_TYPE_PRIVATE: {
+ v4l2_std_id std;
+ max9526_get_std(&std);
+ f->fmt.pix.pixelformat = (u32)std;
+ }
+ break;
+
+ default:
+ f->fmt.pix = sensor->sen.pix;
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control information
+ * from the video_control[] array. Otherwise, returns -EINVAL if the
+ * control is not supported.
+ */
+static int ioctl_queryctrl(struct v4l2_int_device *s,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "max9526:ioctl_queryctrl\n");
+
+ for (i = 0; i < ARRAY_SIZE(max9526_qctrl); i++)
+ if (qc->id && qc->id == max9526_qctrl[i].id) {
+ memcpy(qc, &(max9526_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+ int sat = 0;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526:ioctl_g_ctrl\n");
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_BRIGHTNESS\n");
+ max9526_data.sen.brightness = max9526_read(REG_BRIGHTNESS);
+ vc->value = max9526_data.sen.brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_CONTRAST\n");
+ vc->value = max9526_data.sen.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_SATURATION\n");
+ sat = max9526_read(REG_SATURATION);
+ max9526_data.sen.saturation = sat;
+ vc->value = max9526_data.sen.saturation;
+ break;
+ case V4L2_CID_HUE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_HUE\n");
+ vc->value = max9526_data.sen.hue;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_RED_BALANCE\n");
+ vc->value = max9526_data.sen.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_BLUE_BALANCE\n");
+ vc->value = max9526_data.sen.blue;
+ break;
+ case V4L2_CID_GAMMA:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_EXPOSURE\n");
+ vc->value = max9526_data.sen.ae_mode;
+ break;
+ case V4L2_CID_AUTOGAIN:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_VFLIP\n");
+ break;
+ default:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " Default case\n");
+ vc->value = 0;
+ ret = -EPERM;
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+ u8 tmp;
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526:ioctl_s_ctrl\n");
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_BRIGHTNESS\n");
+ tmp = vc->value;
+ max9526_write_reg(REG_BRIGHTNESS, tmp);
+ max9526_data.sen.brightness = vc->value;
+ break;
+ case V4L2_CID_CONTRAST:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_CONTRAST\n");
+ break;
+ case V4L2_CID_SATURATION:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_SATURATION\n");
+ tmp = vc->value;
+ max9526_write_reg(REG_SATURATION, tmp);
+ max9526_data.sen.saturation = vc->value;
+ break;
+ case V4L2_CID_HUE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_HUE\n");
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_RED_BALANCE\n");
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_BLUE_BALANCE\n");
+ break;
+ case V4L2_CID_GAMMA:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_EXPOSURE\n");
+ break;
+ case V4L2_CID_AUTOGAIN:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " V4L2_CID_VFLIP\n");
+ break;
+ default:
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ " Default case\n");
+ retval = -EPERM;
+ break;
+ }
+
+ return retval;
+}
+
+/*!
+ * ioctl_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index >= 1)
+ return -EINVAL;
+
+ fsize->discrete.width = video_fmts[video_idx].active_width;
+ fsize->discrete.height = video_fmts[video_idx].active_height;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ * VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+ "max9526_decoder");
+ ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_AMBIGUOUS;
+
+ return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526:ioctl_init\n");
+ return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "max9526:ioctl_dev_init\n");
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module.
+ */
+static struct v4l2_int_ioctl_desc max9526_ioctl_desc[] = {
+
+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init},
+
+ /*!
+ * Delinitialise the dev. at slave detach.
+ * The complement of ioctl_dev_init.
+ */
+/* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */
+
+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power},
+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm},
+/* {vidioc_int_g_needs_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
+/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
+ {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init},
+
+ /*!
+ * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
+ */
+/* {vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */
+
+ /*!
+ * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
+ * This ioctl is used to negotiate the image capture size and
+ * pixel format without actually making it take effect.
+ */
+/* {vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
+
+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap},
+
+ /*!
+ * If the requested format is supported, configures the HW to use that
+ * format, returns error code if format not supported or HW can't be
+ * correctly configured.
+ */
+/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
+
+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm},
+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm},
+ {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl},
+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl},
+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl},
+ {vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_framesizes},
+ {vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave max9526_slave = {
+ .ioctls = max9526_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(max9526_ioctl_desc),
+};
+
+static struct v4l2_int_device max9526_int_device = {
+ .module = THIS_MODULE,
+ .name = "max9526",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &max9526_slave,
+ },
+};
+
+
+/***********************************************************************
+ * I2C client and driver.
+ ***********************************************************************/
+
+/*! MAX9526 Reset function.
+ *
+ * @return None.
+ */
+static void max9526_hard_reset(void)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "In max9526:max9526_hard_reset\n");
+
+ /* System Reset */
+ max9526_write_reg(REG_STANDARD_SELECT_SHUTDOWN_CONTROL, 0x04);
+ msleep(10);
+
+ /* Delta to Datasheet poweron state */
+ max9526_write_reg(REG_STANDARD_SELECT_SHUTDOWN_CONTROL, 0x18); /* shutdown */
+ max9526_write_reg(REG_VIDEO_INPUT_SELECT_AND_CLAMP, 0x82); /* autom. input sel. */
+ max9526_write_reg(REG_OUTPUT_TEST_SIGNAL, 0x03); /* select 100% color bars */
+ max9526_write_reg(REG_CLOCK_AND_OUTPUT, 0x04); /* Output HSync/Vsync */
+ max9526_write_reg(REG_MISCELLANEOUS, 0x14); /* Output HSync/Vsync */
+}
+
+/*! MAX9526 I2C attach function.
+ *
+ * @param *adapter struct i2c_adapter *.
+ *
+ * @return Error code indicating success or failure.
+ */
+
+/*!
+ * MAX9526 I2C probe function.
+ * Function set in i2c_driver struct.
+ * Called by insmod.
+ *
+ * @param *adapter I2C adapter descriptor.
+ *
+ * @return Error code indicating success or failure.
+ */
+static int max9526_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret = 0;
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+
+ dev_dbg(dev, "%s sensor data is at %p\n", __func__, &max9526_data);
+
+ /* Set initial values for the sensor struct. */
+ memset(&max9526_data, 0, sizeof(max9526_data));
+ max9526_data.sen.i2c_client = client;
+ max9526_data.sen.streamcap.timeperframe.denominator = 30;
+ max9526_data.sen.streamcap.timeperframe.numerator = 1;
+ max9526_data.std_id = V4L2_STD_ALL;
+ video_idx = MAX9526_NOT_LOCKED;
+ max9526_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ max9526_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ max9526_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */
+ max9526_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
+ max9526_data.sen.on = false;
+
+ max9526_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(max9526_data.sen.sensor_clk)) {
+ dev_err(dev, "get mclk failed\n");
+ return PTR_ERR(max9526_data.sen.sensor_clk);
+ }
+
+ ret = of_property_read_u32(dev->of_node, "mclk",
+ &max9526_data.sen.mclk);
+ if (ret) {
+ dev_err(dev, "mclk frequency is invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(
+ dev->of_node, "mclk_source",
+ (u32 *) &(max9526_data.sen.mclk_source));
+ if (ret) {
+ dev_err(dev, "mclk_source invalid\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "csi_id",
+ &(max9526_data.sen.csi));
+ if (ret) {
+ dev_err(dev, "csi_id invalid\n");
+ return ret;
+ }
+
+ /* MAX9526 is always parallel IF */
+ max9526_data.sen.mipi_camera = 0;
+
+ clk_prepare_enable(max9526_data.sen.sensor_clk);
+
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:max9526 probe i2c address is 0x%02X\n",
+ __func__, max9526_data.sen.i2c_client->addr);
+
+ /*! Read a register to test I2C device address */
+ ret = max9526_read(REG_MISCELLANEOUS) & 0xd0;
+ if(ret != 0x10) {
+ /* if the first read fails, that might go undetected */
+ ret = max9526_read(REG_MISCELLANEOUS) & 0xd0;
+ if(ret != 0x10) {
+ dev_err(dev, "Device seems not to be a MAX9526\n");
+ return -ENODEV;
+ }
+ }
+
+ /* MAX9526 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(dev, "setup pinctrl failed\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ max9526_regulator_enable(dev);
+
+ max9526_power_down(0);
+
+ msleep(1);
+
+ /*! MAX9526 initialization. */
+ max9526_hard_reset();
+
+ pr_debug(" type is %d (expect %d)\n",
+ max9526_int_device.type, v4l2_int_type_slave);
+ pr_debug(" num ioctls is %d\n",
+ max9526_int_device.u.slave->num_ioctls);
+
+ /* This function attaches this structure to the /dev/video0 device.
+ * The pointer in priv points to the max9526_data structure here.*/
+ max9526_int_device.priv = &max9526_data;
+ ret = v4l2_int_device_register(&max9526_int_device);
+
+ clk_disable_unprepare(max9526_data.sen.sensor_clk);
+
+ return ret;
+}
+
+/*!
+ * MAX9526 I2C detach function.
+ * Called on rmmod.
+ *
+ * @param *client struct i2c_client*.
+ *
+ * @return Error code indicating success or failure.
+ */
+static int max9526_detach(struct i2c_client *client)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev,
+ "%s:Removing %s video decoder @ 0x%02X from adapter %s\n",
+ __func__, IF_NAME, client->addr << 1, client->adapter->name);
+
+ /* Power down via i2c */
+ max9526_write_reg(REG_STANDARD_SELECT_SHUTDOWN_CONTROL, 0x18);
+
+ if (dvddio_regulator)
+ regulator_disable(dvddio_regulator);
+
+ if (dvdd_regulator)
+ regulator_disable(dvdd_regulator);
+
+ if (avdd_regulator)
+ regulator_disable(avdd_regulator);
+
+ v4l2_int_device_unregister(&max9526_int_device);
+
+ return 0;
+}
+
+/*!
+ * MAX9526 init function.
+ * Called on insmod.
+ *
+ * @return Error code indicating success or failure.
+ */
+static __init int max9526_init(void)
+{
+ u8 err = 0;
+
+ pr_debug("In max9526_init\n");
+
+ /* Tells the i2c driver what functions to call for this driver. */
+ err = i2c_add_driver(&max9526_i2c_driver);
+ if (err != 0)
+ pr_err("%s:driver registration failed, error=%d\n",
+ __func__, err);
+
+ return err;
+}
+
+/*!
+ * MAX9526 cleanup function.
+ * Called on rmmod.
+ *
+ * @return Error code indicating success or failure.
+ */
+static void __exit max9526_clean(void)
+{
+ dev_dbg(&max9526_data.sen.i2c_client->dev, "In max9526_clean\n");
+ i2c_del_driver(&max9526_i2c_driver);
+}
+
+module_init(max9526_init);
+module_exit(max9526_clean);
+
+MODULE_AUTHOR("max.krummenacher@toradex.com");
+MODULE_DESCRIPTION("Maxim Integrated MAX9526 video decoder driver for i.MX6");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mxc/capture/mxc_mipi_csi.c b/drivers/media/platform/mxc/capture/mxc_mipi_csi.c
index a35563cf5130..95a060691176 100644
--- a/drivers/media/platform/mxc/capture/mxc_mipi_csi.c
+++ b/drivers/media/platform/mxc/capture/mxc_mipi_csi.c
@@ -954,9 +954,13 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
&state->max_num_lanes))
return -EINVAL;
- node = of_graph_get_next_endpoint(node, NULL);
+ /*
+ * Explicitly get endpoint 1 being the sensor one as using overlays may
+ * reverse node order in the final device tree blob.
+ */
+ node = of_graph_get_endpoint_by_regs(node, 0, 1);
if (!node) {
- dev_err(&pdev->dev, "No port node at %s\n",
+ dev_err(&pdev->dev, "No port/endpoint 1 sensor node at %s\n",
pdev->dev.of_node->full_name);
return -EINVAL;
}
@@ -988,38 +992,39 @@ static const struct v4l2_async_notifier_operations mxc_mipi_csi_subdev_ops = {
static int mipi_csis_subdev_host(struct csi_state *state)
{
struct device_node *parent = state->dev->of_node;
- struct device_node *node, *port, *rem;
+ struct device_node *node, *rem;
int ret;
v4l2_async_notifier_init(&state->subdev_notifier);
- /* Attach sensors linked to csi receivers */
- for_each_available_child_of_node(parent, node) {
- if (of_node_cmp(node->name, "port"))
- continue;
-
- /* The csi node can have only port subnode. */
- port = of_get_next_child(node, NULL);
- if (!port)
- continue;
- rem = of_graph_get_remote_port_parent(port);
- of_node_put(port);
- if (rem == NULL) {
- v4l2_info(&state->v4l2_dev,
- "Remote device at %s not found\n",
- port->full_name);
- return -1;
- }
-
- INIT_LIST_HEAD(&state->asd.list);
- state->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
- state->asd.match.fwnode = of_fwnode_handle(rem);
- state->async_subdevs[0] = &state->asd;
+ /*
+ * Explicitly get endpoint 1 being the sensor one as using overlays may
+ * reverse node order in the final device tree blob.
+ */
+ node = of_graph_get_endpoint_by_regs(parent, 0, 1);
+ if (node == NULL) {
+ v4l2_info(&state->v4l2_dev,
+ "Port at %s not found\n",
+ parent->full_name);
+ return -1;
+ }
- of_node_put(rem);
- break;
+ rem = of_graph_get_remote_port_parent(node);
+ of_node_put(node);
+ if (rem == NULL) {
+ v4l2_info(&state->v4l2_dev,
+ "Remote device at %s not found\n",
+ node->full_name);
+ return -1;
}
+ INIT_LIST_HEAD(&state->asd.list);
+ state->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
+ state->asd.match.fwnode = of_fwnode_handle(rem);
+ state->async_subdevs[0] = &state->asd;
+
+ of_node_put(rem);
+
v4l2_async_notifier_add_subdev(&state->subdev_notifier,
&state->asd);
state->subdev_notifier.v4l2_dev = &state->v4l2_dev;
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
index 936514db9944..4fdec11be414 100644
--- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
@@ -27,8 +27,12 @@
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/mutex.h>
#include <linux/mxcfb.h>
#include <linux/of_device.h>
+#include <linux/regmap.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
@@ -37,6 +41,13 @@
#include "mxc_v4l2_capture.h"
#include "ipu_prp_sw.h"
+#if 0
+#undef dev_dbg
+#define dev_dbg(dev, format, arg...) {dev_printk(KERN_ERR, dev, format, ##arg);}
+#undef pr_debug
+#define pr_debug(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
#define init_MUTEX(sem) sema_init(sem, 1)
static struct platform_device_id imx_v4l2_devtype[] = {
@@ -986,7 +997,7 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->bright = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_BRIGHTNESS\n");
status = -ENODEV;
}
break;
@@ -996,7 +1007,7 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->hue = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_HUE\n");
status = -ENODEV;
}
break;
@@ -1006,7 +1017,7 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->contrast = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_CONTRAST\n");
status = -ENODEV;
}
break;
@@ -1016,7 +1027,7 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->saturation = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_SATURATION\n");
status = -ENODEV;
}
break;
@@ -1026,7 +1037,7 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->red = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_RED_BALANCE\n");
status = -ENODEV;
}
break;
@@ -1036,7 +1047,7 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->blue = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_BLUE_BALANCE\n");
status = -ENODEV;
}
break;
@@ -1046,12 +1057,12 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c)
status = vidioc_int_g_ctrl(cam->sensor, c);
cam->ae_mode = c->value;
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_BLACK_LEVEL\n");
status = -ENODEV;
}
break;
default:
- pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n");
+ pr_debug("ERROR: v4l2 capture: unsupported ioctrl!\n");
}
return status;
@@ -1156,7 +1167,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->hue = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_HUE\n");
ret = -ENODEV;
}
break;
@@ -1165,7 +1176,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->contrast = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_CONTRAST\n");
ret = -ENODEV;
}
break;
@@ -1174,7 +1185,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->bright = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_BRIGHTNESS\n");
ret = -ENODEV;
}
break;
@@ -1183,7 +1194,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->saturation = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_SATURATION\n");
ret = -ENODEV;
}
break;
@@ -1192,7 +1203,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->red = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_RED_BALANCE\n");
ret = -ENODEV;
}
break;
@@ -1201,7 +1212,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->blue = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_BLUE_BALANCE\n");
ret = -ENODEV;
}
break;
@@ -1210,7 +1221,7 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
cam->ae_mode = c->value;
ret = vidioc_int_s_ctrl(cam->sensor, c);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_EXPOSURE\n");
ret = -ENODEV;
}
break;
@@ -1340,6 +1351,8 @@ static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr);
if (ifparm.u.bt656.clock_curr == 0)
csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
+ else if (ifparm.u.bt656.clock_curr == 1)
+ csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
else
csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
@@ -1548,6 +1561,39 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
return retval;
}
+static void power_down_callback(struct work_struct *work)
+{
+ cam_data *cam = container_of(work, struct _cam_data, power_down_work.work);
+
+ down(&cam->busy_lock);
+ if (!cam->open_count) {
+ vidioc_int_s_power(cam->sensor, 0);
+ cam->power_on = 0;
+ }
+ up(&cam->busy_lock);
+}
+
+/* cam->busy_lock is held */
+void power_up_camera(cam_data *cam)
+{
+ if (cam->power_on) {
+ cancel_delayed_work(&cam->power_down_work);
+ return;
+ }
+ vidioc_int_s_power(cam->sensor, 1);
+ vidioc_int_init(cam->sensor);
+ vidioc_int_dev_init(cam->sensor);
+ cam->power_on = 1;
+}
+
+
+void power_off_camera(cam_data *cam)
+{
+ schedule_delayed_work(&cam->power_down_work, (HZ * 2));
+}
+
+unsigned long csi_in_use;
+
/*!
* V4L interface - open function
*
@@ -1565,6 +1611,7 @@ static int mxc_v4l_open(struct file *file)
cam_data *cam = video_get_drvdata(dev);
int err = 0;
struct sensor_data *sensor;
+ int csi_bit;
pr_debug("\nIn MVC: mxc_v4l_open\n");
pr_debug(" device name is %s\n", dev->name);
@@ -1577,7 +1624,7 @@ static int mxc_v4l_open(struct file *file)
if (cam->sensor == NULL ||
cam->sensor->type != v4l2_int_type_slave) {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! V4L2_CID_HUE\n");
return -EAGAIN;
}
@@ -1589,11 +1636,45 @@ static int mxc_v4l_open(struct file *file)
}
down(&cam->busy_lock);
+
err = 0;
if (signal_pending(current))
goto oops;
if (cam->open_count++ == 0) {
+ struct regmap *gpr;
+
+ csi_bit = (cam->ipu_id << 1) | cam->csi;
+ if (test_and_set_bit(csi_bit, &csi_in_use)) {
+ pr_err("%s: %s CSI already in use\n", __func__, dev->name);
+ err = -EBUSY;
+ cam->open_count = 0;
+ goto oops;
+ }
+ cam->csi_in_use = 1;
+
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (!IS_ERR(gpr)) {
+ if (of_machine_is_compatible("fsl,imx6q")) {
+ if (cam->ipu_id == cam->csi) {
+ unsigned shift = 19 + cam->csi;
+ unsigned mask = 1 << shift;
+ unsigned val = (cam->mipi_camera ? 0 : 1) << shift;
+
+ regmap_update_bits(gpr, IOMUXC_GPR1, mask, val);
+ }
+ } else if (of_machine_is_compatible("fsl,imx6dl")) {
+ unsigned shift = cam->csi * 3;
+ unsigned mask = 7 << shift;
+ unsigned val = (cam->mipi_camera ? csi_bit : 4) << shift;
+
+ regmap_update_bits(gpr, IOMUXC_GPR13, mask, val);
+ }
+ } else {
+ pr_err("%s: failed to find fsl,imx6q-iomux-gpr regmap\n",
+ __func__);
+ }
+
wait_event_interruptible(cam->power_queue,
cam->low_power == false);
@@ -1691,9 +1772,7 @@ static int mxc_v4l_open(struct file *file)
cam_fmt.fmt.pix.pixelformat,
csi_param);
clk_prepare_enable(sensor->sensor_clk);
- vidioc_int_s_power(cam->sensor, 1);
- vidioc_int_init(cam->sensor);
- vidioc_int_dev_init(cam->sensor);
+ power_up_camera(cam);
}
file->private_data = dev;
@@ -1750,7 +1829,6 @@ static int mxc_v4l_close(struct file *file)
}
if (--cam->open_count == 0) {
- vidioc_int_s_power(cam->sensor, 0);
clk_disable_unprepare(sensor->sensor_clk);
wait_event_interruptible(cam->power_queue,
cam->low_power == false);
@@ -1775,6 +1853,14 @@ static int mxc_v4l_close(struct file *file)
wake_up_interruptible(&cam->enc_queue);
mxc_free_frames(cam);
cam->enc_counter++;
+ power_off_camera(cam);
+
+ if (cam->csi_in_use) {
+ int csi_bit = (cam->ipu_id << 1) | cam->csi;
+
+ clear_bit(csi_bit, &csi_in_use);
+ cam->csi_in_use = 0;
+ }
}
up(&cam->busy_lock);
@@ -2219,7 +2305,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->sensor)
retval = vidioc_int_g_parm(cam->sensor, parm);
else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_G_PARM\n");
retval = -ENODEV;
}
break;
@@ -2231,7 +2317,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->sensor)
retval = mxc_v4l2_s_param(cam, parm);
else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_S_PARM\n");
retval = -ENODEV;
}
break;
@@ -2241,6 +2327,10 @@ static long mxc_v4l_do_ioctl(struct file *file,
case VIDIOC_ENUMSTD: {
struct v4l2_standard *e = arg;
pr_debug(" case VIDIOC_ENUMSTD\n");
+ if (e->index > 0) {
+ retval = -EINVAL;
+ break;
+ }
*e = cam->standard;
break;
}
@@ -2251,7 +2341,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->sensor)
retval = mxc_v4l2_g_std(cam, e);
else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_G_STD\n");
retval = -ENODEV;
}
break;
@@ -2356,7 +2446,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->sensor)
retval = vidioc_int_enum_fmt_cap(cam->sensor, f);
else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_ENUM_FMT\n");
retval = -ENODEV;
}
break;
@@ -2366,7 +2456,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->sensor)
retval = vidioc_int_enum_framesizes(cam->sensor, fsize);
else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_ENUM_FRAMESIZES\n");
retval = -ENODEV;
}
break;
@@ -2377,7 +2467,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
retval = vidioc_int_enum_frameintervals(cam->sensor,
fival);
} else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_ENUM_FRAMEINTERVALS\n");
retval = -ENODEV;
}
break;
@@ -2389,7 +2479,7 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->sensor)
retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p);
else {
- pr_err("ERROR: v4l2 capture: slave not found!\n");
+ pr_err("ERROR: v4l2 capture: slave not found! VIDIOC_DBG_G_CHIP_IDENT\n");
retval = -ENODEV;
}
break;
@@ -2617,9 +2707,10 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
const struct of_device_id *of_id =
of_match_device(mxc_v4l2_dt_ids, &pdev->dev);
struct device_node *np = pdev->dev.of_node;
- int ipu_id, csi_id, mclk_source;
+ int ipu_id, csi_id, mclk_source, mipi_camera;
int ret = 0;
struct v4l2_device *v4l2_dev;
+ static int camera_id;
pr_debug("In MVC: init_camera_struct\n");
@@ -2641,6 +2732,10 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
return ret;
}
+ ret = of_property_read_u32(np, "mipi_camera", &mipi_camera);
+ if (ret)
+ mipi_camera = 0;
+
/* Default everything to 0 */
memset(cam, 0, sizeof(cam_data));
@@ -2663,6 +2758,7 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
init_MUTEX(&cam->param_lock);
init_MUTEX(&cam->busy_lock);
+ INIT_DELAYED_WORK(&cam->power_down_work, power_down_callback);
cam->video_dev = video_device_alloc();
if (cam->video_dev == NULL)
@@ -2729,6 +2825,7 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
cam->ipu_id = ipu_id;
cam->csi = csi_id;
+ cam->mipi_camera = mipi_camera;
cam->mclk_source = mclk_source;
cam->mclk_on[cam->mclk_source] = false;
@@ -2739,7 +2836,7 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL);
cam->self->module = THIS_MODULE;
- sprintf(cam->self->name, "mxc_v4l2_cap%d", cam->csi);
+ sprintf(cam->self->name, "mxc_v4l2_cap%d", camera_id++);
cam->self->type = v4l2_int_type_master;
cam->self->u.master = &mxc_v4l2_master;
@@ -2951,7 +3048,8 @@ static int mxc_v4l2_resume(struct platform_device *pdev)
wake_up_interruptible(&cam->power_queue);
if (cam->sensor && cam->open_count) {
- vidioc_int_s_power(cam->sensor, 1);
+ if ((cam->overlay_on == true) || (cam->capture_on == true))
+ vidioc_int_s_power(cam->sensor, 1);
if (!cam->mclk_on[cam->mclk_source]) {
ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
@@ -3012,8 +3110,9 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
return -1;
}
- if (sdata->csi != cam->csi) {
- pr_debug("%s: csi doesn't match\n", __func__);
+ if ((sdata->ipu_id != cam->ipu_id) || (sdata->csi != cam->csi) || (sdata->mipi_camera != cam->mipi_camera)) {
+ pr_info("%s: ipu(%d:%d)/csi(%d:%d)/mipi(%d:%d) doesn't match\n", __func__,
+ sdata->ipu_id, cam->ipu_id, sdata->csi, cam->csi, sdata->mipi_camera, cam->mipi_camera);
return -1;
}
@@ -3067,6 +3166,10 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
__func__,
cam->crop_current.width, cam->crop_current.height);
+ pr_info("%s: ipu%d:/csi%d %s attached %s:%s\n", __func__,
+ cam->ipu_id, cam->csi, cam->mipi_camera ? "mipi" : "parallel",
+ slave->name, slave->u.slave->master->name);
+
return 0;
}
@@ -3100,6 +3203,20 @@ static void mxc_v4l2_master_detach(struct v4l2_int_device *slave)
vidioc_int_dev_exit(slave);
}
+DEFINE_MUTEX(camera_common_mutex);
+
+void mxc_camera_common_lock(void)
+{
+ mutex_lock(&camera_common_mutex);
+}
+EXPORT_SYMBOL(mxc_camera_common_lock);
+
+void mxc_camera_common_unlock(void)
+{
+ mutex_unlock(&camera_common_mutex);
+}
+EXPORT_SYMBOL(mxc_camera_common_unlock);
+
/*!
* Entry point for the V4L2
*
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
index 6c800cb7b8de..c0a6fef2205e 100644
--- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
@@ -108,6 +108,8 @@ typedef struct _cam_data {
struct semaphore busy_lock;
int open_count;
+ struct delayed_work power_down_work;
+ int power_on;
/* params lock for this camera */
struct semaphore param_lock;
@@ -201,6 +203,8 @@ typedef struct _cam_data {
wait_queue_head_t power_queue;
unsigned int ipu_id;
unsigned int csi;
+ unsigned mipi_camera;
+ int csi_in_use;
u8 mclk_source;
bool mclk_on[2]; /* two mclk sources at most now */
int current_input;
@@ -247,10 +251,15 @@ struct sensor_data {
u32 mclk;
u8 mclk_source;
struct clk *sensor_clk;
+ int ipu_id;
int csi;
+ int mipi_camera; /* 0: parallel camera hw if, != 0: mipi csi hw if */
void (*io_init)(void);
};
void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi);
+void mxc_camera_common_lock(void);
+void mxc_camera_common_unlock(void);
+
#endif /* __MXC_V4L2_CAPTURE_H__ */
diff --git a/drivers/media/platform/mxc/capture/ov5640_mipi.c b/drivers/media/platform/mxc/capture/ov5640_mipi.c
index 118174af2c65..0245808efc14 100644
--- a/drivers/media/platform/mxc/capture/ov5640_mipi.c
+++ b/drivers/media/platform/mxc/capture/ov5640_mipi.c
@@ -28,8 +28,12 @@
#include <linux/clk.h>
#include <linux/of_device.h>
#include <linux/i2c.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/fsl_devices.h>
#include <linux/mipi_csi2.h>
@@ -699,12 +703,40 @@ static void ov5640_standby(s32 enable)
gpio_set_value(pwn_gpio, 1);
else
gpio_set_value(pwn_gpio, 0);
-
+ pr_debug("ov5640_mipi_camera_powerdown: powerdown=%x, power_gp=0x%x\n", enable, pwn_gpio);
msleep(100);
}
+static s32 update_device_addr(struct sensor_data *sensor)
+{
+ int ret;
+ u8 buf[4];
+ unsigned reg = 0x3100;
+ unsigned default_addr = 0x3c;
+ struct i2c_msg msg;
+
+ if (sensor->i2c_client->addr == default_addr)
+ return 0;
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xff;
+ buf[2] = sensor->i2c_client->addr << 1;
+ msg.addr = default_addr;
+ msg.flags = 0;
+ msg.len = 3;
+ msg.buf = buf;
+
+
+ ret = i2c_transfer(sensor->i2c_client->adapter, &msg, 1);
+ if (ret < 0)
+ pr_err("%s: ov5642 ret=%d\n", __func__, ret);
+ return ret;
+}
+
static void ov5640_reset(void)
{
+ mxc_camera_common_lock();
+
/* camera reset */
gpio_set_value(rst_gpio, 1);
@@ -719,7 +751,9 @@ static void ov5640_reset(void)
msleep(1);
gpio_set_value(rst_gpio, 1);
- msleep(5);
+ msleep(20);
+ update_device_addr(&ov5640_data);
+ mxc_camera_common_unlock();
gpio_set_value(pwn_gpio, 1);
}
@@ -803,18 +837,33 @@ static void ov5640_power_off(void)
static s32 ov5640_write_reg(u16 reg, u8 val)
{
+ int ret;
u8 au8Buf[3] = {0};
au8Buf[0] = reg >> 8;
au8Buf[1] = reg & 0xff;
au8Buf[2] = val;
- if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
- pr_err("%s:write reg error:reg=%x,val=%x\n",
- __func__, reg, val);
- return -1;
+#if 0 /* Software reset does not affect the i2c address register like it does on ov5642 */
+ if ((reg == 0x3008) && (val & 0x80)) {
+ mxc_camera_common_lock();
+
+ ret = i2c_master_send(ov5640_data.i2c_client, au8Buf, 3);
+ update_device_addr(&ov5640_data);
+
+ mxc_camera_common_unlock();
+ } else
+#endif
+ {
+ ret = i2c_master_send(ov5640_data.i2c_client, au8Buf, 3);
}
+ if (ret < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x ret=%d\n",
+ __func__, reg, val, ret);
+ return ret;
+ }
+ pr_debug("reg=%x,val=%x\n", reg, val);
return 0;
}
@@ -856,43 +905,64 @@ static void OV5640_stream_off(void)
ov5640_write_reg(0x4202, 0x0f);
}
-
+static const int sclk_rdiv_map[] = {1, 2, 4, 8};
+
static int OV5640_get_sysclk(void)
{
/* calculate sysclk */
- int xvclk = ov5640_data.mclk / 10000;
- int temp1, temp2;
- int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv;
- int Bit_div2x = 1, sclk_rdiv, sysclk;
+ int tmp;
+ unsigned Multiplier, PreDiv, SysDiv, Pll_rdiv, Bit_div2x = 1;
+ unsigned div, sclk_rdiv, sysclk;
u8 temp;
int sclk_rdiv_map[] = {1, 2, 4, 8};
- temp1 = ov5640_read_reg(0x3034, &temp);
- temp2 = temp1 & 0x0f;
- if (temp2 == 8 || temp2 == 10)
- Bit_div2x = temp2 / 2;
-
- temp1 = ov5640_read_reg(0x3035, &temp);
- SysDiv = temp1>>4;
- if (SysDiv == 0)
+ tmp = ov5640_read_reg(0x3034, &temp);
+ if (tmp < 0)
+ return tmp;
+ tmp &= 0x0f;
+ if (tmp == 8 || tmp == 10)
+ Bit_div2x = tmp / 2;
+
+ tmp = ov5640_read_reg(0x3035, &temp);
+ if (tmp < 0)
+ return tmp;
+ SysDiv = tmp >> 4;
+ if (SysDiv == 0)
SysDiv = 16;
- temp1 = ov5640_read_reg(0x3036, &temp);
- Multiplier = temp1;
-
- temp1 = ov5640_read_reg(0x3037, &temp);
- PreDiv = temp1 & 0x0f;
- Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
-
- temp1 = ov5640_read_reg(0x3108, &temp);
- temp2 = temp1 & 0x03;
- sclk_rdiv = sclk_rdiv_map[temp2];
-
- VCO = xvclk * Multiplier / PreDiv;
-
- sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
-
+ tmp = ov5640_read_reg(0x3036, &temp);
+ if (tmp < 0)
+ return tmp;
+ Multiplier = tmp;
+
+ tmp = ov5640_read_reg(0x3037, &temp);
+ if (tmp < 0)
+ return tmp;
+ PreDiv = tmp & 0x0f;
+ Pll_rdiv = ((tmp >> 4) & 0x01) + 1;
+
+ tmp = ov5640_read_reg(0x3108, &temp);
+ if (tmp < 0)
+ return tmp;
+ sclk_rdiv = sclk_rdiv_map[tmp & 0x03];
+
+ sysclk = ov5640_data.mclk / 10000 * Multiplier;
+ div = PreDiv * SysDiv * Pll_rdiv * Bit_div2x * sclk_rdiv;
+ if (!div) {
+ pr_err("%s:Error divide by 0, (%d * %d * %d * %d * %d)\n",
+ __func__, PreDiv, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv);
+ return -EINVAL;
+ }
+ if (!sysclk) {
+ pr_err("%s:Error 0 clk, ov5640_data.mclk=%d, Multiplier=%d\n",
+ __func__, ov5640_data.mclk, Multiplier);
+ return -EINVAL;
+ }
+ sysclk /= div;
+ pr_debug("%s: sysclk(%d) = %d / 10000 * %d / (%d * %d * %d * %d * %d)\n",
+ __func__, sysclk, ov5640_data.mclk, Multiplier,
+ PreDiv, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv);
return sysclk;
}
@@ -1033,6 +1103,7 @@ static int OV5640_get_light_freq(void)
light_freq = 50;
} else {
/* 60Hz */
+ light_freq = 60;
}
}
return light_freq;
@@ -1125,6 +1196,7 @@ static void ov5640_set_virtual_channel(int channel)
ov5640_read_reg(0x4814, &channel_id);
channel_id &= ~(3 << 6);
ov5640_write_reg(0x4814, channel_id | (channel << 6));
+ pr_info("%s: virtual channel=%d\n", __func__, channel);
}
/* download ov5640 settings to sensor through i2c */
@@ -1416,7 +1488,7 @@ static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
OV5640_set_AE_target(AE_Target);
OV5640_get_light_freq();
OV5640_set_bandingfilter();
- ov5640_set_virtual_channel(ov5640_data.csi);
+ ov5640_set_virtual_channel(ov5640_data.csi | (ov5640_data.ipu_id << 1));
/* add delay to wait for sensor stable */
if (mode == ov5640_mode_QSXGA_2592_1944) {
@@ -1433,37 +1505,33 @@ static int ov5640_init_mode(enum ov5640_frame_rate frame_rate,
msleep(msec_wait4stable);
if (mipi_csi2_info) {
- unsigned int i;
-
- i = 0;
+ unsigned int i = 0;
/* wait for mipi sensor ready */
- mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
- while ((mipi_reg == 0x200) && (i < 10)) {
+ while (1) {
mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
- i++;
+ if (mipi_reg != 0x200)
+ break;
+ if (i++ >= 20) {
+ pr_err("mipi csi2 can not receive sensor clk! %x\n", mipi_reg);
+ return -1;
+ }
msleep(10);
}
- if (i >= 10) {
- pr_err("mipi csi2 can not receive sensor clk!\n");
- return -1;
- }
-
i = 0;
-
/* wait for mipi stable */
- mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
- while ((mipi_reg != 0x0) && (i < 10)) {
+ while (1) {
mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
- i++;
+ if (!mipi_reg)
+ break;
+ if (i++ >= 20) {
+ pr_err("mipi csi2 can not receive data correctly!\n");
+ return -1;
+ }
msleep(10);
}
- if (i >= 10) {
- pr_err("mipi csi2 can not reveive data correctly!\n");
- return -1;
- }
}
err:
return retval;
@@ -1985,7 +2053,7 @@ static struct v4l2_int_slave ov5640_slave = {
static struct v4l2_int_device ov5640_int_device = {
.module = THIS_MODULE,
- .name = "ov564x",
+ .name = "ov564x_mipi",
.type = v4l2_int_type_slave,
.u = {
.slave = &ov5640_slave,
@@ -2001,9 +2069,12 @@ static struct v4l2_int_device ov5640_int_device = {
static int ov5640_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct pwm_device *pwm;
struct device *dev = &client->dev;
int retval;
u8 chip_id_high, chip_id_low;
+ struct regmap *gpr;
+ struct sensor_data *sensor = &ov5640_data;
/* request power down pin */
pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
@@ -2013,8 +2084,10 @@ static int ov5640_probe(struct i2c_client *client,
}
retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
"ov5640_mipi_pwdn");
- if (retval < 0)
+ if (retval < 0) {
+ dev_warn(dev, "request of pwn_gpio failed");
return retval;
+ }
/* request reset pin */
rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
@@ -2024,8 +2097,10 @@ static int ov5640_probe(struct i2c_client *client,
}
retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
"ov5640_mipi_reset");
- if (retval < 0)
+ if (retval < 0) {
+ dev_warn(dev, "request of ov5640_mipi_reset failed");
return retval;
+ }
/* Set initial values for the sensor struct. */
memset(&ov5640_data, 0, sizeof(ov5640_data));
@@ -2051,6 +2126,13 @@ static int ov5640_probe(struct i2c_client *client,
return retval;
}
+ retval = of_property_read_u32(dev->of_node, "ipu_id",
+ &sensor->ipu_id);
+ if (retval) {
+ dev_err(dev, "ipu_id missing or invalid\n");
+ return retval;
+ }
+
retval = of_property_read_u32(dev->of_node, "csi_id",
&(ov5640_data.csi));
if (retval) {
@@ -2071,6 +2153,13 @@ static int ov5640_probe(struct i2c_client *client,
ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
ov5640_data.streamcap.timeperframe.numerator = 1;
+ pwm = pwm_get(dev, NULL);
+ if (!IS_ERR(pwm)) {
+ dev_info(dev, "found pwm%d, period=%d\n", pwm->pwm, pwm->state.period);
+ pwm_config(pwm, pwm->state.period >> 1, pwm->state.period);
+ pwm_enable(pwm);
+ }
+
ov5640_power_on(dev);
ov5640_reset();
@@ -2092,12 +2181,31 @@ static int ov5640_probe(struct i2c_client *client,
return -ENODEV;
}
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (!IS_ERR(gpr)) {
+ if (of_machine_is_compatible("fsl,imx6q")) {
+ if (sensor->csi == sensor->ipu_id) {
+ int mask = sensor->csi ? (1 << 20) : (1 << 19);
+
+ regmap_update_bits(gpr, IOMUXC_GPR1, mask, 0);
+ }
+ } else if (of_machine_is_compatible("fsl,imx6dl")) {
+ int mask = sensor->csi ? (7 << 3) : (7 << 0);
+ int val = sensor->csi ? (3 << 3) : (0 << 0);
+
+ regmap_update_bits(gpr, IOMUXC_GPR13, mask, val);
+ }
+ } else {
+ pr_err("%s: failed to find fsl,imx6q-iomux-gpr regmap\n",
+ __func__);
+ }
+
ov5640_standby(1);
ov5640_int_device.priv = &ov5640_data;
retval = v4l2_int_device_register(&ov5640_int_device);
- clk_disable_unprepare(ov5640_data.sensor_clk);
+// clk_disable_unprepare(ov5640_data.sensor_clk);
pr_info("camera ov5640_mipi is found\n");
return retval;
diff --git a/drivers/media/platform/mxc/capture/ov5640_mipi_nv.c b/drivers/media/platform/mxc/capture/ov5640_mipi_nv.c
new file mode 100644
index 000000000000..c10b6091208a
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ov5640_mipi_nv.c
@@ -0,0 +1,1509 @@
+/*
+ * Copyright (c) 2012-2013 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-mediabus.h>
+#include <media/soc_camera.h>
+#include <linux/of_gpio.h>
+
+struct ov5640_reg {
+ u16 addr;
+ u16 val;
+};
+
+#define MIPI_CSI2_SENS_VC0_PAD_SOURCE 0
+#define MIPI_CSI2_SENS_VC1_PAD_SOURCE 1
+#define MIPI_CSI2_SENS_VC2_PAD_SOURCE 2
+#define MIPI_CSI2_SENS_VC3_PAD_SOURCE 3
+#define MIPI_CSI2_SENS_VCX_PADS_NUM 4
+
+#define OV5640_TABLE_WAIT_MS 0
+#define OV5640_TABLE_END 1
+
+/* -> mode_2592x1944 mode_1920x1080 mode_1280x960 mode_640x480 */
+
+/* System and IO Pad Control [0x3000 ~ 0x3052] */
+#define OV5640_SYSTEM_RESET_00 0x3000 /* default 0x30 -> all 0x00 */
+#define OV5640_SYSTEM_RESET_01 0x3001 /* default 0x08 */
+#define OV5640_SYSTEM_RESET_02 0x3002 /* default 0x1c */
+#define OV5640_SYSTEM_RESET_03 0x3003 /* default 0x00 */
+#define OV5640_SYSTEM_CLK_EN_00 0x3004 /* default 0xcf -> all 0xff */
+#define OV5640_SYSTEM_CLK_EN_01 0x3005 /* default 0xf7 */
+#define OV5640_SYSTEM_CLK_EN_02 0x3006 /* default 0xe3 -> all 0xc3 */
+#define OV5640_SYSTEM_CLK_EN_03 0x3007 /* default 0xff */
+#define OV5640_SYSTEM_CTRL 0x3008 /* default 0x02 all -> (0x82, 0x42, 0x02) */
+#define OV5640_CHIP_ID_H 0x300a /* default 0x56 */
+#define OV5640_CHIP_ID_L 0x300b /* default 0x40 */
+#define OV5640_SYSTEM_MIPI_CTRL 0x300e /* default 0x58 -> all 0x45 */
+#define OV5640_IO_CTRL_01 0x3017 /* default 0x00 */
+#define OV5640_IO_CTRL_02 0x3018 /* default 0x00 */
+#define OV5640_SYSTEM_CTRL_2D 0x302d /* default ---- -> all 0x60 !! */
+#define OV5640_SYSTEM_CTRL_2E 0x302e /* default ---- -> all 0x08 !! */
+#define OV5640_SC_PLL_CTRL0 0x3034 /* default 0x1a -> all 0x18 MIPI_MODE */
+#define OV5640_SC_PLL_CTRL1 0x3035 /* default 0x11 -> 0x11 0x11 0x21 0x14 */
+#define OV5640_SC_PLL_CTRL2 0x3036 /* default 0x69 -> 0x7d 0x54 0x70 0x70 */
+#define OV5640_SC_PLL_CTRL3 0x3037 /* default 0x03 -> all 0x13 */
+#define OV5640_SC_PLL_CTRL5 0x3039 /* not use */
+
+#define SYSTEM_CTRL_SRST 0x80 /* Bit[7]: Software reset */
+#define SYSTEM_CTRL_PDOWN 0x40 /* Bit[6]: Software power down */
+#define MIPI_MODE_8BIT 0x08 /* Bit[3:0]: MIPI bit mode - 8-bit mode */
+#define MIPI_MODE_10BIT 0x0a /* Bit[3:0]: MIPI bit mode - 10-bit mode */
+
+/* SCCB Control [0x3100 ~ 0x3108] */
+#define OV5640_SCCB_SYSTEM_CTRL 0x3103 /* default 0x00 -> all 0x03 */
+#define OV5640_SCCB_SCLK 0x3108 /* default 0x16 -> all 0x01 */
+
+/* VCM Control [0x3600 ~ 0x3606] */
+#define OV5640_VCM_DEBUG_MODE_0 0x3600 /* default ---- -> all 0x08 */
+#define OV5640_VCM_DEBUG_MODE_1 0x3601 /* default ---- -> all 0x33 */
+
+/* Timing Control [0x3800 ~ 0x3821] */
+#define OV5640_TIMING_HS_H 0x3800 /* default 0x00 -> 0x00 0x01 0x00 0x00 X_ADDR_ST */
+#define OV5640_TIMING_HS_L 0x3801 /* default 0x00 -> 0x00 0x50 0x00 0x00 */
+#define OV5640_TIMING_VS_H 0x3802 /* default 0x00 -> 0x00 0x01 0x00 0x00 Y_ADDR_ST */
+#define OV5640_TIMING_VS_L 0x3803 /* default 0x00 -> 0x00 0xaa 0x00 0x04 */
+#define OV5640_TIMING_HW_H 0x3804 /* default 0x0a -> 0x0a 0x08 0x0a 0x0a X_ADDR_END */
+#define OV5640_TIMING_HW_L 0x3805 /* default 0x3f -> 0x3f 0xef 0x3f 0x3f 2623 */
+#define OV5640_TIMING_VH_H 0x3806 /* default 0x07 -> 0x07 0x05 0x07 0x07 Y_ADDR_END */
+#define OV5640_TIMING_VH_L 0x3807 /* default 0x9f -> 0x9f 0xf9 0x9f 0x9b */
+#define OV5640_TIMING_DVPHO_H 0x3808 /* default 0x0a -> 0x0a 0x07 0x05 0x02 width[11:8] */
+#define OV5640_TIMING_DVPHO_L 0x3809 /* default 0x20 -> 0x30 0x90 0x18 0x80 width[7:0] */
+#define OV5640_TIMING_DVPVO_H 0x380a /* default 0x07 -> 0x07 0x04 0x03 0x01 height[11:8] */
+#define OV5640_TIMING_DVPVO_L 0x380b /* default 0x98 -> 0x9c 0x48 0xcc 0xe0 height[7:0] */
+#define OV5640_TIMING_HTS_H 0x380c /* default 0x0b -> 0x0b 0x09 0x07 0x07 */
+#define OV5640_TIMING_HTS_L 0x380d /* default 0x1c -> 0x1c 0xc4 0x5e 0x68 */
+#define OV5640_TIMING_VTS_H 0x380e /* default 0x07 -> 0x07 0x04 0x03 0x03 */
+#define OV5640_TIMING_VTS_L 0x380f /* default 0xb0 -> 0xb0 0x60 0xde 0xd8 */
+#define OV5640_TIMING_HOFFSET_H 0x3810 /* default 0x00 */
+#define OV5640_TIMING_HOFFSET_L 0x3811 /* default 0x10 -> 0x08 0x08 0x06 0x10 */
+#define OV5640_TIMING_VOFFSET_H 0x3812 /* default 0x00 */
+#define OV5640_TIMING_VOFFSET_L 0x3813 /* default 0x04 -> 0x02 0x04 0x02 0x06 */
+#define OV5640_TIMING_X_INC 0x3814 /* default 0x11 -> 0x11 0x11 0x31 0x31 */
+#define OV5640_TIMING_Y_INC 0x3815 /* default 0x11 -> 0x11 0x11 0x31 0x31 */
+#define OV5640_TIMING_REG20 0x3820 /* default 0x40 -> 0x40 0x40 0x41 0x41 sensor vflip */
+#define OV5640_TIMING_REG21 0x3821 /* default 0x00 -> 0x06 0x06 0x07 0x07 */
+#define REG20_SENSOR_VFLIP 0x02
+#define REG20_SENSOR_ISP_FLIP 0x04
+#define REG21_BINNING_EN 0x01
+#define REG21_SENSOR_MIRROR 0x02
+#define REG21_ISP_MIRROR 0x04
+
+#define OV5640_ADDR_H(x) ((x >> 8 ) & 0x0f)
+#define OV5640_ADDR_L(x) (x & 0xff)
+#define OV5640_WIDTH_H(x) ((x >> 8 ) & 0x0f)
+#define OV5640_WIDTH_L(x) (x & 0xff)
+#define OV5640_HEIGHT_H(x) ((x >> 8 ) & 0x0f)
+#define OV5640_HEIGHT_L(x) (x & 0xff)
+#define OV5640_HTS_H(x) ((x >> 8 ) & 0x1f)
+#define OV5640_HTS_L(x) (x & 0xff)
+#define OV5640_VTS_H(x) ((x >> 8 ) & 0xff)
+#define OV5640_VTS_L(x) (x & 0xff)
+#define OV5640_H_OFFSET_H(x) ((x >> 8 ) & 0x0F)
+#define OV5640_H_OFFSET_L(x) (x & 0xff)
+#define OV5640_V_OFFSET_H(x) ((x >> 8 ) & 0x03)
+#define OV5640_V_OFFSET_L(x) (x & 0xff)
+
+/* AEC/AGC power down domain control [0x3A00 ~ 0x3A25] */
+#define OV5640_AEC_CTRL_0F 0x3a0f /* default 0x78 -> all 0x30 */
+#define OV5640_AEC_CTRL_10 0x3a10 /* default 0x68 -> all 0x28 */
+#define OV5640_AEC_CTRL_11 0x3a11 /* default 0xd0 -> all 0x60 */
+#define OV5640_AEC_CTRL_1B 0x3a1b /* default 0x78 -> all 0x30 */
+#define OV5640_AEC_CTRL_1E 0x3a1e /* default 0x68 -> all 0x26 */
+#define OV5640_AEC_CTRL_1F 0x3a1f /* default 0x40 -> all 0x14 */
+#define OV5640_AEC_MAX_EXPO60_H 0x3a02 /* default 0x3d -> 0x07 0x04 0x03 0x03 */
+#define OV5640_AEC_MAX_EXPO60_L 0x3a03 /* default 0x80 -> 0xb6 0x60 0xd8 0xd8 */
+#define OV5640_AEC_B50_STEP_H 0x3a08 /* default 0x01 */
+#define OV5640_AEC_B50_STEP_L 0x3a09 /* default 0x27 -> 0x27 0x50 0x27 0x27 */
+#define OV5640_AEC_B60_STEP_H 0x3a0a /* default 0x00 -> 0x00 0x01 0x00 0x00 */
+#define OV5640_AEC_B60_STEP_L 0x3a0b /* default 0xf6 -> 0xf6 0x18 0xf6 0xf6 */
+#define OV5640_AEC_CTRL_0D 0x3a0d /* default 0x08 -> 0x06 0x03 0x03 0x03 */
+#define OV5640_AEC_CTRL_0E 0x3a0e /* default 0x06 -> 0x06 0x04 0x04 0x04 */
+#define OV5640_AEC_CTRL_13 0x3a13 /* default 0x40 -> all 0x43 */
+#define OV5640_AEC_MAX_EXPO_H 0x3a14 /* default 0x0e -> 0x07 0x04 0x03 0x03 */
+#define OV5640_AEC_MAX_EXPO_L 0x3a15 /* default 0x40 -> 0xb0 0xd0 0xd8 0xd8 */
+#define OV5640_AEC_GAIN_CEILING_0 0x3a18 /* default 0x03 -> all 0x00 */
+#define OV5640_AEC_GAIN_CEILING_1 0x3a19 /* default 0xE0 -> all 0xf8 */
+
+/* 50/60Hz detector control [0x3C00 ~ 0x3C1E] */
+#define OV5640_5060_CTRL_01 0x3c01 /* default 0x00 -> all 0x34 */
+#define OV5640_5060_CTRL_04 0x3c04 /* default 0x20 -> all 0x28 */
+#define OV5640_5060_CTRL_05 0x3c05 /* default 0x70 -> all 0x98 */
+
+#define OV5640_5060_THRESHOLD_1_H 0x3c06 /* default 0x00 -> all 0x00 */
+#define OV5640_5060_THRESHOLD_1_L 0x3c07 /* default 0x00 -> all 0x07 0x07 0x07 0x07 0x08 */
+#define OV5640_5060_THRESHOLD_2_H 0x3c08 /* default 0x01 -> all 0x00 */
+#define OV5640_5060_THRESHOLD_2_L 0x3c09 /* default 0x2c -> all 0x1c */
+#define OV5640_5060_SAMPLE_NUM_H 0x3c0a /* default 0x4e -> all 0x9c */
+#define OV5640_5060_SAMPLE_NUM_L 0x3c0b /* default 0x1f -> all 0x40 */
+
+/* BLC Control [0x4000 ~ 0x4033] */
+#define OV5640_BLC_CTRL_01 0x4001 /* default 0x00 -> 0x02 */
+#define OV5640_BLC_CTRL_04 0x4004 /* default 0x08 -> 0x06 0x06 0x02 0x02 */
+
+/* MIPI control [0x4800 ~ 0x4837] */
+#define OV5640_MIPI_CTRL_00 0x4800 /* default 0x04 */
+#define OV5640_MIPI_CTRL_01 0x4801 /* not use */
+#define OV5640_MIPI_CTRL_05 0x4805 /* not use */
+#define OV5640_MIPI_PCLK_PERIOD 0x4837 /* default 0x10 -> 0x0a 0x0a 0x10 0x44 */
+
+/* Format Control [0x4300 ~ 0x430D] */
+#define FMT_CTRL_00 0x4300 /* default 0xF8 -> all 0x32 */
+
+/* Format Control */
+#define FMT_YUV422 0x30
+/* Output sequence */
+#define OFMT_YUYV 0x00
+#define OFMT_YVYU 0x01
+#define OFMT_UYVY 0x02
+#define OFMT_VYUY 0x03
+
+/* ISP Control [0x5000 ~ 0x5063] */
+#define OV5640_ISP_CTRL_00 0x5000 /* default 0x06 -> all 0xa7 */
+#define OV5640_ISP_CTRL_01 0x5001 /* default 0x01 -> 0x83 0x83 0x83 0xa3 */
+#define OV5640_ISP_MUX_CTRL 0x501F /* default 0x00 -> all 0x00 (000: ISP YUV422) */
+#define OV5640_ISP_DEBUG_25 0x5025 /* default ---- -> all 0x00 */
+#define OV5640_ISP_TEST 0x503D /* default 0x00 */
+#define OV5640_ISP_DEBUG_3E 0x503E /* default ---- */
+#define OV5640_ISP_DEBUG_46 0x5046 /* default ---- */
+
+#define ISP_SCALE_DIGITAL 0x80 /* Special digital effect */
+#define ISP_SCALE_EN 0x20 /* Scale enable */
+#define ISP_AUTO_BALANCE_EN 0x01 /* Auto white balance enable */
+#define ISP_COLOR_MATRIX_EN 0x02 /* Color matrix enable */
+#define ISP_TEST_EN 0x80
+#define ISP_TEST_00 0x00 /* 00: Standard eight color bar */
+#define ISP_TEST_01 0x01 /* 01: Gradual change at vertical mode 1 */
+#define ISP_TEST_10 0x02 /* 10: Gradual change at horizontal */
+#define ISP_TEST_11 0x03 /* 11: Gradual change at vertical mode 2 */
+#define ISP_TEST_TRANSPARENT 0x20 /* Transparent */
+#define ISP_TEST_ROLLING 0x40 /* Rolling */
+
+/* AWB Control [0x5180 ~ 0x51D0] */
+#define OV5640_AWB_CTRL_00 0x5180 /* default 0xff */
+#define OV5640_AWB_CTRL_01 0x5181 /* default 0x58 -> all 0xf2 */
+#define OV5640_AWB_CTRL_02 0x5182 /* default 0x11 -> all 0x00 */
+#define OV5640_AWB_CTRL_03 0x5183 /* default 0x90 -> all 0x14 */
+#define OV5640_AWB_CTRL_04 0x5184 /* default 0x25 */
+#define OV5640_AWB_CTRL_05 0x5185 /* default 0x24 */
+#define OV5640_AWB_CTRL_06 0x5186 /* default ---- -> all 0x09 */
+#define OV5640_AWB_CTRL_07 0x5187 /* default ---- -> all 0x09 */
+#define OV5640_AWB_CTRL_08 0x5188 /* default ---- -> all 0x09 */
+#define OV5640_AWB_CTRL_09 0x5189 /* default ---- -> all 0x75 */
+#define OV5640_AWB_CTRL_10 0x518a /* default ---- -> all 0x54 */
+#define OV5640_AWB_CTRL_11 0x518b /* default ---- -> all 0xe0 */
+#define OV5640_AWB_CTRL_12 0x518c /* default ---- -> all 0xb2 */
+#define OV5640_AWB_CTRL_13 0x518d /* default ---- -> all 0x42 */
+#define OV5640_AWB_CTRL_14 0x518e /* default ---- -> all 0x3d */
+#define OV5640_AWB_CTRL_15 0x518f /* default ---- -> all 0x56 */
+#define OV5640_AWB_CTRL_16 0x5190 /* default ---- -> all 0x46 */
+#define OV5640_AWB_CTRL_17 0x5191 /* default 0xff -> all 0xf8 */
+#define OV5640_AWB_CTRL_18 0x5192 /* default 0x00 -> all 0x04 */
+#define OV5640_AWB_CTRL_19 0x5193 /* default 0xf0 -> all 0x70 */
+#define OV5640_AWB_CTRL_20 0x5194 /* default 0xf0 */
+#define OV5640_AWB_CTRL_21 0x5195 /* default 0xf0 */
+#define OV5640_AWB_CTRL_22 0x5196 /* default 0x03 */
+#define OV5640_AWB_CTRL_23 0x5197 /* default 0x02 -> all 0x01 */
+#define OV5640_AWB_CTRL_24 0x5198 /* default ---- -> all 0x04 */
+#define OV5640_AWB_CTRL_25 0x5199 /* default ---- -> all 0x12 */
+#define OV5640_AWB_CTRL_26 0x519a /* default ---- -> all 0x04 */
+#define OV5640_AWB_CTRL_27 0x519b /* default ---- -> all 0x00 */
+#define OV5640_AWB_CTRL_28 0x519c /* default ---- -> all 0x06 */
+#define OV5640_AWB_CTRL_29 0x519d /* default ---- -> all 0x82 */
+#define OV5640_AWB_CTRL_30 0x519e /* default 0x02 -> all 0x38 */
+
+/* CIP Control [0x5300 ~ 0x530F] */
+#define OV5640_CIP_SH_MT_THRES_1 0x5300 /* default 0x08 */
+#define OV5640_CIP_SH_MT_THRES_2 0x5301 /* default 0x48 -> all 0x30 */
+#define OV5640_CIP_SH_MT_OFFSET_1 0x5302 /* default 0x18 -> all 0x10 */
+#define OV5640_CIP_SH_MT_OFFSET_2 0x5303 /* default 0x0e -> all 0x00 */
+#define OV5640_CIP_DNS_THRES_1 0x5304 /* default 0x08 */
+#define OV5640_CIP_DNS_THRES_2 0x5305 /* default 0x48 -> all 0x30 */
+#define OV5640_CIP_DNS_OFFSET_1 0x5306 /* default 0x09 -> all 0x08 */
+#define OV5640_CIP_DNS_OFFSET_2 0x5307 /* default 0x16 */
+#define OV5640_CIP_SH_TH_THRES_1 0x5309 /* default 0x08 */
+#define OV5640_CIP_SH_TH_THRES_2 0x530a /* default 0x48 -> all 0x30 */
+#define OV5640_CIP_SH_TH_OFFSET_1 0x530b /* default 0x04 */
+#define OV5640_CIP_SH_TH_OFFSET_2 0x530c /* default 0x06 */
+
+/* CMX Control [0x5380 ~ 0x538B] */
+#define OV5640_CMX1 0x5381 /* default 0x20 -> all 0x1e */
+#define OV5640_CMX2 0x5382 /* default 0x64 -> all 0x5b */
+#define OV5640_CMX3 0x5383 /* default 0x08 */
+#define OV5640_CMX4 0x5384 /* default 0x30 -> all 0x0a */
+#define OV5640_CMX5 0x5385 /* default 0x80 -> all 0x7e */
+#define OV5640_CMX6 0x5386 /* default 0xc0 -> all 0x88 */
+#define OV5640_CMX7 0x5387 /* default 0xa0 -> all 0x7c */
+#define OV5640_CMX8 0x5388 /* default 0x98 -> all 0x6c */
+#define OV5640_CMX9 0x5389 /* default 0x08 -> all 0x10 */
+#define OV5640_CMX_SIGN_0 0x538A /* default 0x01 */
+#define OV5640_CMX_SIGN_1 0x538B /* default 0x98 */
+
+/* Gamma Control [0x5480 ~ 0x5490] */
+#define OV5640_GAMMA_CTRL_00 0x5480 /* default 0x00 -> all 0x01 */
+#define OV5640_GAMMA_YST_00 0x5481 /* default 0x26 -> all 0x08 */
+#define OV5640_GAMMA_YST_01 0x5482 /* default 0x35 -> all 0x14 */
+
+#define OV5640_GAMMA_YST_02 0x5483 /* default 0x48 -> all 0x28 */
+#define OV5640_GAMMA_YST_03 0x5484 /* default 0x57 -> all 0x51 */
+#define OV5640_GAMMA_YST_04 0x5485 /* default 0x63 -> all 0x65 */
+#define OV5640_GAMMA_YST_05 0x5486 /* default 0x6e -> all 0x71 */
+
+#define OV5640_GAMMA_YST_06 0x5487 /* default 0x77 -> all 0x7d */
+#define OV5640_GAMMA_YST_07 0x5488 /* default 0x80 -> all 0x87 */
+#define OV5640_GAMMA_YST_08 0x5489 /* default 0x88 -> all 0x91 */
+#define OV5640_GAMMA_YST_09 0x548a /* default 0x96 -> all 0x9a */
+#define OV5640_GAMMA_YST_0A 0x548b /* default 0xa3 -> all 0xaa */
+#define OV5640_GAMMA_YST_0B 0x548c /* default 0xaf -> all 0xb8 */
+#define OV5640_GAMMA_YST_0C 0x548d /* default 0xc5 -> all 0xcd */
+#define OV5640_GAMMA_YST_0D 0x548e /* default 0xd7 -> all 0xdd */
+#define OV5640_GAMMA_YST_0E 0x548f /* default 0xe8 -> all 0xea */
+#define OV5640_GAMMA_YST_0F 0x5490 /* default 0x0f -> all 0x1d */
+
+/* SDE Control [0x5580 ~ 0x558C] */
+#define OV5640_SDE_CTRL_0 0x5580 /* default 0x00 -> all 0x02 */
+#define OV5640_SDE_CTRL_3 0x5583 /* default 0x40 */
+#define OV5640_SDE_CTRL_4 0x5584 /* default 0x40 -> all 0x10 */
+#define OV5640_SDE_CTRL_9 0x5589 /* default 0x01 -> all 0x10 */
+#define OV5640_SDE_CTRL_10 0x558a /* default 0x01 -> all 0x00 */
+#define OV5640_SDE_CTRL_11 0x558b /* default 0xff -> all 0xf8 */
+
+/* LENC Control [0x5800 ~ 0x5849] */
+#define OV5640_LENC_GMTRX_00 0x5800 /* default 0x10 -> all 0x23 */
+#define OV5640_LENC_GMTRX_01 0x5801 /* default 0x10 -> all 0x14 */
+#define OV5640_LENC_GMTRX_02 0x5802 /* default 0x10 -> all 0x0f */
+#define OV5640_LENC_GMTRX_03 0x5803 /* default 0x10 -> all 0x0f */
+#define OV5640_LENC_GMTRX_04 0x5804 /* default 0x10 -> all 0x12 */
+#define OV5640_LENC_GMTRX_05 0x5805 /* default 0x10 -> all 0x26 */
+#define OV5640_LENC_GMTRX_10 0x5806 /* default 0x10 -> all 0x0c */
+#define OV5640_LENC_GMTRX_11 0x5807 /* default 0x08 */
+#define OV5640_LENC_GMTRX_12 0x5808 /* default 0x08 -> all 0x05 */
+#define OV5640_LENC_GMTRX_13 0x5809 /* default 0x08 -> all 0x05 */
+#define OV5640_LENC_GMTRX_14 0x580a /* default 0x08 -> all */
+#define OV5640_LENC_GMTRX_15 0x580b /* default 0x10 -> all 0x0d */
+#define OV5640_LENC_GMTRX_20 0x580c /* default 0x10 -> all 0x08 */
+#define OV5640_LENC_GMTRX_21 0x580d /* default 0x08 -> all 0x03 */
+#define OV5640_LENC_GMTRX_22 0x580e /* default 0x00 */
+#define OV5640_LENC_GMTRX_23 0x580f /* default 0x00 */
+#define OV5640_LENC_GMTRX_24 0x5810 /* default 0x08 -> all 0x03 */
+#define OV5640_LENC_GMTRX_25 0x5811 /* default 0x10 -> all 0x09 */
+#define OV5640_LENC_GMTRX_30 0x5812 /* default 0x10 -> all 0x07 */
+#define OV5640_LENC_GMTRX_31 0x5813 /* default 0x08 -> all 0x03 */
+#define OV5640_LENC_GMTRX_32 0x5814 /* default 0x00 */
+#define OV5640_LENC_GMTRX_33 0x5815 /* default 0x00 -> all 0x01 */
+#define OV5640_LENC_GMTRX_34 0x5816 /* default 0x08 -> all 0x03 */
+#define OV5640_LENC_GMTRX_35 0x5817 /* default 0x10 -> all 0x08 */
+#define OV5640_LENC_GMTRX_40 0x5818 /* default 0x10 -> all 0x0d */
+#define OV5640_LENC_GMTRX_41 0x5819 /* default 0x08 */
+#define OV5640_LENC_GMTRX_42 0x581a /* default 0x08 -> all 0x05 */
+#define OV5640_LENC_GMTRX_43 0x581b /* default 0x08 -> all 0x06 */
+#define OV5640_LENC_GMTRX_44 0x581c /* default 0x08 */
+#define OV5640_LENC_GMTRX_45 0x581d /* default 0x10 -> all 0x0e */
+#define OV5640_LENC_GMTRX_50 0x581e /* default 0x10 -> all 0x29 */
+#define OV5640_LENC_GMTRX_51 0x581f /* default 0x10 -> all 0x17 */
+#define OV5640_LENC_GMTRX_52 0x5820 /* default 0x10 -> all 0x11 */
+#define OV5640_LENC_GMTRX_53 0x5821 /* default 0x10 -> all 0x11 */
+#define OV5640_LENC_GMTRX_54 0x5822 /* default 0x10 -> all 0x15 */
+#define OV5640_LENC_GMTRX_55 0x5823 /* default 0x10 -> all 0x28 */
+#define OV5640_LENC_BRMATRX_00 0x5824 /* default 0xaa -> all 0x46 */
+#define OV5640_LENC_BRMATRX_01 0x5825 /* default 0xaa -> all 0x26 */
+#define OV5640_LENC_BRMATRX_02 0x5826 /* default 0xaa -> all 0x08 */
+#define OV5640_LENC_BRMATRX_03 0x5827 /* default 0xaa -> all 0x26 */
+#define OV5640_LENC_BRMATRX_04 0x5828 /* default 0xaa -> all 0x64 */
+#define OV5640_LENC_BRMATRX_05 0x5829 /* default 0xaa -> all 0x26 */
+#define OV5640_LENC_BRMATRX_06 0x582a /* default 0x99 -> all 0x24 */
+#define OV5640_LENC_BRMATRX_07 0x582b /* default 0x99 -> all 0x22 */
+#define OV5640_LENC_BRMATRX_08 0x582c /* default 0x99 -> all 0x24 */
+#define OV5640_LENC_BRMATRX_09 0x582d /* default 0xaa -> all 0x24 */
+#define OV5640_LENC_BRMATRX_20 0x582e /* default 0xaa -> all 0x06 */
+#define OV5640_LENC_BRMATRX_21 0x582f /* default 0x99 -> all 0x22 */
+#define OV5640_LENC_BRMATRX_22 0x5830 /* default 0x88 -> all 0x40 */
+#define OV5640_LENC_BRMATRX_23 0x5831 /* default 0x99 -> all 0x42 */
+#define OV5640_LENC_BRMATRX_24 0x5832 /* default 0xaa -> all 0x24 */
+#define OV5640_LENC_BRMATRX_30 0x5833 /* default 0xaa -> all 0x26 */
+#define OV5640_LENC_BRMATRX_31 0x5834 /* default 0x99 -> all 0x24 */
+#define OV5640_LENC_BRMATRX_32 0x5835 /* default 0x99 -> all 0x22 */
+#define OV5640_LENC_BRMATRX_33 0x5836 /* default 0x99 -> all 0x22 */
+#define OV5640_LENC_BRMATRX_34 0x5837 /* default 0xaa -> all 0x26 */
+#define OV5640_LENC_BRMATRX_40 0x5838 /* default 0xaa -> all 0x44 */
+#define OV5640_LENC_BRMATRX_41 0x5839 /* default 0xaa -> all 0x24 */
+#define OV5640_LENC_BRMATRX_42 0x583a /* default 0xaa -> all 0x26 */
+#define OV5640_LENC_BRMATRX_43 0x583b /* default 0xaa -> all 0x28 */
+#define OV5640_LENC_BRMATRX_44 0x583c /* default 0xaa -> all 0x42 */
+#define OV5640_LENC_BR_OFFSET 0x583d /* default 0x88 -> all 0xce */
+
+
+static struct ov5640_reg mode_2592x1944[] = {
+ /* PLL Control MIPI bit rate/lane = 672MHz, 16-bit mode.
+ * Output size: 2592x1944 (0, 0) - (2623, 1951),
+ * Line Length = 2844, Frame Length = 1968
+ * Scaling method: full resolution (dummy 16 pixel
+ * horizontal, 8 lines) 2608x1952 with dummy
+ */
+
+ {OV5640_SC_PLL_CTRL0, 0x10 | MIPI_MODE_8BIT },
+ {OV5640_SC_PLL_CTRL1, 0x11},
+ {OV5640_SC_PLL_CTRL2, 0x7d}, /* default 0x69 PLL multipier */
+ {OV5640_SC_PLL_CTRL3, 0x03 | (1<<4) }, /* default 0x03 PLL divided by 2 */
+
+ {OV5640_MIPI_CTRL_00, 0x04},
+ {OV5640_MIPI_PCLK_PERIOD, 0x0a},
+
+ {OV5640_ISP_CTRL_00, 0xa7},
+ {OV5640_ISP_CTRL_01, 0x83},
+ {OV5640_ISP_MUX_CTRL, 0x00},
+
+ /* Timing Control */
+ {OV5640_TIMING_HS_H, OV5640_ADDR_H(0) },
+ {OV5640_TIMING_HS_L, OV5640_ADDR_L(0) },
+ {OV5640_TIMING_VS_H, OV5640_ADDR_H(0) },
+ {OV5640_TIMING_VS_L, OV5640_ADDR_L(0) },
+ {OV5640_TIMING_HW_H, OV5640_ADDR_H(2623) },
+ {OV5640_TIMING_HW_L, OV5640_ADDR_L(2623) },
+ {OV5640_TIMING_VH_H, OV5640_ADDR_H(1951) },
+ {OV5640_TIMING_VH_L, OV5640_ADDR_L(1951) },
+ {OV5640_TIMING_DVPHO_H, OV5640_WIDTH_H(2592) },
+ {OV5640_TIMING_DVPHO_L, OV5640_WIDTH_L(2592) },
+ {OV5640_TIMING_DVPVO_H, OV5640_HEIGHT_H(1944) },
+ {OV5640_TIMING_DVPVO_L, OV5640_HEIGHT_L(1944) },
+ {OV5640_TIMING_HTS_H, OV5640_HTS_H(2844) },
+ {OV5640_TIMING_HTS_L, OV5640_HTS_L(2844) },
+ {OV5640_TIMING_VTS_H, OV5640_VTS_H(1968) },
+ {OV5640_TIMING_VTS_L, OV5640_VTS_L(1968) },
+ {OV5640_TIMING_HOFFSET_H, OV5640_H_OFFSET_H(16) }, // (2623-2592-1)/2
+ {OV5640_TIMING_HOFFSET_L, OV5640_H_OFFSET_L(16) },
+ {OV5640_TIMING_VOFFSET_H, OV5640_V_OFFSET_H(4) }, // (1951-1944-1)/2
+ {OV5640_TIMING_VOFFSET_L, OV5640_V_OFFSET_L(4) },
+ {OV5640_TIMING_X_INC, 0x11},
+ {OV5640_TIMING_Y_INC, 0x11},
+ {OV5640_TIMING_REG20, 0x40},
+ {OV5640_TIMING_REG21, 0},
+
+ /* magic registers */
+ {0x3612, 0x2b},
+ {0x3618, 0x04},
+ {0x3708, 0x64},
+ {0x3709, 0x12},
+ {0x370c, 0x00},
+
+ /* AEC/AGC Power Down Domain Control */
+ {OV5640_AEC_MAX_EXPO60_H, 0x07},
+ {OV5640_AEC_MAX_EXPO60_L, 0xb0},
+ {OV5640_AEC_B50_STEP_H, 0x01},
+ {OV5640_AEC_B50_STEP_L, 0x27},
+ {OV5640_AEC_B60_STEP_H, 0x00},
+ {OV5640_AEC_B60_STEP_L, 0xf6},
+ {OV5640_AEC_CTRL_0E, 0x06},
+ {OV5640_AEC_CTRL_0D, 0x08},
+ {OV5640_AEC_MAX_EXPO_H, 0x07},
+ {OV5640_AEC_MAX_EXPO_L, 0xb0},
+ {OV5640_AEC_CTRL_13, 0x43},
+ {OV5640_AEC_GAIN_CEILING_0, 0x00},
+ {OV5640_AEC_GAIN_CEILING_1, 0xf8},
+ {OV5640_AEC_CTRL_0F, 0x30},
+ {OV5640_AEC_CTRL_10, 0x28},
+ {OV5640_AEC_CTRL_1B, 0x30},
+ {OV5640_AEC_CTRL_1E, 0x26},
+ {OV5640_AEC_CTRL_11, 0x60},
+ {OV5640_AEC_CTRL_1F, 0x14},
+
+ {OV5640_SYSTEM_CTRL, 0x02},
+ {OV5640_TABLE_END, 0x0000}
+};
+
+static struct ov5640_reg mode_1920x1080[] = {
+ /* PLL Control MIPI bit rate/lane = 672MHz, 16-bit mode.
+ * Output size: 1936x1088 (336, 426) - (2287, 1529),
+ * Line Length = 2500, Frame Length = 1120.
+ * Scaling method: cropping from full resolution
+ * 1936x1088 with dummy pixels
+ */
+
+ {OV5640_SC_PLL_CTRL0, 0x10 | MIPI_MODE_8BIT },
+ {OV5640_SC_PLL_CTRL1, 0x11},
+ {OV5640_SC_PLL_CTRL2, 0x54}, /* default 0x69 PLL multipier */
+ {OV5640_SC_PLL_CTRL3, 0x03 | (1<<4) }, /* default 0x03 PLL divided by 2 */
+
+ {OV5640_MIPI_CTRL_00, 0x04},
+ {OV5640_MIPI_PCLK_PERIOD, 0x0a},
+
+ {OV5640_ISP_CTRL_00, 0xa7},
+ {OV5640_ISP_CTRL_01, 0x83},
+ {OV5640_ISP_MUX_CTRL, 0x00},
+
+ /* Timing Control */
+ {OV5640_TIMING_HS_H, OV5640_ADDR_H(336) },
+ {OV5640_TIMING_HS_L, OV5640_ADDR_L(336) },
+ {OV5640_TIMING_VS_H, OV5640_ADDR_H(426) },
+ {OV5640_TIMING_VS_L, OV5640_ADDR_L(426) },
+ {OV5640_TIMING_HW_H, OV5640_ADDR_H(2287) },
+ {OV5640_TIMING_HW_L, OV5640_ADDR_L(2287) },
+ {OV5640_TIMING_VH_H, OV5640_ADDR_H(1529) },
+ {OV5640_TIMING_VH_L, OV5640_ADDR_L(1529) },
+ {OV5640_TIMING_DVPHO_H, OV5640_WIDTH_H(1920) }, //1936
+ {OV5640_TIMING_DVPHO_L, OV5640_WIDTH_L(1920) },
+ {OV5640_TIMING_DVPVO_H, OV5640_HEIGHT_H(1080) }, //1088
+ {OV5640_TIMING_DVPVO_L, OV5640_HEIGHT_L(1080) },
+ {OV5640_TIMING_HTS_H, OV5640_HTS_H(2500) },
+ {OV5640_TIMING_HTS_L, OV5640_HTS_L(2500) },
+ {OV5640_TIMING_VTS_H, OV5640_VTS_H(1120) },
+ {OV5640_TIMING_VTS_L, OV5640_VTS_L(1120) },
+ {OV5640_TIMING_HOFFSET_H, OV5640_H_OFFSET_H(15) }, // (2287-336-1936-1)/2
+ {OV5640_TIMING_HOFFSET_L, OV5640_H_OFFSET_L(15) },
+ {OV5640_TIMING_VOFFSET_H, OV5640_V_OFFSET_H(11) }, // (1529-426-1088-1)/2
+ {OV5640_TIMING_VOFFSET_L, OV5640_V_OFFSET_L(11) },
+ {OV5640_TIMING_X_INC, 0x11},
+ {OV5640_TIMING_Y_INC, 0x11},
+ {OV5640_TIMING_REG20, 0x40},
+ {OV5640_TIMING_REG21, 0},
+
+ /* magic registers */
+ {0x3612, 0x2b},
+ {0x3618, 0x04},
+ {0x3708, 0x64},
+ {0x3709, 0x12},
+ {0x370c, 0x00},
+
+ /* AEC/AGC Power Down Domain Control */
+ {OV5640_AEC_MAX_EXPO60_H, 0x04},
+ {OV5640_AEC_MAX_EXPO60_L, 0x60},
+ {OV5640_AEC_B50_STEP_H, 0x01},
+ {OV5640_AEC_B50_STEP_L, 0x50},
+ {OV5640_AEC_B60_STEP_H, 0x01},
+ {OV5640_AEC_B60_STEP_L, 0x18},
+ {OV5640_AEC_CTRL_0E, 0x03},
+ {OV5640_AEC_CTRL_0D, 0x04},
+ {OV5640_AEC_MAX_EXPO_H, 0x04},
+ {OV5640_AEC_MAX_EXPO_L, 0x60},
+ {OV5640_AEC_CTRL_13, 0x43},
+ {OV5640_AEC_GAIN_CEILING_0, 0x00},
+ {OV5640_AEC_GAIN_CEILING_1, 0xf8},
+ {OV5640_AEC_CTRL_0F, 0x30},
+ {OV5640_AEC_CTRL_10, 0x28},
+ {OV5640_AEC_CTRL_1B, 0x30},
+ {OV5640_AEC_CTRL_1E, 0x26},
+ {OV5640_AEC_CTRL_11, 0x60},
+ {OV5640_AEC_CTRL_1F, 0x14},
+
+ {OV5640_SYSTEM_CTRL, 0x02},
+ {OV5640_TABLE_END, 0x0000}
+};
+
+static struct ov5640_reg mode_1280x960[] = {
+ /* PLL Control MIPI bit rate/lane = 448MHz, 16-bit mode.
+ * Output size: 1304x972 (0, 0) - (2623, 1951),
+ * Line Length = 1886, Frame Length = 990.
+ * Scaling method: subsampling in vertical and horizontal
+ * 1296x968 supports 2x2 binning
+ */
+
+ {OV5640_SC_PLL_CTRL0, 0x10 | MIPI_MODE_8BIT },
+ {OV5640_SC_PLL_CTRL1, 0x21},
+ {OV5640_SC_PLL_CTRL2, 0x70}, /* default 0x69 PLL multipier */
+ {OV5640_SC_PLL_CTRL3, 0x03 | (1<<4) }, /* default 0x03 PLL divided by 2 */
+
+ {OV5640_MIPI_CTRL_00, 0x04},
+ {OV5640_MIPI_PCLK_PERIOD, 0x10},
+
+ {OV5640_ISP_CTRL_00, 0xa7},
+ {OV5640_ISP_CTRL_01, 0x83},
+ {OV5640_ISP_MUX_CTRL, 0x00},
+
+ /* Timing Control */
+ {OV5640_TIMING_HS_H, OV5640_ADDR_H(0) },
+ {OV5640_TIMING_HS_L, OV5640_ADDR_L(0) },
+ {OV5640_TIMING_VS_H, OV5640_ADDR_H(0) },
+ {OV5640_TIMING_VS_L, OV5640_ADDR_L(0) },
+ {OV5640_TIMING_HW_H, OV5640_ADDR_H(2623) },
+ {OV5640_TIMING_HW_L, OV5640_ADDR_L(2623) },
+ {OV5640_TIMING_VH_H, OV5640_ADDR_H(1951) },
+ {OV5640_TIMING_VH_L, OV5640_ADDR_L(1951) },
+ {OV5640_TIMING_DVPHO_H, OV5640_WIDTH_H(1280) },
+ {OV5640_TIMING_DVPHO_L, OV5640_WIDTH_L(1280) },
+ {OV5640_TIMING_DVPVO_H, OV5640_HEIGHT_H(960) },
+ {OV5640_TIMING_DVPVO_L, OV5640_HEIGHT_L(960) },
+ {OV5640_TIMING_HTS_H, OV5640_HTS_H(1886) },
+ {OV5640_TIMING_HTS_L, OV5640_HTS_L(1886) },
+ {OV5640_TIMING_VTS_H, OV5640_VTS_H(990) },
+ {OV5640_TIMING_VTS_L, OV5640_VTS_L(990) },
+ {OV5640_TIMING_HOFFSET_H, OV5640_H_OFFSET_H(31) }, // (2623-0-(1280*2)-1)/2
+ {OV5640_TIMING_HOFFSET_L, OV5640_H_OFFSET_L(31) },
+ {OV5640_TIMING_VOFFSET_H, OV5640_V_OFFSET_H(15) }, // (1951-0-(960*2)-1)/2
+ {OV5640_TIMING_VOFFSET_L, OV5640_V_OFFSET_L(15) },
+ {OV5640_TIMING_X_INC, 0x11 | (3<<4) },
+ {OV5640_TIMING_Y_INC, 0x11 | (3<<4) },
+ {OV5640_TIMING_REG20, 0x40},
+ {OV5640_TIMING_REG21, REG21_BINNING_EN},
+
+ /* magic registers */
+ {0x3612, 0x29},
+ {0x3618, 0x00},
+ {0x3708, 0x62},
+ {0x3709, 0x52},
+ {0x370c, 0x03},
+
+ /* AEC/AGC Power Down Domain Control */
+ {OV5640_AEC_MAX_EXPO60_H, 0x03},
+ {OV5640_AEC_MAX_EXPO60_L, 0xd8},
+ {OV5640_AEC_B50_STEP_H, 0x01},
+ {OV5640_AEC_B50_STEP_L, 0x27},
+ {OV5640_AEC_B60_STEP_H, 0x00},
+ {OV5640_AEC_B60_STEP_L, 0xf6},
+ {OV5640_AEC_CTRL_0E, 0x03},
+ {OV5640_AEC_CTRL_0D, 0x04},
+ {OV5640_AEC_MAX_EXPO_H, 0x03},
+ {OV5640_AEC_MAX_EXPO_L, 0xd8},
+ {OV5640_AEC_CTRL_13, 0x43},
+ {OV5640_AEC_GAIN_CEILING_0, 0x00},
+ {OV5640_AEC_GAIN_CEILING_1, 0xf8},
+ {OV5640_AEC_CTRL_0F, 0x30},
+ {OV5640_AEC_CTRL_10, 0x28},
+ {OV5640_AEC_CTRL_1B, 0x30},
+ {OV5640_AEC_CTRL_1E, 0x26},
+ {OV5640_AEC_CTRL_11, 0x60},
+ {OV5640_AEC_CTRL_1F, 0x14},
+
+ {OV5640_SYSTEM_CTRL, 0x02},
+ {OV5640_TABLE_END, 0x0000}
+};
+
+static struct ov5640_reg mode_640x480[] = {
+ /* PLL Control MIPI bit rate/lane = ?MHz, 16-bit mode.
+ * Output size: 640x480 (0, 4) - (2623, 1951),
+ * Line Length = 1896, Frame Length = 984.
+ * Scaling method: subsampling from 1280x960
+ * 648x484 with dummy
+ * supports 2x2 binning
+ */
+
+ {OV5640_SC_PLL_CTRL0, 0x10 | MIPI_MODE_8BIT },
+ {OV5640_SC_PLL_CTRL1, 0x14},
+ {OV5640_SC_PLL_CTRL2, 0x70}, /* default 0x69 PLL multipier */
+ {OV5640_SC_PLL_CTRL3, 0x03 | (1<<4) }, /* default 0x03 PLL divided by 2 */
+
+ {OV5640_MIPI_CTRL_00, 0x04},
+ {OV5640_MIPI_PCLK_PERIOD, 0x44},
+
+ {OV5640_ISP_CTRL_00, 0xa7},
+ {OV5640_ISP_CTRL_01, 0x83 | ISP_SCALE_EN},
+ {OV5640_ISP_MUX_CTRL, 0x00},
+
+ /* Timing Control */
+ {OV5640_TIMING_HS_H, OV5640_ADDR_H(0) },
+ {OV5640_TIMING_HS_L, OV5640_ADDR_L(0) },
+ {OV5640_TIMING_VS_H, OV5640_ADDR_H(0) },
+ {OV5640_TIMING_VS_L, OV5640_ADDR_L(4) },
+ {OV5640_TIMING_HW_H, OV5640_ADDR_H(2623) },
+ {OV5640_TIMING_HW_L, OV5640_ADDR_L(2623) },
+ {OV5640_TIMING_VH_H, OV5640_ADDR_H(1947) },
+ {OV5640_TIMING_VH_L, OV5640_ADDR_L(1947) },
+ {OV5640_TIMING_DVPHO_H, OV5640_WIDTH_H(640) },
+ {OV5640_TIMING_DVPHO_L, OV5640_WIDTH_L(640) },
+ {OV5640_TIMING_DVPVO_H, OV5640_HEIGHT_H(480) },
+ {OV5640_TIMING_DVPVO_L, OV5640_HEIGHT_L(480) },
+ {OV5640_TIMING_HTS_H, OV5640_HTS_H(1896) },
+ {OV5640_TIMING_HTS_L, OV5640_HTS_L(1896) },
+ {OV5640_TIMING_VTS_H, OV5640_VTS_H(984) },
+ {OV5640_TIMING_VTS_L, OV5640_VTS_L(984) },
+ {OV5640_TIMING_HOFFSET_H, OV5640_H_OFFSET_H(31) }, // (2623-0-(640*2*2)-1)/2
+ {OV5640_TIMING_HOFFSET_L, OV5640_H_OFFSET_L(31) },
+ {OV5640_TIMING_VOFFSET_H, OV5640_V_OFFSET_H(11) }, // (1947-4-(480*2*2)-1)/2
+ {OV5640_TIMING_VOFFSET_L, OV5640_V_OFFSET_L(11) },
+ {OV5640_TIMING_X_INC, 0x11 | (3<<4) },
+ {OV5640_TIMING_Y_INC, 0x11 | (3<<4) },
+ {OV5640_TIMING_REG20, 0x40},
+ {OV5640_TIMING_REG21, REG21_BINNING_EN},
+
+ /* magic registers */
+ {0x3612, 0x29},
+ {0x3618, 0x00},
+ {0x3708, 0x64},
+ {0x3709, 0x52},
+ {0x370c, 0x03},
+
+ /* AEC/AGC Power Down Domain Control */
+ {OV5640_AEC_MAX_EXPO60_H, 0x03},
+ {OV5640_AEC_MAX_EXPO60_L, 0xd8},
+ {OV5640_AEC_B50_STEP_H, 0x01},
+ {OV5640_AEC_B50_STEP_L, 0x27},
+ {OV5640_AEC_B60_STEP_H, 0x00},
+ {OV5640_AEC_B60_STEP_L, 0xf6},
+ {OV5640_AEC_CTRL_0E, 0x03},
+ {OV5640_AEC_CTRL_0D, 0x04},
+ {OV5640_AEC_MAX_EXPO_H, 0x03},
+ {OV5640_AEC_MAX_EXPO_L, 0xd8},
+ {OV5640_AEC_CTRL_13, 0x43},
+ {OV5640_AEC_GAIN_CEILING_0, 0x00},
+ {OV5640_AEC_GAIN_CEILING_1, 0xf8},
+ {OV5640_AEC_CTRL_0F, 0x30},
+ {OV5640_AEC_CTRL_10, 0x28},
+ {OV5640_AEC_CTRL_1B, 0x30},
+ {OV5640_AEC_CTRL_1E, 0x26},
+ {OV5640_AEC_CTRL_11, 0x60},
+ {OV5640_AEC_CTRL_1F, 0x14},
+
+ {OV5640_SYSTEM_CTRL, 0x02},
+ {OV5640_TABLE_END, 0x0000},
+};
+
+static struct ov5640_reg mode_common_registers[] = {
+
+ /* SCCB Control */
+ {OV5640_SCCB_SYSTEM_CTRL, 0x03}, /* Clock from PLL */
+ {OV5640_SCCB_SCLK, 0x01}, /* PCLK = pll_clki, SCLK = pll_clki/2 */
+
+ /* System Control */
+ {OV5640_SYSTEM_CTRL, 0x02 | SYSTEM_CTRL_SRST }, /* Software reset */
+ {OV5640_TABLE_WAIT_MS, 5},
+ {OV5640_SYSTEM_CTRL, 0x02 | SYSTEM_CTRL_PDOWN }, /* Software power down */
+ {OV5640_SYSTEM_RESET_00, 0x00},
+ {OV5640_SYSTEM_RESET_01, 0x00},
+ {OV5640_SYSTEM_RESET_02, 0x1c},
+ {OV5640_SYSTEM_CLK_EN_00, 0xff},
+ {OV5640_SYSTEM_CLK_EN_02, 0xc3},
+ {OV5640_SYSTEM_MIPI_CTRL, 0x45},
+
+ {OV5640_SYSTEM_CTRL_2D, 0x60}, /* magic values */
+ {OV5640_SYSTEM_CTRL_2E, 0x08}, /* magic values */
+
+ /* Format Control */
+ {FMT_CTRL_00, FMT_YUV422 | OFMT_UYVY },
+
+ /* VCM Control */
+/* {OV5640_VCM_DEBUG_MODE_0, 0x08},*/
+/* {OV5640_VCM_DEBUG_MODE_1, 0x33},*/
+
+ /* 50/60Hz detector control */
+ {OV5640_5060_CTRL_01, 0x34},
+ {OV5640_5060_CTRL_04, 0x28},
+ {OV5640_5060_CTRL_05, 0x98},
+ {OV5640_5060_THRESHOLD_1_H, 0x00},
+ {OV5640_5060_THRESHOLD_1_L, 0x07},
+ {OV5640_5060_THRESHOLD_2_H, 0x00},
+ {OV5640_5060_THRESHOLD_2_L, 0x1c},
+ {OV5640_5060_SAMPLE_NUM_H, 0x9c},
+ {OV5640_5060_SAMPLE_NUM_L, 0x40},
+
+ /* BLC Control */
+ {OV5640_BLC_CTRL_01, 0x02},
+ {OV5640_BLC_CTRL_04, 0x06},
+
+ /* AWB Control */
+ {OV5640_AWB_CTRL_00, 0xff},
+ {OV5640_AWB_CTRL_01, 0xf2},
+ {OV5640_AWB_CTRL_02, 0x00},
+ {OV5640_AWB_CTRL_03, 0x14},
+ {OV5640_AWB_CTRL_04, 0x25},
+ {OV5640_AWB_CTRL_05, 0x24},
+ {OV5640_AWB_CTRL_06, 0x09},
+ {OV5640_AWB_CTRL_07, 0x09},
+ {OV5640_AWB_CTRL_08, 0x09},
+ {OV5640_AWB_CTRL_09, 0x75},
+ {OV5640_AWB_CTRL_10, 0x54},
+ {OV5640_AWB_CTRL_11, 0xe0},
+ {OV5640_AWB_CTRL_12, 0xb2},
+ {OV5640_AWB_CTRL_13, 0x42},
+ {OV5640_AWB_CTRL_14, 0x3d},
+ {OV5640_AWB_CTRL_15, 0x56},
+ {OV5640_AWB_CTRL_16, 0x46},
+ {OV5640_AWB_CTRL_17, 0xf8},
+ {OV5640_AWB_CTRL_18, 0x04},
+ {OV5640_AWB_CTRL_19, 0x70},
+ {OV5640_AWB_CTRL_20, 0xf0},
+ {OV5640_AWB_CTRL_21, 0xf0},
+ {OV5640_AWB_CTRL_22, 0x03},
+ {OV5640_AWB_CTRL_23, 0x01},
+ {OV5640_AWB_CTRL_24, 0x04},
+ {OV5640_AWB_CTRL_25, 0x12},
+ {OV5640_AWB_CTRL_26, 0x04},
+ {OV5640_AWB_CTRL_27, 0x00},
+ {OV5640_AWB_CTRL_28, 0x06},
+ {OV5640_AWB_CTRL_29, 0x82},
+ {OV5640_AWB_CTRL_30, 0x38},
+
+ /* CMX Control */
+ {OV5640_CMX1, 0x1e},
+ {OV5640_CMX2, 0x5b},
+ {OV5640_CMX3, 0x08},
+ {OV5640_CMX4, 0x0a},
+ {OV5640_CMX5, 0x7e},
+ {OV5640_CMX6, 0x88},
+ {OV5640_CMX7, 0x7c},
+ {OV5640_CMX8, 0x6c},
+ {OV5640_CMX9, 0x10},
+ {OV5640_CMX_SIGN_0, 0x01},
+ {OV5640_CMX_SIGN_1, 0x98},
+
+ /* CIP Control */
+ {OV5640_CIP_SH_MT_THRES_1, 0x08},
+ {OV5640_CIP_SH_MT_THRES_2, 0x30},
+ {OV5640_CIP_SH_MT_OFFSET_1, 0x10},
+ {OV5640_CIP_SH_MT_OFFSET_2, 0x00},
+ {OV5640_CIP_DNS_THRES_1, 0x08},
+ {OV5640_CIP_DNS_THRES_2, 0x30},
+ {OV5640_CIP_DNS_OFFSET_1, 0x08},
+ {OV5640_CIP_DNS_OFFSET_2, 0x16},
+ {OV5640_CIP_SH_TH_THRES_1, 0x08},
+ {OV5640_CIP_SH_TH_THRES_2, 0x30},
+ {OV5640_CIP_SH_TH_OFFSET_1, 0x04},
+ {OV5640_CIP_SH_TH_OFFSET_2, 0x06},
+
+ /* Gamma Control */
+ {OV5640_GAMMA_CTRL_00, 0x01},
+ {OV5640_GAMMA_YST_00, 0x08},
+ {OV5640_GAMMA_YST_01, 0x14},
+ {OV5640_GAMMA_YST_02, 0x28},
+ {OV5640_GAMMA_YST_03, 0x51},
+ {OV5640_GAMMA_YST_04, 0x65},
+ {OV5640_GAMMA_YST_05, 0x71},
+ {OV5640_GAMMA_YST_06, 0x7d},
+ {OV5640_GAMMA_YST_07, 0x87},
+ {OV5640_GAMMA_YST_08, 0x91},
+ {OV5640_GAMMA_YST_09, 0x9a},
+ {OV5640_GAMMA_YST_0A, 0xaa},
+ {OV5640_GAMMA_YST_0B, 0xb8},
+ {OV5640_GAMMA_YST_0C, 0xcd},
+ {OV5640_GAMMA_YST_0D, 0xdd},
+ {OV5640_GAMMA_YST_0E, 0xea},
+ {OV5640_GAMMA_YST_0F, 0x1d},
+
+ /* SDE Control */
+ {OV5640_SDE_CTRL_0, 0x02},
+ {OV5640_SDE_CTRL_3, 0x40},
+ {OV5640_SDE_CTRL_4, 0x10},
+ {OV5640_SDE_CTRL_9, 0x10},
+ {OV5640_SDE_CTRL_10, 0x00},
+ {OV5640_SDE_CTRL_11, 0xf8},
+
+ /* LENC Control */
+ {OV5640_LENC_GMTRX_00, 0x23},
+ {OV5640_LENC_GMTRX_01, 0x14},
+ {OV5640_LENC_GMTRX_02, 0x0f},
+ {OV5640_LENC_GMTRX_03, 0x0f},
+ {OV5640_LENC_GMTRX_04, 0x12},
+ {OV5640_LENC_GMTRX_05, 0x26},
+ {OV5640_LENC_GMTRX_10, 0x0c},
+ {OV5640_LENC_GMTRX_11, 0x08},
+ {OV5640_LENC_GMTRX_12, 0x05},
+ {OV5640_LENC_GMTRX_13, 0x05},
+ {OV5640_LENC_GMTRX_14, 0x08},
+ {OV5640_LENC_GMTRX_15, 0x0d},
+ {OV5640_LENC_GMTRX_20, 0x08},
+ {OV5640_LENC_GMTRX_21, 0x03},
+ {OV5640_LENC_GMTRX_22, 0x00},
+ {OV5640_LENC_GMTRX_23, 0x00},
+ {OV5640_LENC_GMTRX_24, 0x03},
+ {OV5640_LENC_GMTRX_25, 0x09},
+ {OV5640_LENC_GMTRX_30, 0x07},
+ {OV5640_LENC_GMTRX_31, 0x03},
+ {OV5640_LENC_GMTRX_32, 0x00},
+ {OV5640_LENC_GMTRX_33, 0x01},
+ {OV5640_LENC_GMTRX_34, 0x03},
+ {OV5640_LENC_GMTRX_35, 0x08},
+ {OV5640_LENC_GMTRX_40, 0x0d},
+ {OV5640_LENC_GMTRX_41, 0x08},
+ {OV5640_LENC_GMTRX_42, 0x05},
+ {OV5640_LENC_GMTRX_43, 0x06},
+ {OV5640_LENC_GMTRX_44, 0x08},
+ {OV5640_LENC_GMTRX_45, 0x0e},
+ {OV5640_LENC_GMTRX_50, 0x29},
+ {OV5640_LENC_GMTRX_51, 0x17},
+ {OV5640_LENC_GMTRX_52, 0x11},
+ {OV5640_LENC_GMTRX_53, 0x11},
+ {OV5640_LENC_GMTRX_54, 0x15},
+ {OV5640_LENC_GMTRX_55, 0x28},
+ {OV5640_LENC_BRMATRX_00, 0x46},
+ {OV5640_LENC_BRMATRX_01, 0x26},
+ {OV5640_LENC_BRMATRX_02, 0x08},
+ {OV5640_LENC_BRMATRX_03, 0x26},
+ {OV5640_LENC_BRMATRX_04, 0x64},
+ {OV5640_LENC_BRMATRX_05, 0x26},
+ {OV5640_LENC_BRMATRX_06, 0x24},
+ {OV5640_LENC_BRMATRX_07, 0x22},
+ {OV5640_LENC_BRMATRX_08, 0x24},
+ {OV5640_LENC_BRMATRX_09, 0x24},
+ {OV5640_LENC_BRMATRX_20, 0x06},
+ {OV5640_LENC_BRMATRX_21, 0x22},
+ {OV5640_LENC_BRMATRX_22, 0x40},
+ {OV5640_LENC_BRMATRX_23, 0x42},
+ {OV5640_LENC_BRMATRX_24, 0x24},
+ {OV5640_LENC_BRMATRX_30, 0x26},
+ {OV5640_LENC_BRMATRX_31, 0x24},
+ {OV5640_LENC_BRMATRX_32, 0x22},
+ {OV5640_LENC_BRMATRX_33, 0x22},
+ {OV5640_LENC_BRMATRX_34, 0x26},
+ {OV5640_LENC_BRMATRX_40, 0x44},
+ {OV5640_LENC_BRMATRX_41, 0x24},
+ {OV5640_LENC_BRMATRX_42, 0x26},
+ {OV5640_LENC_BRMATRX_43, 0x28},
+ {OV5640_LENC_BRMATRX_44, 0x42},
+ {OV5640_LENC_BR_OFFSET, 0xce},
+
+ /* magic registers */
+ {0x3620, 0x52},
+ {0x3621, 0xe0},
+ {0x3622, 0x01},
+ {0x3630, 0x36},
+ {0x3631, 0x0e},
+ {0x3632, 0xe2},
+ {0x3633, 0x12},
+ {0x3634, 0x40},
+ {0x3635, 0x13},
+ {0x3636, 0x03},
+ {0x3703, 0x5a},
+ {0x3704, 0xa0},
+ {0x3705, 0x1a},
+ {0x370b, 0x60},
+ {0x3715, 0x78},
+ {0x3717, 0x01},
+ {0x371b, 0x20},
+ {0x3731, 0x12},
+ {0x3901, 0x0a},
+ {0x3905, 0x02},
+ {0x3906, 0x10},
+ {0x471c, 0x50},
+
+ {OV5640_TABLE_END, 0x0000},
+};
+
+enum {
+ OV5640_MODE_640x480,
+ OV5640_MODE_1280x960,
+ OV5640_MODE_1920x1080,
+ OV5640_MODE_2592x1944,
+ OV5640_SIZE_LAST,
+};
+
+static struct ov5640_reg *mode_table[] = {
+ mode_640x480,
+ mode_1280x960,
+ mode_1920x1080,
+ mode_2592x1944,
+};
+
+static int pwn_gpio, rst_gpio;
+static int test_pattern;
+
+module_param(test_pattern, int, 0644);
+
+static struct ov5640_reg tp_cbars[] = {
+ {OV5640_ISP_TEST, ISP_TEST_EN | ISP_TEST_00 | ISP_TEST_TRANSPARENT | ISP_TEST_ROLLING },
+ {OV5640_TABLE_END, 0x0000}
+};
+
+#define to_ov5640(sd) container_of(sd, struct ov5640_priv, subdev)
+
+#define SIZEOF_I2C_TRANSBUF 32
+
+struct ov5640_priv {
+ struct v4l2_subdev subdev;
+ struct media_pad pads[MIPI_CSI2_SENS_VCX_PADS_NUM];
+ struct v4l2_mbus_framefmt mf;
+
+ int ident;
+ u16 chip_id;
+ u8 revision;
+ bool on;
+
+ int mode;
+
+ struct i2c_client *client;
+ u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF];
+};
+
+static const struct v4l2_frmsize_discrete ov5640_frmsizes[] = {
+ {640, 480},
+ {1280, 960},
+ {1920, 1080},
+ {2592, 1944},
+};
+
+static uint32_t ov5640_codes[] = {
+ MEDIA_BUS_FMT_UYVY8_2X8,
+};
+
+static int ov5640_find_mode(u32 width, u32 height)
+{
+ int i;
+
+ for (i = 0; i < OV5640_SIZE_LAST; i++) {
+ if ((ov5640_frmsizes[i].width >= width) &&
+ (ov5640_frmsizes[i].height >= height))
+ break;
+ }
+
+ /* If not found, select biggest */
+ if (i >= OV5640_SIZE_LAST)
+ i = OV5640_SIZE_LAST - 1;
+
+ return i;
+}
+
+static int ov5640_read_reg(struct i2c_client *client, u16 addr, u8 *val)
+{
+ int err;
+ struct i2c_msg msg[2];
+ unsigned char data[3];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = data;
+
+ /* high byte goes out first */
+ data[0] = (u8) (addr >> 8);
+ data[1] = (u8) (addr & 0xff);
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = data + 2;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err != 2)
+ return -EINVAL;
+
+ *val = data[2];
+
+ return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov5640_write_reg(struct i2c_client *client, u16 addr, u8 value)
+{
+ int count;
+ struct i2c_msg msg[1];
+ unsigned char data[4];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ data[0] = addr;
+ data[1] = (u8) (addr & 0xff);
+ data[2] = value;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 3;
+ msg[0].buf = data;
+
+ count = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (count == ARRAY_SIZE(msg)) {
+ return 0;
+ }
+ dev_err(&client->dev,
+ "ov5840: i2c transfer failed, addr: %x, value: %02x\n",
+ addr, (u32)value);
+ return -EIO;
+}
+#endif
+
+static int ov5640_write_bulk_reg(struct i2c_client *client, u8 *data, int len)
+{
+ int err;
+ struct i2c_msg msg;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = len;
+ msg.buf = data;
+
+ err = i2c_transfer(client->adapter, &msg, 1);
+ if (err == 1)
+ return 0;
+
+ dev_err(&client->dev, "ov5640: i2c transfer failed at %x\n",
+ (int)data[0] << 8 | data[1]);
+
+ return err;
+}
+
+static int ov5640_write_table(struct ov5640_priv *priv,
+ struct ov5640_reg table[])
+{
+ int err;
+ struct ov5640_reg *next, *n_next;
+ u8 *b_ptr = priv->i2c_trans_buf;
+ unsigned int buf_filled = 0;
+ u16 val;
+
+ for (next = table; next->addr != OV5640_TABLE_END; next++) {
+ if (next->addr == OV5640_TABLE_WAIT_MS) {
+ msleep(next->val);
+ continue;
+ }
+
+ val = next->val;
+
+ if (!buf_filled) {
+ b_ptr = priv->i2c_trans_buf;
+ *b_ptr++ = next->addr >> 8;
+ *b_ptr++ = next->addr & 0xff;
+ buf_filled = 2;
+ }
+ *b_ptr++ = val;
+ buf_filled++;
+
+ n_next = next + 1;
+ if (n_next->addr != OV5640_TABLE_END &&
+ n_next->addr != OV5640_TABLE_WAIT_MS &&
+ buf_filled < SIZEOF_I2C_TRANSBUF &&
+ n_next->addr == next->addr + 1) {
+ continue;
+ }
+
+ err = ov5640_write_bulk_reg(priv->client,
+ priv->i2c_trans_buf, buf_filled);
+ if (err)
+ return err;
+
+ buf_filled = 0;
+ }
+ return 0;
+}
+
+static void ov5640_set_default_fmt(struct ov5640_priv *priv)
+{
+ struct v4l2_mbus_framefmt *mf = &priv->mf;
+
+ mf->width = ov5640_frmsizes[OV5640_MODE_1920x1080].width;
+ mf->height = ov5640_frmsizes[OV5640_MODE_1920x1080].height;
+ mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->field = V4L2_FIELD_NONE;
+ mf->colorspace = V4L2_COLORSPACE_SRGB;
+}
+
+/* Start/Stop streaming from the device */
+static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct ov5640_priv *priv = to_ov5640(sd);
+ int ret = 0;
+
+ if (!enable) {
+ ov5640_set_default_fmt(priv);
+ return 0;
+ }
+
+ ret = ov5640_write_table(priv, mode_common_registers);
+ if (ret)
+ return ret;
+
+ ret = ov5640_write_table(priv, mode_table[priv->mode]);
+ if (ret)
+ return ret;
+
+ if (test_pattern == 1) {
+ ret = ov5640_write_table(priv, tp_cbars);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int ov5640_try_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ int mode;
+
+ mode = ov5640_find_mode(mf->width, mf->height);
+ mf->width = ov5640_frmsizes[mode].width;
+ mf->height = ov5640_frmsizes[mode].height;
+
+ mf->field = V4L2_FIELD_NONE;
+ mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->colorspace = V4L2_COLORSPACE_SRGB;
+
+ return 0;
+}
+
+static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index >= ARRAY_SIZE(ov5640_codes))
+ return -EINVAL;
+
+ code->code = ov5640_codes[code->index];
+ return 0;
+}
+
+static int ov5640_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct ov5640_priv *priv = to_ov5640(sd);
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad) {
+ return -EINVAL;
+ }
+
+ memcpy(mf, &priv->mf, sizeof(struct v4l2_mbus_framefmt));
+
+ return 0;
+}
+
+/* set the format we will capture in */
+static int ov5640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ struct ov5640_priv *priv = to_ov5640(sd);
+ int ret;
+
+ ret = ov5640_try_fmt(sd, mf);
+ if (ret < 0)
+ return ret;
+
+ priv->mode = ov5640_find_mode(mf->width, mf->height);
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
+ memcpy(&priv->mf, mf, sizeof(struct v4l2_mbus_framefmt));
+
+ return 0;
+}
+
+static int ov5640_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct ov5640_priv *sensor = to_ov5640(sd);
+
+ sensor->on = on;
+
+ return 0;
+}
+
+static int ov5640_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ return 0;
+}
+
+/* Get chip identification */
+static int ov5640_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *id)
+{
+ struct ov5640_priv *priv = to_ov5640(sd);
+
+ id->ident = priv->ident;
+ id->revision = priv->revision;
+
+ return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov5640_get_register(struct v4l2_subdev *sd,
+ struct v4l2_dbg_register *reg)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret;
+ u8 val;
+
+ if (reg->reg & ~0xffff)
+ return -EINVAL;
+
+ reg->size = 2;
+
+ ret = ov5640_read_reg(client, reg->reg, &val);
+ if (ret)
+ return ret;
+
+ reg->val = (__u64)val;
+
+ return ret;
+}
+
+static int ov5640_set_register(struct v4l2_subdev *sd,
+ struct v4l2_dbg_register *reg)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ if (reg->reg & ~0xffff || reg->val & ~0xff)
+ return -EINVAL;
+
+ return ov5640_write_reg(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov5640_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+ struct v4l2_mbus_frame_desc *fd)
+{
+ return 0;
+}
+
+static int ov5640_set_frame_desc(struct v4l2_subdev *sd,
+ unsigned int pad,
+ struct v4l2_mbus_frame_desc *fd)
+{
+ return 0;
+}
+
+static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index >= OV5640_SIZE_LAST)
+ return -EINVAL;
+
+ fse->min_width = fse->max_width = ov5640_frmsizes[fse->index].width;
+ fse->min_height = fse->max_height = ov5640_frmsizes[fse->index].height;
+
+ return 0;
+}
+
+static int ov5640_enum_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ if (fie->index > 1)
+ return -EINVAL;
+
+ /* Force 30 fps */
+ fie->interval.numerator = 1;
+ fie->interval.denominator = 30;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ov5640_pad_ops = {
+ .enum_mbus_code = ov5640_enum_mbus_code,
+ .set_fmt = ov5640_set_fmt,
+ .get_fmt = ov5640_get_fmt,
+ .get_frame_desc = ov5640_get_frame_desc,
+ .set_frame_desc = ov5640_set_frame_desc,
+ .enum_frame_size = ov5640_enum_framesizes,
+ .enum_frame_interval = ov5640_enum_frame_interval,
+};
+
+static struct v4l2_subdev_video_ops ov5640_video_ops = {
+ .s_stream = ov5640_s_stream,
+ .querystd = ov5640_querystd,
+};
+
+static struct v4l2_subdev_core_ops ov5640_core_ops = {
+ .g_chip_ident = ov5640_g_chip_ident,
+ .s_power = ov5640_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .g_register = ov5640_get_register,
+ .s_register = ov5640_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5640_subdev_ops = {
+ .core = &ov5640_core_ops,
+ .video = &ov5640_video_ops,
+ .pad = &ov5640_pad_ops,
+};
+
+int ov5640_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ return 0;
+}
+
+struct media_entity_operations ov5640_entity_ops = {
+ .link_setup = ov5640_link_setup,
+};
+
+
+static inline void ov5640_power_down(int enable)
+{
+ if (pwn_gpio < 0)
+ return;
+
+ if (!enable)
+ gpio_set_value_cansleep(pwn_gpio, 0);
+ else
+ gpio_set_value_cansleep(pwn_gpio, 1);
+
+ msleep(2);
+}
+
+static void ov5640_reset(void)
+{
+ if (rst_gpio < 0 || pwn_gpio < 0)
+ return;
+
+ /* camera reset */
+ gpio_set_value(rst_gpio, 1);
+
+ /* camera power dowmn */
+ gpio_set_value(pwn_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(rst_gpio, 0);
+ msleep(1);
+
+ gpio_set_value(pwn_gpio, 0);
+ msleep(5);
+
+ gpio_set_value(rst_gpio, 1);
+ msleep(5);
+}
+
+/*
+ * i2c_driver function
+ */
+static int ov5640_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct pinctrl *pinctrl;
+ struct device *dev = &client->dev;
+ struct v4l2_subdev *sd;
+ int retval;
+ u8 chip_id_high, chip_id_low;
+
+ struct ov5640_priv *priv;
+
+ priv = devm_kzalloc(&client->dev, sizeof(struct ov5640_priv),
+ GFP_KERNEL);
+ if (!priv) {
+ dev_err(&client->dev, "Failed to allocate private data!\n");
+ return -ENOMEM;
+ }
+
+ /* init using default mode */
+ priv->mode = 2;
+ ov5640_set_default_fmt(priv);
+
+ /* ov5640 pinctrl */
+ pinctrl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(dev, "no pin available\n");
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_warn(dev, "no sensor pwdn pin available");
+ } else {
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_mipi_pwdn");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set power pin\n");
+ dev_warn(dev, "retval=%d\n", retval);
+ return retval;
+ }
+ }
+
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio))
+ dev_warn(dev, "no sensor reset pin available");
+ else {
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "ov5640_mipi_reset");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set reset pin\n");
+ return retval;
+ }
+ }
+
+ priv->client = client;
+
+ ov5640_reset();
+
+ ov5640_power_down(0);
+
+ retval = ov5640_read_reg(client, OV5640_CHIP_ID_H, &chip_id_high);
+ if (retval < 0 || chip_id_high != 0x56) {
+ pr_warning("camera ov5640_mipi is not found\n");
+ return -ENODEV;
+ }
+ retval = ov5640_read_reg(client, OV5640_CHIP_ID_L, &chip_id_low);
+ if (retval < 0 || chip_id_low != 0x40) {
+ pr_warning("camera ov5640_mipi is not found\n");
+ return -ENODEV;
+ }
+
+ sd = &priv->subdev;
+ v4l2_i2c_subdev_init(sd, client, &ov5640_subdev_ops);
+
+ ov5640_s_stream(sd, 1);
+
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ priv->pads[MIPI_CSI2_SENS_VC0_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ priv->pads[MIPI_CSI2_SENS_VC1_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ priv->pads[MIPI_CSI2_SENS_VC2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ priv->pads[MIPI_CSI2_SENS_VC3_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+ retval = media_entity_pads_init(&sd->entity, MIPI_CSI2_SENS_VCX_PADS_NUM,
+ priv->pads);
+ if (retval < 0)
+ return retval;
+
+ sd->entity.ops = &ov5640_entity_ops;
+ retval = v4l2_async_register_subdev(&priv->subdev);
+
+ if (retval < 0)
+ dev_err(&client->dev, "%s--Async register failed, ret=%d\n", __func__, retval);
+
+ pr_info("camera ov5640_mipi is found, ret: %d\n", retval);
+ return retval;
+}
+
+static int ov5640_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static const struct i2c_device_id ov5640_id[] = {
+ {"ov5640_mipi", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ov5640_id);
+
+static struct i2c_driver ov5640_i2c_driver = {
+ .driver = {
+ .name = "ov5640_mipi_nv",
+ },
+ .probe = ov5640_probe,
+ .remove = ov5640_remove,
+ .id_table = ov5640_id,
+};
+
+static int __init ov5640_module_init(void)
+{
+ return i2c_add_driver(&ov5640_i2c_driver);
+}
+
+static void __exit ov5640_module_exit(void)
+{
+ i2c_del_driver(&ov5640_i2c_driver);
+}
+
+module_init(ov5640_module_init);
+module_exit(ov5640_module_exit);
+
+MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV5640");
+MODULE_AUTHOR("Andrew Chew <achew@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/mxc/capture/tc358743_h2c.c b/drivers/media/platform/mxc/capture/tc358743_h2c.c
new file mode 100644
index 000000000000..8d2e8f7f1ab8
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/tc358743_h2c.c
@@ -0,0 +1,3401 @@
+/*
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * Modifyed by: Edison Fernández <edison.fernandez@ridgerun.com>
+ * Added support to use it with Nitrogen6x
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/fsl_devices.h>
+#include <linux/mutex.h>
+#include <linux/mipi_csi2.h>
+#include <linux/pwm.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-int-device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+//#include <mach/audmux.h>
+#include <linux/slab.h>
+#include "mxc_v4l2_capture.h"
+
+#define CODEC_CLOCK 16500000
+/* SSI clock sources */
+#define IMX_SSP_SYS_CLK 0
+
+
+#define TC358743_VOLTAGE_ANALOG 2800000
+#define TC358743_VOLTAGE_DIGITAL_CORE 1500000
+#define TC358743_VOLTAGE_DIGITAL_IO 1800000
+
+#define MIN_FPS 30
+#define MAX_FPS 60
+#define DEFAULT_FPS 60
+
+#define TC358743_XCLK_MIN 27000000
+#define TC358743_XCLK_MAX 42000000
+
+#define TC358743_CHIP_ID_HIGH_BYTE 0x0
+#define TC358743_CHIP_ID_LOW_BYTE 0x0
+#define TC3587430_HDMI_DETECT 0x0f //0x10
+
+#define TC_VOLTAGE_ANALOG 2800000
+#define TC_VOLTAGE_DIGITAL_CORE 1500000
+#define TC_VOLTAGE_DIGITAL_IO 1800000
+
+enum tc358743_mode {
+ tc358743_mode_INIT, /*only for sensor init*/
+ tc358743_mode_INIT1, /*only for sensor init*/
+ tc358743_mode_480P_720_480,
+ tc358743_mode_720P_60_1280_720,
+ tc358743_mode_480P_640_480,
+ tc358743_mode_1080P_1920_1080,
+ tc358743_mode_INIT2, /*only for sensor init*/
+ tc358743_mode_INIT3, /*only for sensor init*/
+ tc358743_mode_INIT4, /*only for sensor init*/
+ tc358743_mode_INIT5, /*only for sensor init*/
+ tc358743_mode_INIT6, /*only for sensor init*/
+ tc358743_mode_720P_1280_720,
+ tc358743_mode_MAX ,
+};
+
+enum tc358743_frame_rate {
+ tc358743_60_fps,
+ tc358743_30_fps,
+ tc358743_max_fps
+};
+
+struct reg_value {
+ u16 u16RegAddr;
+ u32 u32Val;
+ u32 u32Mask;
+ u8 u8Length;
+ u32 u32Delay_ms;
+};
+
+struct tc358743_mode_info {
+ enum tc358743_mode mode;
+ u32 width;
+ u32 height;
+ u32 vformat;
+ u32 fps;
+ u32 lanes;
+ u32 freq;
+ struct reg_value *init_data_ptr;
+ u32 init_data_size;
+ __u32 flags;
+};
+
+static struct delayed_work det_work;
+static struct sensor_data tc358743_data;
+static int pwn_gpio, rst_gpio;
+static struct regulator *io_regulator;
+static struct regulator *core_regulator;
+static struct regulator *analog_regulator;
+static struct regulator *gpo_regulator;
+
+static u16 hpd_active = 1;
+
+#define DET_WORK_TIMEOUT_DEFAULT 100
+#define DET_WORK_TIMEOUT_DEFERRED 2000
+#define MAX_BOUNCE 5
+
+static DEFINE_MUTEX(access_lock);
+static int det_work_disable = 0;
+static int det_work_timeout = DET_WORK_TIMEOUT_DEFAULT;
+static u32 hdmi_mode = 0, lock = 0, bounce = 0, fps = 0, audio = 2;
+
+static int tc358743_init_mode(enum tc358743_frame_rate frame_rate,
+ enum tc358743_mode mode);
+
+static int tc358743_toggle_hpd(int active);
+
+static void tc_standby(s32 enable)
+{
+ if (gpio_is_valid(pwn_gpio))
+ gpio_set_value(pwn_gpio, enable ? 1 : 0);
+ pr_debug("tc_standby: powerdown=%x, power_gp=0x%x\n", enable, pwn_gpio);
+ msleep(2);
+}
+
+static void tc_reset(void)
+{
+ /* camera reset */
+ gpio_set_value(rst_gpio, 1);
+
+ /* camera power dowmn */
+ if (gpio_is_valid(pwn_gpio)) {
+ gpio_set_value(pwn_gpio, 1);
+ msleep(5);
+
+ gpio_set_value(pwn_gpio, 0);
+ }
+ msleep(5);
+
+ gpio_set_value(rst_gpio, 0);
+ msleep(1);
+
+ gpio_set_value(rst_gpio, 1);
+ msleep(20);
+
+ if (gpio_is_valid(pwn_gpio))
+ gpio_set_value(pwn_gpio, 1);
+}
+
+static int tc_power_on(struct device *dev)
+{
+ int ret = 0;
+
+ io_regulator = devm_regulator_get(dev, "DOVDD");
+ if (!IS_ERR(io_regulator)) {
+ regulator_set_voltage(io_regulator,
+ TC_VOLTAGE_DIGITAL_IO,
+ TC_VOLTAGE_DIGITAL_IO);
+ ret = regulator_enable(io_regulator);
+ if (ret) {
+ pr_err("%s:io set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:io set voltage ok\n", __func__);
+ }
+ } else {
+ pr_err("%s: cannot get io voltage error\n", __func__);
+ io_regulator = NULL;
+ }
+
+ core_regulator = devm_regulator_get(dev, "DVDD");
+ if (!IS_ERR(core_regulator)) {
+ regulator_set_voltage(core_regulator,
+ TC_VOLTAGE_DIGITAL_CORE,
+ TC_VOLTAGE_DIGITAL_CORE);
+ ret = regulator_enable(core_regulator);
+ if (ret) {
+ pr_err("%s:core set voltage error\n", __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:core set voltage ok\n", __func__);
+ }
+ } else {
+ core_regulator = NULL;
+ pr_err("%s: cannot get core voltage error\n", __func__);
+ }
+
+ analog_regulator = devm_regulator_get(dev, "AVDD");
+ if (!IS_ERR(analog_regulator)) {
+ regulator_set_voltage(analog_regulator,
+ TC_VOLTAGE_ANALOG,
+ TC_VOLTAGE_ANALOG);
+ ret = regulator_enable(analog_regulator);
+ if (ret) {
+ pr_err("%s:analog set voltage error\n",
+ __func__);
+ return ret;
+ } else {
+ dev_dbg(dev,
+ "%s:analog set voltage ok\n", __func__);
+ }
+ } else {
+ analog_regulator = NULL;
+ pr_err("%s: cannot get analog voltage error\n", __func__);
+ }
+
+ return ret;
+}
+
+static void det_work_enable(int i)
+{
+ mutex_lock(&access_lock);
+ if (i) {
+ det_work_timeout = DET_WORK_TIMEOUT_DEFERRED;
+ schedule_delayed_work(&(det_work), msecs_to_jiffies(det_work_timeout));
+ det_work_disable = 0;
+ } else {
+ det_work_disable = 1;
+ det_work_timeout = DET_WORK_TIMEOUT_DEFERRED;
+ }
+ mutex_unlock(&access_lock);
+ pr_debug("%s: %d %d\n", __func__, det_work_disable, det_work_timeout);
+}
+
+static u8 cHDMIEDID[256] = {
+ /* FIXME! This is the edid that my ASUS HDMI monitor returns */
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x69, 0xf3, 0x24, 0xd6, 0x12, 0x00, 0x00,
+ 0x16, 0x16, 0x01, 0x03, 0x80, 0x34, 0x1d, 0x78, 0x2a, 0xc7, 0x20, 0xa4, 0x55, 0x49, 0x99, 0x27,
+ 0x13, 0x50, 0x54, 0xbf, 0xef, 0x00, 0x71, 0x4f, 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
+ 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x09, 0x25, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x36, 0x4c,
+ 0x4d, 0x54, 0x46, 0x30, 0x30, 0x34, 0x38, 0x32, 0x32, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x37,
+ 0x4b, 0x1e, 0x55, 0x10, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x48, 0x32, 0x34, 0x32, 0x48, 0x0a, 0x20, 0x01, 0x78,
+ 0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03, 0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
+ 0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x07, 0x01, 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
+ 0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0x09, 0x25,
+ 0x21, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
+ 0x09, 0x25, 0x21, 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
+ 0x55, 0x40, 0x09, 0x25, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
+ 0x0c, 0x40, 0x55, 0x00, 0x09, 0x25, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+};
+
+/*!
+ * Maintains the information on the current state of the sesor.
+ */
+
+static struct reg_value tc358743_setting_YUV422_2lane_30fps_720P_1280_720_125MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000004, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000040, 0x00000000, 2, 0},
+ {0x0014, 0x00000000, 0x00000000, 2, 0},
+ {0x0016, 0x000005ff, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x0000402d, 0x00000000, 2, 0},
+ {0x0022, 0x00000213, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00000e00, 0x00000000, 4, 0},
+ {0x0214, 0x00000001, 0x00000000, 4, 0},
+ {0x0218, 0x00000801, 0x00000000, 4, 0},
+ {0x021c, 0x00000001, 0x00000000, 4, 0},
+ {0x0220, 0x00000001, 0x00000000, 4, 0},
+ {0x0224, 0x00004800, 0x00000000, 4, 0},
+ {0x0228, 0x00000005, 0x00000000, 4, 0},
+ {0x022c, 0x00000000, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, //non-continuous clock
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa300be82, 0x00000000, 4, 0},
+// HDMI Interrupt Mask
+ {0x8502, 0x00000001, 0x00000000, 1, 0},
+ {0x8512, 0x000000fe, 0x00000000, 1, 0},
+ {0x8514, 0x00000000, 0x00000000, 1, 0},
+ {0x8515, 0x00000000, 0x00000000, 1, 0},
+ {0x8516, 0x00000000, 0x00000000, 1, 0},
+// HDMI Audio RefClk (26 MHz)
+ {0x8531, 0x00000001, 0x00000000, 1, 0},
+ {0x8540, 0x0000008c, 0x00000000, 1, 0},
+ {0x8541, 0x0000000a, 0x00000000, 1, 0},
+ {0x8630, 0x000000b0, 0x00000000, 1, 0},
+ {0x8631, 0x0000001e, 0x00000000, 1, 0},
+ {0x8632, 0x00000004, 0x00000000, 1, 0},
+ {0x8670, 0x00000001, 0x00000000, 1, 0},
+// HDMI PHY
+ {0x8532, 0x00000080, 0x00000000, 1, 0},
+ {0x8536, 0x00000040, 0x00000000, 1, 0},
+ {0x853f, 0x0000000a, 0x00000000, 1, 0},
+// EDID
+ {0x85c7, 0x00000001, 0x00000000, 1, 0},
+ {0x85cb, 0x00000001, 0x00000000, 1, 0},
+// HDMI System
+ {0x8543, 0x00000032, 0x00000000, 1, 0},
+// {0x8544, 0x00000000, 0x00000000, 1, 1000},
+// {0x8544, 0x00000001, 0x00000000, 1, 100},
+ {0x8545, 0x00000031, 0x00000000, 1, 0},
+ {0x8546, 0x0000002d, 0x00000000, 1, 0},
+// HDCP Setting
+ {0x85d1, 0x00000001, 0x00000000, 1, 0},
+ {0x8560, 0x00000024, 0x00000000, 1, 0},
+ {0x8563, 0x00000011, 0x00000000, 1, 0},
+ {0x8564, 0x0000000f, 0x00000000, 1, 0},
+// Video settings
+ {0x8573, 0x00000081, 0x00000000, 1, 0},
+ {0x8571, 0x00000002, 0x00000000, 1, 0},
+// HDMI Audio In Setting
+ {0x8600, 0x00000000, 0x00000000, 1, 0},
+ {0x8602, 0x000000f3, 0x00000000, 1, 0},
+ {0x8603, 0x00000002, 0x00000000, 1, 0},
+ {0x8604, 0x0000000c, 0x00000000, 1, 0},
+ {0x8606, 0x00000005, 0x00000000, 1, 0},
+ {0x8607, 0x00000000, 0x00000000, 1, 0},
+ {0x8620, 0x00000022, 0x00000000, 1, 0},
+ {0x8640, 0x00000001, 0x00000000, 1, 0},
+ {0x8641, 0x00000065, 0x00000000, 1, 0},
+ {0x8642, 0x00000007, 0x00000000, 1, 0},
+// {0x8651, 0x00000003, 0x00000000, 1, 0}, // Inverted LRCK polarity - (Sony) format
+ {0x8652, 0x00000002, 0x00000000, 1, 0}, // Left-justified I2S (Phillips) format
+// {0x8652, 0x00000000, 0x00000000, 1, 0}, // Right-justified (Sony) format
+ {0x8665, 0x00000010, 0x00000000, 1, 0},
+// InfoFrame Extraction
+ {0x8709, 0x000000ff, 0x00000000, 1, 0},
+ {0x870b, 0x0000002c, 0x00000000, 1, 0},
+ {0x870c, 0x00000053, 0x00000000, 1, 0},
+ {0x870d, 0x00000001, 0x00000000, 1, 0},
+ {0x870e, 0x00000030, 0x00000000, 1, 0},
+ {0x9007, 0x00000010, 0x00000000, 1, 0},
+ {0x854a, 0x00000001, 0x00000000, 1, 0},
+// Output Control
+ {0x0004, 0x00000cf7, 0x00000000, 2, 0},
+ };
+
+static struct reg_value tc358743_setting_YUV422_4lane_720P_60fps_1280_720_133Mhz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000004, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0014, 0x0000ffff, 0x00000000, 2, 0},
+ {0x0016, 0x000005ff, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x00004062, 0x00000000, 2, 0},
+ {0x0022, 0x00000613, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00000d00, 0x00000000, 4, 0},
+ {0x0214, 0x00000001, 0x00000000, 4, 0},
+ {0x0218, 0x00000701, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000001, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000005, 0x00000000, 4, 0},
+ {0x022c, 0x00000000, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0},
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa300be86, 0x00000000, 4, 0},
+// HDMI Interrupt Mask
+ {0x8502, 0x00000001, 0x00000000, 1, 0},
+ {0x8512, 0x000000fe, 0x00000000, 1, 0},
+ {0x8514, 0x00000000, 0x00000000, 1, 0},
+ {0x8515, 0x00000000, 0x00000000, 1, 0},
+ {0x8516, 0x00000000, 0x00000000, 1, 0},
+// HDMI Audio RefClk (26 MHz)
+ {0x8531, 0x00000001, 0x00000000, 1, 0},
+ {0x8540, 0x00000a8c, 0x00000000, 1, 0},
+ {0x8630, 0x00041eb0, 0x00000000, 1, 0},
+ {0x8670, 0x00000001, 0x00000000, 1, 0},
+// HDMI PHY
+ {0x8532, 0x00000080, 0x00000000, 1, 0},
+ {0x8536, 0x00000040, 0x00000000, 1, 0},
+ {0x853f, 0x0000000a, 0x00000000, 1, 0},
+// HDMI System
+ {0x8543, 0x00000032, 0x00000000, 1, 0},
+ {0x8544, 0x00000000, 0x00000000, 1, 0},
+ {0x8545, 0x00000031, 0x00000000, 1, 0},
+ {0x8546, 0x0000002d, 0x00000000, 1, 0},
+// EDID
+ {0x85c7, 0x00000001, 0x00000000, 1, 0},
+ {0x85cb, 0x00000001, 0x00000000, 1, 0},
+// HDCP Setting
+ {0x85d1, 0x00000001, 0x00000000, 1, 0},
+ {0x8560, 0x00000024, 0x00000000, 1, 0},
+ {0x8563, 0x00000011, 0x00000000, 1, 0},
+ {0x8564, 0x0000000f, 0x00000000, 1, 0},
+// RGB --> YUV Conversion
+// {0x8574, 0x00000000, 0x00000000, 1, 0},
+ {0x8573, 0x00000081, 0x00000000, 1, 0},
+ {0x8571, 0x00000002, 0x00000000, 1, 0},
+// HDMI Audio In Setting
+ {0x8600, 0x00000000, 0x00000000, 1, 0},
+ {0x8602, 0x000000f3, 0x00000000, 1, 0},
+ {0x8603, 0x00000002, 0x00000000, 1, 0},
+ {0x8604, 0x0000000c, 0x00000000, 1, 0},
+ {0x8606, 0x00000005, 0x00000000, 1, 0},
+ {0x8607, 0x00000000, 0x00000000, 1, 0},
+ {0x8620, 0x00000022, 0x00000000, 1, 0},
+ {0x8640, 0x00000001, 0x00000000, 1, 0},
+ {0x8641, 0x00000065, 0x00000000, 1, 0},
+ {0x8642, 0x00000007, 0x00000000, 1, 0},
+ {0x8652, 0x00000002, 0x00000000, 1, 0},
+ {0x8665, 0x00000010, 0x00000000, 1, 0},
+// InfoFrame Extraction
+ {0x8709, 0x000000ff, 0x00000000, 1, 0},
+ {0x870b, 0x0000002c, 0x00000000, 1, 0},
+ {0x870c, 0x00000053, 0x00000000, 1, 0},
+ {0x870d, 0x00000001, 0x00000000, 1, 0},
+ {0x870e, 0x00000030, 0x00000000, 1, 0},
+ {0x9007, 0x00000010, 0x00000000, 1, 0},
+ {0x854a, 0x00000001, 0x00000000, 1, 0},
+// Output Control
+ {0x0004, 0x00000cf7, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_2lane_color_bar_1280_720_125MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x0000405c, 0x00000000, 2, 0},
+ {0x0022, 0x00000613, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00000e00, 0x00000000, 4, 0},
+ {0x0214, 0x00000001, 0x00000000, 4, 0},
+ {0x0218, 0x00000801, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000001, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000006, 0x00000000, 4, 0},
+ {0x022c, 0x00000000, 0x00000000, 4, 0},
+ {0x0234, 0x00000007, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, //non-continuous clock
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa30080a2, 0x00000000, 4, 0},
+// 1280x720 colorbar
+ {0x000a, 0x00000a00, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 128 pixel black - repeat 128 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(128<<16)},
+// 128 pixel blue - repeat 64 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel red - repeat 64 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel pink - repeat 64 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel green - repeat 64 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel light blue - repeat 64 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel yellow - repeat 64 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel white - repeat 64 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(64<<16)},
+// 720 lines
+ {0x7090, 0x000002cf, 0x00000000, 2, 0},
+ {0x7092, 0x00000580, 0x00000000, 2, 0},
+ {0x7094, 0x00000010, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_4lane_color_bar_1280_720_125MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x0000405c, 0x00000000, 2, 0},
+ {0x0022, 0x00000613, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00000e00, 0x00000000, 4, 0},
+ {0x0214, 0x00000001, 0x00000000, 4, 0},
+ {0x0218, 0x00000801, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000001, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000006, 0x00000000, 4, 0},
+ {0x022c, 0x00000000, 0x00000000, 4, 0},
+ {0x0234, 0x0000001F, 0x00000000, 4, 0}, //{0x0234, 0x00000007, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, //non-continuous clock
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa30080a6, 0x00000000, 4, 0}, //{0x0500, 0xa30080a2, 0x00000000, 4, 0},
+// 1280x720 colorbar
+ {0x000a, 0x00000a00, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 128 pixel black - repeat 128 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(128<<16)},
+// 128 pixel blue - repeat 64 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel red - repeat 64 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel pink - repeat 64 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel green - repeat 64 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel light blue - repeat 64 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel yellow - repeat 64 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel white - repeat 64 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(64<<16)},
+// 720 lines
+ {0x7090, 0x000002cf, 0x00000000, 2, 0},
+ {0x7092, 0x00000300, 0x00000000, 2, 0}, //{0x7092, 0x00000580, 0x00000000, 2, 0},
+ {0x7094, 0x00000010, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+
+static struct reg_value tc358743_setting_YUV422_4lane_color_bar_1024_720_200MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x00004050, 0x00000000, 2, 0},
+ {0x0022, 0x00000213, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001800, 0x00000000, 4, 0},
+ {0x0214, 0x00000002, 0x00000000, 4, 0},
+ {0x0218, 0x00001102, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000003, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000007, 0x00000000, 4, 0},
+ {0x022c, 0x00000001, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, //non-continuous clock
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa30080a6, 0x00000000, 4, 0},
+// 1280x720 colorbar
+ {0x000a, 0x00000800, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 128 pixel black - repeat 128 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(128<<16)},
+// 128 pixel blue - repeat 64 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel red - repeat 64 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel pink - repeat 64 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel green - repeat 64 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel light blue - repeat 64 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel yellow - repeat 64 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel white - repeat 64 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(64<<16)},
+// 720 lines
+ {0x0020, 0x0000406f, 0x00000000, 2, 100},
+ {0x7090, 0x000002cf, 0x00000000, 2, 0},
+ {0x7092, 0x00000540, 0x00000000, 2, 0},
+ {0x7094, 0x00000010, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_4lane_color_bar_1280_720_300MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x000080c7, 0x00000000, 2, 0},
+ {0x0022, 0x00000213, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001e00, 0x00000000, 4, 0},
+ {0x0214, 0x00000003, 0x00000000, 4, 0},
+ {0x0218, 0x00001402, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000003, 0x00000000, 4, 0},
+ {0x0224, 0x00004a00, 0x00000000, 4, 0},
+ {0x0228, 0x00000008, 0x00000000, 4, 0},
+ {0x022c, 0x00000002, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, //non-continuous clock
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa30080a6, 0x00000000, 4, 0},
+// 1280x720 colorbar
+ {0x000a, 0x00000a00, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 128 pixel black - repeat 128 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(128<<16)},
+// 128 pixel blue - repeat 64 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel red - repeat 64 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel pink - repeat 64 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel green - repeat 64 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel light blue - repeat 64 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel yellow - repeat 64 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel white - repeat 64 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(64<<16)},
+// 720 lines
+ {0x7090, 0x000002cf, 0x00000000, 2, 0},
+ {0x7092, 0x000006b8, 0x00000000, 2, 0},
+ {0x7094, 0x00000010, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_4lane_color_bar_1920_1023_300MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x000080c7, 0x00000000, 2, 0},
+ {0x0022, 0x00000213, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001e00, 0x00000000, 4, 0},
+ {0x0214, 0x00000003, 0x00000000, 4, 0},
+ {0x0218, 0x00001402, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000003, 0x00000000, 4, 0},
+ {0x0224, 0x00004a00, 0x00000000, 4, 0},
+ {0x0228, 0x00000008, 0x00000000, 4, 0},
+ {0x022c, 0x00000002, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, //non-continuous clock
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa30080a6, 0x00000000, 4, 0},
+// 1920x1023 colorbar
+ {0x000a, 0x00000f00, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 128 pixel black - repeat 128 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(128<<16)},
+// 128 pixel blue - repeat 64 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel red - repeat 64 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel pink - repeat 64 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel green - repeat 64 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel light blue - repeat 64 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel yellow - repeat 64 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(64<<16)},
+// 128 pixel white - repeat 64 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(64<<16)},
+// 1023 lines
+ {0x7090, 0x000003fe, 0x00000000, 2, 0},
+ {0x7092, 0x000004d8, 0x00000000, 2, 0},
+ {0x7094, 0x0000002d, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_2lane_color_bar_640_480_174MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x00008073, 0x00000000, 2, 0},
+ {0x0022, 0x00000213, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+// {0x014c, 0x00000000, 0x00000000, 4, 0},
+// {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001200, 0x00000000, 4, 0},
+ {0x0214, 0x00000002, 0x00000000, 4, 0},
+ {0x0218, 0x00000b02, 0x00000000, 4, 0},
+ {0x021c, 0x00000001, 0x00000000, 4, 0},
+ {0x0220, 0x00000103, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000008, 0x00000000, 4, 0},
+ {0x022c, 0x00000002, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000000, 0x00000000, 4, 0},
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xA3008082, 0x00000000, 4, 0},
+// 640x480 colorbar
+ {0x000a, 0x00000500, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 80 pixel black - repeate 80 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(80<<16)},
+// 80 pixel blue - repeate 40 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel red - repeate 40 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel pink - repeate 40 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel green - repeate 40 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel light blue - repeate 40 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel yellow - repeate 40 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel white - repeate 40 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(40<<16)},
+// 480 lines
+ {0x7090, 0x000001df, 0x00000000, 2, 0},
+ {0x7092, 0x00000898, 0x00000000, 2, 0},
+ {0x7094, 0x00000285, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_2lane_color_bar_640_480_108MHz_cont[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0010, 0x0000001e, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x0000404F, 0x00000000, 2, 0},
+ {0x0022, 0x00000613, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001800, 0x00000000, 4, 0},
+ {0x0214, 0x00000002, 0x00000000, 4, 0},
+ {0x0218, 0x00001102, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000003, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000007, 0x00000000, 4, 0},
+ {0x022c, 0x00000001, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0},
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xA30080A2, 0x00000000, 4, 0},
+// 640x480 colorbar
+ {0x000a, 0x00000500, 0x00000000, 2, 0},
+ {0x7080, 0x00000082, 0x00000000, 2, 0},
+// 80 pixel black - repeate 80 times
+ {0x7000, 0x0000007f, 0x00000000, 2, (1<<24)|(80<<16)},
+// 80 pixel blue - repeate 40 times
+ {0x7000, 0x000000ff, 0x00000000, 2, 0},
+ {0x7000, 0x00000000, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel red - repeate 40 times
+ {0x7000, 0x00000000, 0x00000000, 2, 0},
+ {0x7000, 0x000000ff, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel pink - repeate 40 times
+ {0x7000, 0x00007fff, 0x00000000, 2, 0},
+ {0x7000, 0x00007fff, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel green - repeate 40 times
+ {0x7000, 0x00007f00, 0x00000000, 2, 0},
+ {0x7000, 0x00007f00, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel light blue - repeate 40 times
+ {0x7000, 0x0000c0ff, 0x00000000, 2, 0},
+ {0x7000, 0x0000c000, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel yellow - repeate 40 times
+ {0x7000, 0x0000ff00, 0x00000000, 2, 0},
+ {0x7000, 0x0000ffff, 0x00000000, 2, (2<<24)|(40<<16)},
+// 80 pixel white - repeate 40 times
+ {0x7000, 0x0000ff7f, 0x00000000, 2, 0},
+ {0x7000, 0x0000ff7f, 0x00000000, 2, (2<<24)|(40<<16)},
+// 480 lines
+ {0x7090, 0x000001df, 0x00000000, 2, 0},
+ {0x7092, 0x00000700, 0x00000000, 2, 0},
+ {0x7094, 0x00000010, 0x00000000, 2, 0},
+ {0x7080, 0x00000083, 0x00000000, 2, 0},
+};
+
+//480p RGB2YUV442
+static struct reg_value tc358743_setting_YUV422_2lane_60fps_640_480_125Mhz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000004, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000040, 0x00000000, 2, 0},
+// {0x000a, 0x000005a0, 0x00000000, 2, 0},
+// {0x0010, 0x0000001e, 0x00000000, 2, 0},
+ {0x0014, 0x00000000, 0x00000000, 2, 0},
+ {0x0016, 0x000005ff, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x0000405c, 0x00000000, 2, 0},
+ {0x0022, 0x00000613, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00000d00, 0x00000000, 4, 0},
+ {0x0214, 0x00000001, 0x00000000, 4, 0},
+ {0x0218, 0x00000701, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000001, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000005, 0x00000000, 4, 0},
+ {0x022c, 0x00000000, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0},
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xA30080A2, 0x00000000, 4, 0},
+// HDMI Interrupt Mask
+ {0x8502, 0x00000001, 0x00000000, 1, 0},
+ {0x8512, 0x000000fe, 0x00000000, 1, 0},
+ {0x8514, 0x00000000, 0x00000000, 1, 0},
+ {0x8515, 0x00000000, 0x00000000, 1, 0},
+ {0x8516, 0x00000000, 0x00000000, 1, 0},
+// HDMI Audio RefClk (26 MHz)
+ {0x8531, 0x00000001, 0x00000000, 1, 0},
+ {0x8540, 0x00000a8c, 0x00000000, 1, 0},
+ {0x8630, 0x00041eb0, 0x00000000, 1, 0},
+ {0x8670, 0x00000001, 0x00000000, 1, 0},
+// HDMI PHY
+ {0x8532, 0x00000080, 0x00000000, 1, 0},
+ {0x8536, 0x00000040, 0x00000000, 1, 0},
+ {0x853f, 0x0000000a, 0x00000000, 1, 0},
+// HDMI System
+ {0x8543, 0x00000032, 0x00000000, 1, 0},
+ {0x8544, 0x00000000, 0x00000000, 1, 100},
+// {0x8544, 0x00000001, 0x00000000, 1, 100},
+ {0x8545, 0x00000031, 0x00000000, 1, 0},
+ {0x8546, 0x0000002d, 0x00000000, 1, 0},
+// EDID
+ {0x85c7, 0x00000001, 0x00000000, 1, 0},
+ {0x85cb, 0x00000001, 0x00000000, 1, 0},
+// HDCP Setting
+ {0x85d1, 0x00000001, 0x00000000, 1, 0},
+ {0x8560, 0x00000024, 0x00000000, 1, 0},
+ {0x8563, 0x00000011, 0x00000000, 1, 0},
+ {0x8564, 0x0000000f, 0x00000000, 1, 0},
+// RGB --> YUV Conversion
+ {0x8573, 0x00000081, 0x00000000, 1, 0},
+ {0x8571, 0x00000002, 0x00000000, 1, 0},
+// HDMI Audio In Setting
+ {0x8600, 0x00000000, 0x00000000, 1, 0},
+ {0x8602, 0x000000f3, 0x00000000, 1, 0},
+ {0x8603, 0x00000002, 0x00000000, 1, 0},
+ {0x8604, 0x0000000c, 0x00000000, 1, 0},
+ {0x8606, 0x00000005, 0x00000000, 1, 0},
+ {0x8607, 0x00000000, 0x00000000, 1, 0},
+ {0x8620, 0x00000022, 0x00000000, 1, 0},
+ {0x8640, 0x00000001, 0x00000000, 1, 0},
+ {0x8641, 0x00000065, 0x00000000, 1, 0},
+ {0x8642, 0x00000007, 0x00000000, 1, 0},
+ {0x8652, 0x00000002, 0x00000000, 1, 0},
+ {0x8665, 0x00000010, 0x00000000, 1, 0},
+// InfoFrame Extraction
+ {0x8709, 0x000000ff, 0x00000000, 1, 0},
+ {0x870b, 0x0000002c, 0x00000000, 1, 0},
+ {0x870c, 0x00000053, 0x00000000, 1, 0},
+ {0x870d, 0x00000001, 0x00000000, 1, 0},
+ {0x870e, 0x00000030, 0x00000000, 1, 0},
+ {0x9007, 0x00000010, 0x00000000, 1, 0},
+ {0x854a, 0x00000001, 0x00000000, 1, 0},
+// Output Control
+ {0x0004, 0x00000cf7, 0x00000000, 2, 0},
+ };
+
+//480p RGB2YUV442
+static struct reg_value tc358743_setting_YUV422_2lane_60fps_720_480_125Mhz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000004, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},
+ {0x0006, 0x00000040, 0x00000000, 2, 0},
+ {0x000a, 0x000005a0, 0x00000000, 2, 0},
+// {0x0010, 0x0000001e, 0x00000000, 2, 0},
+ {0x0014, 0x00000000, 0x00000000, 2, 0},
+ {0x0016, 0x000005ff, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x0000405b, 0x00000000, 2, 0},
+ {0x0022, 0x00000613, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00000d00, 0x00000000, 4, 0},
+ {0x0214, 0x00000001, 0x00000000, 4, 0},
+ {0x0218, 0x00000701, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000001, 0x00000000, 4, 0},
+ {0x0224, 0x00004000, 0x00000000, 4, 0},
+ {0x0228, 0x00000005, 0x00000000, 4, 0},
+ {0x022c, 0x00000000, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0},
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xA30080A2, 0x00000000, 4, 0},
+// HDMI Interrupt Mask
+ {0x8502, 0x00000001, 0x00000000, 1, 0},
+ {0x8512, 0x000000fe, 0x00000000, 1, 0},
+ {0x8514, 0x00000000, 0x00000000, 1, 0},
+ {0x8515, 0x00000000, 0x00000000, 1, 0},
+ {0x8516, 0x00000000, 0x00000000, 1, 0},
+// HDMI Audio RefClk (27 MHz)
+ {0x8531, 0x00000001, 0x00000000, 1, 0},
+ {0x8540, 0x00000a8c, 0x00000000, 1, 0},
+ {0x8630, 0x00041eb0, 0x00000000, 1, 0},
+ {0x8670, 0x00000001, 0x00000000, 1, 0},
+// HDMI PHY
+ {0x8532, 0x00000080, 0x00000000, 1, 0},
+ {0x8536, 0x00000040, 0x00000000, 1, 0},
+ {0x853f, 0x0000000a, 0x00000000, 1, 0},
+// HDMI System
+ {0x8543, 0x00000032, 0x00000000, 1, 0},
+ {0x8544, 0x00000000, 0x00000000, 1, 100},
+// {0x8544, 0x00000001, 0x00000000, 1, 100},
+ {0x8545, 0x00000031, 0x00000000, 1, 0},
+ {0x8546, 0x0000002d, 0x00000000, 1, 0},
+// EDID
+ {0x85c7, 0x00000001, 0x00000000, 1, 0},
+ {0x85cb, 0x00000001, 0x00000000, 1, 0},
+// HDCP Setting
+ {0x85d1, 0x00000001, 0x00000000, 1, 0},
+ {0x8560, 0x00000024, 0x00000000, 1, 0},
+ {0x8563, 0x00000011, 0x00000000, 1, 0},
+ {0x8564, 0x0000000f, 0x00000000, 1, 0},
+// RGB --> YUV Conversion
+ {0x8573, 0x00000081, 0x00000000, 1, 0},
+ {0x8571, 0x00000002, 0x00000000, 1, 0},
+// HDMI Audio In Setting
+ {0x8600, 0x00000000, 0x00000000, 1, 0},
+ {0x8602, 0x000000f3, 0x00000000, 1, 0},
+ {0x8603, 0x00000002, 0x00000000, 1, 0},
+ {0x8604, 0x0000000c, 0x00000000, 1, 0},
+ {0x8606, 0x00000005, 0x00000000, 1, 0},
+ {0x8607, 0x00000000, 0x00000000, 1, 0},
+ {0x8620, 0x00000022, 0x00000000, 1, 0},
+ {0x8640, 0x00000001, 0x00000000, 1, 0},
+ {0x8641, 0x00000065, 0x00000000, 1, 0},
+ {0x8642, 0x00000007, 0x00000000, 1, 0},
+ {0x8652, 0x00000002, 0x00000000, 1, 0},
+ {0x8665, 0x00000010, 0x00000000, 1, 0},
+// InfoFrame Extraction
+ {0x8709, 0x000000ff, 0x00000000, 1, 0},
+ {0x870b, 0x0000002c, 0x00000000, 1, 0},
+ {0x870c, 0x00000053, 0x00000000, 1, 0},
+ {0x870d, 0x00000001, 0x00000000, 1, 0},
+ {0x870e, 0x00000030, 0x00000000, 1, 0},
+ {0x9007, 0x00000010, 0x00000000, 1, 0},
+ {0x854a, 0x00000001, 0x00000000, 1, 0},
+// Output Control
+ {0x0004, 0x00000cf7, 0x00000000, 2, 0},
+ };
+
+static struct reg_value tc358743_setting_YUV422_4lane_1080P_60fps_1920_1080_300MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0},
+ {0x0004, 0x00000084, 0x00000000, 2, 0},
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},//0},
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},//0},
+ {0x0006, 0x00000000, 0x00000000, 2, 0},
+ {0x0014, 0x00000000, 0x00000000, 2, 0},
+ {0x0016, 0x000005ff, 0x00000000, 2, 0},
+// Program CSI Tx PLL
+ {0x0020, 0x000080c7, 0x00000000, 2, 0},
+ {0x0022, 0x00000213, 0x00000000, 2, 0},
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0},
+ {0x0144, 0x00000000, 0x00000000, 4, 0},
+ {0x0148, 0x00000000, 0x00000000, 4, 0},
+ {0x014c, 0x00000000, 0x00000000, 4, 0},
+ {0x0150, 0x00000000, 0x00000000, 4, 0},
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001e00, 0x00000000, 4, 0},
+ {0x0214, 0x00000003, 0x00000000, 4, 0},
+ {0x0218, 0x00001402, 0x00000000, 4, 0},
+ {0x021c, 0x00000000, 0x00000000, 4, 0},
+ {0x0220, 0x00000003, 0x00000000, 4, 0},
+ {0x0224, 0x00004a00, 0x00000000, 4, 0},
+ {0x0228, 0x00000008, 0x00000000, 4, 0},
+ {0x022c, 0x00000002, 0x00000000, 4, 0},
+ {0x0234, 0x0000001f, 0x00000000, 4, 0},
+ {0x0238, 0x00000001, 0x00000000, 4, 0},
+ {0x0204, 0x00000001, 0x00000000, 4, 0},
+ {0x0518, 0x00000001, 0x00000000, 4, 0},
+ {0x0500, 0xa30080a6, 0x00000000, 4, 0},
+// HDMI Interrupt Mask
+ {0x8502, 0x00000001, 0x00000000, 1, 0},
+ {0x8512, 0x000000fe, 0x00000000, 1, 0},
+ {0x8514, 0x00000000, 0x00000000, 1, 0},
+ {0x8515, 0x00000000, 0x00000000, 1, 0},
+ {0x8516, 0x00000000, 0x00000000, 1, 0},
+// HDMI Audio RefClk (27 MHz)
+ {0x8531, 0x00000001, 0x00000000, 1, 0},
+ {0x8540, 0x00000a8c, 0x00000000, 1, 0},
+ {0x8630, 0x00041eb0, 0x00000000, 1, 0},
+ {0x8670, 0x00000001, 0x00000000, 1, 0},
+// HDMI PHY
+ {0x8532, 0x00000080, 0x00000000, 1, 0},
+ {0x8536, 0x00000040, 0x00000000, 1, 0},
+ {0x853f, 0x0000000a, 0x00000000, 1, 0},
+// HDMI System
+ {0x8543, 0x00000032, 0x00000000, 1, 0},
+ {0x8544, 0x00000010, 0x00000000, 1, 100},
+ {0x8545, 0x00000031, 0x00000000, 1, 0},
+ {0x8546, 0x0000002d, 0x00000000, 1, 0},
+// EDID
+ {0x85c7, 0x00000001, 0x00000000, 1, 0},
+ {0x85cb, 0x00000001, 0x00000000, 1, 0},
+// HDCP Setting
+ {0x85d1, 0x00000001, 0x00000000, 1, 0},
+ {0x8560, 0x00000024, 0x00000000, 1, 0},
+ {0x8563, 0x00000011, 0x00000000, 1, 0},
+ {0x8564, 0x0000000f, 0x00000000, 1, 0},
+// RGB --> YUV Conversion
+ {0x8571, 0x00000002, 0x00000000, 1, 0},
+ {0x8573, 0x00000081, 0x00000000, 1, 0},
+ {0x8576, 0x00000060, 0x00000000, 1, 0},
+// HDMI Audio In Setting
+ {0x8600, 0x00000000, 0x00000000, 1, 0},
+ {0x8602, 0x000000f3, 0x00000000, 1, 0},
+ {0x8603, 0x00000002, 0x00000000, 1, 0},
+ {0x8604, 0x0000000c, 0x00000000, 1, 0},
+ {0x8606, 0x00000005, 0x00000000, 1, 0},
+ {0x8607, 0x00000000, 0x00000000, 1, 0},
+ {0x8620, 0x00000022, 0x00000000, 1, 0},
+ {0x8640, 0x00000001, 0x00000000, 1, 0},
+ {0x8641, 0x00000065, 0x00000000, 1, 0},
+ {0x8642, 0x00000007, 0x00000000, 1, 0},
+ {0x8652, 0x00000002, 0x00000000, 1, 0},
+ {0x8665, 0x00000010, 0x00000000, 1, 0},
+// InfoFrame Extraction
+ {0x8709, 0x000000ff, 0x00000000, 1, 0},
+ {0x870b, 0x0000002c, 0x00000000, 1, 0},
+ {0x870c, 0x00000053, 0x00000000, 1, 0},
+ {0x870d, 0x00000001, 0x00000000, 1, 0},
+ {0x870e, 0x00000030, 0x00000000, 1, 0},
+ {0x9007, 0x00000010, 0x00000000, 1, 0},
+ {0x854a, 0x00000001, 0x00000000, 1, 0},
+// Output Control
+ {0x0004, 0x00000cf7, 0x00000000, 2, 0},
+};
+
+static struct reg_value tc358743_setting_YUV422_4lane_1080P_30fps_1920_1080_300MHz[] = {
+ {0x7080, 0x00000000, 0x00000000, 2, 0}, // IR control resister
+ {0x0004, 0x00000084, 0x00000000, 2, 0}, // Internal Generated output pattern,Do not send InfoFrame data out to CSI2,Audio output to CSI2-TX i/f,I2C address index increments on every data byte transfer, disable audio and video TX buffers
+ {0x0002, 0x00000f00, 0x00000000, 2, 100},//0}, // Reset devices and set normal operatio (not sleep)
+ {0x0002, 0x00000000, 0x00000000, 2, 1000},//0}, // Clear reset bits
+ {0x0006, 0x000001f8, 0x00000000, 2, 0}, // FIFO level = 1f8 = 504
+ {0x0014, 0x00000000, 0x00000000, 2, 0}, // Clear interrupt status bits
+ {0x0016, 0x000005ff, 0x00000000, 2, 0}, // Mask audio mute, CSI-TX, and the other interrups
+// Program CSI Tx PLL
+ //{0x0020, 0x000080c7, 0x00000000, 2, 0}, // Input divider setting = 0x8 -> Division ratio = (PRD3..0) + 1 = 9, Feedback divider setting = 0xc7 -> Division ratio = (FBD8...0) + 1 = 200
+ {0x0020, 0x000080c7, 0x00000000, 2, 0}, // Input divider setting = 0x8 -> Division ratio = (PRD3..0) + 1 = 9, Feedback divider setting = 0xc7 -> Division ratio = (FBD8...0) + 1 = 200
+ {0x0022, 0x00000213, 0x00000000, 2, 0}, // HSCK frequency = 500MHz – 1GHz HSCK frequency, Loop bandwidth setting = 50% of maximum loop bandwidth (default), REFCLK toggling –> normal operation, REFCLK stops -> no oscillation, Bypass clock = normal operation, clocks switched off (output LOW), PLL Reset normal operation, PLL Enable = PLL on
+// CSI Tx PHY (32-bit Registers)
+ {0x0140, 0x00000000, 0x00000000, 4, 0}, // Clock Lane DPHY Control: Bypass Lane Enable from PPI Layer enable.
+ {0x0144, 0x00000000, 0x00000000, 4, 0}, // Data Lane 0 DPHY Control: Bypass Lane Enable from PPI Layer enable.
+ {0x0148, 0x00000000, 0x00000000, 4, 0}, // Data Lane 1 DPHY Control: Bypass Lane Enable from PPI Layer enable.
+ {0x014c, 0x00000000, 0x00000000, 4, 0}, // Data Lane 2 DPHY Control: Bypass Lane Enable from PPI Layer enable.
+ {0x0150, 0x00000000, 0x00000000, 4, 0}, // Data Lane 3 DPHY Control: Bypass Lane Enable from PPI Layer enable.
+// CSI Tx PPI (32-bit Registers)
+ {0x0210, 0x00001e00, 0x00000000, 4, 0}, // LINEINITCNT: Line Initialization Wait Counter = 0x1e00 = 7680
+ {0x0214, 0x00000003, 0x00000000, 4, 0}, // LPTXTIMECNT: SYSLPTX Timing Generation Counter = 3
+ {0x0218, 0x00001402, 0x00000000, 4, 0}, // TCLK_HEADERCNT: TCLK_ZERO Counter = 0x14 = 20, TCLK_PREPARE Counter = 0x02 = 2
+ {0x021c, 0x00000000, 0x00000000, 4, 0}, // TCLK_TRAILCNT: TCLK_TRAIL Counter = 0
+ {0x0220, 0x00000003, 0x00000000, 4, 0}, // THS_HEADERCNT: THS_ZERO Counter = 0, THS_PREPARE Counter = 3
+ {0x0224, 0x00004a00, 0x00000000, 4, 0}, // TWAKEUP: TWAKEUP Counter = 0x4a00 = 18944
+ {0x0228, 0x00000008, 0x00000000, 4, 0}, // TCLK_POSTCNT: TCLK_POST Counter = 8
+ {0x022c, 0x00000002, 0x00000000, 4, 0}, // THS_TRAILCNT: THS_TRAIL Counter = 2
+ {0x0234, 0x0000001f, 0x00000000, 4, 0}, // HSTXVREGEN: Enable voltage regulators for lanes and clk
+ {0x0238, 0x00000001, 0x00000000, 4, 0}, // TXOPTIONCNTRL: Set Continuous Clock Mode
+ {0x0204, 0x00000001, 0x00000000, 4, 0}, // PPI STARTCNTRL: start PPI function
+ {0x0518, 0x00000001, 0x00000000, 4, 0}, // CSI_START: start
+ {0x0500, 0xa30080a6, 0x00000000, 4, 0}, // CSI Configuration Register: set register 0x040C with data 0x80a6 (CSI MOde, Disables the HTX_TO timer, High-Speed data transfer is performed to Tx, DSCClk Stays in HS mode when Data Lane goes to LP, 4 Data Lanes,The EOT packet is automatically granted at the end of HS transfer then is transmitted)
+// HDMI Interrupt Mask
+ {0x8502, 0x00000001, 0x00000000, 1, 0}, // SYSTEM INTERRUPT: clear DDC power change detection interrupt
+ {0x8512, 0x000000fe, 0x00000000, 1, 0}, // SYS INTERRUPT MASK: DDC power change detection interrupt not masked
+ {0x8514, 0x00000000, 0x00000000, 1, 0}, // PACKET INTERRUPT MASK: unmask all
+ {0x8515, 0x00000000, 0x00000000, 1, 0}, // CBIT INTERRUPT MASK: unmask all
+ {0x8516, 0x00000000, 0x00000000, 1, 0}, // AUDIO INTERRUPT MASK: unmask all
+// HDMI Audio RefClk (27 MHz)
+ {0x8531, 0x00000001, 0x00000000, 1, 0}, // PHY CONTROL0: 27MHz, DDC5V detection operation.
+ {0x8540, 0x00000a8c, 0x00000000, 1, 0}, // SYS FREQ0 Register: 27MHz
+ {0x8630, 0x00041eb0, 0x00000000, 1, 0}, // Audio FS Lock Detect Control: for 27MHz
+ {0x8670, 0x00000001, 0x00000000, 1, 0}, // AUDIO PLL Setting: For REFCLK = 27MHz
+// HDMI PHY
+ {0x8532, 0x00000080, 0x00000000, 1, 0}, //
+ {0x8536, 0x00000040, 0x00000000, 1, 0}, //
+ {0x853f, 0x0000000a, 0x00000000, 1, 0}, //
+// HDMI System
+ {0x8543, 0x00000032, 0x00000000, 1, 0}, // DDC CONTROL: DDC_ACK output terminal H active, DDC5V_active detect delay 200ms
+ {0x8544, 0x00000010, 0x00000000, 1, 100}, // HPD Control Register: HOTPLUG output ON/OFF control mode = DDC5V detection interlock
+ {0x8545, 0x00000031, 0x00000000, 1, 0}, // ANA CONTROL: PLL charge pump setting for Audio = normal, DAC/PLL power ON/OFF setting for Audio = ON
+ {0x8546, 0x0000002d, 0x00000000, 1, 0}, // AVMUTE CONTROL: AVM_CTL = 0x2d
+// EDID
+ {0x85c7, 0x00000001, 0x00000000, 1, 0}, // EDID MODE REGISTER: nternal EDID-RAM & DDC2B mode
+ {0x85cb, 0x00000001, 0x00000000, 1, 0}, // EDID Length REGISTER 2: EDID data size stored in RAM (upper address bits) = 0x1 (Size = 0x100 = 256)
+// HDCP Setting
+ {0x85d1, 0x00000001, 0x00000000, 1, 0}, //
+ {0x8560, 0x00000024, 0x00000000, 1, 0}, // HDCP MODE: HDCP automatic reset when DVI⇔HDMI switched = on, HDCP Line Rekey timing switch = 7clk mode (Data island delay ON), Bcaps[5] KSVINFO_READY(0x8840[5]) auto clear mode = Auto clear using AKSV write
+ {0x8563, 0x00000011, 0x00000000, 1, 0}, //
+ {0x8564, 0x0000000f, 0x00000000, 1, 0}, //
+// RGB --> YUV Conversion
+ {0x8571, 0x00000002, 0x00000000, 1, 0}, //
+ {0x8573, 0x000000c1, 0x00000000, 1, 0}, // VOUT SET2 REGISTER: 422 fixed output, Video Output 422 conversion mode selection 000: During 444 input, 3tap filter; during 422 input, simple decimation, Enable RGB888 to YUV422 Conversion (Fixed Color output)
+ {0x8574, 0x00000008, 0x00000000, 1, 0}, // VOUT SET3 REGISTER (VOUT_SET3): Follow register bit 0x8573[7] setting
+ {0x8576, 0x00000060, 0x00000000, 1, 0}, // VOUT_COLOR: Output Color = 601 YCbCr Limited, Input Pixel Repetition judgment = automatic, Input Pixel Repetition HOST setting = no repetition
+// HDMI Audio In Setting
+ {0x8600, 0x00000000, 0x00000000, 1, 0},
+ {0x8602, 0x000000f3, 0x00000000, 1, 0},
+ {0x8603, 0x00000002, 0x00000000, 1, 0},
+ {0x8604, 0x0000000c, 0x00000000, 1, 0},
+ {0x8606, 0x00000005, 0x00000000, 1, 0},
+ {0x8607, 0x00000000, 0x00000000, 1, 0},
+ {0x8620, 0x00000022, 0x00000000, 1, 0},
+ {0x8640, 0x00000001, 0x00000000, 1, 0},
+ {0x8641, 0x00000065, 0x00000000, 1, 0},
+ {0x8642, 0x00000007, 0x00000000, 1, 0},
+ {0x8652, 0x00000002, 0x00000000, 1, 0},
+ {0x8665, 0x00000010, 0x00000000, 1, 0},
+// InfoFrame Extraction
+ {0x8709, 0x000000ff, 0x00000000, 1, 0}, // PACKET INTERRUPT MODE: all enable
+ {0x870b, 0x0000002c, 0x00000000, 1, 0}, // NO PACKET LIMIT: NO_ACP_LIMIT = 0x2, NO_AVI_LIMIT = 0xC
+ {0x870c, 0x00000053, 0x00000000, 1, 0}, // When VS receive interrupt is detected, VS storage register automatic clear, When ACP receive interrupt is detected, ACP storage register automatic clear, When AVI receive interrupt occurs, judge input video signal with RGB and no Repetition, When AVI receive interrupt is detected, AVI storage register automatic clear.
+ {0x870d, 0x00000001, 0x00000000, 1, 0}, // ERROR PACKET LIMIT: Packet continuing receive error occurrence detection threshold = 1
+ {0x870e, 0x00000030, 0x00000000, 1, 0}, // NO PACKET LIMIT:
+ {0x9007, 0x00000010, 0x00000000, 1, 0}, //
+ {0x854a, 0x00000001, 0x00000000, 1, 0}, // Initialization completed flag
+// Output Control
+ {0x0004, 0x00000cf7, 0x00000000, 2, 0}, // Configuration Control Register: Power Island Normal, I2S/TDM clock are free running, Enable 2 Audio channels, Audio channel number Auto detect by HW, I2S/TDM Data no delay, Select YCbCr422 8-bit (HDMI YCbCr422 12-bit data format), Send InfoFrame data out to CSI2, Audio output to I2S i/f (valid for 2 channel only), I2C address index increments on every data byte transfer, Audio and Video tx buffres enable.
+};
+
+/* list of image formats supported by TCM825X sensor */
+static const struct v4l2_fmtdesc tc358743_formats[] = {
+ {
+ .description = "RGB888 (RGB24)",
+ .pixelformat = V4L2_PIX_FMT_RGB24, /* 24 RGB-8-8-8 */
+ .flags = MIPI_DT_RGB888 // 0x24
+ },
+ {
+ .description = "RAW12 (Y/CbCr 4:2:0)",
+ .pixelformat = V4L2_PIX_FMT_UYVY, /* 12 Y/CbCr 4:2:0 */
+ .flags = MIPI_DT_RAW12 // 0x2c
+ },
+ {
+ .description = "YUV 4:2:2 8-bit",
+ .pixelformat = V4L2_PIX_FMT_YUYV, /* 8 8-bit color */
+ .flags = MIPI_DT_YUV422 // 0x1e /* UYVY... */
+ },
+};
+
+
+static struct tc358743_mode_info tc358743_mode_info_data[2][tc358743_mode_MAX] = {
+ [0][tc358743_mode_720P_60_1280_720] =
+ {tc358743_mode_720P_60_1280_720, 1280, 720, 12, 0, 4, 133,
+ tc358743_setting_YUV422_4lane_720P_60fps_1280_720_133Mhz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_720P_60fps_1280_720_133Mhz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_1080P_1920_1080] =
+ {tc358743_mode_1080P_1920_1080, 1920, 1080, 15, 0x0b, 4, 300,
+ tc358743_setting_YUV422_4lane_1080P_60fps_1920_1080_300MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_1080P_60fps_1920_1080_300MHz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_INIT1] =
+ {tc358743_mode_INIT1, 1280, 720, 12, 0, 2, 125,
+ tc358743_setting_YUV422_2lane_color_bar_1280_720_125MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_color_bar_1280_720_125MHz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_INIT2] =
+ {tc358743_mode_INIT2, 1280, 720, 12, 0, 4, 125,
+ tc358743_setting_YUV422_4lane_color_bar_1280_720_125MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1280_720_125MHz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_INIT] =
+ {tc358743_mode_INIT, 640, 480, 6, 1, 2, 108,
+ tc358743_setting_YUV422_2lane_color_bar_640_480_108MHz_cont,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_color_bar_640_480_108MHz_cont),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_INIT4] =
+ {tc358743_mode_INIT4, 640, 480, 6, 1, 2, 174,
+ tc358743_setting_YUV422_2lane_color_bar_640_480_174MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_color_bar_640_480_174MHz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_INIT3] =
+ {tc358743_mode_INIT3, 1024, 720, 6, 1, 4, 300,
+ tc358743_setting_YUV422_4lane_color_bar_1024_720_200MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1024_720_200MHz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_720P_1280_720] =
+ {tc358743_mode_720P_1280_720, 1280, 720, 12, (0x3e)<<8|(0x3c), 2, 125,
+ tc358743_setting_YUV422_2lane_30fps_720P_1280_720_125MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_30fps_720P_1280_720_125MHz),
+ MIPI_DT_YUV422,
+ },
+ [0][tc358743_mode_480P_720_480] =
+ {tc358743_mode_480P_720_480, 720, 480, 6, (0x02)<<8|(0x00), 2, 125,
+ tc358743_setting_YUV422_2lane_60fps_720_480_125Mhz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_60fps_720_480_125Mhz),
+ MIPI_DT_YUV422,
+ },
+ [0][tc358743_mode_480P_640_480] =
+ {tc358743_mode_480P_640_480, 640, 480, 6, (0x02)<<8|(0x00), 2, 125,
+ tc358743_setting_YUV422_2lane_60fps_640_480_125Mhz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_60fps_640_480_125Mhz),
+ MIPI_DT_YUV422,
+ },
+ [0][tc358743_mode_INIT5] =
+ {tc358743_mode_INIT5, 1280, 720, 12, 0, 4, 300,
+ tc358743_setting_YUV422_4lane_color_bar_1280_720_300MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1280_720_300MHz),
+ MIPI_DT_YUV422
+ },
+ [0][tc358743_mode_INIT6] =
+ {tc358743_mode_INIT6, 1920, 1023, 15, 0, 4, 300,
+ tc358743_setting_YUV422_4lane_color_bar_1920_1023_300MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1920_1023_300MHz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_720P_60_1280_720] =
+ {tc358743_mode_720P_60_1280_720, 1280, 720, 12, 0, 4, 133,
+ tc358743_setting_YUV422_4lane_720P_60fps_1280_720_133Mhz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_720P_60fps_1280_720_133Mhz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_1080P_1920_1080] =
+ {tc358743_mode_1080P_1920_1080, 1920, 1080, 15, 0xa, 4, 300,
+ tc358743_setting_YUV422_4lane_1080P_30fps_1920_1080_300MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_1080P_30fps_1920_1080_300MHz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_INIT1] =
+ {tc358743_mode_INIT1, 1280, 720, 12, 0, 2, 125,
+ tc358743_setting_YUV422_2lane_color_bar_1280_720_125MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_color_bar_1280_720_125MHz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_INIT2] =
+ {tc358743_mode_INIT2, 1280, 720, 12, 0, 4, 125,
+ tc358743_setting_YUV422_4lane_color_bar_1280_720_125MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1280_720_125MHz),
+ MIPI_DT_YUV422
+ },
+
+ [1][tc358743_mode_INIT] =
+ {tc358743_mode_INIT, 640, 480, 6, 1, 2, 108,
+ tc358743_setting_YUV422_2lane_color_bar_640_480_108MHz_cont,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_color_bar_640_480_108MHz_cont),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_INIT4] =
+ {tc358743_mode_INIT4, 640, 480, 6, 1, 2, 174,
+ tc358743_setting_YUV422_2lane_color_bar_640_480_174MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_color_bar_640_480_174MHz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_INIT3] =
+ {tc358743_mode_INIT3, 1024, 720, 6, 1, 4, 300,
+ tc358743_setting_YUV422_4lane_color_bar_1024_720_200MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1024_720_200MHz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_720P_1280_720] =
+ {tc358743_mode_720P_1280_720, 1280, 720, 12, (0x3e)<<8|(0x3c), 2, 125,
+ tc358743_setting_YUV422_2lane_30fps_720P_1280_720_125MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_30fps_720P_1280_720_125MHz),
+ MIPI_DT_YUV422,
+ },
+ [1][tc358743_mode_480P_720_480] =
+ {tc358743_mode_480P_720_480, 720, 480, 6, (0x02)<<8|(0x00), 2, 125,
+ tc358743_setting_YUV422_2lane_60fps_720_480_125Mhz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_60fps_720_480_125Mhz),
+ MIPI_DT_YUV422,
+ },
+ [0][tc358743_mode_480P_640_480] =
+ {tc358743_mode_480P_640_480, 640, 480, 1, (0x02)<<8|(0x00), 2, 125,
+ tc358743_setting_YUV422_2lane_60fps_640_480_125Mhz,
+ ARRAY_SIZE(tc358743_setting_YUV422_2lane_60fps_640_480_125Mhz),
+ MIPI_DT_YUV422,
+ },
+ [1][tc358743_mode_INIT5] =
+ {tc358743_mode_INIT5, 1280, 720, 12, 0, 4, 300,
+ tc358743_setting_YUV422_4lane_color_bar_1280_720_300MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1280_720_300MHz),
+ MIPI_DT_YUV422
+ },
+ [1][tc358743_mode_INIT6] =
+ {tc358743_mode_INIT6, 1920, 1023, 15, 0, 4, 300,
+ tc358743_setting_YUV422_4lane_color_bar_1920_1023_300MHz,
+ ARRAY_SIZE(tc358743_setting_YUV422_4lane_color_bar_1920_1023_300MHz),
+ MIPI_DT_YUV422
+ },
+};
+
+static int tc358743_probe(struct i2c_client *adapter,
+ const struct i2c_device_id *device_id);
+static int tc358743_remove(struct i2c_client *client);
+
+static s32 tc358743_read_reg(u16 reg, u32 *val);
+static s32 tc358743_write_reg(u16 reg, u32 val, int len);
+
+static const struct i2c_device_id tc358743_id[] = {
+ {"tc358743_mipi", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tc358743_id);
+
+static struct i2c_driver tc358743_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tc358743_mipi",
+ },
+ .probe = tc358743_probe,
+ .remove = tc358743_remove,
+ .id_table = tc358743_id,
+};
+
+struct _reg_size
+{
+ u16 startaddr, endaddr;
+ int size;
+}
+tc358743_read_reg_size [] =
+{
+ {0x0000, 0x005a, 2},
+ {0x0140, 0x0150, 4},
+ {0x0204, 0x0238, 4},
+ {0x040c, 0x0418, 4},
+ {0x044c, 0x0454, 4},
+ {0x0500, 0x0518, 4},
+ {0x0600, 0x06cc, 4},
+ {0x7000, 0x7100, 2},
+ {0x8500, 0x8bff, 1},
+ {0x8c00, 0x8fff, 4},
+ {0x9000, 0x90ff, 1},
+ {0x9100, 0x92ff, 1},
+ {0, 0, 0},
+};
+
+static s32 tc358743_write_reg(u16 reg, u32 val, int len)
+{
+ int i = 0;
+ u32 data = val;
+ u8 au8Buf[6] = {0};
+ int size = 0;
+
+ while (0 != tc358743_read_reg_size[i].startaddr ||
+ 0 != tc358743_read_reg_size[i].endaddr ||
+ 0 != tc358743_read_reg_size[i].size) {
+ if (tc358743_read_reg_size[i].startaddr <= reg
+ && tc358743_read_reg_size[i].endaddr >= reg) {
+ size = tc358743_read_reg_size[i].size;
+ break;
+ }
+ i++;
+ }
+ if (!size) {
+ pr_err("%s:write reg error:reg=%x is not found\n",__func__, reg);
+ return -1;
+ }
+ if (size == 3) {
+ size = 2;
+ } else if (size != len) {
+ pr_err("%s:write reg len error:reg=%x %d instead of %d\n",
+ __func__, reg, len, size);
+ return 0;
+ }
+
+ while (len > 0) {
+ i = 0;
+ au8Buf[i++] = (reg >> 8) & 0xff;
+ au8Buf[i++] = reg & 0xff;
+ while (size-- > 0)
+ {
+ au8Buf[i++] = (u8)data;
+ data >>= 8;
+ }
+
+ if (i2c_master_send(tc358743_data.i2c_client, au8Buf, i) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, val);
+ return -1;
+ }
+ len -= (u8)size;
+ reg += (u16)size;
+ }
+
+ return 0;
+}
+
+static s32 tc358743_read_reg(u16 reg, u32 *val)
+{
+ u8 au8RegBuf[2] = {0};
+ u32 u32RdVal = 0;
+ int i=0;
+ int size = 0;
+
+ while (0 != tc358743_read_reg_size[i].startaddr ||
+ 0 != tc358743_read_reg_size[i].endaddr ||
+ 0 != tc358743_read_reg_size[i].size) {
+ if (tc358743_read_reg_size[i].startaddr <= reg &&
+ tc358743_read_reg_size[i].endaddr >= reg) {
+ size = tc358743_read_reg_size[i].size;
+ break;
+ }
+ i++;
+ }
+ if (!size)
+ return -1;
+
+ au8RegBuf[0] = reg >> 8;
+ au8RegBuf[1] = reg & 0xff;
+
+ if (2 != i2c_master_send(tc358743_data.i2c_client, au8RegBuf, 2)) {
+ pr_err("%s:read reg error:reg=%x\n",
+ __func__, reg);
+ return -1;
+ }
+
+ if (size /*of(u32RdVal)*/ != i2c_master_recv(tc358743_data.i2c_client, (char *)&u32RdVal, size /*of(u32RdVal)*/)) {
+ pr_err("%s:read reg error:reg=%x,val=%x\n",
+ __func__, reg, u32RdVal);
+ return -1;
+ }
+ *val = u32RdVal;
+ return size;
+}
+
+static int tc358743_write_edid(u8 *edid, int len)
+{
+ int i = 0, off = 0;
+ u8 au8Buf[8+2] = {0};
+ int size = 0;
+ u16 reg;
+
+ reg = 0x8C00;
+ off = 0;
+ size = ARRAY_SIZE(au8Buf)-2;
+ pr_debug("Write EDID: %d (%d)\n", len, size);
+ while (len > 0) {
+ i = 0;
+ au8Buf[i++] = (reg >> 8) & 0xff;
+ au8Buf[i++] = reg & 0xff;
+ while (i < ARRAY_SIZE(au8Buf)) {
+ au8Buf[i++] = edid[off++];
+ }
+
+ if (i2c_master_send(tc358743_data.i2c_client, au8Buf, i) < 0) {
+ pr_err("%s:write reg error:reg=%x,val=%x\n",
+ __func__, reg, off);
+ return -1;
+ }
+ len -= (u8)size;
+ reg += (u16)size;
+ }
+ pr_debug("Activate EDID\n");
+ tc358743_write_reg(0x85c7, 0x01, 1);
+ tc358743_write_reg(0x85ca, 0x00, 1);
+ tc358743_write_reg(0x85cb, 0x01, 1);
+ return 0;
+}
+
+static int tc358743_reset(struct sensor_data *sensor)
+{
+ u32 tgt_fps; /* target frames per secound */
+ enum tc358743_frame_rate frame_rate = tc358743_60_fps;
+ int ret = -1;
+
+ det_work_enable(0);
+ while (ret) {
+ tc_standby(1);
+ mdelay(100);
+ tc_standby(0);
+ mdelay(1000);
+
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 60)
+ frame_rate = tc358743_60_fps;
+ else if (tgt_fps == 30)
+ frame_rate = tc358743_30_fps;
+
+ pr_debug("%s: capture mode: %d extended mode: %d fps: %d\n", __func__,sensor->streamcap.capturemode, sensor->streamcap.extendedmode, tgt_fps);
+
+ ret = tc358743_init_mode(frame_rate,
+ sensor->streamcap.capturemode);
+ if (ret)
+ pr_err("%s: Fail to init tc35874! - retry\n", __func__);
+ }
+ det_work_enable(1);
+ return ret;
+}
+
+void mipi_csi2_swreset(struct mipi_csi2_info *info);
+#include "../../../../mxc/mipi/mxc_mipi_csi2.h"
+static int tc358743_init_mode(enum tc358743_frame_rate frame_rate,
+ enum tc358743_mode mode)
+{
+
+ struct reg_value *pModeSetting = NULL;
+ s32 i = 0;
+ s32 iModeSettingArySize = 0;
+ register u32 RepeateLines = 0;
+ register int RepeateTimes = 0;
+ register u32 Delay_ms = 0;
+ register u16 RegAddr = 0;
+ register u32 Mask = 0;
+ register u32 Val = 0;
+ u8 Length;
+ u32 RegVal = 0;
+ int retval = 0;
+ void *mipi_csi2_info;
+ u32 mipi_reg;
+ u32 mipi_reg_test[10];
+
+ pr_debug("%s rate: %d mode: %d\n", __func__, frame_rate, mode);
+ if ((mode > tc358743_mode_MAX || mode < 0)
+ && (mode != tc358743_mode_INIT)) {
+ pr_debug("%s Wrong tc358743 mode detected! %d. Set mode 0\n", __func__, mode);
+ mode = 0;
+ }
+
+ mipi_csi2_info = mipi_csi2_get_info();
+ pr_debug("%s rate: %d mode: %d, info %p\n", __func__, frame_rate, mode, mipi_csi2_info);
+
+ /* initial mipi dphy */
+ tc358743_toggle_hpd(!hpd_active);
+ if (mipi_csi2_info) {
+ pr_debug("%s: mipi_csi2_info:\n"
+ "mipi_en: %d\n"
+ "ipu_id: %d\n"
+ "csi_id: %d\n"
+ "v_channel: %d\n"
+ "lanes: %d\n"
+ "datatype: %d\n"
+ "dphy_clk: %p\n"
+ "pixel_clk: %p\n"
+ "mipi_csi2_base:%p\n"
+ "pdev: %p\n"
+ , __func__,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->mipi_en,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->ipu_id,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->csi_id,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->v_channel,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->lanes,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->datatype,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->dphy_clk,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->pixel_clk,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->mipi_csi2_base,
+ ((struct mipi_csi2_info *)mipi_csi2_info)->pdev
+ );
+ if (!mipi_csi2_get_status(mipi_csi2_info))
+ mipi_csi2_enable(mipi_csi2_info);
+
+ if (mipi_csi2_get_status(mipi_csi2_info)) {
+ int ifmt;
+ if (tc358743_mode_info_data[frame_rate][mode].lanes != 0) {
+ pr_debug("%s Change lanes: from %d to %d\n", __func__, ((struct mipi_csi2_info *)mipi_csi2_info)->lanes, tc358743_mode_info_data[frame_rate][mode].lanes);
+ ((struct mipi_csi2_info *)mipi_csi2_info)->lanes = tc358743_mode_info_data[frame_rate][mode].lanes;
+ ((struct mipi_csi2_info *)mipi_csi2_info)->lanes = tc358743_mode_info_data[frame_rate][mode].lanes;
+ }
+ pr_debug("Now Using %d lanes\n",mipi_csi2_set_lanes(mipi_csi2_info));
+
+ /*Only reset MIPI CSI2 HW at sensor initialize*/
+ if (!hdmi_mode) // is this during reset
+ mipi_csi2_reset(mipi_csi2_info);
+
+
+ pr_debug("%s format: %x\n", __func__, tc358743_data.pix.pixelformat);
+ for (ifmt = 0; ifmt < ARRAY_SIZE(tc358743_formats); ifmt++)
+ if (tc358743_mode_info_data[frame_rate][mode].flags == tc358743_formats[ifmt].flags) {
+ tc358743_data.pix.pixelformat = tc358743_formats[ifmt].pixelformat;
+ pr_debug("%s: %s (%x, %x)\n", __func__, tc358743_formats[ifmt].description, tc358743_data.pix.pixelformat, tc358743_formats[ifmt].flags);
+ mipi_csi2_set_datatype(mipi_csi2_info, tc358743_formats[ifmt].flags);
+ break;
+ }
+ if (ifmt >= ARRAY_SIZE(tc358743_formats)) {
+ pr_err("currently this sensor format (0x%x) can not be supported!\n", tc358743_data.pix.pixelformat);
+ return -1;
+ }
+ } else {
+ pr_err("Can not enable mipi csi2 driver!\n");
+ return -1;
+ }
+ } else {
+ pr_err("Fail to get mipi_csi2_info!\n");
+ return -1;
+ }
+
+ {
+ pModeSetting =
+ tc358743_mode_info_data[frame_rate][mode].init_data_ptr;
+ iModeSettingArySize =
+ tc358743_mode_info_data[frame_rate][mode].init_data_size;
+
+ tc358743_data.pix.width =
+ tc358743_mode_info_data[frame_rate][mode].width;
+ tc358743_data.pix.height =
+ tc358743_mode_info_data[frame_rate][mode].height;
+ pr_debug("%s: Set %d regs from %p for frs %d mode %d with width %d height %d\n", __func__,
+ iModeSettingArySize,
+ pModeSetting,
+ frame_rate,
+ mode,
+ tc358743_data.pix.width,
+ tc358743_data.pix.height);
+ for (i = 0; i < iModeSettingArySize; ++i) {
+ pModeSetting = tc358743_mode_info_data[frame_rate][mode].init_data_ptr + i;
+
+ Delay_ms = pModeSetting->u32Delay_ms & (0xffff);
+ RegAddr = pModeSetting->u16RegAddr;
+ Val = pModeSetting->u32Val;
+ Mask = pModeSetting->u32Mask;
+ Length = pModeSetting->u8Length;
+ if (Mask) {
+ retval = tc358743_read_reg(RegAddr, &RegVal);
+ if (retval < 0)
+ break;
+
+ RegVal &= ~(u8)Mask;
+ Val &= Mask;
+ Val |= RegVal;
+ }
+
+ retval = tc358743_write_reg(RegAddr, Val, Length);
+ if (retval < 0)
+ break;
+
+ if (Delay_ms)
+ msleep(Delay_ms);
+
+ if (0 != ((pModeSetting->u32Delay_ms>>16) & (0xff))) {
+ if (!RepeateTimes) {
+ RepeateTimes = (pModeSetting->u32Delay_ms>>16) & (0xff);
+ RepeateLines = (pModeSetting->u32Delay_ms>>24) & (0xff);
+ }
+ if (--RepeateTimes > 0) {
+ i -= RepeateLines;
+ }
+ }
+ }
+ if (retval < 0) {
+ pr_err("%s: Fail to write REGS to tc35874!\n", __func__);
+ goto err;
+ }
+ }
+ if (!hdmi_mode) // is this during reset
+ if ((retval = tc358743_write_edid(cHDMIEDID, ARRAY_SIZE(cHDMIEDID))))
+ pr_err("%s: Fail to write EDID to tc35874!\n", __func__);
+
+ tc358743_toggle_hpd(hpd_active);
+ if (mipi_csi2_info) {
+ unsigned int i = 0;
+
+ /* wait for mipi sensor ready */
+ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
+ while ((mipi_reg == 0x200) && (i < 10)) {
+ mipi_reg_test[i] = mipi_reg;
+ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info);
+ i++;
+ msleep(10);
+ }
+
+ if (i >= 10) {
+ pr_err("mipi csi2 can not receive sensor clk!\n");
+ return -1;
+ }
+
+ {
+ int j;
+ for (j = 0; j < i; j++)
+ {
+ pr_debug("%d mipi csi2 dphy status %x\n", j, mipi_reg_test[j]);
+ }
+ }
+
+ i = 0;
+
+ /* wait for mipi stable */
+ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
+ while ((mipi_reg != 0x0) && (i < 10)) {
+ mipi_reg_test[i] = mipi_reg;
+ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info);
+ i++;
+ msleep(10);
+ }
+
+ if (i >= 10) {
+ pr_err("mipi csi2 can not reveive data correctly!\n");
+ return -1;
+ }
+
+ {
+ int j;
+ for (j = 0; j < i; j++) {
+ pr_debug("%d mipi csi2 err1 %x\n", j, mipi_reg_test[j]);
+ }
+ }
+ }
+err:
+ return (retval>0)?0:retval;
+}
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ pr_debug("%s\n", __func__);
+ if (s == NULL) {
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+ p->u.bt656.clock_curr = TC358743_XCLK_MIN; //tc358743_data.mclk;
+ pr_debug("%s: clock_curr=mclk=%d\n", __func__, tc358743_data.mclk);
+ p->if_type = V4L2_IF_TYPE_BT656;
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.clock_min = TC358743_XCLK_MIN;
+ p->u.bt656.clock_max = TC358743_XCLK_MAX;
+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @on: indicates power mode (on or off)
+ *
+ * Turns the power on or off, depending on the value of on and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct sensor_data *sensor = s->priv;
+
+ pr_debug("%s: %d\n", __func__, on);
+ if (on && !sensor->on) {
+ if (io_regulator)
+ if (regulator_enable(io_regulator) != 0)
+ return -EIO;
+ if (core_regulator)
+ if (regulator_enable(core_regulator) != 0)
+ return -EIO;
+ if (gpo_regulator)
+ if (regulator_enable(gpo_regulator) != 0)
+ return -EIO;
+ if (analog_regulator)
+ if (regulator_enable(analog_regulator) != 0)
+ return -EIO;
+ /* Make sure power on */
+ tc_standby(0);
+
+ } else if (!on && sensor->on) {
+ if (analog_regulator)
+ regulator_disable(analog_regulator);
+ if (core_regulator)
+ regulator_disable(core_regulator);
+ if (io_regulator)
+ regulator_disable(io_regulator);
+ if (gpo_regulator)
+ regulator_disable(gpo_regulator);
+ if (!hdmi_mode)
+ tc358743_reset(sensor);
+ }
+
+ sensor->on = on;
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ int ret = 0;
+
+ pr_debug("%s type: %x\n", __func__, a->type);
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = sensor->streamcap.capability;
+ cparm->timeperframe = sensor->streamcap.timeperframe;
+ cparm->capturemode = sensor->streamcap.capturemode;
+ cparm->extendedmode = sensor->streamcap.extendedmode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ det_work_enable(1);
+ pr_debug("%s done %d\n", __func__, ret);
+ return ret;
+}
+
+static int tc358743_toggle_hpd(int active)
+{
+ int ret = 0;
+ if (active) {
+ ret += tc358743_write_reg(0x8544, 0x00, 1);
+ mdelay(500);
+ ret += tc358743_write_reg(0x8544, 0x10, 1);
+ } else {
+ ret += tc358743_write_reg(0x8544, 0x10, 1);
+ mdelay(500);
+ ret += tc358743_write_reg(0x8544, 0x00, 1);
+ }
+ return ret;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ struct sensor_data *sensor = s->priv;
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ enum tc358743_frame_rate frame_rate = tc358743_60_fps, frame_rate_now = tc358743_60_fps;
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+ det_work_enable(0);
+ /* Make sure power on */
+ tc_standby(0);
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ /* Check that the new frame rate is allowed. */
+ if ((timeperframe->numerator == 0) ||
+ (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ /* Actual frame rate we use */
+ tgt_fps = timeperframe->denominator /
+ timeperframe->numerator;
+
+ if (tgt_fps == 60)
+ frame_rate = tc358743_60_fps;
+ else if (tgt_fps == 30)
+ frame_rate = tc358743_30_fps;
+ else {
+ pr_err(" The camera frame rate is not supported!\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ if ((u32)a->parm.capture.capturemode > tc358743_mode_MAX) {
+ a->parm.capture.capturemode = 0;
+ pr_debug("%s: Forse extended mode: %d \n", __func__,(u32)a->parm.capture.capturemode);
+ }
+
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 60)
+ frame_rate_now = tc358743_60_fps;
+ else if (tgt_fps == 30)
+ frame_rate_now = tc358743_30_fps;
+
+ if (frame_rate_now != frame_rate ||
+ sensor->streamcap.capturemode != (u32)a->parm.capture.capturemode ||
+ sensor->streamcap.extendedmode != (u32)a->parm.capture.extendedmode) {
+ sensor->streamcap.timeperframe = *timeperframe;
+ sensor->streamcap.capturemode =
+ (u32)a->parm.capture.capturemode;
+ sensor->streamcap.extendedmode =
+ (u32)a->parm.capture.extendedmode;
+
+ pr_debug("%s: capture mode: %d extended mode: %d \n", __func__,sensor->streamcap.capturemode, sensor->streamcap.extendedmode);
+
+ ret = tc358743_init_mode(frame_rate,
+ sensor->streamcap.capturemode);
+ } else {
+ pr_debug("%s: Keep current settings\n", __func__);
+ }
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_debug(" type is not " \
+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
+ a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_debug(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret)
+ det_work_enable(1);
+ return ret;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ vc->value = tc358743_data.brightness;
+ break;
+ case V4L2_CID_HUE:
+ vc->value = tc358743_data.hue;
+ break;
+ case V4L2_CID_CONTRAST:
+ vc->value = tc358743_data.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ vc->value = tc358743_data.saturation;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ vc->value = tc358743_data.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ vc->value = tc358743_data.blue;
+ break;
+ case V4L2_CID_EXPOSURE:
+ vc->value = tc358743_data.ae_mode;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ int retval = 0;
+
+ pr_debug("In tc358743:ioctl_s_ctrl %d\n",
+ vc->id);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ break;
+ case V4L2_CID_CONTRAST:
+ break;
+ case V4L2_CID_SATURATION:
+ break;
+ case V4L2_CID_HUE:
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ break;
+ case V4L2_CID_RED_BALANCE:
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ break;
+ case V4L2_CID_GAMMA:
+ break;
+ case V4L2_CID_EXPOSURE:
+ break;
+ case V4L2_CID_AUTOGAIN:
+ break;
+ case V4L2_CID_GAIN:
+ break;
+ case V4L2_CID_HFLIP:
+ break;
+ case V4L2_CID_VFLIP:
+ break;
+ default:
+ retval = -EPERM;
+ break;
+ }
+
+ return retval;
+}
+
+int get_pixelformat(int index)
+{
+ int ifmt;
+
+ for (ifmt = 0; ifmt < ARRAY_SIZE(tc358743_formats); ifmt++)
+ if (tc358743_mode_info_data[0][index].flags == tc358743_formats[ifmt].flags)
+ break;
+
+ if (ifmt == ARRAY_SIZE(tc358743_formats))
+ ifmt = 0; /* Default = RBG888 */
+ return ifmt;
+}
+
+/*!
+ * ioctl_enum_framesizes - V4L2 sensor interface handler for
+ * VIDIOC_ENUM_FRAMESIZES ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
+ *
+ * Return 0 if successful, otherwise -EINVAL.
+ */
+static int ioctl_enum_framesizes(struct v4l2_int_device *s,
+ struct v4l2_frmsizeenum *fsize)
+{
+ pr_debug("%s, INDEX: %d\n", __func__,fsize->index);
+ if (fsize->index > tc358743_mode_MAX)
+ return -EINVAL;
+
+ fsize->pixel_format = tc358743_formats[get_pixelformat(fsize->index)].pixelformat;
+ fsize->discrete.width =
+ tc358743_mode_info_data[0][fsize->index].width;
+ fsize->discrete.height =
+ tc358743_mode_info_data[0][fsize->index].height;
+ pr_debug("%s %d:%d format: %x\n", __func__, fsize->discrete.width, fsize->discrete.height, fsize->pixel_format);
+ return 0;
+}
+
+/*!
+ * ioctl_g_chip_ident - V4L2 sensor interface handler for
+ * VIDIOC_DBG_G_CHIP_IDENT ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @id: pointer to int
+ *
+ * Return 0.
+ */
+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
+{
+ ((struct v4l2_dbg_chip_ident *)id)->match.type =
+ V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,
+ "tc358743_mipi");
+
+ return 0;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+/*!
+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
+ * @s: pointer to standard V4L2 device structure
+ * @fmt: pointer to standard V4L2 fmt description structure
+ *
+ * Return 0.
+ */
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_fmtdesc *fmt)
+{
+ pr_debug("%s\n", __func__);
+ if (fmt->index > tc358743_mode_MAX)
+ return -EINVAL;
+
+ fmt->pixelformat = tc358743_formats[get_pixelformat(fmt->index)].pixelformat;
+
+ pr_debug("%s: format: %x\n", __func__, fmt->pixelformat);
+ return 0;
+}
+
+static int ioctl_try_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_format *f)
+{
+ struct sensor_data *sensor = s->priv;
+ u32 tgt_fps; /* target frames per secound */
+ enum tc358743_frame_rate frame_rate;
+// enum image_size isize;
+ int ifmt;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ pr_debug("%s\n", __func__);
+
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 60) {
+ frame_rate = tc358743_60_fps;
+ } else if (tgt_fps == 30) {
+ frame_rate = tc358743_30_fps;
+ } else {
+ pr_debug("%s: %d fps (%d,%d) is not supported\n", __func__, tgt_fps, sensor->streamcap.timeperframe.denominator,sensor->streamcap.timeperframe.numerator);
+ return -EINVAL;
+ }
+
+ tc358743_data.pix.width = pix->width = tc358743_mode_info_data[frame_rate][sensor->streamcap.capturemode].width;
+ tc358743_data.pix.height = pix->height = tc358743_mode_info_data[frame_rate][sensor->streamcap.capturemode].height;
+
+ for (ifmt = 0; ifmt < ARRAY_SIZE(tc358743_formats); ifmt++)
+ if (tc358743_mode_info_data[frame_rate][sensor->streamcap.capturemode].flags == tc358743_formats[ifmt].flags)
+ break;
+
+ if (ifmt == ARRAY_SIZE(tc358743_formats))
+ ifmt = 0; /* Default = RBG888 */
+
+ tc358743_data.pix.pixelformat = pix->pixelformat = tc358743_formats[ifmt].pixelformat;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = pix->width * 4;
+ pix->sizeimage = pix->bytesperline * pix->height;
+ pix->priv = 0;
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_UYVY:
+ default:
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ break;
+ }
+
+ {
+ u32 u32val;
+ int ret = tc358743_read_reg(0x8520,&u32val);
+ pr_debug("SYS_STATUS: 0x%x, ret val: %d \n",u32val,ret);
+ ret = tc358743_read_reg(0x8521,&u32val);
+ pr_debug("VI_STATUS0: 0x%x, ret val: %d \n",u32val,ret);
+ ret = tc358743_read_reg(0x8522,&u32val);
+ pr_debug("VI_STATUS1: 0x%x, ret val: %d \n",u32val,ret);
+ ret = tc358743_read_reg(0x8525,&u32val);
+ pr_debug("VI_STATUS2: 0x%x, ret val: %d \n",u32val,ret);
+ ret = tc358743_read_reg(0x8528,&u32val);
+ pr_debug("VI_STATUS3: 0x%x, ret val: %d \n",u32val,ret);
+ pr_debug("%s %d:%d format: %x\n", __func__, pix->width, pix->height, pix->pixelformat);
+ }
+ return 0;
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+
+ pr_debug("%s\n", __func__);
+ return ioctl_try_fmt_cap(s, f);
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ struct sensor_data *sensor = s->priv;
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ int ret = 0;
+ enum tc358743_frame_rate frame_rate;
+ void *mipi_csi2_info;
+
+ pr_debug("%s\n", __func__);
+ tc358743_data.on = true;
+
+ /* mclk */
+ tgt_xclk = tc358743_data.mclk;
+ tgt_xclk = min(tgt_xclk, (u32)TC358743_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)TC358743_XCLK_MIN);
+ tc358743_data.mclk = tgt_xclk;
+
+ pr_debug("%s: Setting mclk to %d MHz\n", __func__, tc358743_data.mclk / 1000000);
+// set_mclk_rate(&tc358743_data.mclk, tc358743_data.mclk_source);
+// pr_debug("%s: After mclk to %d MHz\n", __func__, tc358743_data.mclk / 1000000);
+
+ /* Default camera frame rate is set in probe */
+ tgt_fps = sensor->streamcap.timeperframe.denominator /
+ sensor->streamcap.timeperframe.numerator;
+
+ if (tgt_fps == 60)
+ frame_rate = tc358743_60_fps;
+ else if (tgt_fps == 30)
+ frame_rate = tc358743_30_fps;
+ else
+ return -EINVAL;
+
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ /* enable mipi csi2 */
+ if (mipi_csi2_info) {
+ mipi_csi2_enable(mipi_csi2_info);
+ } else {
+ pr_err("Fail to get mipi_csi2_info!\n");
+ return -EPERM;
+ }
+
+ pr_debug("%s done\n", __func__);
+ return ret;
+}
+
+/*!
+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Delinitialise the device when slave detaches to the master.
+ */
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+ void *mipi_csi2_info;
+
+ mipi_csi2_info = mipi_csi2_get_info();
+
+ /* disable mipi csi2 */
+ if (mipi_csi2_info)
+ if (mipi_csi2_get_status(mipi_csi2_info))
+ mipi_csi2_disable(mipi_csi2_info);
+
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc tc358743_ioctl_desc[] = {
+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*) ioctl_dev_init},
+ {vidioc_int_dev_exit_num, ioctl_dev_exit},
+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func*) ioctl_s_power},
+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*) ioctl_g_ifparm},
+ {vidioc_int_init_num, (v4l2_int_ioctl_func*) ioctl_init},
+ {vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap},
+ {vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap},
+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl},
+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
+ {vidioc_int_enum_framesizes_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_framesizes},
+ {vidioc_int_g_chip_ident_num,
+ (v4l2_int_ioctl_func *) ioctl_g_chip_ident},
+};
+
+static struct v4l2_int_slave tc358743_slave = {
+ .ioctls = tc358743_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(tc358743_ioctl_desc),
+};
+
+static struct v4l2_int_device tc358743_int_device = {
+ .module = THIS_MODULE,
+ .name = "tc358743",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &tc358743_slave,
+ },
+};
+
+
+#ifdef AUDIO_ENABLE
+struct imx_ssi {
+ struct platform_device *ac97_dev;
+
+ struct snd_soc_dai *imx_ac97;
+ struct clk *clk;
+ void __iomem *base;
+ int irq;
+ int fiq_enable;
+ unsigned int offset;
+
+ unsigned int flags;
+
+ void (*ac97_reset) (struct snd_ac97 *ac97);
+ void (*ac97_warm_reset)(struct snd_ac97 *ac97);
+
+ struct imx_pcm_dma_params dma_params_rx;
+ struct imx_pcm_dma_params dma_params_tx;
+
+ int enabled;
+
+ struct platform_device *soc_platform_pdev;
+ struct platform_device *soc_platform_pdev_fiq;
+};
+#define SSI_SCR 0x10
+#define SSI_SRCR 0x20
+#define SSI_STCCR 0x24
+#define SSI_SRCCR 0x28
+#define SSI_SCR_I2S_MODE_NORM (0 << 5)
+#define SSI_SCR_I2S_MODE_MSTR (1 << 5)
+#define SSI_SCR_I2S_MODE_SLAVE (2 << 5)
+#define SSI_I2S_MODE_MASK (3 << 5)
+#define SSI_SCR_SYN (1 << 4)
+#define SSI_SRCR_RSHFD (1 << 4)
+#define SSI_SRCR_RSCKP (1 << 3)
+#define SSI_SRCR_RFSI (1 << 2)
+#define SSI_SRCR_REFS (1 << 0)
+#define SSI_STCCR_WL(x) ((((x) - 2) >> 1) << 13)
+#define SSI_STCCR_WL_MASK (0xf << 13)
+#define SSI_SRCCR_WL(x) ((((x) - 2) >> 1) << 13)
+#define SSI_SRCCR_WL_MASK (0xf << 13)
+/* Audio setup */
+
+static int imxpac_tc358743_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret) {
+ pr_err("%s: failed set cpu dai format\n", __func__);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret) {
+ pr_err("%s: failed set codec dai format\n", __func__);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+ CODEC_CLOCK, SND_SOC_CLOCK_OUT);
+ if (ret) {
+ pr_err("%s: failed setting codec sysclk\n", __func__);
+ return ret;
+ }
+ snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n");
+ return ret;
+ }
+#if 1
+// clear SSI_SRCR_RXBIT0 and SSI_SRCR_RSHFD in order to push Right-justified MSB data fro
+ {
+ struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 scr = 0, srcr = 0, stccr = 0, srccr = 0;
+
+ pr_debug("%s: base %p\n", __func__, (void *)ssi->base);
+ scr = readl(ssi->base + SSI_SCR);
+ pr_debug("%s: SSI_SCR before: %p\n", __func__, (void *)scr);
+ writel(scr, ssi->base + SSI_SCR);
+ pr_debug("%s: SSI_SCR after: %p\n", __func__, (void *)scr);
+
+ srcr = readl(ssi->base + SSI_SRCR);
+ pr_debug("%s: SSI_SRCR before: %p\n", __func__, (void *)srcr);
+ writel(srcr, ssi->base + SSI_SRCR);
+ pr_debug("%s: SSI_SRCR after: %p\n", __func__, (void *)srcr);
+
+ stccr = readl(ssi->base + SSI_STCCR);
+ pr_debug("%s: SSI_STCCR before: %p\n", __func__, (void *)stccr);
+ stccr &= ~SSI_STCCR_WL_MASK;
+ stccr |= SSI_STCCR_WL(16);
+ writel(stccr, ssi->base + SSI_STCCR);
+ pr_debug("%s: SSI_STCCR after: %p\n", __func__, (void *)stccr);
+
+ srccr = readl(ssi->base + SSI_SRCCR);
+ pr_debug("%s: SSI_SRCCR before: %p\n", __func__, (void *)srccr);
+ srccr &= ~SSI_SRCCR_WL_MASK;
+ srccr |= SSI_SRCCR_WL(16);
+ writel(srccr, ssi->base + SSI_SRCCR);
+ pr_debug("%s: SSI_SRCCR after: %p\n", __func__, (void *)srccr);
+ }
+#endif
+ return 0;
+}
+
+
+
+/* Headphones jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins_a[] = {
+};
+
+/* imx_3stack card dapm widgets */
+static struct snd_soc_dapm_widget imx_3stack_dapm_widgets_a[] = {
+};
+
+
+
+static struct snd_kcontrol_new tc358743_machine_controls_a[] = {
+};
+
+/* imx_3stack machine connections to the codec pins */
+static struct snd_soc_dapm_route audio_map_a[] = {
+};
+
+static int imx_3stack_tc358743_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int ret;
+ struct snd_soc_jack *hs_jack;
+
+ struct snd_soc_jack_pin *hs_jack_pins;
+ int hs_jack_pins_size;
+ struct snd_soc_dapm_widget *imx_3stack_dapm_widgets;
+ int imx_3stack_dapm_widgets_size;
+ struct snd_kcontrol_new *tc358743_machine_controls;
+ int tc358743_machine_controls_size;
+ struct snd_soc_dapm_route *audio_map;
+ int audio_map_size;
+ int gpio_num = -1;
+ char *gpio_name;
+
+ pr_debug("%s started\n", __func__);
+
+ hs_jack_pins = hs_jack_pins_a;
+ hs_jack_pins_size = ARRAY_SIZE(hs_jack_pins_a);
+ imx_3stack_dapm_widgets = imx_3stack_dapm_widgets_a;
+ imx_3stack_dapm_widgets_size = ARRAY_SIZE(imx_3stack_dapm_widgets_a);
+ tc358743_machine_controls = tc358743_machine_controls_a;
+ tc358743_machine_controls_size = ARRAY_SIZE(tc358743_machine_controls_a);
+ audio_map = audio_map_a;
+ audio_map_size = ARRAY_SIZE(audio_map_a);
+ gpio_num = -1; //card_a_gpio_num;
+ gpio_name = NULL;
+
+ ret = snd_soc_add_controls(codec, tc358743_machine_controls,
+ tc358743_machine_controls_size);
+ if (ret) {
+ pr_err("%s: snd_soc_add_controls failed. err = %d\n", __func__, ret);
+ return ret;
+ }
+ /* Add imx_3stack specific widgets */
+ snd_soc_dapm_new_controls(&codec->dapm, imx_3stack_dapm_widgets,
+ imx_3stack_dapm_widgets_size);
+
+ /* Set up imx_3stack specific audio path audio_map */
+ snd_soc_dapm_add_routes(&codec->dapm, audio_map, audio_map_size);
+
+ snd_soc_dapm_enable_pin(&codec->dapm, hs_jack_pins->pin);
+ snd_soc_dapm_sync(&codec->dapm);
+
+ hs_jack = kzalloc(sizeof(struct snd_soc_jack), GFP_KERNEL);
+
+
+ ret = snd_soc_jack_new(codec, hs_jack_pins->pin,
+ SND_JACK_HEADPHONE, hs_jack);
+ if (ret) {
+ pr_err("%s: snd_soc_jack_new failed. err = %d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = snd_soc_jack_add_pins(hs_jack,hs_jack_pins_size,
+ hs_jack_pins);
+ if (ret) {
+ pr_err("%s: snd_soc_jack_add_pinsfailed. err = %d\n", __func__, ret);
+ return ret;
+ }
+ return 0;
+}
+
+
+static struct snd_soc_ops imxpac_tc358743_snd_ops = {
+ .hw_params = imxpac_tc358743_hw_params,
+};
+
+static struct snd_soc_dai_link imxpac_tc358743_dai = {
+ .name = "tc358743",
+ .stream_name = "TC358743",
+ .codec_dai_name = "tc358743-hifi",
+ .platform_name = "imx-pcm-audio.2",
+ .codec_name = "tc358743_mipi.1-000f",
+ .cpu_dai_name = "imx-ssi.2",
+ .init = imx_3stack_tc358743_init,
+ .ops = &imxpac_tc358743_snd_ops,
+};
+
+static struct snd_soc_card imxpac_tc358743 = {
+ .name = "cpuimx-audio_hdmi_in",
+ .dai_link = &imxpac_tc358743_dai,
+ .num_links = 1,
+};
+
+static struct platform_device *imxpac_tc358743_snd_device;
+static struct platform_device *imxpac_tc358743_snd_device;
+
+static int imx_audmux_config(int slave, int master)
+{
+ unsigned int ptcr, pdcr;
+ slave = slave - 1;
+ master = master - 1;
+
+ /* SSI0 mastered by port 5 */
+ ptcr = MXC_AUDMUX_V2_PTCR_SYN |
+ MXC_AUDMUX_V2_PTCR_TFSDIR |
+ MXC_AUDMUX_V2_PTCR_TFSEL(master | 0x8) |
+ MXC_AUDMUX_V2_PTCR_TCLKDIR |
+ MXC_AUDMUX_V2_PTCR_RFSDIR |
+ MXC_AUDMUX_V2_PTCR_RFSEL(master | 0x8) |
+ MXC_AUDMUX_V2_PTCR_RCLKDIR |
+ MXC_AUDMUX_V2_PTCR_RCSEL(master | 0x8) |
+ MXC_AUDMUX_V2_PTCR_TCSEL(master | 0x8);
+ pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(master);
+ mxc_audmux_v2_configure_port(slave, ptcr, pdcr);
+
+ ptcr = MXC_AUDMUX_V2_PTCR_SYN;
+ pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(master);
+ mxc_audmux_v2_configure_port(master, ptcr, pdcr);
+ return 0;
+}
+
+static int __devinit imx_tc358743_probe(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+ int ret = 0;
+
+
+ imx_audmux_config(plat->src_port, plat->ext_port);
+
+ ret = -EINVAL;
+ if (plat->init && plat->init())
+ return ret;
+
+ printk("%s %d %s\n",__func__,__LINE__,pdev->name);
+ return 0;
+}
+
+static int imx_tc358743_remove(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ if (plat->finit)
+ plat->finit();
+
+ return 0;
+}
+
+static struct platform_driver imx_tc358743_audio1_driver = {
+ .probe = imx_tc358743_probe,
+ .remove = imx_tc358743_remove,
+ .driver = {
+ .name = "imx-tc358743",
+ },
+};
+
+
+/* Codec setup */
+static int tc358743_codec_probe(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static int tc358743_codec_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static int tc358743_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+// tc358743_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int tc358743_codec_resume(struct snd_soc_codec *codec)
+{
+// tc358743_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+
+static int tc358743_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ return 0;
+}
+
+static const u8 tc358743_reg[0] = {
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_tc358743 = {
+ .set_bias_level = tc358743_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(tc358743_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = tc358743_reg,
+ .probe = tc358743_codec_probe,
+ .remove = tc358743_codec_remove,
+ .suspend = tc358743_codec_suspend,
+ .resume = tc358743_codec_resume,
+};
+
+#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
+#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static int tc358743_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ return 0;
+}
+
+static int tc358743_mute(struct snd_soc_dai *dai, int mute)
+{
+ return 0;
+}
+
+static int tc358743_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ return 0;
+}
+
+static int tc358743_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ return 0;
+}
+
+static struct snd_soc_dai_ops tc358743_dai_ops = {
+ .hw_params = tc358743_hw_params,
+ .digital_mute = tc358743_mute,
+ .set_sysclk = tc358743_set_dai_sysclk,
+ .set_fmt = tc358743_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver tc358743_dai = {
+ .name = "tc358743-hifi",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AIC3X_RATES,
+ .formats = AIC3X_FORMATS,},
+ .ops = &tc358743_dai_ops,
+ .symmetric_rates = 1,
+};
+
+#endif
+
+static char tc358743_mode_list[16][12] =
+{
+ "None",
+ "VGA",
+ "240p/480i",
+ "288p/576i",
+ "W240p/480i",
+ "W288p/576i",
+ "480p",
+ "576p",
+ "W480p",
+ "W576p",
+ "WW480p",
+ "WW576p",
+ "720p",
+ "1035i",
+ "1080i",
+ "1080p"
+};
+
+static char tc358743_fps_list[tc358743_max_fps+1] =
+{
+[tc358743_60_fps] = 60,
+[tc358743_30_fps] = 30,
+[tc358743_max_fps] = 0
+};
+
+static int tc358743_audio_list[16] =
+{
+ 44100,
+ 0,
+ 48000,
+ 32000,
+ 22050,
+ 384000,
+ 24000,
+ 352800,
+ 88200,
+ 768000,
+ 96000,
+ 705600,
+ 176400,
+ 0,
+ 192000,
+ 0
+};
+
+static char str_on[80];
+static void report_netlink(void)
+{
+ char *envp[2];
+ envp[0] = &str_on[0];
+ envp[1] = NULL;
+ sprintf(envp[0], "HDMI RX: %d (%s) %d %d", (unsigned char)hdmi_mode & 0xf, tc358743_mode_list[(unsigned char)hdmi_mode & 0xf], tc358743_fps_list[fps], tc358743_audio_list[audio]);
+ kobject_uevent_env(&(tc358743_data.i2c_client->dev.kobj), KOBJ_CHANGE, envp);
+ det_work_timeout = DET_WORK_TIMEOUT_DEFAULT;
+ pr_debug("%s: HDMI RX (%d) mode: %s fps: %d (%d, %d) audio: %d\n", __func__, (unsigned char)hdmi_mode, tc358743_mode_list[(unsigned char)hdmi_mode & 0xf], fps, bounce, det_work_timeout, tc358743_audio_list[audio]);
+}
+
+static void det_worker(struct work_struct *work)
+{
+ u32 u32val;
+ u16 reg;
+ int ret;
+
+ mutex_lock(&access_lock);
+ if (!det_work_disable) {
+ reg = 0x8621;
+ ret = tc358743_read_reg(reg, &u32val);
+ if (ret > 0) {
+ if (audio != (((unsigned char)u32val) & 0x0f)) {
+ audio = ((unsigned char)u32val) & 0x0f;
+ report_netlink();
+ }
+ }
+ reg = 0x852f;
+ ret = tc358743_read_reg(reg, &u32val);
+ if (ret > 0) {
+ while (1) {
+ if (u32val & TC3587430_HDMI_DETECT) {
+ lock = u32val & TC3587430_HDMI_DETECT;
+ reg = 0x8521;
+ ret = tc358743_read_reg(reg, &u32val);
+ if (ret < 0) {
+ pr_err("%s: Error reading mode\n", __func__);
+ }
+ } else {
+ if (lock) { // check if it is realy un-plug
+ lock = 0;
+ u32val = 0x0;
+ hdmi_mode = 0xF0; // fake mode to detect un-plug if mode was not detected before.
+ }
+ }
+ if ((unsigned char)hdmi_mode != (unsigned char)u32val) {
+ if (u32val)
+ det_work_timeout = DET_WORK_TIMEOUT_DEFERRED;
+ else
+ det_work_timeout = DET_WORK_TIMEOUT_DEFAULT;
+ bounce = MAX_BOUNCE;
+ pr_debug("%s: HDMI RX (%d != %d) mode: %s fps: %d (%d, %d)\n", __func__, (unsigned char)hdmi_mode, (unsigned char)u32val, tc358743_mode_list[(unsigned char)hdmi_mode & 0xf], fps, bounce, det_work_timeout);
+ hdmi_mode = u32val;
+ } else if (bounce) {
+ bounce--;
+ det_work_timeout = DET_WORK_TIMEOUT_DEFAULT;
+ }
+
+ if (1 == bounce) {
+ if (hdmi_mode >= 0xe) {
+ reg = 0x852f;
+ ret = tc358743_read_reg(reg, &u32val);
+ if (ret > 0)
+ fps = ((((unsigned char)u32val) & 0x0f) > 0xa)? tc358743_60_fps: tc358743_30_fps;
+ }
+ reg = 0x8621;
+ ret = tc358743_read_reg(reg, &u32val);
+ if (ret > 0) {
+ audio = ((unsigned char)u32val) & 0x0f;
+ report_netlink();
+ }
+ }
+ break;
+ }
+ } else {
+ pr_err("%s: Error reading lock\n", __func__);
+ }
+ } else {
+ det_work_timeout = DET_WORK_TIMEOUT_DEFERRED;
+ }
+ mutex_unlock(&access_lock);
+ schedule_delayed_work(&(det_work), msecs_to_jiffies(det_work_timeout));
+}
+
+static irqreturn_t tc358743_detect_handler(int irq, void *data)
+{
+
+ pr_debug("%s: IRQ %d\n", __func__, tc358743_data.i2c_client->irq);
+ schedule_delayed_work(&(det_work), msecs_to_jiffies(det_work_timeout));
+ return IRQ_HANDLED;
+}
+
+
+/*!
+ * tc358743 I2C probe function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+#define DUMP_LENGTH 256
+static u16 regoffs = 0;
+
+static ssize_t tc358743_show_regdump(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i, len = 0;
+ int retval;
+ u32 u32val;
+
+ mutex_lock(&access_lock);
+ for (i=0; i<DUMP_LENGTH; ) {
+ retval = tc358743_read_reg(regoffs+i, &u32val);
+ if (retval < 0) {
+ u32val =0xff;
+ retval = 1;
+ }
+ while (retval-- > 0) {
+ if (0 == (i & 0xf))
+ len += sprintf(buf+len, "\n%04X:", regoffs+i);
+ len += sprintf(buf+len, " %02X", u32val&0xff);
+ u32val >>= 8;
+ i++;
+ }
+ }
+ mutex_unlock(&access_lock);
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+
+static DEVICE_ATTR(regdump, S_IRUGO, tc358743_show_regdump, NULL);
+
+static ssize_t tc358743_store_regoffs(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 val;
+ int retval;
+ retval = sscanf(buf, "%x", &val);
+ if (1 == retval)
+ regoffs = (u16)val;
+ return count;
+}
+
+static ssize_t tc358743_show_regoffs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+
+ len += sprintf(buf+len, "0x%04X\n", regoffs);
+ return len;
+}
+
+static DEVICE_ATTR(regoffs, S_IRUGO|S_IWUSR, tc358743_show_regoffs, tc358743_store_regoffs);
+
+static ssize_t tc358743_store_hpd(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 val;
+ int retval;
+ retval = sscanf(buf, "%d", &val);
+ if (1 == retval)
+ hpd_active = (u16)val;
+ return count;
+}
+
+static ssize_t tc358743_show_hpd(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+
+ len += sprintf(buf+len, "%d\n", hpd_active);
+ return len;
+}
+
+static DEVICE_ATTR(hpd, S_IRUGO|S_IWUSR, tc358743_show_hpd, tc358743_store_hpd);
+
+static ssize_t tc358743_show_hdmirx(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+
+ len += sprintf(buf+len, "%d\n", hdmi_mode);
+ return len;
+}
+
+static DEVICE_ATTR(hdmirx, S_IRUGO, tc358743_show_hdmirx, NULL);
+
+static ssize_t tc358743_show_fps(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+
+ len += sprintf(buf+len, "%d\n", tc358743_fps_list[fps]);
+ return len;
+}
+
+static DEVICE_ATTR(fps, S_IRUGO, tc358743_show_fps, NULL);
+
+#ifdef AUDIO_ENABLE
+static ssize_t tc358743_show_audio(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+
+ len += sprintf(buf+len, "%d\n", tc358743_audio_list[audio]);
+ return len;
+}
+
+static DEVICE_ATTR(audio, S_IRUGO, tc358743_show_audio, NULL);
+#endif
+
+static int tc358743_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pwm_device *pwm;
+ struct device *dev = &client->dev;
+ int retval;
+ struct regmap *gpr;
+ struct sensor_data *sensor = &tc358743_data;
+ u32 u32val;
+
+
+ /* request power down pin */
+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(pwn_gpio)) {
+ dev_warn(dev, "no sensor pwdn pin available");
+ } else {
+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
+ "tc_mipi_pwdn");
+ if (retval < 0) {
+ dev_warn(dev, "request of pwn_gpio failed");
+ return retval;
+ }
+ }
+ /* request reset pin */
+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ dev_warn(dev, "no sensor reset pin available");
+ return -EINVAL;
+ }
+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
+ "tc_mipi_reset");
+ if (retval < 0) {
+ dev_warn(dev, "request of tc_mipi_reset failed");
+ return retval;
+ }
+
+ /* Set initial values for the sensor struct. */
+ memset(sensor, 0, sizeof(*sensor));
+
+ sensor->sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(sensor->sensor_clk)) {
+ /* assuming clock enabled by default */
+ sensor->sensor_clk = NULL;
+ dev_err(dev, "clock-frequency missing or invalid\n");
+ return PTR_ERR(sensor->sensor_clk);
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk",
+ &(sensor->mclk));
+ if (retval) {
+ dev_err(dev, "mclk missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "mclk_source",
+ (u32 *) &(sensor->mclk_source));
+ if (retval) {
+ dev_err(dev, "mclk_source missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "ipu_id",
+ &sensor->ipu_id);
+ if (retval) {
+ dev_err(dev, "ipu_id missing or invalid\n");
+ return retval;
+ }
+
+ retval = of_property_read_u32(dev->of_node, "csi_id",
+ &(sensor->csi));
+ if (retval) {
+ dev_err(dev, "csi id missing or invalid\n");
+ return retval;
+ }
+ if (((unsigned)sensor->ipu_id > 1) || ((unsigned)sensor->csi > 1)) {
+ dev_err(dev, "invalid ipu/csi\n");
+ return -EINVAL;
+ }
+
+ clk_prepare_enable(sensor->sensor_clk);
+
+ sensor->io_init = tc_reset;
+ sensor->i2c_client = client;
+ sensor->pix.pixelformat = tc358743_formats[0].pixelformat;
+ sensor->streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ V4L2_CAP_TIMEPERFRAME;
+ sensor->streamcap.capturemode = 0;
+ sensor->streamcap.extendedmode = tc358743_mode_1080P_1920_1080;
+ sensor->streamcap.timeperframe.denominator = DEFAULT_FPS;
+ sensor->streamcap.timeperframe.numerator = 1;
+
+ sensor->pix.width = tc358743_mode_info_data[0][sensor->streamcap.capturemode].width;
+ sensor->pix.height = tc358743_mode_info_data[0][sensor->streamcap.capturemode].height;
+ pr_debug("%s: format: %x, capture mode: %d extended mode: %d fps: %d width: %d height: %d\n",__func__,
+ sensor->pix.pixelformat,
+ sensor->streamcap.capturemode, sensor->streamcap.extendedmode,
+ sensor->streamcap.timeperframe.denominator *
+ sensor->streamcap.timeperframe.numerator,
+ sensor->pix.width,
+ sensor->pix.height);
+
+ pwm = pwm_get(dev, NULL);
+ if (!IS_ERR(pwm)) {
+ dev_info(dev, "found pwm%d, period=%d\n", pwm->pwm, pwm->period);
+ pwm_config(pwm, pwm->period >> 1, pwm->period);
+ pwm_enable(pwm);
+ }
+
+ tc_power_on(dev);
+ tc_reset();
+ tc_standby(0);
+
+ retval = tc358743_read_reg(TC358743_CHIP_ID_HIGH_BYTE, &u32val);
+ if (retval < 0) {
+ pr_err("%s:cannot find camera\n", __func__);
+ retval = -ENODEV;
+ goto err4;
+ }
+
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (!IS_ERR(gpr)) {
+ if (of_machine_is_compatible("fsl,imx6q")) {
+ if (sensor->csi == sensor->ipu_id) {
+ int mask = sensor->csi ? (1 << 20) : (1 << 19);
+
+ regmap_update_bits(gpr, IOMUXC_GPR1, mask, 0);
+ }
+ } else if (of_machine_is_compatible("fsl,imx6dl")) {
+ int mask = sensor->csi ? (7 << 3) : (7 << 0);
+ int val = sensor->csi ? (3 << 3) : (0 << 0);
+
+ if (sensor->ipu_id) {
+ dev_err(dev, "invalid ipu\n");
+ return -EINVAL;
+ }
+ regmap_update_bits(gpr, IOMUXC_GPR13, mask, val);
+ }
+ } else {
+ pr_err("%s: failed to find fsl,imx6q-iomux-gpr regmap\n",
+ __func__);
+ }
+
+ tc358743_int_device.priv = sensor;
+
+ //retval = device_create_file(&client->dev, &dev_attr_audio);
+ retval = device_create_file(&client->dev, &dev_attr_fps);
+ retval = device_create_file(&client->dev, &dev_attr_hdmirx);
+ retval = device_create_file(&client->dev, &dev_attr_hpd);
+ retval = device_create_file(&client->dev, &dev_attr_regoffs);
+ retval = device_create_file(&client->dev, &dev_attr_regdump);
+
+ if (retval) {
+ pr_err("%s: create bin file failed, error=%d\n",
+ __func__, retval);
+ goto err4;
+ }
+
+#ifdef AUDIO_ENABLE
+/* Audio setup */
+ retval = snd_soc_register_codec(&client->dev,
+ &soc_codec_dev_tc358743, &tc358743_dai, 1);
+ if (retval) {
+ pr_err("%s: register failed, error=%d\n",
+ __func__, retval);
+ goto err4;
+ }
+
+ retval = platform_driver_register(&imx_tc358743_audio1_driver);
+ if (retval) {
+ pr_err("%s: Platform driver register failed, error=%d\n",
+ __func__, retval);
+ goto err4;
+ }
+
+ imxpac_tc358743_snd_device = platform_device_alloc("soc-audio", 5);
+ if (!imxpac_tc358743_snd_device) {
+ pr_err("%s: Platform device allocation failed, error=%d\n",
+ __func__, retval);
+ goto err4;
+ }
+
+ platform_set_drvdata(imxpac_tc358743_snd_device, &imxpac_tc358743);
+ retval = platform_device_add(imxpac_tc358743_snd_device);
+
+ if (retval) {
+ pr_err("%s: Platform device add failed, error=%d\n",
+ __func__, retval);
+ platform_device_put(imxpac_tc358743_snd_device);
+ goto err4;
+ }
+#endif
+
+#if 1
+ INIT_DELAYED_WORK(&(det_work), det_worker);
+ if (sensor->i2c_client->irq) {
+ retval = request_irq(sensor->i2c_client->irq, tc358743_detect_handler,
+ IRQF_SHARED | IRQF_TRIGGER_FALLING,
+ "tc358743_det", sensor);
+ if (retval < 0)
+ dev_warn(&sensor->i2c_client->dev,
+ "cound not request det irq %d\n",
+ sensor->i2c_client->irq);
+ }
+
+ schedule_delayed_work(&(det_work), msecs_to_jiffies(det_work_timeout));
+#endif
+ retval = tc358743_reset(sensor);
+
+ tc_standby(1);
+ retval = v4l2_int_device_register(&tc358743_int_device);
+ if (retval) {
+ pr_err("%s: v4l2_int_device_register failed, error=%d\n",
+ __func__, retval);
+ goto err4;
+ }
+ pr_debug("%s: finished, error=%d\n",
+ __func__, retval);
+ return retval;
+
+err4:
+ pr_err("%s: failed, error=%d\n",
+ __func__, retval);
+ return retval;
+}
+
+/*!
+ * tc358743 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int tc358743_remove(struct i2c_client *client)
+{
+ // Stop delayed work
+ cancel_delayed_work_sync(&(det_work));
+
+ // Remove IRQ
+ if (tc358743_data.i2c_client->irq) {
+ free_irq(tc358743_data.i2c_client->irq, &tc358743_data);
+ }
+
+ /*Remove sysfs entries*/
+ device_remove_file(&client->dev, &dev_attr_fps);
+ device_remove_file(&client->dev, &dev_attr_hdmirx);
+ device_remove_file(&client->dev, &dev_attr_hpd);
+ device_remove_file(&client->dev, &dev_attr_regoffs);
+ device_remove_file(&client->dev, &dev_attr_regdump);
+
+ v4l2_int_device_unregister(&tc358743_int_device);
+
+ if (gpo_regulator) {
+ regulator_disable(gpo_regulator);
+ regulator_put(gpo_regulator);
+ }
+
+ if (analog_regulator) {
+ regulator_disable(analog_regulator);
+ regulator_put(analog_regulator);
+ }
+
+ if (core_regulator) {
+ regulator_disable(core_regulator);
+ regulator_put(core_regulator);
+ }
+
+ if (io_regulator) {
+ regulator_disable(io_regulator);
+ regulator_put(io_regulator);
+ }
+
+ return 0;
+}
+
+/*!
+ * tc358743 init function
+ * Called by insmod tc358743_camera.ko.
+ *
+ * @return Error code indicating success or failure
+ */
+static __init int tc358743_init(void)
+{
+ int err;
+
+ err = i2c_add_driver(&tc358743_i2c_driver);
+ if (err != 0)
+ pr_err("%s:driver registration failed, error=%d\n",
+ __func__, err);
+
+ return err;
+}
+
+/*!
+ * tc358743 cleanup function
+ * Called on rmmod tc358743_camera.ko
+ *
+ * @return Error code indicating success or failure
+ */
+static void __exit tc358743_clean(void)
+{
+ i2c_del_driver(&tc358743_i2c_driver);
+}
+
+module_init(tc358743_init);
+module_exit(tc358743_clean);
+
+MODULE_AUTHOR("Panasonic Avionics Corp.");
+MODULE_DESCRIPTION("Toshiba TC358743 HDMI-to-CSI2 Bridge MIPI Input Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("CSI");
diff --git a/drivers/media/platform/mxc/output/mxc_vout.c b/drivers/media/platform/mxc/output/mxc_vout.c
index 2082c1afe724..372654305f48 100644
--- a/drivers/media/platform/mxc/output/mxc_vout.c
+++ b/drivers/media/platform/mxc/output/mxc_vout.c
@@ -378,8 +378,7 @@ static int update_setting_from_fbi(struct mxc_vout_output *vout,
if (!strcmp(fbi->fix.id, g_fb_setting[i].name)) {
vout->crop_bounds = g_fb_setting[i].crop_bounds;
vout->disp_fmt = g_fb_setting[i].disp_fmt;
- vout->disp_support_csc =
- g_fb_setting[i].disp_support_csc;
+ vout->disp_support_csc = false;
vout->disp_support_windows =
g_fb_setting[i].disp_support_windows;
found = true;
diff --git a/drivers/mfd/pca9450.c b/drivers/mfd/pca9450.c
index 85ce6e3eef68..6dac29aabe10 100644
--- a/drivers/mfd/pca9450.c
+++ b/drivers/mfd/pca9450.c
@@ -176,6 +176,10 @@ static struct pca9450_board *pca9450_parse_dt(struct i2c_client *client,
else
board_info->irq_base = -1;
+ r = of_property_read_u32(np, "i2c-lt-en", &prop);
+ if (!r)
+ board_info->i2c_lt_en = 0x100 | prop;
+
return board_info;
err_intr:
@@ -236,6 +240,17 @@ static int pca9450_i2c_probe(struct i2c_client *i2c,
}
dev_info(pca9450->dev, "Device ID=0x%X\n", ret);
+ if ((pmic_plat_data->i2c_lt_en > 0xff) &&
+ (pmic_plat_data->i2c_lt_en < 0x104)) {
+ ret = pca9450_reg_write(pca9450, PCA9450_CONFIG2,
+ pmic_plat_data->i2c_lt_en & 0xff);
+ if (ret < 0) {
+ dev_err(pca9450->dev, "%s(): Read PCA9450_REG_DEVICE failed!\n",
+ __func__);
+ goto err;
+ }
+ }
+
pca9450_irq_init(pca9450, of_pmic_plat_data);
ret = mfd_add_devices(pca9450->dev, -1,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 6e8d06c7fe5f..a56ab6cc4d79 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2795,8 +2795,9 @@ static void sdhci_timeout_data_timer(struct timer_list *t)
if (host->data || host->data_cmd ||
(host->cmd && sdhci_data_line_cmd(host->cmd))) {
- pr_err("%s: Timeout waiting for hardware interrupt.\n",
- mmc_hostname(host->mmc));
+ pr_err("%s: Timeout waiting for hardware interrupt. retries left=%d opcode=%x\n",
+ mmc_hostname(host->mmc), host->cmd ? host->cmd->retries : 0,
+ host->cmd ? host->cmd->opcode : 0);
sdhci_dumpregs(host);
if (host->data) {
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 9ffcc335d080..009165b8952d 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -1456,6 +1456,10 @@ static int acquire_resources(struct gpmi_nand_data *this)
if (ret)
goto exit_regs;
+ ret = acquire_dma_channels(this);
+ if (ret)
+ goto exit_regs;
+
ret = gpmi_get_clks(this);
if (ret)
goto exit_clock;
@@ -2992,12 +2996,11 @@ static int gpmi_nand_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int gpmi_pm_suspend(struct device *dev)
{
- int ret;
+ struct gpmi_nand_data *this = dev_get_drvdata(dev);
+ release_dma_channels(this);
pinctrl_pm_select_sleep_state(dev);
- ret = pm_runtime_force_suspend(dev);
-
- return ret;
+ return 0;
}
static int gpmi_pm_resume(struct device *dev)
@@ -3005,14 +3008,12 @@ static int gpmi_pm_resume(struct device *dev)
struct gpmi_nand_data *this = dev_get_drvdata(dev);
int ret;
- ret = pm_runtime_force_resume(dev);
- if (ret) {
- dev_err(this->dev, "Error in resume %d\n", ret);
- return ret;
- }
-
pinctrl_pm_select_default_state(dev);
+ ret = acquire_dma_channels(this);
+ if (ret < 0)
+ return ret;
+
/* re-init the GPMI registers */
ret = gpmi_init(this);
if (ret) {
@@ -3047,8 +3048,6 @@ static int gpmi_runtime_suspend(struct device *dev)
gpmi_disable_clk(this);
release_bus_freq(BUS_FREQ_HIGH);
- release_dma_channels(this);
-
return 0;
}
@@ -3062,11 +3061,6 @@ static int gpmi_runtime_resume(struct device *dev)
return ret;
request_bus_freq(BUS_FREQ_HIGH);
-
- ret = acquire_dma_channels(this);
- if (ret < 0)
- return ret;
-
return 0;
}
diff --git a/drivers/mxc/hantro_845_h1/Kconfig b/drivers/mxc/hantro_845_h1/Kconfig
index 72936da4ef4a..1b2f81856c75 100755
--- a/drivers/mxc/hantro_845_h1/Kconfig
+++ b/drivers/mxc/hantro_845_h1/Kconfig
@@ -8,6 +8,7 @@ menu "MXC HANTRO(Video Processing Unit) encoder support"
config MXC_HANTRO_845_H1
tristate "Support for MXC HANTRO(Video Processing Unit) encoder"
default y
+ select COMPAT
---help---
VPU codec device.
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index c5b82f78421f..eb9cc785a4a3 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -3102,14 +3102,16 @@ void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id)
_ipu_get(ipu);
+ if (ipu->irq_list[irq].dev_id != dev_id)
+ return;
+
spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
/* disable the interrupt */
reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
reg &= ~IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- if (ipu->irq_list[irq].dev_id == dev_id)
- memset(&ipu->irq_list[irq], 0, sizeof(ipu->irq_list[irq]));
+ memset(&ipu->irq_list[irq], 0, sizeof(ipu->irq_list[irq]));
spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.c b/drivers/mxc/mipi/mxc_mipi_csi2.c
index 62b77a117a68..860080ada273 100644
--- a/drivers/mxc/mipi/mxc_mipi_csi2.c
+++ b/drivers/mxc/mipi/mxc_mipi_csi2.c
@@ -461,7 +461,7 @@ static int mipi_csi2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, gmipi_csi2);
- dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed\n");
+ dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed ipu%d csi%d\n", gmipi_csi2->ipu_id, gmipi_csi2->csi_id);
dev_info(&pdev->dev, "i.MX MIPI CSI2 dphy version is 0x%x\n",
mipi_csi2_dphy_ver);
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 7370a38a1ebd..7369a0a9808d 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -2149,7 +2149,12 @@ static int __maybe_unused flexcan_suspend(struct device *device)
if (err)
return err;
} else {
- flexcan_chip_stop(dev);
+ err = flexcan_chip_disable(priv);
+ if (err) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+ return err;
+ }
err = pm_runtime_force_suspend(device);
if (err)
@@ -2202,6 +2207,7 @@ static int __maybe_unused flexcan_runtime_suspend(struct device *device)
struct flexcan_priv *priv = netdev_priv(dev);
flexcan_clks_disable(priv);
+ pinctrl_pm_select_sleep_state(priv->dev);
return 0;
}
@@ -2211,6 +2217,7 @@ static int __maybe_unused flexcan_runtime_resume(struct device *device)
struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev);
+ pinctrl_pm_select_default_state(priv->dev);
return flexcan_clks_enable(priv);
}
diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig
index 1c50788055cb..d4b68eb5d386 100644
--- a/drivers/net/can/spi/Kconfig
+++ b/drivers/net/can/spi/Kconfig
@@ -15,4 +15,6 @@ config CAN_MCP251X
Driver for the Microchip MCP251x and MCP25625 SPI CAN
controllers.
+source "drivers/net/can/spi/mcp25xxfd/Kconfig"
+
endmenu
diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile
index f115b2c46623..769197785331 100644
--- a/drivers/net/can/spi/Makefile
+++ b/drivers/net/can/spi/Makefile
@@ -6,3 +6,5 @@
obj-$(CONFIG_CAN_HI311X) += hi311x.o
obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
+
+obj-y += mcp25xxfd/
diff --git a/drivers/net/can/spi/mcp25xxfd/Kconfig b/drivers/net/can/spi/mcp25xxfd/Kconfig
new file mode 100644
index 000000000000..1d2bd95febfe
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menuconfig CAN_MCP25XXFD
+ tristate "Microchip MCP25xxFD SPI CAN controllers"
+ depends on HAS_DMA
+ help
+ Driver for the Microchip MCP25XXFD SPI FD-CAN controller family.
+
+if CAN_MCP25XXFD
+
+config CAN_MCP25XXFD_DEBUG_FS
+ bool "Enable debugfs for MCP25xxFD SPI driver"
+ depends on DEBUG_FS
+ help
+ Choose Y to enable RX/TX and FIFO statistics.
+
+endif
diff --git a/drivers/net/can/spi/mcp25xxfd/Makefile b/drivers/net/can/spi/mcp25xxfd/Makefile
new file mode 100644
index 000000000000..5b3c6819d716
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_CAN_MCP25XXFD) += mcp25xxfd.o
+
+mcp25xxfd-objs := mcp25xxfd_base.o
+mcp25xxfd-objs += mcp25xxfd_can.o
+mcp25xxfd-objs += mcp25xxfd_can_fifo.o
+mcp25xxfd-objs += mcp25xxfd_can_int.o
+mcp25xxfd-objs += mcp25xxfd_can_rx.o
+mcp25xxfd-objs += mcp25xxfd_can_tx.o
+mcp25xxfd-objs += mcp25xxfd_clock.o
+mcp25xxfd-objs += mcp25xxfd_cmd.o
+mcp25xxfd-objs += mcp25xxfd_crc.o
+mcp25xxfd-objs += mcp25xxfd_ecc.o
+mcp25xxfd-objs += mcp25xxfd_int.o
+
+mcp25xxfd-$(CONFIG_CAN_MCP25XXFD_DEBUG_FS) += mcp25xxfd_can_debugfs.o
+mcp25xxfd-$(CONFIG_CAN_MCP25XXFD_DEBUG_FS) += mcp25xxfd_debugfs.o
+mcp25xxfd-$(CONFIG_GPIOLIB) += mcp25xxfd_gpio.o
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.c
new file mode 100644
index 000000000000..d9396e8819e8
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "mcp25xxfd_base.h"
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_clock.h"
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_debugfs.h"
+#include "mcp25xxfd_ecc.h"
+#include "mcp25xxfd_gpio.h"
+#include "mcp25xxfd_int.h"
+#include "mcp25xxfd_priv.h"
+
+/* Device description and rational:
+ *
+ * The mcp25xxfd is a CanFD controller that also supports can2.0 only
+ * modes.
+ * It is connected via spi to the host and requires at minimum a single
+ * irq line in addition to the SPI lines - it is not mentioned explicitly
+ * in the documentation but in principle SPI 3-wire should be possible.
+ *
+ * The clock connected is typically 4MHz, 20MHz or 40MHz.
+ * When using a 4MHz clock the controller can use an integrated PLL to
+ * get 40MHz.
+ *
+ * The controller itself has 2KB of SRAM for CAN-data.
+ * ECC can get enabled for SRAM.
+ * CRC-16 checksumming of SPI transfers can get implemented
+ * - some optimization options may not be efficient in such a situation.
+ * - more SPI bus bandwidth is used for transfer of CRCs and
+ * transfer length information
+ *
+ * It also contains 2 GPIO pins that can get used either as interrupt lines
+ * or GPIO IN or Out or STANDBY flags.
+ * In addition there is a PIN that allows output of a (divided) clock out
+ * or as a SOF (Start of Can FRAME) interrupt line - e.g for wakeup.
+ */
+
+int mcp25xxfd_base_power_enable(struct regulator *reg, int enable)
+{
+ if (IS_ERR_OR_NULL(reg))
+ return 0;
+
+ if (enable)
+ return regulator_enable(reg);
+ else
+ return regulator_disable(reg);
+}
+
+static const struct of_device_id mcp25xxfd_of_match[] = {
+ {
+ .compatible = "microchip,mcp2517fd",
+ .data = (void *)CAN_MCP2517FD,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp25xxfd_of_match);
+
+static int mcp25xxfd_base_probe(struct spi_device *spi)
+{
+ const struct of_device_id *of_id =
+ of_match_device(mcp25xxfd_of_match, &spi->dev);
+ struct mcp25xxfd_priv *priv;
+ int ret;
+
+ /* as irq_create_fwspec_mapping() can return 0, check for it */
+ if (spi->irq <= 0) {
+ dev_err(&spi->dev, "no valid irq line defined: irq = %i\n",
+ spi->irq);
+ return -EINVAL;
+ }
+
+ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ /* cross assigns */
+ spi_set_drvdata(spi, priv);
+ priv->spi = spi;
+
+ /* assign name */
+ snprintf(priv->device_name, sizeof(priv->device_name),
+ DEVICE_NAME "-%s", dev_name(&priv->spi->dev));
+
+ /* assign model from of or driver_data */
+ if (of_id)
+ priv->model = (enum mcp25xxfd_model)of_id->data;
+ else
+ priv->model = spi_get_device_id(spi)->driver_data;
+
+ mutex_init(&priv->spi_rxtx_lock);
+
+ ret = mcp25xxfd_clock_init(priv);
+ if (ret)
+ goto out_free;
+
+ /* Configure the SPI bus */
+ spi->bits_per_word = 8;
+ ret = spi_setup(spi);
+ if (ret)
+ goto out_clk;
+
+ priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
+ if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto out_clk;
+ }
+
+ ret = mcp25xxfd_base_power_enable(priv->power, 1);
+ if (ret)
+ goto out_clk;
+
+ /* this will also enable the MCP25XXFD_CLK_USER_CAN clock */
+ ret = mcp25xxfd_clock_probe(priv);
+ if (ret)
+ goto out_probe;
+
+ /* enable the can controller clock */
+ ret = mcp25xxfd_clock_start(priv, MCP25XXFD_CLK_USER_CAN);
+ if (ret)
+ goto out_probe;
+
+ /* try to identify the can-controller - we need the clock here */
+ ret = mcp25xxfd_can_probe(priv);
+ if (ret)
+ goto out_ctlclk;
+
+ /* add debugfs */
+ mcp25xxfd_debugfs_setup(priv);
+
+ /* disable interrupts */
+ ret = mcp25xxfd_int_enable(priv, false);
+ if (ret)
+ goto out_debugfs;
+
+ /* setup ECC for SRAM */
+ ret = mcp25xxfd_ecc_enable(priv);
+ if (ret)
+ goto out_debugfs;
+
+ /* setting up GPIO */
+ ret = mcp25xxfd_gpio_setup(priv);
+ if (ret)
+ goto out_debugfs;
+
+ /* setting up CAN */
+ ret = mcp25xxfd_can_setup(priv);
+ if (ret)
+ goto out_gpio;
+
+ /* and put controller to sleep by stopping the can clock */
+ ret = mcp25xxfd_clock_stop(priv, MCP25XXFD_CLK_USER_CAN);
+ if (ret)
+ goto out_can;
+
+ dev_info(&spi->dev,
+ "MCP%x successfully initialized.\n", priv->model);
+ return 0;
+
+out_can:
+ mcp25xxfd_can_remove(priv);
+out_gpio:
+ mcp25xxfd_gpio_remove(priv);
+out_debugfs:
+ mcp25xxfd_debugfs_remove(priv);
+out_ctlclk:
+ mcp25xxfd_clock_stop(priv, MCP25XXFD_CLK_USER_CAN);
+out_probe:
+ mcp25xxfd_base_power_enable(priv->power, 0);
+out_clk:
+ mcp25xxfd_clock_release(priv);
+out_free:
+ dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
+ return ret;
+}
+
+static int mcp25xxfd_base_remove(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* remove can */
+ mcp25xxfd_can_remove(priv);
+
+ /* remove gpio */
+ mcp25xxfd_gpio_remove(priv);
+
+ /* clear all running clocks */
+ mcp25xxfd_clock_stop(priv, priv->clk_user_mask);
+
+ mcp25xxfd_debugfs_remove(priv);
+
+ mcp25xxfd_base_power_enable(priv->power, 0);
+
+ mcp25xxfd_clock_release(priv);
+
+ return 0;
+}
+
+static int __maybe_unused mcp25xxfd_base_suspend(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ mutex_lock(&priv->clk_user_lock);
+ priv->clk_sleep_mask = priv->clk_user_mask;
+ mutex_unlock(&priv->clk_user_lock);
+
+ /* disable interrupts */
+ mcp25xxfd_int_enable(priv, false);
+
+ /* stop the clocks */
+ mcp25xxfd_clock_stop(priv, priv->clk_sleep_mask);
+
+ /* disable power to controller */
+ return mcp25xxfd_base_power_enable(priv->power, 0);
+}
+
+static int __maybe_unused mcp25xxfd_base_resume(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int ret = 0;
+
+ /* enable power to controller */
+ mcp25xxfd_base_power_enable(priv->power, 1);
+
+ /* if there is no sleep mask, then there is nothing to wake */
+ if (!priv->clk_sleep_mask)
+ return 0;
+
+ /* start the clocks */
+ ret = mcp25xxfd_clock_start(priv, priv->clk_sleep_mask);
+ if (ret)
+ return 0;
+
+ /* clear the sleep mask */
+ mutex_lock(&priv->clk_user_lock);
+ priv->clk_sleep_mask = 0;
+ mutex_unlock(&priv->clk_user_lock);
+
+ /* enable the interrupts again */
+ return mcp25xxfd_int_enable(priv, true);
+}
+
+static SIMPLE_DEV_PM_OPS(mcp25xxfd_base_pm_ops, mcp25xxfd_base_suspend,
+ mcp25xxfd_base_resume);
+
+static const struct spi_device_id mcp25xxfd_id_table[] = {
+ {
+ .name = "mcp2517fd",
+ .driver_data = (kernel_ulong_t)CAN_MCP2517FD,
+ },
+ {
+ .name = "mcp2518fd",
+ .driver_data = (kernel_ulong_t)CAN_MCP2518FD,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, mcp25xxfd_id_table);
+
+static struct spi_driver mcp25xxfd_can_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = mcp25xxfd_of_match,
+ .pm = &mcp25xxfd_base_pm_ops,
+ },
+ .id_table = mcp25xxfd_id_table,
+ .probe = mcp25xxfd_base_probe,
+ .remove = mcp25xxfd_base_remove,
+};
+module_spi_driver(mcp25xxfd_can_driver);
+
+MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
+MODULE_DESCRIPTION("Microchip 25XXFD CAN driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.h
new file mode 100644
index 000000000000..4559ac60645c
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_base.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_BASE_H
+#define __MCP25XXFD_BASE_H
+
+#include <linux/regulator/consumer.h>
+
+int mcp25xxfd_base_power_enable(struct regulator *reg, int enable);
+
+#endif /* __MCP25XXFD_BASE_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c
new file mode 100644
index 000000000000..91de7ac3ec73
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c
@@ -0,0 +1,687 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+/* controller details
+ *
+ * It has 32 FIFOs (of up to 32 CAN-frames).
+ *
+ * There are 4 Fifo types which can get configured:
+ * * TEF - Transmission Event Fifo - which consumes FIFO 0
+ * even if it is not configured
+ * * Tansmission Queue - for up to 32 Frames.
+ * this queue reorders CAN frames to get transmitted following the
+ * typical CAN dominant/recessive rules on the can bus itself.
+ * This FIFO is optional.
+ * * TX FIFO: generic TX fifos that can contain arbitrary data
+ * and which come with a configurable priority for transmission
+ * It is also possible to have the Controller automatically trigger
+ * a transfer when a Filter Rule for a RTR frame matches.
+ * Each of these fifos in principle can get configured for distinct
+ * dlc sizes (8 thru 64 bytes)
+ * * RX FIFO: generic RX fifo which is filled via filter-rules.
+ * Each of these fifos in principle can get configured for distinct
+ * dlc sizes (8 thru 64 bytes)
+ * Unfortunately there is no filter rule that would allow triggering
+ * on different frame sizes, so for all practical purposes the
+ * RX fifos have to be of the same size (unless one wants to experience
+ * lost data).
+ * When a Can Frame is transmitted from the TX Queue or an individual
+ * TX FIFO then a small TEF Frame can get added to the TEF FIFO queue
+ * to log the Transmission of the frame - this includes ID, Flags
+ * (including a custom identifier/index) and the timestamp (see below).
+ *
+ * The controller provides an optional free running counter with a divider
+ * for timestamping of RX frames as well as for TEF entries.
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_base.h"
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_can_debugfs.h"
+#include "mcp25xxfd_can_fifo.h"
+#include "mcp25xxfd_can_int.h"
+#include "mcp25xxfd_can_priv.h"
+#include "mcp25xxfd_can_tx.h"
+#include "mcp25xxfd_clock.h"
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_int.h"
+#include "mcp25xxfd_priv.h"
+#include "mcp25xxfd_regs.h"
+
+#include <uapi/linux/can/netlink.h>
+
+/* module parameters */
+static unsigned int bw_sharing_log2bits;
+module_param(bw_sharing_log2bits, uint, 0664);
+MODULE_PARM_DESC(bw_sharing_log2bits,
+ "Delay between 2 transmissions in number of arbitration bit times\n");
+static bool enable_edge_filter;
+module_param(enable_edge_filter, bool, 0664);
+MODULE_PARM_DESC(enable_edge_filter,
+ "Enable ISO11898-1:2015 edge_filtering");
+static unsigned int tdc_mode = 2;
+module_param(tdc_mode, uint, 0664);
+MODULE_PARM_DESC(tdc_mode,
+ "Transmitter Delay Mode - 0 = disabled, 1 = fixed, 2 = auto\n");
+static unsigned int tdc_value;
+module_param(tdc_value, uint, 0664);
+MODULE_PARM_DESC(tdc_value,
+ "Transmission Delay Value - range: [0:63] SCLK");
+static int tdc_offset = 64; /* outside of range to use computed values */
+module_param(tdc_offset, int, 0664);
+MODULE_PARM_DESC(tdc_offset,
+ "Transmission Delay offset - range: [-64:63] SCLK");
+
+/* everything related to bit timing */
+static
+const struct can_bittiming_const mcp25xxfd_can_nominal_bittiming_const = {
+ .name = DEVICE_NAME,
+ .tseg1_min = 2,
+ .tseg1_max = BIT(MCP25XXFD_CAN_NBTCFG_TSEG1_BITS),
+ .tseg2_min = 1,
+ .tseg2_max = BIT(MCP25XXFD_CAN_NBTCFG_TSEG2_BITS),
+ .sjw_max = BIT(MCP25XXFD_CAN_NBTCFG_SJW_BITS),
+ .brp_min = 1,
+ .brp_max = BIT(MCP25XXFD_CAN_NBTCFG_BRP_BITS),
+ .brp_inc = 1,
+};
+
+static
+const struct can_bittiming_const mcp25xxfd_can_data_bittiming_const = {
+ .name = DEVICE_NAME,
+ .tseg1_min = 1,
+ .tseg1_max = BIT(MCP25XXFD_CAN_DBTCFG_TSEG1_BITS),
+ .tseg2_min = 1,
+ .tseg2_max = BIT(MCP25XXFD_CAN_DBTCFG_TSEG2_BITS),
+ .sjw_max = BIT(MCP25XXFD_CAN_DBTCFG_SJW_BITS),
+ .brp_min = 1,
+ .brp_max = BIT(MCP25XXFD_CAN_DBTCFG_BRP_BITS),
+ .brp_inc = 1,
+};
+
+static int mcp25xxfd_can_do_set_nominal_bittiming(struct net_device *net)
+{
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+ struct can_bittiming *bt = &cpriv->can.bittiming;
+
+ int sjw = bt->sjw;
+ int pseg2 = bt->phase_seg2;
+ int pseg1 = bt->phase_seg1;
+ int propseg = bt->prop_seg;
+ int brp = bt->brp;
+
+ int tseg1 = propseg + pseg1;
+ int tseg2 = pseg2;
+
+ /* calculate nominal bit timing */
+ cpriv->regs.nbtcfg = ((sjw - 1) << MCP25XXFD_CAN_NBTCFG_SJW_SHIFT) |
+ ((tseg2 - 1) << MCP25XXFD_CAN_NBTCFG_TSEG2_SHIFT) |
+ ((tseg1 - 1) << MCP25XXFD_CAN_NBTCFG_TSEG1_SHIFT) |
+ ((brp - 1) << MCP25XXFD_CAN_NBTCFG_BRP_SHIFT);
+
+ return mcp25xxfd_cmd_write(cpriv->priv->spi, MCP25XXFD_CAN_NBTCFG,
+ cpriv->regs.nbtcfg);
+}
+
+static int mcp25xxfd_can_do_set_data_bittiming(struct net_device *net)
+{
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+ struct mcp25xxfd_priv *priv = cpriv->priv;
+ struct can_bittiming *bt = &cpriv->can.data_bittiming;
+ struct spi_device *spi = priv->spi;
+
+ int sjw = bt->sjw;
+ int pseg2 = bt->phase_seg2;
+ int pseg1 = bt->phase_seg1;
+ int propseg = bt->prop_seg;
+ int brp = bt->brp;
+
+ int tseg1 = propseg + pseg1;
+ int tseg2 = pseg2;
+
+ int tdco;
+ int ret;
+
+ /* set up Transmitter delay compensation */
+ cpriv->regs.tdc = 0;
+ /* configure TDC mode */
+ if (tdc_mode < 4)
+ cpriv->regs.tdc = tdc_mode << MCP25XXFD_CAN_TDC_TDCMOD_SHIFT;
+ else
+ cpriv->regs.tdc = MCP25XXFD_CAN_TDC_TDCMOD_AUTO <<
+ MCP25XXFD_CAN_TDC_TDCMOD_SHIFT;
+
+ /* configure TDC offsets */
+ if ((tdc_offset >= -64) && tdc_offset < 64)
+ tdco = tdc_offset;
+ else
+ tdco = clamp_t(int, bt->brp * tseg1, -64, 63);
+ cpriv->regs.tdc |= (tdco << MCP25XXFD_CAN_TDC_TDCO_SHIFT) &
+ MCP25XXFD_CAN_TDC_TDCO_MASK;
+
+ /* configure TDC value */
+ if (tdc_value < 64)
+ cpriv->regs.tdc |= tdc_value << MCP25XXFD_CAN_TDC_TDCV_SHIFT;
+
+ /* enable edge filtering */
+ if (enable_edge_filter)
+ cpriv->regs.tdc |= MCP25XXFD_CAN_TDC_EDGFLTEN;
+
+ /* set TDC */
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_CAN_TDC, cpriv->regs.tdc);
+ if (ret)
+ return ret;
+
+ /* calculate data bit timing */
+ cpriv->regs.dbtcfg = ((sjw - 1) << MCP25XXFD_CAN_DBTCFG_SJW_SHIFT) |
+ ((tseg2 - 1) << MCP25XXFD_CAN_DBTCFG_TSEG2_SHIFT) |
+ ((tseg1 - 1) << MCP25XXFD_CAN_DBTCFG_TSEG1_SHIFT) |
+ ((brp - 1) << MCP25XXFD_CAN_DBTCFG_BRP_SHIFT);
+
+ return mcp25xxfd_cmd_write(spi, MCP25XXFD_CAN_DBTCFG,
+ cpriv->regs.dbtcfg);
+}
+
+int mcp25xxfd_can_get_mode(struct mcp25xxfd_priv *priv, u32 *reg)
+{
+ int ret;
+
+ ret = mcp25xxfd_cmd_read(priv->spi, MCP25XXFD_CAN_CON, reg);
+ if (ret)
+ return ret;
+
+ return (*reg & MCP25XXFD_CAN_CON_OPMOD_MASK) >>
+ MCP25XXFD_CAN_CON_OPMOD_SHIFT;
+}
+
+int mcp25xxfd_can_switch_mode_no_wait(struct mcp25xxfd_priv *priv,
+ u32 *reg, int mode)
+{
+ u32 dummy;
+ int ret;
+
+ /* get the current mode/register - if reg is NULL
+ * when the can controller is not setup yet
+ * typically by calling mcp25xxfd_can_sleep_mode
+ * (this only happens during initialization phase)
+ */
+ if (reg) {
+ if (!*reg) {
+ ret = mcp25xxfd_can_get_mode(priv, reg);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+ /* alternatively use dummy */
+ dummy = 0;
+ reg = &dummy;
+ }
+
+ /* compute the effective mode in osc*/
+ *reg &= ~(MCP25XXFD_CAN_CON_REQOP_MASK |
+ MCP25XXFD_CAN_CON_OPMOD_MASK);
+ *reg |= (mode << MCP25XXFD_CAN_CON_REQOP_SHIFT) |
+ (mode << MCP25XXFD_CAN_CON_OPMOD_SHIFT);
+
+ /* if the opmode is sleep then the oscilator will be disabled
+ * and also not ready, so fake this change
+ */
+ if (mode == MCP25XXFD_CAN_CON_MODE_SLEEP)
+ mcp25xxfd_clock_fake_sleep(priv);
+
+ /* request the mode switch */
+ return mcp25xxfd_cmd_write(priv->spi, MCP25XXFD_CAN_CON, *reg);
+}
+
+int mcp25xxfd_can_switch_mode(struct mcp25xxfd_priv *priv, u32 *reg, int mode)
+{
+ int ret, i;
+
+ /* trigger the mode switch itself */
+ ret = mcp25xxfd_can_switch_mode_no_wait(priv, reg, mode);
+ if (ret)
+ return ret;
+
+ /* if we are in now sleep mode then return immediately
+ * the controller does not respond back!
+ */
+ if (mode == MCP25XXFD_CAN_CON_MODE_SLEEP)
+ return 0;
+
+ /* wait for it to stabilize/switch mode
+ * we assume 256 rounds should be enough as this is > 12ms
+ * at 1MHz Can Bus speed without any extra overhead
+ *
+ * The assumption here is that it depends on bus activity
+ * how long it takes the controller to switch modes
+ */
+ for (i = 0; i < 256; i++) {
+ /* get the mode */
+ ret = mcp25xxfd_can_get_mode(priv, reg);
+ if (ret < 0)
+ return ret;
+ /* check that we have reached our mode */
+ if (ret == mode)
+ return 0;
+ }
+
+ dev_err(&priv->spi->dev, "Failed to switch to mode %u in time\n",
+ mode);
+ return -ETIMEDOUT;
+}
+
+static int mcp25xxfd_can_probe_modeswitch(struct mcp25xxfd_priv *priv)
+{
+ u32 mode_data;
+ int ret;
+
+ /* so we should be in config mode now, so move to INT_LOOPBACK */
+ ret = mcp25xxfd_can_switch_mode(priv, &mode_data,
+ MCP25XXFD_CAN_CON_MODE_INT_LOOPBACK);
+ if (ret) {
+ dev_err(&priv->spi->dev,
+ "Failed to switch into loopback mode\n");
+ return ret;
+ }
+
+ /* and back into config mode */
+ ret = mcp25xxfd_can_switch_mode(priv, &mode_data,
+ MCP25XXFD_CAN_CON_MODE_CONFIG);
+ if (ret) {
+ dev_err(&priv->spi->dev,
+ "Failed to switch back to config mode\n");
+ return ret;
+ }
+
+ /* so we have checked basic functionality successfully */
+ return 0;
+}
+
+int mcp25xxfd_can_sleep_mode(struct mcp25xxfd_priv *priv)
+{
+ return mcp25xxfd_can_switch_mode(priv, NULL,
+ MCP25XXFD_CAN_CON_MODE_SLEEP);
+}
+
+int mcp25xxfd_can_probe(struct mcp25xxfd_priv *priv)
+{
+ struct spi_device *spi = priv->spi;
+ u32 mode_data;
+ int mode, ret;
+
+ /* read TXQCON - the TXEN bit should always read as 1 */
+ ret = mcp25xxfd_cmd_read(spi, MCP25XXFD_CAN_TXQCON, &mode_data);
+ if (ret)
+ return ret;
+ if ((mode_data & MCP25XXFD_CAN_TXQCON_TXEN) == 0) {
+ dev_err(&spi->dev,
+ "Register TXQCON does not have bit TXEN set - reads as %08x - this may be a problem with spi bus signal quality - try reducing spi-clock speed if this can get reproduced",
+ mode_data);
+ return -EINVAL;
+ }
+
+ /* try to get the current mode */
+ mode = mcp25xxfd_can_get_mode(priv, &mode_data);
+ if (mode < 0)
+ return mode;
+
+ /* we would expect to be in config mode, as a SPI-reset should
+ * have moved us into config mode.
+ * But then the documentation says that SPI-reset may only work
+ * reliably when already in config mode
+ */
+
+ /* so if we are in config mode then everything is fine
+ * and we check that a mode switch works propperly
+ */
+ if (mode == MCP25XXFD_CAN_CON_MODE_CONFIG)
+ return mcp25xxfd_can_probe_modeswitch(priv);
+
+ /* if the bitfield is 0 then there is something is wrong */
+ if (!mode_data) {
+ dev_err(&spi->dev,
+ "got controller config register reading as 0\n");
+ return -EINVAL;
+ }
+
+ /* any other mode is unexpected */
+ dev_err(&spi->dev,
+ "Found controller in unexpected mode %i - register reads as %08x\n",
+ mode, mode_data);
+
+ /* so try to move to config mode
+ * if this fails, then everything is lost and the controller
+ * is not identified
+ * This action MAY be destructive if a different device is connected
+ * but note that the first hurdle (oscillator) was already
+ * successful - so we should be safe...
+ */
+ ret = mcp25xxfd_can_switch_mode(priv, &mode_data,
+ MCP25XXFD_CAN_CON_MODE_CONFIG);
+ if (ret) {
+ dev_err(&priv->spi->dev,
+ "Mode did not switch to config as expected - could not identify controller - register reads as %08x\n",
+ mode_data);
+ return -EINVAL;
+ }
+ /* check that modeswitch is really working */
+ return mcp25xxfd_can_probe_modeswitch(priv);
+}
+
+static int mcp25xxfd_can_config(struct net_device *net)
+{
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+ struct mcp25xxfd_priv *priv = cpriv->priv;
+ struct spi_device *spi = priv->spi;
+ int ret;
+
+ /* setup value of con_register */
+ cpriv->regs.con = MCP25XXFD_CAN_CON_STEF; /* enable TEF, disable TXQ */
+
+ /* transmission bandwidth sharing bits */
+ if (bw_sharing_log2bits > 12)
+ bw_sharing_log2bits = 12;
+ cpriv->regs.con |= bw_sharing_log2bits <<
+ MCP25XXFD_CAN_CON_TXBWS_SHIFT;
+
+ /* non iso FD mode */
+ if (!(cpriv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO))
+ cpriv->regs.con |= MCP25XXFD_CAN_CON_ISOCRCEN;
+
+ /* one shot */
+ if (cpriv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ cpriv->regs.con |= MCP25XXFD_CAN_CON_RTXAT;
+
+ /* apply it now together with a mode switch */
+ ret = mcp25xxfd_can_switch_mode(cpriv->priv, &cpriv->regs.con,
+ MCP25XXFD_CAN_CON_MODE_CONFIG);
+ if (ret)
+ return 0;
+
+ /* time stamp control register - 1ns resolution */
+ cpriv->regs.tscon = 0;
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_CAN_TBC, 0);
+ if (ret)
+ return ret;
+
+ cpriv->regs.tscon = MCP25XXFD_CAN_TSCON_TBCEN |
+ ((cpriv->can.clock.freq / 1000000)
+ << MCP25XXFD_CAN_TSCON_TBCPRE_SHIFT);
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_CAN_TSCON, cpriv->regs.tscon);
+ if (ret)
+ return ret;
+
+ /* setup fifos */
+ ret = mcp25xxfd_can_fifo_setup(cpriv);
+ if (ret)
+ return ret;
+
+ /* setup can bittiming now - the do_set_bittiming methods
+ * are not used as they get callled before open
+ */
+ ret = mcp25xxfd_can_do_set_nominal_bittiming(net);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_can_do_set_data_bittiming(net);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+/* mode setting */
+static int mcp25xxfd_can_do_set_mode(struct net_device *net,
+ enum can_mode mode)
+{
+ switch (mode) {
+ case CAN_MODE_START:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/* binary error counters */
+static int mcp25xxfd_can_get_berr_counter(const struct net_device *net,
+ struct can_berr_counter *bec)
+{
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+
+ bec->txerr = (cpriv->status.trec & MCP25XXFD_CAN_TREC_TEC_MASK) >>
+ MCP25XXFD_CAN_TREC_TEC_SHIFT;
+ bec->rxerr = (cpriv->status.trec & MCP25XXFD_CAN_TREC_REC_MASK) >>
+ MCP25XXFD_CAN_TREC_REC_SHIFT;
+
+ return 0;
+}
+
+static int mcp25xxfd_can_open(struct net_device *net)
+{
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+ struct spi_device *spi = cpriv->priv->spi;
+ int ret;
+
+ ret = open_candev(net);
+ if (ret) {
+ netdev_err(net, "unable to set initial baudrate!\n");
+ return ret;
+ }
+
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ /* clear those statistics */
+ memset(&cpriv->stats, 0, sizeof(cpriv->stats));
+#endif
+
+ /* request an IRQ but keep disabled for now */
+ ret = request_threaded_irq(spi->irq, NULL,
+ mcp25xxfd_can_int,
+ IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+ cpriv->priv->device_name, cpriv);
+ if (ret) {
+ dev_err(&spi->dev, "failed to acquire irq %d - %i\n",
+ spi->irq, ret);
+ goto out_candev;
+ }
+ disable_irq(spi->irq);
+ cpriv->irq.allocated = true;
+ cpriv->irq.enabled = false;
+
+ /* enable power to the transceiver */
+ ret = mcp25xxfd_base_power_enable(cpriv->transceiver, 1);
+ if (ret)
+ goto out_irq;
+
+ /* enable clock (so that spi works) */
+ ret = mcp25xxfd_clock_start(cpriv->priv, MCP25XXFD_CLK_USER_CAN);
+ if (ret)
+ goto out_transceiver;
+
+ /* configure controller for reception */
+ ret = mcp25xxfd_can_config(net);
+ if (ret)
+ goto out_canclock;
+
+ /* setting up state */
+ cpriv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ /* enable interrupts */
+ ret = mcp25xxfd_int_enable(cpriv->priv, true);
+ if (ret)
+ goto out_canconfig;
+
+ /* switch to active mode */
+ ret = mcp25xxfd_can_switch_mode(cpriv->priv, &cpriv->regs.con,
+ (net->mtu == CAN_MTU) ?
+ MCP25XXFD_CAN_CON_MODE_CAN2_0 :
+ MCP25XXFD_CAN_CON_MODE_MIXED);
+ if (ret)
+ goto out_int;
+
+ /* start the tx_queue */
+ mcp25xxfd_can_tx_queue_manage(cpriv,
+ MCP25XXFD_CAN_TX_QUEUE_STATE_STARTED);
+
+ return 0;
+
+out_int:
+ mcp25xxfd_int_enable(cpriv->priv, false);
+out_canconfig:
+ mcp25xxfd_can_fifo_release(cpriv);
+out_canclock:
+ mcp25xxfd_clock_stop(cpriv->priv, MCP25XXFD_CLK_USER_CAN);
+out_transceiver:
+ mcp25xxfd_base_power_enable(cpriv->transceiver, 0);
+out_irq:
+ free_irq(spi->irq, cpriv);
+ cpriv->irq.allocated = false;
+ cpriv->irq.enabled = false;
+out_candev:
+ close_candev(net);
+ return ret;
+}
+
+static void mcp25xxfd_can_shutdown(struct mcp25xxfd_can_priv *cpriv)
+{
+ /* switch us to CONFIG mode - this disables the controller */
+ mcp25xxfd_can_switch_mode(cpriv->priv, &cpriv->regs.con,
+ MCP25XXFD_CAN_CON_MODE_CONFIG);
+}
+
+static int mcp25xxfd_can_stop(struct net_device *net)
+{
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+ struct mcp25xxfd_priv *priv = cpriv->priv;
+ struct spi_device *spi = priv->spi;
+
+ /* disable inerrupts on controller */
+ mcp25xxfd_int_enable(cpriv->priv, false);
+
+ /* stop transmit queue */
+ mcp25xxfd_can_tx_queue_manage(cpriv,
+ MCP25XXFD_CAN_TX_QUEUE_STATE_STOPPED);
+
+ /* release fifos and debugfs */
+ mcp25xxfd_can_fifo_release(cpriv);
+
+ /* shutdown the can controller */
+ mcp25xxfd_can_shutdown(cpriv);
+
+ /* stop the clock */
+ mcp25xxfd_clock_stop(cpriv->priv, MCP25XXFD_CLK_USER_CAN);
+
+ /* and disable the transceiver */
+ mcp25xxfd_base_power_enable(cpriv->transceiver, 0);
+
+ /* disable interrupt on host */
+ free_irq(spi->irq, cpriv);
+ cpriv->irq.allocated = false;
+ cpriv->irq.enabled = false;
+
+ /* close the can_decice */
+ close_candev(net);
+
+ return 0;
+}
+
+static const struct net_device_ops mcp25xxfd_netdev_ops = {
+ .ndo_open = mcp25xxfd_can_open,
+ .ndo_stop = mcp25xxfd_can_stop,
+ .ndo_start_xmit = mcp25xxfd_can_tx_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
+};
+
+/* probe and remove */
+int mcp25xxfd_can_setup(struct mcp25xxfd_priv *priv)
+{
+ struct spi_device *spi = priv->spi;
+ struct mcp25xxfd_can_priv *cpriv;
+ struct net_device *net;
+ struct regulator *transceiver;
+ int ret;
+
+ /* get transceiver power regulator*/
+ transceiver = devm_regulator_get_optional(&spi->dev,
+ "xceiver");
+ if (PTR_ERR(transceiver) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ /* allocate can device */
+ net = alloc_candev(sizeof(*cpriv), TX_ECHO_SKB_MAX);
+ if (!net)
+ return -ENOMEM;
+
+ /* and do some cross-asignments */
+ cpriv = netdev_priv(net);
+ cpriv->priv = priv;
+ priv->cpriv = cpriv;
+
+ /* setup network */
+ SET_NETDEV_DEV(net, &spi->dev);
+ net->netdev_ops = &mcp25xxfd_netdev_ops;
+ net->flags |= IFF_ECHO;
+
+ /* assign transceiver */
+ cpriv->transceiver = transceiver;
+
+ /* setup can */
+ cpriv->can.clock.freq = priv->clock_freq;
+ cpriv->can.bittiming_const =
+ &mcp25xxfd_can_nominal_bittiming_const;
+ cpriv->can.data_bittiming_const =
+ &mcp25xxfd_can_data_bittiming_const;
+ /* we are not setting bit-timing methods here as they get
+ * called by the framework before open so the controller is
+ * still in sleep mode, which does not help
+ * things are configured in open instead
+ */
+ cpriv->can.do_set_mode =
+ mcp25xxfd_can_do_set_mode;
+ cpriv->can.do_get_berr_counter =
+ mcp25xxfd_can_get_berr_counter;
+ cpriv->can.ctrlmode_supported =
+ CAN_CTRLMODE_FD |
+ CAN_CTRLMODE_FD_NON_ISO |
+ CAN_CTRLMODE_LOOPBACK |
+ CAN_CTRLMODE_LISTENONLY |
+ CAN_CTRLMODE_BERR_REPORTING |
+ CAN_CTRLMODE_ONE_SHOT;
+
+ ret = register_candev(net);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to register can device\n");
+ goto out;
+ }
+
+ mcp25xxfd_can_debugfs_setup(cpriv);
+
+ return 0;
+out:
+ free_candev(net);
+ priv->cpriv = NULL;
+
+ return ret;
+}
+
+void mcp25xxfd_can_remove(struct mcp25xxfd_priv *priv)
+{
+ if (priv->cpriv) {
+ unregister_candev(priv->cpriv->can.dev);
+ free_candev(priv->cpriv->can.dev);
+ priv->cpriv = NULL;
+ }
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.h
new file mode 100644
index 000000000000..6fca746d2dd5
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_H
+#define __MCP25XXFD_CAN_H
+
+#include "mcp25xxfd_can_debugfs.h"
+#include "mcp25xxfd_can_priv.h"
+#include "mcp25xxfd_priv.h"
+#include "mcp25xxfd_regs.h"
+
+/* get the optimal controller target mode */
+static inline
+int mcp25xxfd_can_targetmode(struct mcp25xxfd_can_priv *cpriv)
+{
+ return (cpriv->can.dev->mtu == CAN_MTU) ?
+ MCP25XXFD_CAN_CON_MODE_CAN2_0 : MCP25XXFD_CAN_CON_MODE_MIXED;
+}
+
+static inline
+void mcp25xxfd_can_queue_frame(struct mcp25xxfd_can_priv *cpriv,
+ s32 fifo, u32 ts, bool is_rx)
+{
+ int idx = cpriv->fifos.submit_queue_count;
+
+ cpriv->fifos.submit_queue[idx].fifo = fifo;
+ cpriv->fifos.submit_queue[idx].ts = ts;
+ cpriv->fifos.submit_queue[idx].is_rx = is_rx;
+
+ cpriv->fifos.submit_queue_count++;
+}
+
+/* get the current controller mode */
+int mcp25xxfd_can_get_mode(struct mcp25xxfd_priv *priv, u32 *reg);
+
+/* to put us to sleep fully we need the CAN controller to enter sleep mode */
+int mcp25xxfd_can_sleep_mode(struct mcp25xxfd_priv *priv);
+
+/* switch controller mode */
+int mcp25xxfd_can_switch_mode_no_wait(struct mcp25xxfd_priv *priv,
+ u32 *reg, int mode);
+int mcp25xxfd_can_switch_mode(struct mcp25xxfd_priv *priv,
+ u32 *reg, int mode);
+
+/* probe the can controller */
+int mcp25xxfd_can_probe(struct mcp25xxfd_priv *priv);
+
+/* setup and the can controller net interface */
+int mcp25xxfd_can_setup(struct mcp25xxfd_priv *priv);
+void mcp25xxfd_can_remove(struct mcp25xxfd_priv *priv);
+
+#endif /* __MCP25XXFD_CAN_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.c
new file mode 100644
index 000000000000..a7be645a2fd9
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include "mcp25xxfd_can_debugfs.h"
+#include "mcp25xxfd_can_priv.h"
+#include "mcp25xxfd_can_tx.h"
+
+static void mcp25xxfd_can_debugfs_regs(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("regs", root);
+
+ debugfs_create_x32("con", 0444, dir, &cpriv->regs.con);
+ debugfs_create_x32("tdc", 0444, dir, &cpriv->regs.tdc);
+ debugfs_create_x32("tscon", 0444, dir, &cpriv->regs.tscon);
+ debugfs_create_x32("tefcon", 0444, dir, &cpriv->regs.tscon);
+ debugfs_create_x32("nbtcfg", 0444, dir, &cpriv->regs.nbtcfg);
+ debugfs_create_x32("dbtcfg", 0444, dir, &cpriv->regs.dbtcfg);
+}
+
+static void mcp25xxfd_can_debugfs_status(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("status", root);
+
+ debugfs_create_x32("intf", 0444, dir, &cpriv->status.intf);
+ debugfs_create_x32("rx_if", 0444, dir, &cpriv->status.rxif);
+ debugfs_create_x32("tx_if", 0444, dir, &cpriv->status.txif);
+ debugfs_create_x32("rx_ovif", 0444, dir, &cpriv->status.rxovif);
+ debugfs_create_x32("tx_atif", 0444, dir, &cpriv->status.txatif);
+ debugfs_create_x32("tx_req", 0444, dir, &cpriv->status.txreq);
+ debugfs_create_x32("trec", 0444, dir, &cpriv->status.trec);
+}
+
+static void mcp25xxfd_can_debugfs_stats(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("stats", root);
+ char name[32];
+ u64 *data;
+ int i;
+
+# define DEBUGFS_CREATE(name, var) debugfs_create_u64(name, 0444, dir, \
+ &cpriv->stats.var)
+ DEBUGFS_CREATE("irq_calls", irq_calls);
+ DEBUGFS_CREATE("irq_loops", irq_loops);
+ DEBUGFS_CREATE("irq_thread_rescheduled", irq_thread_rescheduled);
+
+ DEBUGFS_CREATE("int_system_error", int_serr_count);
+ DEBUGFS_CREATE("int_system_error_tx", int_serr_tx_count);
+ DEBUGFS_CREATE("int_system_error_rx", int_serr_rx_count);
+ DEBUGFS_CREATE("int_mode_switch", int_mod_count);
+ DEBUGFS_CREATE("int_rx", int_rx_count);
+ DEBUGFS_CREATE("int_tx_attempt", int_txat_count);
+ DEBUGFS_CREATE("int_tef", int_tef_count);
+ DEBUGFS_CREATE("int_rx_overflow", int_rxov_count);
+ DEBUGFS_CREATE("int_ecc_error", int_ecc_count);
+ DEBUGFS_CREATE("int_rx_invalid_message", int_ivm_count);
+ DEBUGFS_CREATE("int_crcerror", int_cerr_count);
+
+ DEBUGFS_CREATE("tef_reads", tef_reads);
+ DEBUGFS_CREATE("tef_conservative_reads", tef_conservative_reads);
+ DEBUGFS_CREATE("tef_optimized_reads", tef_optimized_reads);
+ DEBUGFS_CREATE("tef_read_splits", tef_read_splits);
+
+ for (i = 0; i < MCP25XXFD_CAN_TEF_READ_BINS - 1; i++) {
+ snprintf(name, sizeof(name),
+ "tef_optimized_reads_%i", i + 1);
+ data = &cpriv->stats.tef_optimized_read_sizes[i];
+ debugfs_create_u64(name, 0444, dir, data);
+ }
+ snprintf(name, sizeof(name), "tef_optimized_reads_%i+", i + 1);
+ debugfs_create_u64(name, 0444, dir,
+ &cpriv->stats.tef_optimized_read_sizes[i]);
+
+ DEBUGFS_CREATE("tx_frames_fd", tx_fd_count);
+ DEBUGFS_CREATE("tx_frames_brs", tx_brs_count);
+
+ DEBUGFS_CREATE("rx_reads", rx_reads);
+ DEBUGFS_CREATE("rx_reads_prefetched_too_few",
+ rx_reads_prefetched_too_few);
+ DEBUGFS_CREATE("rx_reads_prefetched_too_few_bytes",
+ rx_reads_prefetched_too_few_bytes);
+ DEBUGFS_CREATE("rx_reads_prefetched_too_many",
+ rx_reads_prefetched_too_many);
+ DEBUGFS_CREATE("rx_reads_prefetched_too_many_bytes",
+ rx_reads_prefetched_too_many_bytes);
+ DEBUGFS_CREATE("rx_single_reads", rx_single_reads);
+ DEBUGFS_CREATE("rx_bulk_reads", rx_bulk_reads);
+
+ for (i = 0; i < MCP25XXFD_CAN_RX_BULK_READ_BINS - 1; i++) {
+ snprintf(name, sizeof(name), "rx_bulk_reads_%i", i + 1);
+ data = &cpriv->stats.rx_bulk_read_sizes[i];
+ debugfs_create_u64(name, 0444, dir, data);
+ }
+ snprintf(name, sizeof(name), "rx_bulk_reads_%i+", i + 1);
+ debugfs_create_u64(name, 0444, dir,
+ &cpriv->stats.rx_bulk_read_sizes[i]);
+
+ if (cpriv->can.dev->mtu == CANFD_MTU)
+ debugfs_create_u32("rx_reads_prefetch_predicted_len", 0444,
+ dir, &cpriv->rx_history.predicted_len);
+#undef DEBUGFS_CREATE
+}
+
+static void mcp25xxfd_can_debugfs_tef(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("tef", root);
+
+ debugfs_create_u32("count", 0444, dir, &cpriv->fifos.tef.count);
+ debugfs_create_u32("size", 0444, dir, &cpriv->fifos.tef.size);
+}
+
+static void mcp25xxfd_can_debugfs_fifo_info(struct mcp25xxfd_fifo_info *info,
+ int index, struct dentry *root)
+{
+ struct dentry *dir;
+ char name[4];
+
+ snprintf(name, sizeof(name), "%02i", index);
+ dir = debugfs_create_dir(name, root);
+
+ debugfs_create_u32("is_rx", 0444, dir, &info->is_rx);
+ debugfs_create_x32("offset", 0444, dir, &info->offset);
+ debugfs_create_u32("priority", 0444, dir, &info->priority);
+
+ debugfs_create_u64("use_count", 0444, dir, &info->use_count);
+}
+
+static void mcp25xxfd_can_debugfs_fifos(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("fifos", root);
+ int i;
+
+ /* now present all fifos - there is no fifo 0 */
+ for (i = 1; i < 32; i++)
+ mcp25xxfd_can_debugfs_fifo_info(&cpriv->fifos.info[i], i, dir);
+}
+
+static void mcp25xxfd_can_debugfs_rxtx_fifos(struct mcp25xxfd_fifo *d,
+ struct dentry *root)
+{
+ int i, f;
+ char name[4];
+ char link[32];
+
+ debugfs_create_u32("count", 0444, root, &d->count);
+ debugfs_create_u32("size", 0444, root, &d->size);
+ debugfs_create_u32("start", 0444, root, &d->start);
+
+ for (f = d->start, i = 0; i < d->count; f++, i++) {
+ snprintf(name, sizeof(name), "%02i", i);
+ snprintf(link, sizeof(link), "../fifos/%02i", f);
+
+ debugfs_create_symlink(name, root, link);
+ }
+}
+
+static void mcp25xxfd_can_debugfs_rx_fifos(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("rx_fifos", root);
+
+ mcp25xxfd_can_debugfs_rxtx_fifos(&cpriv->fifos.rx, dir);
+}
+
+static void mcp25xxfd_can_debugfs_tx_fifos(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct dentry *dir = debugfs_create_dir("tx_fifos", root);
+
+ mcp25xxfd_can_debugfs_rxtx_fifos(&cpriv->fifos.rx, dir);
+}
+
+static void mcp25xxfd_can_debugfs_tx_queue(struct mcp25xxfd_can_priv *cpriv,
+ struct dentry *root)
+{
+ struct mcp25xxfd_tx_spi_message_queue *queue = cpriv->fifos.tx_queue;
+ struct dentry *dir;
+
+ if (!queue)
+ return;
+
+ dir = debugfs_create_dir("tx_queue", root);
+
+ debugfs_create_u32("state", 0444, dir, &queue->state);
+ debugfs_create_x32("fifos_idle", 0444, dir, &queue->idle);
+ debugfs_create_x32("fifos_in_fill_fifo_transfer",
+ 0444, dir, &queue->in_fill_fifo_transfer);
+ debugfs_create_x32("fifos_in_trigger_fifo_transfer",
+ 0444, dir, &queue->in_trigger_fifo_transfer);
+ debugfs_create_x32("fifos_in_can_transfer",
+ 0444, dir, &queue->in_can_transfer);
+ debugfs_create_x32("fifos_transferred",
+ 0444, dir, &queue->transferred);
+}
+
+void mcp25xxfd_can_debugfs_remove(struct mcp25xxfd_can_priv *cpriv)
+{
+ debugfs_remove_recursive(cpriv->debugfs_dir);
+ cpriv->debugfs_dir = NULL;
+}
+
+void mcp25xxfd_can_debugfs_setup(struct mcp25xxfd_can_priv *cpriv)
+{
+ struct dentry *root;
+
+ /* remove first as we get called during probe and also
+ * when the can_device is configured/removed
+ */
+ mcp25xxfd_can_debugfs_remove(cpriv);
+
+ root = debugfs_create_dir("can", cpriv->priv->debugfs_dir);
+ cpriv->debugfs_dir = root;
+
+ mcp25xxfd_can_debugfs_regs(cpriv, root);
+ mcp25xxfd_can_debugfs_stats(cpriv, root);
+ mcp25xxfd_can_debugfs_status(cpriv, root);
+ mcp25xxfd_can_debugfs_tef(cpriv, root);
+ mcp25xxfd_can_debugfs_fifos(cpriv, root);
+ mcp25xxfd_can_debugfs_rx_fifos(cpriv, root);
+ mcp25xxfd_can_debugfs_tx_fifos(cpriv, root);
+ mcp25xxfd_can_debugfs_tx_queue(cpriv, root);
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.h
new file mode 100644
index 000000000000..a8391370d4bf
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_debugfs.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_DEBUGFS_H
+#define __MCP25XXFD_CAN_DEBUGFS_H
+
+#include "mcp25xxfd_can_priv.h"
+
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+
+#include <linux/debugfs.h>
+
+#define MCP25XXFD_DEBUGFS_INCR(counter) ((counter)++)
+#define MCP25XXFD_DEBUGFS_ADD(counter, val) ((counter) += (val))
+#define MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, counter) \
+ (((cpriv)->stats.counter)++)
+#define MCP25XXFD_DEBUGFS_STATS_ADD(cpriv, counter, val) \
+ (((cpriv)->stats.counter) += (val))
+
+void mcp25xxfd_can_debugfs_setup(struct mcp25xxfd_can_priv *cpriv);
+void mcp25xxfd_can_debugfs_remove(struct mcp25xxfd_can_priv *cpriv);
+
+#else /* CONFIG_CAN_MCP25XXFD_DEBUG_FS */
+
+#define MCP25XXFD_DEBUGFS_INCR(counter)
+#define MCP25XXFD_DEBUGFS_ADD(counter, val)
+#define MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, counter)
+#define MCP25XXFD_DEBUGFS_STATS_ADD(cpriv, counter, val)
+
+static inline
+void mcp25xxfd_can_debugfs_setup(struct mcp25xxfd_can_priv *cpriv)
+{
+}
+
+static inline
+void mcp25xxfd_can_debugfs_remove(struct mcp25xxfd_can_priv *cpriv)
+{
+}
+
+#endif /* CONFIG_CAN_MCP25XXFD_DEBUG_FS */
+#endif /* __MCP25XXFD_CAN_DEBUGFS_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.c
new file mode 100644
index 000000000000..990c3a77da9d
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+/* here we define and configure the fifo layout */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_can_fifo.h"
+#include "mcp25xxfd_can_priv.h"
+#include "mcp25xxfd_can_tx.h"
+#include "mcp25xxfd_cmd.h"
+
+/* some controller parameters are currently not configurable via netlink
+ * so we allow to control them via module parameters (that can changed
+ * in /sys if needed) - theses are only needed during setup if the can_device
+ */
+static unsigned int tx_fifos;
+module_param(tx_fifos, uint, 0664);
+MODULE_PARM_DESC(tx_fifos,
+ "Number of tx-fifos to configure - recommended value is < 7\n");
+
+static bool three_shot;
+module_param(three_shot, bool, 0664);
+MODULE_PARM_DESC(three_shot, "Use 3 shots when one-shot is requested");
+
+static int mcp25xxfd_can_fifo_get_address(struct mcp25xxfd_can_priv *cpriv)
+{
+ int fifo, ret;
+
+ /* we need to move out of config mode to force address computation */
+ ret = mcp25xxfd_can_switch_mode(cpriv->priv, &cpriv->regs.con,
+ MCP25XXFD_CAN_CON_MODE_INT_LOOPBACK);
+ if (ret)
+ return ret;
+
+ /* and get back into config mode */
+ ret = mcp25xxfd_can_switch_mode(cpriv->priv, &cpriv->regs.con,
+ MCP25XXFD_CAN_CON_MODE_CONFIG);
+ if (ret)
+ return ret;
+
+ /* read address and config back in */
+ for (fifo = 1; fifo < 32; fifo++) {
+ ret = mcp25xxfd_cmd_read(cpriv->priv->spi,
+ MCP25XXFD_CAN_FIFOUA(fifo),
+ &cpriv->fifos.info[fifo].offset);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_fifo_setup_config(struct mcp25xxfd_can_priv *cpriv,
+ struct mcp25xxfd_fifo *desc,
+ u32 flags, u32 flags_last)
+{
+ u32 val;
+ int i, p, f, c, ret;
+
+ /* now setup the fifos themselves */
+ for (i = 0, f = desc->start, c = desc->count, p = 31;
+ c > 0; i++, f++, p--, c--) {
+ /* select the effective value */
+ val = (c > 1) ? flags : flags_last;
+
+ /* are we in tx mode */
+ if (flags & MCP25XXFD_CAN_FIFOCON_TXEN) {
+ cpriv->fifos.info[f].is_rx = false;
+ cpriv->fifos.info[f].priority = p;
+ val |= (p << MCP25XXFD_CAN_FIFOCON_TXPRI_SHIFT);
+ } else {
+ cpriv->fifos.info[f].is_rx = true;
+ }
+
+ /* write the config to the controller in one go */
+ ret = mcp25xxfd_cmd_write(cpriv->priv->spi,
+ MCP25XXFD_CAN_FIFOCON(f), val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_fifo_setup_tx(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 tx_flags = MCP25XXFD_CAN_FIFOCON_FRESET | /* reset FIFO */
+ MCP25XXFD_CAN_FIFOCON_TXEN | /* a tx FIFO */
+ MCP25XXFD_CAN_FIFOCON_TXATIE | /* state in txatif */
+ (cpriv->fifos.payload_mode <<
+ MCP25XXFD_CAN_FIFOCON_PLSIZE_SHIFT) | /* paylod size */
+ (0 << MCP25XXFD_CAN_FIFOCON_FSIZE_SHIFT); /* 1 FIFO deep */
+
+ /* handle oneshot/three-shot */
+ if (cpriv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ if (three_shot)
+ tx_flags |= MCP25XXFD_CAN_FIFOCON_TXAT_THREE_SHOT <<
+ MCP25XXFD_CAN_FIFOCON_TXAT_SHIFT;
+ else
+ tx_flags |= MCP25XXFD_CAN_FIFOCON_TXAT_ONE_SHOT <<
+ MCP25XXFD_CAN_FIFOCON_TXAT_SHIFT;
+ else
+ tx_flags |= MCP25XXFD_CAN_FIFOCON_TXAT_UNLIMITED <<
+ MCP25XXFD_CAN_FIFOCON_TXAT_SHIFT;
+
+ return mcp25xxfd_can_fifo_setup_config(cpriv, &cpriv->fifos.tx,
+ tx_flags, tx_flags);
+}
+
+static int mcp25xxfd_can_fifo_setup_rx(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 rx_flags = MCP25XXFD_CAN_FIFOCON_FRESET | /* reset FIFO */
+ MCP25XXFD_CAN_FIFOCON_RXTSEN | /* RX timestamps */
+ MCP25XXFD_CAN_FIFOCON_TFERFFIE | /* FIFO Full */
+ MCP25XXFD_CAN_FIFOCON_TFHRFHIE | /* FIFO Half Full*/
+ MCP25XXFD_CAN_FIFOCON_TFNRFNIE | /* FIFO not empty */
+ (cpriv->fifos.payload_mode <<
+ MCP25XXFD_CAN_FIFOCON_PLSIZE_SHIFT) |
+ (0 << MCP25XXFD_CAN_FIFOCON_FSIZE_SHIFT); /* 1 FIFO deep */
+ /* enable overflow int on last fifo */
+ u32 rx_flags_last = rx_flags | MCP25XXFD_CAN_FIFOCON_RXOVIE;
+
+ return mcp25xxfd_can_fifo_setup_config(cpriv, &cpriv->fifos.rx,
+ rx_flags, rx_flags_last);
+}
+
+static int mcp25xxfd_can_fifo_setup_rxfilter(struct mcp25xxfd_can_priv *cpriv)
+{
+ u8 filter_con[32];
+ int c, f;
+
+ /* clear the filters and filter mappings for all filters */
+ memset(filter_con, 0, sizeof(filter_con));
+
+ /* and now set up the rx filters */
+ for (c = 0, f = cpriv->fifos.rx.start; c < cpriv->fifos.rx.count;
+ c++, f++) {
+ /* set up filter config - we can use the mask of filter 0 */
+ filter_con[c] = MCP25XXFD_CAN_FLTCON_FLTEN(0) |
+ (f << MCP25XXFD_CAN_FLTCON_SHIFT(0));
+ }
+
+ /* and set up filter control */
+ return mcp25xxfd_cmd_write_regs(cpriv->priv->spi,
+ MCP25XXFD_CAN_FLTCON(0),
+ (u32 *)filter_con, sizeof(filter_con));
+}
+
+static int mcp25xxfd_can_fifo_compute(struct mcp25xxfd_can_priv *cpriv)
+{
+ int tef_memory_used, tx_memory_used, rx_memory_available;
+
+ /* default settings as per MTU/CANFD */
+ switch (cpriv->can.dev->mtu) {
+ case CAN_MTU:
+ /* mtu is 8 */
+ cpriv->fifos.payload_size = 8;
+ cpriv->fifos.payload_mode = MCP25XXFD_CAN_TXQCON_PLSIZE_8;
+
+ /* 6 tx fifos */
+ cpriv->fifos.tx.count = 6;
+
+ break;
+ case CANFD_MTU:
+ /* wish there was a way to have hw filters
+ * that can separate based on length ...
+ */
+ /* MTU is 64 */
+ cpriv->fifos.payload_size = 64;
+ cpriv->fifos.payload_mode = MCP25XXFD_CAN_TXQCON_PLSIZE_64;
+
+ /* 6 tx fifos */
+ cpriv->fifos.tx.count = 6;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* compute effective sizes */
+ cpriv->fifos.tef.size = sizeof(struct mcp25xxfd_can_obj_tef);
+ cpriv->fifos.tx.size = sizeof(struct mcp25xxfd_can_obj_tx) +
+ cpriv->fifos.payload_size;
+ cpriv->fifos.rx.size = sizeof(struct mcp25xxfd_can_obj_rx) +
+ cpriv->fifos.payload_size;
+
+ /* if defined as a module parameter modify the number of tx_fifos */
+ if (tx_fifos) {
+ netdev_info(cpriv->can.dev,
+ "Using %i tx-fifos as per module parameter\n",
+ tx_fifos);
+ cpriv->fifos.tx.count = tx_fifos;
+ if (tx_fifos > 6)
+ netdev_info(cpriv->can.dev,
+ "You may trigger a bug where during a spi transfer bit 7, 15, 23 or 31 of TXREQ may flip due to CAN bus activity or similar so the recommended value is < 7\n");
+ }
+
+ /* there can be at the most 30 tx fifos (TEF and at least 1 RX fifo */
+ if (cpriv->fifos.tx.count > 30) {
+ netdev_err(cpriv->can.dev,
+ "There is an absolute maximum of 30 tx-fifos\n");
+ return -EINVAL;
+ }
+
+ /* set tef fifos to the number of tx fifos */
+ cpriv->fifos.tef.count = cpriv->fifos.tx.count;
+
+ /* compute size of the tx fifos and TEF */
+ tx_memory_used = cpriv->fifos.tx.count * cpriv->fifos.tx.size;
+ tef_memory_used = cpriv->fifos.tef.count * cpriv->fifos.tef.size;
+
+ /* calculate evailable memory for RX_fifos */
+ rx_memory_available = MCP25XXFD_SRAM_SIZE - tx_memory_used -
+ tef_memory_used;
+
+ /* we need at least one RX Frame */
+ if (rx_memory_available < cpriv->fifos.rx.size) {
+ netdev_err(cpriv->can.dev,
+ "Configured %i tx-fifos exceeds available memory already\n",
+ cpriv->fifos.tx.count);
+ return -EINVAL;
+ }
+
+ /* calculate possible amount of RX fifos */
+ cpriv->fifos.rx.count = rx_memory_available / cpriv->fifos.rx.size;
+
+ /* so now calculate effective number of rx-fifos
+ * there are only 31 fifos available in total,
+ * so we need to limit ourselves
+ */
+ if (cpriv->fifos.rx.count + cpriv->fifos.tx.count > 31)
+ cpriv->fifos.rx.count = 31 - cpriv->fifos.tx.count;
+
+ /* define the layout now that we have gotten everything */
+ cpriv->fifos.tx.start = 1;
+ cpriv->fifos.rx.start = cpriv->fifos.tx.start + cpriv->fifos.tx.count;
+
+ return 0;
+}
+
+static int mcp25xxfd_can_fifo_clear_regs(struct mcp25xxfd_can_priv *cpriv,
+ u32 start, u32 end)
+{
+ size_t len = end - start;
+ u8 *data = kzalloc(len, GFP_KERNEL);
+ int ret;
+
+ if (!data)
+ return -ENOMEM;
+
+ ret = mcp25xxfd_cmd_write_regs(cpriv->priv->spi,
+ start, (u32 *)data, len);
+
+ kfree(data);
+
+ return ret;
+}
+
+static int mcp25xxfd_can_fifo_clear(struct mcp25xxfd_can_priv *cpriv)
+{
+ int ret;
+
+ memset(&cpriv->fifos.info, 0, sizeof(cpriv->fifos.info));
+ memset(&cpriv->fifos.tx, 0, sizeof(cpriv->fifos.tx));
+ memset(&cpriv->fifos.rx, 0, sizeof(cpriv->fifos.rx));
+
+ /* clear FIFO config */
+ ret = mcp25xxfd_can_fifo_clear_regs(cpriv, MCP25XXFD_CAN_FIFOCON(1),
+ MCP25XXFD_CAN_FIFOCON(32));
+ if (ret)
+ return ret;
+
+ /* clear the filter mask - match any frame with every filter */
+ return mcp25xxfd_can_fifo_clear_regs(cpriv, MCP25XXFD_CAN_FLTCON(0),
+ MCP25XXFD_CAN_FLTCON(32));
+}
+
+int mcp25xxfd_can_fifo_setup(struct mcp25xxfd_can_priv *cpriv)
+{
+ int ret;
+
+ /* clear fifo config */
+ ret = mcp25xxfd_can_fifo_clear(cpriv);
+ if (ret)
+ return ret;
+
+ /* compute fifos counts */
+ ret = mcp25xxfd_can_fifo_compute(cpriv);
+ if (ret)
+ return ret;
+
+ /* configure TEF */
+ if (cpriv->fifos.tef.count)
+ cpriv->regs.tefcon =
+ MCP25XXFD_CAN_TEFCON_FRESET |
+ MCP25XXFD_CAN_TEFCON_TEFNEIE |
+ MCP25XXFD_CAN_TEFCON_TEFTSEN |
+ ((cpriv->fifos.tef.count - 1) <<
+ MCP25XXFD_CAN_TEFCON_FSIZE_SHIFT);
+ else
+ cpriv->regs.tefcon = 0;
+ ret = mcp25xxfd_cmd_write(cpriv->priv->spi, MCP25XXFD_CAN_TEFCON,
+ cpriv->regs.tefcon);
+ if (ret)
+ return ret;
+
+ /* TXQueue disabled */
+ ret = mcp25xxfd_cmd_write(cpriv->priv->spi, MCP25XXFD_CAN_TXQCON, 0);
+ if (ret)
+ return ret;
+
+ /* configure FIFOS themselves */
+ ret = mcp25xxfd_can_fifo_setup_tx(cpriv);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_can_fifo_setup_rx(cpriv);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_can_fifo_setup_rxfilter(cpriv);
+ if (ret)
+ return ret;
+
+ /* get fifo addresses */
+ ret = mcp25xxfd_can_fifo_get_address(cpriv);
+ if (ret)
+ return ret;
+
+ /* setup tx_fifo_queue */
+ ret = mcp25xxfd_can_tx_queue_alloc(cpriv);
+ if (ret)
+ return ret;
+
+ /* add the can info to debugfs */
+ mcp25xxfd_can_debugfs_setup(cpriv);
+
+ return 0;
+}
+
+void mcp25xxfd_can_fifo_release(struct mcp25xxfd_can_priv *cpriv)
+{
+ mcp25xxfd_can_tx_queue_free(cpriv);
+ mcp25xxfd_can_fifo_clear(cpriv);
+ mcp25xxfd_can_debugfs_remove(cpriv);
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.h
new file mode 100644
index 000000000000..ed2daa05220a
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_fifo.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_FIFO_H
+#define __MCP25XXFD_CAN_FIFO_H
+
+#include "mcp25xxfd_can_priv.h"
+
+int mcp25xxfd_can_fifo_setup(struct mcp25xxfd_can_priv *cpriv);
+void mcp25xxfd_can_fifo_release(struct mcp25xxfd_can_priv *cpriv);
+
+#endif /* __MCP25XXFD_CAN_FIFO_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_id.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_id.h
new file mode 100644
index 000000000000..00a6c6639bd5
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_id.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_IF_H
+#define __MCP25XXFD_CAN_IF_H
+
+#include <uapi/linux/can.h>
+
+#include "mcp25xxfd_can_id.h"
+#include "mcp25xxfd_regs.h"
+
+/* ideally these would be defined in uapi/linux/can.h */
+#define MCP25XXFD_CAN_EFF_SID_SHIFT (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)
+#define MCP25XXFD_CAN_EFF_SID_BITS CAN_SFF_ID_BITS
+#define MCP25XXFD_CAN_EFF_SID_MASK \
+ GENMASK(MCP25XXFD_CAN_EFF_SID_SHIFT + MCP25XXFD_CAN_EFF_SID_BITS - 1, \
+ MCP25XXFD_CAN_EFF_SID_SHIFT)
+#define MCP25XXFD_CAN_EFF_EID_SHIFT 0
+#define MCP25XXFD_CAN_EFF_EID_BITS MCP25XXFD_CAN_EFF_SID_SHIFT
+#define MCP25XXFD_CAN_EFF_EID_MASK \
+ GENMASK(MCP25XXFD_CAN_EFF_EID_SHIFT + MCP25XXFD_CAN_EFF_EID_BITS - 1, \
+ MCP25XXFD_CAN_EFF_EID_SHIFT)
+
+static inline
+void mcp25xxfd_can_id_from_mcp25xxfd(u32 mcp_id, u32 mcp_flags, u32 *can_id)
+{
+ u32 sid = (mcp_id & MCP25XXFD_CAN_OBJ_ID_SID_MASK) >>
+ MCP25XXFD_CAN_OBJ_ID_SID_SHIFT;
+ u32 eid = (mcp_id & MCP25XXFD_CAN_OBJ_ID_EID_MASK) >>
+ MCP25XXFD_CAN_OBJ_ID_EID_SHIFT;
+
+ /* select normal or extended ids */
+ if (mcp_flags & MCP25XXFD_CAN_OBJ_FLAGS_IDE) {
+ *can_id = (eid << MCP25XXFD_CAN_EFF_EID_SHIFT) |
+ (sid << MCP25XXFD_CAN_EFF_SID_SHIFT) |
+ CAN_EFF_FLAG;
+ } else {
+ *can_id = sid << MCP25XXFD_CAN_EFF_EID_SHIFT;
+ }
+ /* handle rtr */
+ *can_id |= (mcp_flags & MCP25XXFD_CAN_OBJ_FLAGS_RTR) ? CAN_RTR_FLAG : 0;
+}
+
+static inline
+void mcp25xxfd_can_id_to_mcp25xxfd(u32 can_id, u32 *id, u32 *flags)
+{
+ /* depending on can_id flag compute extended or standard ids */
+ if (can_id & CAN_EFF_FLAG) {
+ int sid = (can_id & MCP25XXFD_CAN_EFF_SID_MASK) >>
+ MCP25XXFD_CAN_EFF_SID_SHIFT;
+ int eid = (can_id & MCP25XXFD_CAN_EFF_EID_MASK) >>
+ MCP25XXFD_CAN_EFF_EID_SHIFT;
+ *id = (eid << MCP25XXFD_CAN_OBJ_ID_EID_SHIFT) |
+ (sid << MCP25XXFD_CAN_OBJ_ID_SID_SHIFT);
+ *flags = MCP25XXFD_CAN_OBJ_FLAGS_IDE;
+ } else {
+ *id = can_id & CAN_SFF_MASK;
+ *flags = 0;
+ }
+
+ /* Handle RTR */
+ *flags |= (can_id & CAN_RTR_FLAG) ? MCP25XXFD_CAN_OBJ_FLAGS_RTR : 0;
+}
+
+#endif /* __MCP25XXFD_CAN_IF_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.c
new file mode 100644
index 000000000000..54c70bcea2ce
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.c
@@ -0,0 +1,740 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_can_debugfs.h"
+#include "mcp25xxfd_can_int.h"
+#include "mcp25xxfd_can_priv.h"
+#include "mcp25xxfd_can_rx.h"
+#include "mcp25xxfd_can_tx.h"
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_ecc.h"
+#include "mcp25xxfd_int.h"
+#include "mcp25xxfd_regs.h"
+
+static unsigned int reschedule_int_thread_after = 4;
+module_param(reschedule_int_thread_after, uint, 0664);
+MODULE_PARM_DESC(reschedule_int_thread_after,
+ "Reschedule the interrupt thread after this many loops\n");
+
+static void mcp25xxfd_can_int_send_error_skb(struct mcp25xxfd_can_priv *cpriv)
+{
+ struct net_device *net = cpriv->can.dev;
+ struct sk_buff *skb;
+ struct can_frame *frame;
+
+ /* allocate error frame */
+ skb = alloc_can_err_skb(net, &frame);
+ if (!skb) {
+ netdev_err(net, "cannot allocate error skb\n");
+ return;
+ }
+
+ /* setup can error frame data */
+ frame->can_id |= cpriv->error_frame.id;
+ memcpy(frame->data, cpriv->error_frame.data, sizeof(frame->data));
+
+ /* and submit it */
+ netif_rx(skb);
+}
+
+static int mcp25xxfd_can_int_compare_obj_ts(const void *a, const void *b)
+{
+ s32 ats = ((struct mcp25xxfd_obj_ts *)a)->ts;
+ s32 bts = ((struct mcp25xxfd_obj_ts *)b)->ts;
+
+ if (ats < bts)
+ return -1;
+ if (ats > bts)
+ return 1;
+ return 0;
+}
+
+static int mcp25xxfd_can_int_submit_frames(struct mcp25xxfd_can_priv *cpriv)
+{
+ struct mcp25xxfd_obj_ts *queue = cpriv->fifos.submit_queue;
+ int count = cpriv->fifos.submit_queue_count;
+ int i, fifo;
+ int ret;
+
+ /* skip processing if the queue count is 0 */
+ if (count == 0)
+ goto out;
+
+ /* sort the fifos (rx and tx - actually TEF) by receive timestamp */
+ sort(queue, count, sizeof(*queue),
+ mcp25xxfd_can_int_compare_obj_ts, NULL);
+
+ /* now submit the fifos */
+ for (i = 0; i < count; i++) {
+ fifo = queue[i].fifo;
+ ret = (queue[i].is_rx) ?
+ mcp25xxfd_can_rx_submit_frame(cpriv, fifo) :
+ mcp25xxfd_can_tx_submit_frame(cpriv, fifo);
+ if (ret)
+ return ret;
+ }
+
+ /* if we have received or transmitted something
+ * and the IVMIE is disabled, then enable it
+ * this is mostly to avoid unnecessary interrupts during a
+ * disconnected CAN BUS
+ */
+ if (!(cpriv->status.intf | MCP25XXFD_CAN_INT_IVMIE)) {
+ cpriv->status.intf |= MCP25XXFD_CAN_INT_IVMIE;
+ ret = mcp25xxfd_cmd_write_mask(cpriv->priv->spi,
+ MCP25XXFD_CAN_INT,
+ cpriv->status.intf,
+ MCP25XXFD_CAN_INT_IVMIE);
+ if (ret)
+ return ret;
+ }
+
+out:
+ /* enable tx_queue if necessary */
+ mcp25xxfd_can_tx_queue_restart(cpriv);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_clear_int_flags(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 clearable_irq_active = cpriv->status.intf &
+ MCP25XXFD_CAN_INT_IF_CLEAR_MASK;
+ u32 clear_irq = cpriv->status.intf & (~MCP25XXFD_CAN_INT_IF_CLEAR_MASK);
+
+ /* if no clearable flags are set then skip the whole transfer */
+ if (!clearable_irq_active)
+ return 0;
+
+ return mcp25xxfd_cmd_write_mask(cpriv->priv->spi, MCP25XXFD_CAN_INT,
+ clear_irq, clearable_irq_active);
+}
+
+static
+int mcp25xxfd_can_int_handle_serrif_txmab(struct mcp25xxfd_can_priv *cpriv)
+{
+ int mode = mcp25xxfd_can_targetmode(cpriv);
+
+ cpriv->can.dev->stats.tx_fifo_errors++;
+ cpriv->can.dev->stats.tx_errors++;
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_serr_tx_count);
+
+ /* data7 contains custom mcp25xxfd error flags */
+ cpriv->error_frame.data[7] |= MCP25XXFD_CAN_ERR_DATA7_MCP25XXFD_SERR_TX;
+
+ /* and switch back into the correct mode */
+ return mcp25xxfd_can_switch_mode_no_wait(cpriv->priv,
+ &cpriv->regs.con, mode);
+}
+
+static
+int mcp25xxfd_can_int_handle_serrif_rxmab(struct mcp25xxfd_can_priv *cpriv)
+{
+ cpriv->can.dev->stats.rx_dropped++;
+ cpriv->can.dev->stats.rx_errors++;
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_serr_rx_count);
+
+ /* data7 contains custom mcp25xxfd error flags */
+ cpriv->error_frame.data[7] |= MCP25XXFD_CAN_ERR_DATA7_MCP25XXFD_SERR_RX;
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_handle_serrif(struct mcp25xxfd_can_priv *cpriv)
+{
+ if (!(cpriv->status.intf & MCP25XXFD_CAN_INT_SERRIF))
+ return 0;
+
+ /* increment statistics counter now */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_serr_count);
+
+ /* interrupt flags have been cleared already */
+
+ /* Errors here are:
+ * * Bus Bandwidth Error: when a RX Message Assembly Buffer
+ * is still full when the next message has already arrived
+ * the recived message shall be ignored
+ * * TX MAB Underflow: when a TX Message is invalid
+ * due to ECC errors or TXMAB underflow
+ * in this situatioon the system will transition to
+ * Restricted or Listen Only mode
+ */
+
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |= CAN_ERR_CRTL_UNSPEC;
+
+ /* a mode change + invalid message would indicate
+ * TX MAB Underflow
+ */
+ if ((cpriv->status.intf & MCP25XXFD_CAN_INT_MODIF) &&
+ (cpriv->status.intf & MCP25XXFD_CAN_INT_IVMIF)) {
+ return mcp25xxfd_can_int_handle_serrif_txmab(cpriv);
+ }
+
+ /* for RX there is only the RXIF an indicator
+ * - surprizingly RX-MAB does not change mode or anything
+ */
+ if (cpriv->status.intf & MCP25XXFD_CAN_INT_RXIF)
+ return mcp25xxfd_can_int_handle_serrif_rxmab(cpriv);
+
+ /* the final case */
+ dev_warn_ratelimited(&cpriv->priv->spi->dev,
+ "unidentified system interrupt - intf = %08x\n",
+ cpriv->status.intf);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_handle_modif(struct mcp25xxfd_can_priv *cpriv)
+{
+ struct spi_device *spi = cpriv->priv->spi;
+ int mode;
+ int ret;
+
+ /* Note that this irq does not get triggered in all situations
+ * for example SERRIF will move to RESTICTED or LISTENONLY
+ * but MODIF will not be raised!
+ */
+
+ if (!(cpriv->status.intf & MCP25XXFD_CAN_INT_MODIF))
+ return 0;
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_mod_count);
+
+ /* get the current mode */
+ ret = mcp25xxfd_can_get_mode(cpriv->priv, &mode);
+ if (ret < 0)
+ return ret;
+ mode = ret;
+
+ /* switches to the same mode as before are ignored
+ * - this typically happens if the driver is shortly
+ * switching to a different mode and then returning to the
+ * original mode
+ */
+ if (mode == cpriv->mode)
+ return 0;
+
+ /* if we are restricted, then return to "normal" mode */
+ if (mode == MCP25XXFD_CAN_CON_MODE_RESTRICTED) {
+ cpriv->mode = mode;
+ mode = mcp25xxfd_can_targetmode(cpriv);
+ return mcp25xxfd_can_switch_mode_no_wait(cpriv->priv,
+ &cpriv->regs.con,
+ mode);
+ }
+
+ /* the controller itself will transition to sleep, so we ignore it */
+ if (mode == MCP25XXFD_CAN_CON_MODE_SLEEP) {
+ cpriv->mode = mode;
+ return 0;
+ }
+
+ /* these we need to handle correctly, so warn and give context */
+ dev_warn(&spi->dev,
+ "Controller unexpectedly switched from mode %u to %u\n",
+ cpriv->mode, mode);
+
+ /* assign the mode as current */
+ cpriv->mode = mode;
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_handle_eccif(struct mcp25xxfd_can_priv *cpriv)
+{
+ if (!(cpriv->status.intf & MCP25XXFD_CAN_INT_ECCIF))
+ return 0;
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_ecc_count);
+
+ /* and prepare ERROR FRAME */
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |= CAN_ERR_CRTL_UNSPEC;
+ /* data7 contains custom mcp25xxfd error flags */
+ cpriv->error_frame.data[7] |= MCP25XXFD_CAN_ERR_DATA7_MCP25XXFD_ECC;
+
+ /* delegate to interrupt cleaning */
+ return mcp25xxfd_ecc_clear_int(cpriv->priv);
+}
+
+static void mcp25xxfd_can_int_handle_ivmif_tx(struct mcp25xxfd_can_priv *cpriv,
+ u32 *mask)
+{
+ /* check if it is really a known tx error */
+ if ((cpriv->bus.bdiag[1] &
+ (MCP25XXFD_CAN_BDIAG1_DBIT1ERR |
+ MCP25XXFD_CAN_BDIAG1_DBIT0ERR |
+ MCP25XXFD_CAN_BDIAG1_NACKERR |
+ MCP25XXFD_CAN_BDIAG1_NBIT1ERR |
+ MCP25XXFD_CAN_BDIAG1_NBIT0ERR
+ )) == 0)
+ return;
+
+ /* mark it as a protocol error */
+ cpriv->error_frame.id |= CAN_ERR_PROT;
+
+ /* and update statistics */
+ cpriv->can.dev->stats.tx_errors++;
+
+ /* and handle all the known cases */
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_NACKERR) {
+ /* TX-Frame not acknowledged - connected to CAN-bus? */
+ *mask |= MCP25XXFD_CAN_BDIAG1_NACKERR;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_TX;
+ cpriv->can.dev->stats.tx_aborted_errors++;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_NBIT1ERR) {
+ /* TX-Frame CAN-BUS Level is unexpectedly dominant */
+ *mask |= MCP25XXFD_CAN_BDIAG1_NBIT1ERR;
+ cpriv->can.dev->stats.tx_carrier_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_BIT1;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_NBIT0ERR) {
+ /* TX-Frame CAN-BUS Level is unexpectedly recessive */
+ *mask |= MCP25XXFD_CAN_BDIAG1_NBIT0ERR;
+ cpriv->can.dev->stats.tx_carrier_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_BIT0;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_DBIT1ERR) {
+ /* TX-Frame CAN-BUS Level is unexpectedly dominant
+ * during data phase
+ */
+ *mask |= MCP25XXFD_CAN_BDIAG1_DBIT1ERR;
+ cpriv->can.dev->stats.tx_carrier_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_BIT1;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_DBIT0ERR) {
+ /* TX-Frame CAN-BUS Level is unexpectedly recessive
+ * during data phase
+ */
+ *mask |= MCP25XXFD_CAN_BDIAG1_DBIT0ERR;
+ cpriv->can.dev->stats.tx_carrier_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_BIT0;
+ }
+}
+
+static void mcp25xxfd_can_int_handle_ivmif_rx(struct mcp25xxfd_can_priv *cpriv,
+ u32 *mask)
+{
+ /* check if it is really a known tx error */
+ if ((cpriv->bus.bdiag[1] &
+ (MCP25XXFD_CAN_BDIAG1_DCRCERR |
+ MCP25XXFD_CAN_BDIAG1_DSTUFERR |
+ MCP25XXFD_CAN_BDIAG1_DFORMERR |
+ MCP25XXFD_CAN_BDIAG1_NCRCERR |
+ MCP25XXFD_CAN_BDIAG1_NSTUFERR |
+ MCP25XXFD_CAN_BDIAG1_NFORMERR
+ )) == 0)
+ return;
+
+ /* mark it as a protocol error */
+ cpriv->error_frame.id |= CAN_ERR_PROT;
+
+ /* and update statistics */
+ cpriv->can.dev->stats.rx_errors++;
+
+ /* handle the cases */
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_DCRCERR) {
+ /* RX-Frame with bad CRC during data phase */
+ *mask |= MCP25XXFD_CAN_BDIAG1_DCRCERR;
+ cpriv->can.dev->stats.rx_crc_errors++;
+ cpriv->error_frame.data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_DSTUFERR) {
+ /* RX-Frame with bad stuffing during data phase */
+ *mask |= MCP25XXFD_CAN_BDIAG1_DSTUFERR;
+ cpriv->can.dev->stats.rx_frame_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_STUFF;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_DFORMERR) {
+ /* RX-Frame with bad format during data phase */
+ *mask |= MCP25XXFD_CAN_BDIAG1_DFORMERR;
+ cpriv->can.dev->stats.rx_frame_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_FORM;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_NCRCERR) {
+ /* RX-Frame with bad CRC during data phase */
+ *mask |= MCP25XXFD_CAN_BDIAG1_NCRCERR;
+ cpriv->can.dev->stats.rx_crc_errors++;
+ cpriv->error_frame.data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_NSTUFERR) {
+ /* RX-Frame with bad stuffing during data phase */
+ *mask |= MCP25XXFD_CAN_BDIAG1_NSTUFERR;
+ cpriv->can.dev->stats.rx_frame_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_STUFF;
+ }
+ if (cpriv->bus.bdiag[1] & MCP25XXFD_CAN_BDIAG1_NFORMERR) {
+ /* RX-Frame with bad format during data phase */
+ *mask |= MCP25XXFD_CAN_BDIAG1_NFORMERR;
+ cpriv->can.dev->stats.rx_frame_errors++;
+ cpriv->error_frame.data[2] |= CAN_ERR_PROT_FORM;
+ }
+}
+
+static int mcp25xxfd_can_int_handle_ivmif(struct mcp25xxfd_can_priv *cpriv)
+{
+ struct spi_device *spi = cpriv->priv->spi;
+ u32 mask, bdiag1;
+ int ret;
+
+ if (!(cpriv->status.intf & MCP25XXFD_CAN_INT_IVMIF))
+ return 0;
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_ivm_count);
+
+ /* if we have a systemerror as well,
+ * then ignore it as they correlate
+ */
+ if (cpriv->status.intf & MCP25XXFD_CAN_INT_SERRIF)
+ return 0;
+
+ /* read bus diagnostics */
+ ret = mcp25xxfd_cmd_read_regs(spi, MCP25XXFD_CAN_BDIAG0,
+ cpriv->bus.bdiag,
+ sizeof(cpriv->bus.bdiag));
+ if (ret)
+ return ret;
+
+ /* clear the masks of bits to clear */
+ mask = 0;
+
+ /* check rx and tx errors */
+ mcp25xxfd_can_int_handle_ivmif_tx(cpriv, &mask);
+ mcp25xxfd_can_int_handle_ivmif_rx(cpriv, &mask);
+
+ /* clear flags if we have bits masked */
+ if (!mask) {
+ /* the unsupported case, where we are not
+ * clearing any registers
+ */
+ dev_warn_once(&spi->dev,
+ "found IVMIF situation not supported by driver - bdiag = [0x%08x, 0x%08x]",
+ cpriv->bus.bdiag[0], cpriv->bus.bdiag[1]);
+ return -EINVAL;
+ }
+
+ /* clear the bits in bdiag1 */
+ bdiag1 = cpriv->bus.bdiag[1] & (~mask);
+ /* and write it */
+ ret = mcp25xxfd_cmd_write_mask(spi, MCP25XXFD_CAN_BDIAG1, bdiag1, mask);
+ if (ret)
+ return ret;
+
+ /* and clear the interrupt flag until we have received or transmited */
+ cpriv->status.intf &= ~(MCP25XXFD_CAN_INT_IVMIE);
+ return mcp25xxfd_cmd_write_mask(spi, MCP25XXFD_CAN_INT,
+ cpriv->status.intf,
+ MCP25XXFD_CAN_INT_IVMIE);
+}
+
+static int mcp25xxfd_can_int_handle_cerrif(struct mcp25xxfd_can_priv *cpriv)
+{
+ if (!(cpriv->status.intf & MCP25XXFD_CAN_INT_CERRIF))
+ return 0;
+
+ /* this interrupt exists primarilly to counter possible
+ * bus off situations more detailed information
+ * can be found and controlled in the TREC register
+ */
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_cerr_count);
+
+ netdev_warn(cpriv->can.dev, "CAN Bus error experienced");
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_error_counters(struct mcp25xxfd_can_priv *cpriv)
+{
+ if (cpriv->status.trec & MCP25XXFD_CAN_TREC_TXWARN) {
+ cpriv->bus.new_state = CAN_STATE_ERROR_WARNING;
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |= CAN_ERR_CRTL_TX_WARNING;
+ }
+ if (cpriv->status.trec & MCP25XXFD_CAN_TREC_RXWARN) {
+ cpriv->bus.new_state = CAN_STATE_ERROR_WARNING;
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |= CAN_ERR_CRTL_RX_WARNING;
+ }
+ if (cpriv->status.trec & MCP25XXFD_CAN_TREC_TXBP) {
+ cpriv->bus.new_state = CAN_STATE_ERROR_PASSIVE;
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+ }
+ if (cpriv->status.trec & MCP25XXFD_CAN_TREC_RXBP) {
+ cpriv->bus.new_state = CAN_STATE_ERROR_PASSIVE;
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+ }
+ if (cpriv->status.trec & MCP25XXFD_CAN_TREC_TXBO) {
+ cpriv->bus.new_state = CAN_STATE_BUS_OFF;
+ cpriv->error_frame.id |= CAN_ERR_BUSOFF;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_error_handling(struct mcp25xxfd_can_priv *cpriv)
+{
+ /* based on the last state state check the new state */
+ switch (cpriv->can.state) {
+ case CAN_STATE_ERROR_ACTIVE:
+ if (cpriv->bus.new_state >= CAN_STATE_ERROR_WARNING &&
+ cpriv->bus.new_state <= CAN_STATE_BUS_OFF)
+ cpriv->can.can_stats.error_warning++;
+ /* fallthrough */
+ case CAN_STATE_ERROR_WARNING:
+ if (cpriv->bus.new_state >= CAN_STATE_ERROR_PASSIVE &&
+ cpriv->bus.new_state <= CAN_STATE_BUS_OFF)
+ cpriv->can.can_stats.error_passive++;
+ break;
+ default:
+ break;
+ }
+ cpriv->can.state = cpriv->bus.new_state;
+
+ /* and send error packet */
+ if (cpriv->error_frame.id)
+ mcp25xxfd_can_int_send_error_skb(cpriv);
+
+ /* handle BUS OFF */
+ if (cpriv->can.state == CAN_STATE_BUS_OFF) {
+ if (cpriv->can.restart_ms == 0) {
+ cpriv->can.can_stats.bus_off++;
+ can_bus_off(cpriv->can.dev);
+ }
+ } else {
+ /* restart the tx queue if needed */
+ mcp25xxfd_can_tx_queue_restart(cpriv);
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_int_handle_status(struct mcp25xxfd_can_priv *cpriv)
+{
+ char *errfunc;
+ int ret;
+
+#define HANDLE_ERROR(name) \
+ do { \
+ if (ret) { \
+ errfunc = name; \
+ goto err; \
+ } \
+ } while (0)
+
+ /* clear all the interrupts asap - we have them on file allready */
+ ret = mcp25xxfd_can_int_clear_int_flags(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_clear_int_flags");
+
+ /* set up new state and error frame for this loop */
+ cpriv->bus.new_state = cpriv->bus.state;
+ memset(&cpriv->error_frame, 0, sizeof(cpriv->error_frame));
+
+ /* setup the process queue by clearing the counter */
+ cpriv->fifos.submit_queue_count = 0;
+
+ /* handle interrupts */
+
+ /* system error interrupt needs to get handled first
+ * to get us out of restricted mode
+ */
+ ret = mcp25xxfd_can_int_handle_serrif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_handle_serrif");
+
+ /* mode change interrupt */
+ ret = mcp25xxfd_can_int_handle_modif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_handle_modif");
+
+ /* handle the rx */
+ ret = mcp25xxfd_can_rx_handle_int_rxif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_rx_handle_int_rxif");
+
+ /* handle aborted TX FIFOs */
+ ret = mcp25xxfd_can_tx_handle_int_txatif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_tx_handle_int_txatif");
+
+ /* handle the TEF */
+ ret = mcp25xxfd_can_tx_handle_int_tefif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_rx_handle_int_tefif");
+
+ /* handle error interrupt flags */
+ ret = mcp25xxfd_can_rx_handle_int_rxovif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_rx_handle_int_rxovif");
+
+ /* sram ECC error interrupt */
+ ret = mcp25xxfd_can_int_handle_eccif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_handle_eccif");
+
+ /* message format interrupt */
+ ret = mcp25xxfd_can_int_handle_ivmif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_handle_ivmif");
+
+ /* handle bus errors in more detail */
+ ret = mcp25xxfd_can_int_handle_cerrif(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_handle_cerrif");
+
+ /* error counter handling */
+ ret = mcp25xxfd_can_int_error_counters(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_error_counters");
+
+ /* error counter handling */
+ ret = mcp25xxfd_can_int_error_handling(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_error_handling");
+
+ /* and submit can frames to network stack */
+ ret = mcp25xxfd_can_int_submit_frames(cpriv);
+ HANDLE_ERROR("mcp25xxfd_can_int_submit_frames");
+
+ return 0;
+err:
+ netdev_err(cpriv->can.dev, "%s returned with error code %i\n",
+ errfunc, ret);
+ return ret;
+}
+
+#undef HANDLE_ERROR
+
+irqreturn_t mcp25xxfd_can_int(int irq, void *dev_id)
+{
+ struct mcp25xxfd_can_priv *cpriv = dev_id;
+ int loops, ret;
+
+ /* count interrupt calls */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, irq_calls);
+
+ /* loop forever unless we need to exit */
+ for (loops = 1; true; loops++) {
+ /* count irq loops */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, irq_loops);
+
+ /* read interrupt status flags in bulk */
+ ret = mcp25xxfd_cmd_read_regs(cpriv->priv->spi,
+ MCP25XXFD_CAN_INT,
+ &cpriv->status.intf,
+ sizeof(cpriv->status));
+ switch (ret) {
+ case 0: /* no errors, so process */
+ break;
+ case -EILSEQ: /* a crc error, so run the loop again */
+ continue;
+ default: /* all other error cases */
+ netdev_err(cpriv->can.dev,
+ "reading can registers returned with error code %i\n",
+ ret);
+ goto fail;
+ }
+
+ /* only act if the IE mask configured has active IF bits
+ * otherwise the Interrupt line should be deasserted already
+ * so we can exit the loop
+ */
+ if (((cpriv->status.intf >> MCP25XXFD_CAN_INT_IE_SHIFT) &
+ cpriv->status.intf) == 0)
+ break;
+
+ /* handle the interrupts for real */
+ ret = mcp25xxfd_can_int_handle_status(cpriv);
+ switch (ret) {
+ case 0: /* no errors, so process */
+ case -EILSEQ: /* a crc error, so run the loop again */
+ break;
+ default: /* all other error cases */
+ goto fail;
+ }
+
+ /* allow voluntarily rescheduling every so often to avoid
+ * long CS lows at the end of a transfer on low power CPUs
+ * avoiding SERR happening
+ */
+ if (loops % reschedule_int_thread_after == 0) {
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv,
+ irq_thread_rescheduled);
+ cond_resched();
+ }
+ }
+
+ return IRQ_HANDLED;
+
+fail:
+ netdev_err(cpriv->can.dev,
+ "experienced unexpected error %i in interrupt handler - disabling interrupts\n",
+ ret);
+ /* note that if we experienced an spi error,
+ * then this would produce another error
+ */
+ mcp25xxfd_int_enable(cpriv->priv, false);
+
+ /* we could also put the driver in bus-off mode */
+
+ return IRQ_HANDLED;
+}
+
+int mcp25xxfd_can_int_clear(struct mcp25xxfd_priv *priv)
+{
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_CAN_INT, 0,
+ MCP25XXFD_CAN_INT_IF_MASK);
+}
+
+int mcp25xxfd_can_int_enable(struct mcp25xxfd_priv *priv, bool enable)
+{
+ struct mcp25xxfd_can_priv *cpriv = priv->cpriv;
+ const u32 mask = MCP25XXFD_CAN_INT_TEFIE |
+ MCP25XXFD_CAN_INT_RXIE |
+ MCP25XXFD_CAN_INT_MODIE |
+ MCP25XXFD_CAN_INT_SERRIE |
+ MCP25XXFD_CAN_INT_IVMIE |
+ MCP25XXFD_CAN_INT_CERRIE |
+ MCP25XXFD_CAN_INT_RXOVIE |
+ MCP25XXFD_CAN_INT_ECCIE;
+ u32 value = cpriv ? cpriv->status.intf : 0;
+ int ret;
+
+ /* apply mask and */
+ value &= ~(MCP25XXFD_CAN_INT_IE_MASK);
+ if (enable)
+ value |= mask;
+
+ /* and write to int register */
+ ret = mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_CAN_INT,
+ value, mask);
+ if (ret)
+ return ret;
+ if (!cpriv)
+ return 0;
+
+ cpriv->status.intf = value;
+
+ /* enable/disable interrupt handler */
+ if (cpriv->irq.allocated) {
+ if (enable && !cpriv->irq.enabled)
+ enable_irq(cpriv->priv->spi->irq);
+ if (!enable && cpriv->irq.enabled)
+ disable_irq(cpriv->priv->spi->irq);
+ cpriv->irq.enabled = enable;
+ } else {
+ cpriv->irq.enabled = false;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.h
new file mode 100644
index 000000000000..cc2ad992c307
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_int.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_CAN_INT_H
+#define __MCP25XXFD_CAN_INT_H
+
+#include "mcp25xxfd_priv.h"
+
+int mcp25xxfd_can_int_clear(struct mcp25xxfd_priv *priv);
+int mcp25xxfd_can_int_enable(struct mcp25xxfd_priv *priv, bool enable);
+
+irqreturn_t mcp25xxfd_can_int(int irq, void *dev_id);
+
+#endif /* __MCP25XXFD_CAN_INT_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h
new file mode 100644
index 000000000000..7bc1894dced8
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h
@@ -0,0 +1,204 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_PRIV_H
+#define __MCP25XXFD_CAN_PRIV_H
+
+#include <linux/can/dev.h>
+#include <linux/dcache.h>
+
+#include "mcp25xxfd_priv.h"
+
+#define TX_ECHO_SKB_MAX 32
+
+/* information on each fifo type */
+struct mcp25xxfd_fifo {
+ u32 count;
+ u32 start;
+ u32 size;
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ u64 dlc_usage[16];
+ u64 fd_count;
+#endif /* CONFIG_CAN_MCP25XXFD_DEBUG_FS */
+};
+
+/* used for sorting incoming messages */
+struct mcp25xxfd_obj_ts {
+ s32 ts; /* using signed to handle rollover correctly when sorting */
+ u16 fifo;
+ s16 is_rx;
+};
+
+/* general info on each fifo */
+struct mcp25xxfd_fifo_info {
+ u32 is_rx;
+ u32 offset;
+ u32 priority;
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ u64 use_count;
+#endif /* CONFIG_CAN_MCP25XXFD_DEBUG_FS */
+};
+
+struct mcp25xxfd_can_priv {
+ /* can_priv has to be the first one to be usable with alloc_candev
+ * which expects struct can_priv to be right at the start of the
+ * priv structure
+ */
+ struct can_priv can;
+ struct mcp25xxfd_priv *priv;
+ struct regulator *transceiver;
+
+ /* the can mode currently active */
+ int mode;
+
+ /* interrupt state */
+ struct {
+ int enabled;
+ int allocated;
+ } irq;
+
+ /* can config registers */
+ struct {
+ u32 con;
+ u32 tdc;
+ u32 tscon;
+ u32 tefcon;
+ u32 nbtcfg;
+ u32 dbtcfg;
+ } regs;
+
+ /* can status registers (mostly) - read in one go
+ * bdiag0 and bdiag1 are optional, but when
+ * berr counters are requested on a regular basis
+ * during high CAN-bus load this would trigger the fact
+ * that spi_sync would get queued for execution in the
+ * spi thread and the spi handler would not get
+ * called inline in the interrupt thread without any
+ * context switches or wakeups...
+ */
+ struct {
+ u32 intf;
+ /* ASSERT(CAN_INT + 4 == CAN_RXIF) */
+ u32 rxif;
+ /* ASSERT(CAN_RXIF + 4 == CAN_TXIF) */
+ u32 txif;
+ /* ASSERT(CAN_TXIF + 4 == CAN_RXOVIF) */
+ u32 rxovif;
+ /* ASSERT(CAN_RXOVIF + 4 == CAN_TXATIF) */
+ u32 txatif;
+ /* ASSERT(CAN_TXATIF + 4 == CAN_TXREQ) */
+ u32 txreq;
+ /* ASSERT(CAN_TXREQ + 4 == CAN_TREC) */
+ u32 trec;
+ } status;
+
+ /* information of fifo setup */
+ struct {
+ /* define payload size and mode */
+ u32 payload_size;
+ u32 payload_mode;
+
+ /* infos on fifo layout */
+
+ /* TEF */
+ struct {
+ u32 count;
+ u32 size;
+ u32 index;
+ } tef;
+
+ /* info on each fifo */
+ struct mcp25xxfd_fifo_info info[32];
+
+ /* extra info on rx/tx fifo groups */
+ struct mcp25xxfd_fifo tx;
+ struct mcp25xxfd_fifo rx;
+
+ /* queue of can frames that need to get submitted
+ * to the network stack during an interrupt loop in one go
+ * (this gets sorted by timestamp before submission
+ * and contains both rx frames as well tx frames that have
+ * gone over the CAN bus successfully
+ */
+ struct mcp25xxfd_obj_ts submit_queue[32];
+ int submit_queue_count;
+
+ /* the tx queue of spi messages */
+ struct mcp25xxfd_tx_spi_message_queue *tx_queue;
+ } fifos;
+
+ /* statistics exposed via debugfs */
+#define MCP25XXFD_CAN_TEF_READ_BINS 8
+#define MCP25XXFD_CAN_RX_BULK_READ_BINS 8
+
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ struct dentry *debugfs_dir;
+
+ struct {
+ u64 irq_calls;
+ u64 irq_loops;
+ u64 irq_thread_rescheduled;
+
+ u64 int_serr_count;
+ u64 int_serr_rx_count;
+ u64 int_serr_tx_count;
+ u64 int_mod_count;
+ u64 int_rx_count;
+ u64 int_txat_count;
+ u64 int_tef_count;
+ u64 int_rxov_count;
+ u64 int_ecc_count;
+ u64 int_ivm_count;
+ u64 int_cerr_count;
+
+ u64 tx_fd_count;
+ u64 tx_brs_count;
+
+ u64 tef_reads;
+ u64 tef_read_splits;
+ u64 tef_conservative_reads;
+ u64 tef_optimized_reads;
+ u64 tef_optimized_read_sizes[MCP25XXFD_CAN_TEF_READ_BINS];
+
+ u64 rx_reads;
+ u64 rx_reads_prefetched_too_few;
+ u64 rx_reads_prefetched_too_few_bytes;
+ u64 rx_reads_prefetched_too_many;
+ u64 rx_reads_prefetched_too_many_bytes;
+ u64 rx_single_reads;
+ u64 rx_bulk_reads;
+ u64 rx_bulk_read_sizes[MCP25XXFD_CAN_RX_BULK_READ_BINS];
+ } stats;
+#endif /* CONFIG_CAN_MCP25XXFD_DEBUG_FS */
+
+ /* history of rx-dlc */
+ struct {
+#define MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE 32
+ u8 dlc[MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE];
+ u8 brs[MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE];
+ u8 index;
+ u32 predicted_len;
+ } rx_history;
+
+ /* bus state */
+ struct {
+ u32 state;
+ u32 new_state;
+ u32 bdiag[2];
+ } bus;
+
+ /* can error messages */
+ struct {
+ u32 id;
+ u8 data[8];
+ } error_frame;
+
+ /* a copy of mcp25xxfd-sram in ram */
+ u8 sram[MCP25XXFD_SRAM_SIZE];
+};
+
+#endif /* __MCP25XXFD_CAN_PRIV_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c
new file mode 100644
index 000000000000..a9e0da434e29
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c
@@ -0,0 +1,521 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ *
+ * Based on Microchip MCP251x CAN controller driver written by
+ * David Vrabel, Copyright 2006 Arcom Control Systems Ltd.
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_can_debugfs.h"
+#include "mcp25xxfd_can_id.h"
+#include "mcp25xxfd_can_priv.h"
+#include "mcp25xxfd_can_rx.h"
+
+/* module parameters */
+static unsigned int rx_prefetch_bytes = -1;
+module_param(rx_prefetch_bytes, uint, 0664);
+MODULE_PARM_DESC(rx_prefetch_bytes,
+ "number of bytes to blindly prefetch when reading a rx-fifo");
+
+static struct sk_buff *
+mcp25xxfd_can_rx_submit_normal_frame(struct mcp25xxfd_can_priv *cpriv,
+ u32 id, u32 dlc, u8 **data)
+{
+ struct can_frame *frame;
+ struct sk_buff *skb;
+
+ /* allocate frame */
+ skb = alloc_can_skb(cpriv->can.dev, &frame);
+ if (!skb)
+ return NULL;
+
+ /* set id, dlc and flags */
+ frame->can_id = id;
+ frame->can_dlc = dlc;
+
+ /* and set the pointer to data */
+ *data = frame->data;
+
+ return skb;
+}
+
+/* it is almost identical except for the type of the frame... */
+static struct sk_buff *
+mcp25xxfd_can_rx_submit_fd_frame(struct mcp25xxfd_can_priv *cpriv,
+ u32 id, u32 flags, u32 len, u8 **data)
+{
+ struct canfd_frame *frame;
+ struct sk_buff *skb;
+
+ /* allocate frame */
+ skb = alloc_canfd_skb(cpriv->can.dev, &frame);
+ if (!skb)
+ return NULL;
+
+ /* set id, dlc and flags */
+ frame->can_id = id;
+ frame->len = len;
+ frame->flags |= flags;
+
+ /* and set the pointer to data */
+ *data = frame->data;
+
+ return skb;
+}
+
+int mcp25xxfd_can_rx_submit_frame(struct mcp25xxfd_can_priv *cpriv, int fifo)
+{
+ struct net_device *net = cpriv->can.dev;
+ int addr = cpriv->fifos.info[fifo].offset;
+ struct mcp25xxfd_can_obj_rx *rx =
+ (struct mcp25xxfd_can_obj_rx *)(cpriv->sram + addr);
+ u8 *data = NULL;
+ struct sk_buff *skb;
+ u32 id, dlc, len, flags;
+
+ /* compute the can_id */
+ mcp25xxfd_can_id_from_mcp25xxfd(rx->id, rx->flags, &id);
+
+ /* and dlc */
+ dlc = (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_DLC_MASK) >>
+ MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT;
+ len = can_dlc2len(dlc);
+
+ /* update stats */
+ net->stats.rx_packets++;
+ net->stats.rx_bytes += len;
+ MCP25XXFD_DEBUGFS_INCR(cpriv->fifos.rx.dlc_usage[dlc]);
+ if (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_FDF)
+ MCP25XXFD_DEBUGFS_INCR(cpriv->fifos.rx.fd_count);
+
+ /* add to rx_history */
+ cpriv->rx_history.dlc[cpriv->rx_history.index] = dlc;
+ cpriv->rx_history.brs[cpriv->rx_history.index] =
+ (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_BRS) ? CANFD_BRS : 0;
+ cpriv->rx_history.index++;
+ if (cpriv->rx_history.index >= MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE)
+ cpriv->rx_history.index = 0;
+
+ /* allocate the skb buffer */
+ if (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_FDF) {
+ flags = 0;
+ flags |= (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_BRS) ?
+ CANFD_BRS : 0;
+ flags |= (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_ESI) ?
+ CANFD_ESI : 0;
+ skb = mcp25xxfd_can_rx_submit_fd_frame(cpriv, id, flags,
+ len, &data);
+ } else {
+ skb = mcp25xxfd_can_rx_submit_normal_frame(cpriv, id,
+ len, &data);
+ }
+ if (!skb) {
+ netdev_err(net, "cannot allocate RX skb\n");
+ net->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ /* copy the payload data */
+ memcpy(data, rx->data, len);
+
+ /* and submit the frame */
+ netif_rx_ni(skb);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_rx_read_frame(struct mcp25xxfd_can_priv *cpriv,
+ int fifo, int prefetch_bytes, bool read)
+{
+ struct spi_device *spi = cpriv->priv->spi;
+ struct net_device *net = cpriv->can.dev;
+ int addr = cpriv->fifos.info[fifo].offset;
+ struct mcp25xxfd_can_obj_rx *rx =
+ (struct mcp25xxfd_can_obj_rx *)(cpriv->sram + addr);
+ int dlc;
+ int len, ret;
+
+ /* we read the header plus prefetch_bytes */
+ if (read) {
+ MCP25XXFD_DEBUGFS_INCR(cpriv->stats.rx_single_reads);
+ ret = mcp25xxfd_cmd_readn(spi, MCP25XXFD_SRAM_ADDR(addr),
+ rx, sizeof(*rx) + prefetch_bytes);
+ if (ret)
+ return ret;
+ }
+
+ /* transpose the headers to CPU format */
+ rx->id = le32_to_cpu(*(__le32 *)&rx->id);
+ rx->flags = le32_to_cpu(*(__le32 *)&rx->flags);
+ rx->ts = le32_to_cpu(*(__le32 *)&rx->ts);
+
+ /* compute len */
+ dlc = (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_DLC_MASK) >>
+ MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT;
+ len = can_dlc2len(min_t(int, dlc, (net->mtu == CANFD_MTU) ? 15 : 8));
+
+ /* read the remaining data for canfd frames */
+ if (read && len > prefetch_bytes) {
+ /* update stats */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv,
+ rx_reads_prefetched_too_few);
+ MCP25XXFD_DEBUGFS_STATS_ADD(cpriv,
+ rx_reads_prefetched_too_few_bytes,
+ len - prefetch_bytes);
+ /* here the extra portion reading data after prefetch */
+ ret = mcp25xxfd_cmd_readn(spi,
+ MCP25XXFD_SRAM_ADDR(addr) +
+ sizeof(*rx) + prefetch_bytes,
+ &rx->data[prefetch_bytes],
+ len - prefetch_bytes);
+ if (ret)
+ return ret;
+ }
+
+ /* update stats */
+ MCP25XXFD_DEBUGFS_INCR(cpriv->stats.rx_reads);
+ if (len < prefetch_bytes) {
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv,
+ rx_reads_prefetched_too_many);
+ MCP25XXFD_DEBUGFS_STATS_ADD(cpriv,
+ rx_reads_prefetched_too_many,
+ prefetch_bytes - len);
+ }
+
+ /* clear the rest of the buffer - just to be safe */
+ memset(rx->data + len, 0, ((net->mtu == CANFD_MTU) ? 64 : 8) - len);
+
+ /* increment the statistics counter */
+ MCP25XXFD_DEBUGFS_INCR(cpriv->fifos.info[fifo].use_count);
+
+ /* add the fifo to the process queues */
+ mcp25xxfd_can_queue_frame(cpriv, fifo, rx->ts, true);
+
+ /* and clear the interrupt flag for that fifo */
+ return mcp25xxfd_cmd_write_mask(spi, MCP25XXFD_CAN_FIFOCON(fifo),
+ MCP25XXFD_CAN_FIFOCON_FRESET,
+ MCP25XXFD_CAN_FIFOCON_FRESET);
+}
+
+static int mcp25xxfd_can_read_rx_frame_bulk(struct mcp25xxfd_can_priv *cpriv,
+ int fstart,
+ int fend)
+{
+ struct net_device *net = cpriv->can.dev;
+ int count = abs(fend - fstart) + 1;
+ int flowest = min_t(int, fstart, fend);
+ int addr = cpriv->fifos.info[flowest].offset;
+ struct mcp25xxfd_can_obj_rx *rx =
+ (struct mcp25xxfd_can_obj_rx *)(cpriv->sram + addr);
+ int len = (sizeof(*rx) + ((net->mtu == CANFD_MTU) ? 64 : 8)) * count;
+ int fifo, i, ret;
+
+ /* update stats */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, rx_bulk_reads);
+ i = min_t(int, MCP25XXFD_CAN_RX_BULK_READ_BINS - 1, count - 1);
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, rx_bulk_read_sizes[i]);
+
+ /* we read the header plus read_min data bytes */
+ ret = mcp25xxfd_cmd_readn(cpriv->priv->spi, MCP25XXFD_SRAM_ADDR(addr),
+ rx, len);
+ if (ret)
+ return ret;
+
+ /* now process all of them - no need to read... */
+ for (fifo = fstart; count > 0; fifo ++, count--) {
+ ret = mcp25xxfd_can_rx_read_frame(cpriv, fifo, 8, false);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* predict dlc size based on historic behaviour */
+static int mcp25xxfd_can_rx_predict_prefetch(struct mcp25xxfd_can_priv *cpriv)
+{
+ int dlc, i, top;
+ u8 histo[16];
+
+ /* if we have a prefetch set then use that one */
+ if (rx_prefetch_bytes != -1)
+ return min_t(int, rx_prefetch_bytes,
+ (cpriv->can.dev->mtu == CANFD_MTU) ? 64 : 8);
+
+ /* memset */
+ memset(histo, 0, sizeof(histo));
+
+ /* for all others compute the histogram */
+ for (i = 0; i < MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE; i++)
+ histo[cpriv->rx_history.dlc[i]]++;
+
+ /* and now find the highest fit */
+ for (i = (cpriv->can.dev->mtu == CANFD_MTU) ? 15 : 8, dlc = 8, top = 0;
+ i >= 0; i--) {
+ if (top < histo[i]) {
+ top = histo[i];
+ dlc = i;
+ }
+ }
+
+ /* compute length from dlc */
+ cpriv->rx_history.predicted_len = can_dlc2len(dlc);
+
+ /* return the predicted length */
+ return cpriv->rx_history.predicted_len;
+}
+
+/* at least in can2.0 mode we can read multiple RX-fifos in one go
+ * in case they are ajactent to each other and thus we can reduce
+ * the number of spi messages produced and this improves spi-bus
+ * usage efficiency.
+ * In canFD mode this may also be possible, but would need some
+ * statistics to decide if it is worth reading a full 64 bytes
+ * in one go.
+ * But those statistics can get used to predict how many bytes
+ * to read together with the can header (which is fixed to 8 at
+ * this very moment.
+ *
+ * notes on the rational here:
+ * * Reading just the CAN header info takes:
+ * * bytes read
+ * * 2 bytes command+address
+ * * 12 bytes data (id, flags, timestamp)
+ * * so that is at the very least 112 SCK (= 14 byte * 8 SCK/1 byte)
+ * - on a Raspberry pi 3 for such short requests actually
+ * 126 SCK (=14 byte * 9 SCK/1 byte)
+ * * some SPI framework overhead which is observed to be 5-10 us
+ * on a raspberry pi 3 (time between SCK and stop SCK start)
+ * * with an effective 17.85 MHz SPI clock on a RPI it takes in total:
+ * it takes 12us = 6us + 6us
+ * * now reading 8 bytes of CAN data (can2.0) takes:
+ * * bytes read
+ * * 2 bytes command+address
+ * * 8 bytes data
+ * * so that is at the very least 80 SCK (= 10 byte * 8 SCK/1 byte)
+ * - on a Raspberry pi 3 for such short requests actually
+ * 90 SCK (= 10 byte * 9 SCK/1 byte)
+ * * some SPI framework overhead which is observed to be 5-10 us
+ * on a raspberry pi 3 (time between SCK and stop SCK start)
+ * * with an effective 17.85 MHz SPI clock on a RPI it takes in total:
+ * it takes 11us = 5.0us + 6us
+ * * now reading CAN header plus 8 bytes of CAN data (can2.0) takes:
+ * * bytes read
+ * * 2 bytes command+address
+ * * 20 bytes data
+ * * so that is at the very least 176 SCK (= 22 byte * 8 SCK/1 byte)
+ * - on a Raspberry pi 3 for such short requests actually
+ * 198 SCK (= 22 byte * 9 SCK/1 byte)
+ * * some SPI framework overhead which is observed to be 5-10 us
+ * on a raspberry pi 3 (time between SCK and stop SCK start)
+ * * with an effective 17.85 MHz SPI clock on a RPI it takes in total:
+ * it takes 17.1us = 11.1us + 6us
+ * * this is faster than the 2 individual SPI transfers for header
+ * and data which is in total 23us
+ * * this is even true for the case where we only have a single
+ * data byte (DLC=1) - the time here is 19.5us on a RPI3
+ * * the only time where we are less efficient is for the DLC=0 case.
+ * but the assumption here is that this is a rare case
+ * To put it into perspective here the full table for a RPI3:
+ * LE 2m pr0 pr1 pr2 pr3 pr4 pr5 pr6 pr7 pr8 pr12 pr16 pr20 pr24 pr32 pr48
+ * pr64
+ * 0 7.1 7.1
+ * 1 14.6 7.6 8.1 8.6 9.1 9.6 10.1 10.6 11.1 13.1
+ * 2 15.1 8.1 8.6 9.1 9.6 10.1 10.6 11.1 13.1
+ * 3 15.6 8.6 9.1 9.6 10.1 10.6 11.1 13.1 15.1
+ * 4 16.1 9.1 9.6 10.1 10.6 11.1 13.1 15.1
+ * 5 16.6 9.6 10.1 10.6 11.1 13.1 15.1
+ * 6 17.1 10.1 10.6 11.1 13.1 15.1
+ * 7 17.6 10.6 11.1 13.1 15.1 17.1
+ * 8 18.1 11.1 13.1 15.1 17.1
+ * 12 20.1 13.1 15.1 17.1 19.2
+ * 16 22.1 15.1 17.1 19.2
+ * 20 24.1 17.1 19.2 23.2
+ * 24 26.2 19.2 23.2
+ * 32 30.2 23.2
+ * 48 38.3 31.3
+ * 64 46.3 39.3
+ * (Parameters: SPI Clock=17.8MHz, SCK/byte=9, overhead=6us)
+ * Legend:
+ * LE = length,
+ * 2m = 2 SPI messages (header+data - except for LEN=0, only header)
+ * prX/pX = prefecth length times (only shown when < 2m and Len >= Prefetch)
+ *
+ * The diagonal schows the "optimal" time when the size of the Can frame would
+ * be known ahead of time - i.e if it would be possible to define RX reception
+ * filters based on can DLC values
+ *
+ * So for any Can frame except for LEN=0 the prefetch data solution is
+ * better for prefetch of data=12 for CanFD.
+ *
+ * Here another table showing the optimal prefetch limits for SPI speeds
+ * vs overhead_us at 8 or 9 SCLK/byte
+ *
+ * MHZ 2us@8 2us@9 4us@8 4us@9 6us@8 6us@9 8us@8 8us@9
+ * 10.0 8b*** 8b*** 8b 8b* 12b** 8b* 12b 12b*
+ * 12.5 8b** 8b*** 12b*** 8b 12b 12b* 16b* 16b**
+ * 15.0 8b** 8b** 12b** 12b*** 16b** 12b 20b** 16b
+ * 17.5 8b* 8b* 12b* 12b** 16b 16b** 20b 20b**
+ * 20.0 8b 8b* 16b*** 12b* 20b** 16b 24b* 20b
+ * (a * signifies not a full match, but for any length > count(*))
+ *
+ * So 8 bytes prefetch seems to be a very good tradeoff for can frame
+ * except for DLC/LEN=0 frames.
+ * The question here is mainly: how many frames do we have with DLC=0
+ * vs all others.
+ *
+ * With some statistics of recent CAN frames this may be set dynamically
+ * in the future.
+ *
+ * For this to work efficiently we would also need an estimate on
+ * the SPI framework overhead, which is a function of the spi-bus-driver
+ * implementation details, CPU type and speed as well as system load.
+ * Also the effective SPI-clock speed is needed as well as the
+ * number of spi clock cycles it takes for a single byte to get transferred
+ * The bcm283x SOC for example pauses the SPI clock one cycle after
+ * every byte it sends unless the data is fed to the controller by DMA.
+ * (but for short transfers DMA mapping is very expensive and not worth
+ * the effort. PIO and - in some situations - polling is used instead to
+ * reduce the number of interrupts and the need for thread scheduling as
+ * much as possible)
+ *
+ * This also means that for can2.0 only configured interfaces
+ * reading multiple rx fifos is a realistic option of optimization
+ */
+
+static int mcp25xxfd_can_rx_read_single_frames(struct mcp25xxfd_can_priv *cpriv,
+ int prefetch)
+{
+ int i, f, ret;
+
+ /* loop all frames */
+ for (i = 0, f = cpriv->fifos.rx.start; i < cpriv->fifos.rx.count;
+ i++, f++) {
+ if (cpriv->status.rxif & BIT(f)) {
+ /* read the frame */
+ ret = mcp25xxfd_can_rx_read_frame(cpriv, f,
+ prefetch, true);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_rx_read_bulk_frames(struct mcp25xxfd_can_priv *cpriv)
+{
+ int i, start, end;
+ int ret;
+
+ /* iterate over fifos trying to find fifos next to each other */
+ for (i = 0, start = cpriv->fifos.rx.start, end = start;
+ i < cpriv->fifos.rx.count; i++, end++, start = end) {
+ /* if bit is not set then continue */
+ if (!(cpriv->status.rxif & BIT(start)))
+ continue;
+ /* find the last fifo with a bit set in sequence */
+ for (end = start; cpriv->status.rxif & BIT(end + 1); end++)
+ ;
+ /* and now read those fifos in bulk */
+ ret = mcp25xxfd_can_read_rx_frame_bulk(cpriv, start, end);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_rx_read_fd_frames(struct mcp25xxfd_can_priv *cpriv)
+{
+ int i, count_dlc15, count_brs, prefetch;
+
+ /* get a prediction on prefetch */
+ prefetch = mcp25xxfd_can_rx_predict_prefetch(cpriv);
+
+ /* if the prefetch is < 64 then just read single */
+ if (prefetch < 64)
+ return mcp25xxfd_can_rx_read_single_frames(cpriv, prefetch);
+
+ /* check if we have mostly brs frames of those DLC=15 frames */
+ for (i = 0, count_brs = 0, count_dlc15 = 0;
+ i < MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE; i++)
+ if (cpriv->rx_history.dlc[i] == 15) {
+ count_dlc15++;
+ if (cpriv->rx_history.brs[i])
+ count_brs++;
+ }
+
+ /* if we have at least 33% brs frames then run bulk */
+ if (count_brs * 3 >= count_dlc15)
+ return mcp25xxfd_can_rx_read_bulk_frames(cpriv);
+ else
+ return mcp25xxfd_can_rx_read_single_frames(cpriv, prefetch);
+}
+
+static int mcp25xxfd_can_rx_read_frames(struct mcp25xxfd_can_priv *cpriv)
+{
+ if (cpriv->can.dev->mtu == CANFD_MTU)
+ return mcp25xxfd_can_rx_read_fd_frames(cpriv);
+ else
+ return mcp25xxfd_can_rx_read_bulk_frames(cpriv);
+}
+
+int mcp25xxfd_can_rx_handle_int_rxif(struct mcp25xxfd_can_priv *cpriv)
+{
+ if (!cpriv->status.rxif)
+ return 0;
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_rx_count);
+
+ /* read all the fifos */
+ return mcp25xxfd_can_rx_read_frames(cpriv);
+}
+
+int mcp25xxfd_can_rx_handle_int_rxovif(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 mask = MCP25XXFD_CAN_FIFOSTA_RXOVIF;
+ int ret, i, reg;
+
+ if (!cpriv->status.rxovif)
+ return 0;
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_rxov_count);
+
+ /* clear all fifos that have an overflow bit set */
+ for (i = 0; i < 32; i++) {
+ if (cpriv->status.rxovif & BIT(i)) {
+ /* clear fifo status */
+ reg = MCP25XXFD_CAN_FIFOSTA(i);
+ ret = mcp25xxfd_cmd_write_mask(cpriv->priv->spi,
+ reg, 0, mask);
+ if (ret)
+ return ret;
+
+ /* update statistics */
+ cpriv->can.dev->stats.rx_over_errors++;
+ cpriv->can.dev->stats.rx_errors++;
+
+ /* and prepare ERROR FRAME */
+ cpriv->error_frame.id |= CAN_ERR_CRTL;
+ cpriv->error_frame.data[1] |=
+ CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.h
new file mode 100644
index 000000000000..71953e2f3615
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_RX_H
+#define __MCP25XXFD_CAN_RX_H
+
+#include "mcp25xxfd_priv.h"
+
+int mcp25xxfd_can_rx_submit_frame(struct mcp25xxfd_can_priv *cpriv, int fifo);
+
+int mcp25xxfd_can_rx_handle_int_rxif(struct mcp25xxfd_can_priv *cpriv);
+int mcp25xxfd_can_rx_handle_int_rxovif(struct mcp25xxfd_can_priv *cpriv);
+
+#endif /* __MCP25XXFD_CAN_RX_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.c
new file mode 100644
index 000000000000..07526a23c054
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.c
@@ -0,0 +1,781 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ *
+ * Based on Microchip MCP251x CAN controller driver written by
+ * David Vrabel, Copyright 2006 Arcom Control Systems Ltd.
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_can_id.h"
+#include "mcp25xxfd_can_tx.h"
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_regs.h"
+
+/* mostly bit manipulations to move between stages */
+static struct mcp25xxfd_tx_spi_message *
+mcp25xxfd_can_tx_queue_first_spi_message(struct mcp25xxfd_tx_spi_message_queue *
+ queue, u32 *bitmap)
+{
+ u32 first = ffs(*bitmap);
+
+ if (!first)
+ return NULL;
+
+ return queue->fifo2message[first - 1];
+}
+
+static void mcp25xxfd_can_tx_queue_remove_spi_message(u32 *bitmap, int fifo)
+{
+ *bitmap &= ~BIT(fifo);
+}
+
+static void mcp25xxfd_can_tx_queue_add_spi_message(u32 *bitmap, int fifo)
+{
+ *bitmap |= BIT(fifo);
+}
+
+static void mcp25xxfd_can_tx_queue_move_spi_message(u32 *src, u32 *dest,
+ int fifo)
+{
+ mcp25xxfd_can_tx_queue_remove_spi_message(src, fifo);
+ mcp25xxfd_can_tx_queue_add_spi_message(dest, fifo);
+}
+
+static void mcp25xxfd_can_tx_spi_message_fill_fifo_complete(void *context)
+{
+ struct mcp25xxfd_tx_spi_message *msg = context;
+ struct mcp25xxfd_can_priv *cpriv = msg->cpriv;
+ struct mcp25xxfd_tx_spi_message_queue *q = cpriv->fifos.tx_queue;
+ unsigned long flags;
+
+ /* reset transfer length to without data (DLC = 0) */
+ msg->fill_fifo.xfer.len = sizeof(msg->fill_fifo.data.cmd) +
+ sizeof(msg->fill_fifo.data.header);
+
+ /* we need to hold this lock to protect us from
+ * concurrent access by start_xmit
+ */
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+
+ /* move to in_trigger_fifo_transfer */
+ mcp25xxfd_can_tx_queue_move_spi_message(&q->in_fill_fifo_transfer,
+ &q->in_trigger_fifo_transfer,
+ msg->fifo);
+
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+}
+
+static void mcp25xxfd_can_tx_spi_message_trigger_fifo_complete(void *context)
+{
+ struct mcp25xxfd_tx_spi_message *msg = context;
+ struct mcp25xxfd_can_priv *cpriv = msg->cpriv;
+ struct mcp25xxfd_tx_spi_message_queue *q = cpriv->fifos.tx_queue;
+ unsigned long flags;
+
+ /* we need to hold this lock to protect us from
+ * concurrent access by the interrupt thread
+ */
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+
+ /* move to can_transfer */
+ mcp25xxfd_can_tx_queue_move_spi_message(&q->in_trigger_fifo_transfer,
+ &q->in_can_transfer,
+ msg->fifo);
+
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+}
+
+static
+void mcp25xxfd_can_tx_message_init(struct mcp25xxfd_can_priv *cpriv,
+ struct mcp25xxfd_tx_spi_message *msg,
+ int fifo)
+{
+ const u32 trigger = MCP25XXFD_CAN_FIFOCON_TXREQ |
+ MCP25XXFD_CAN_FIFOCON_UINC;
+ const int first_byte = mcp25xxfd_cmd_first_byte(trigger);
+ u32 addr;
+
+ /* and initialize the structure */
+ msg->cpriv = cpriv;
+ msg->fifo = fifo;
+
+ /* init fill_fifo */
+ spi_message_init(&msg->fill_fifo.msg);
+ msg->fill_fifo.msg.complete =
+ mcp25xxfd_can_tx_spi_message_fill_fifo_complete;
+ msg->fill_fifo.msg.context = msg;
+
+ msg->fill_fifo.xfer.speed_hz = cpriv->priv->spi_use_speed_hz;
+ msg->fill_fifo.xfer.tx_buf = msg->fill_fifo.data.cmd;
+ msg->fill_fifo.xfer.len = sizeof(msg->fill_fifo.data.cmd) +
+ sizeof(msg->fill_fifo.data.header);
+ spi_message_add_tail(&msg->fill_fifo.xfer, &msg->fill_fifo.msg);
+
+ addr = MCP25XXFD_SRAM_ADDR(cpriv->fifos.info[fifo].offset);
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_WRITE, addr,
+ msg->fill_fifo.data.cmd);
+
+ /* init trigger_fifo */
+ spi_message_init(&msg->trigger_fifo.msg);
+ msg->trigger_fifo.msg.complete =
+ mcp25xxfd_can_tx_spi_message_trigger_fifo_complete;
+ msg->trigger_fifo.msg.context = msg;
+
+ msg->trigger_fifo.xfer.speed_hz = cpriv->priv->spi_use_speed_hz;
+ msg->trigger_fifo.xfer.tx_buf = msg->trigger_fifo.data.cmd;
+ msg->trigger_fifo.xfer.len = sizeof(msg->trigger_fifo.data.cmd) +
+ sizeof(msg->trigger_fifo.data.data);
+ spi_message_add_tail(&msg->trigger_fifo.xfer, &msg->trigger_fifo.msg);
+
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_WRITE,
+ MCP25XXFD_CAN_FIFOCON(fifo) + first_byte,
+ msg->trigger_fifo.data.cmd);
+ msg->trigger_fifo.data.data = trigger >> (8 * first_byte);
+
+ /* and add to idle tx transfers */
+ mcp25xxfd_can_tx_queue_add_spi_message(&cpriv->fifos.tx_queue->idle,
+ fifo);
+}
+
+static
+void mcp25xxfd_can_tx_queue_manage_nolock(struct mcp25xxfd_can_priv *cpriv,
+ int state)
+{
+ struct net_device *net = cpriv->can.dev;
+
+ /* skip early */
+ if (state == cpriv->fifos.tx_queue->state)
+ return;
+
+ /* start/stop netif_queue if necessary */
+ switch (cpriv->fifos.tx_queue->state) {
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_RUNABLE:
+ switch (state) {
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_RESTART:
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_STARTED:
+ netif_wake_queue(net);
+ cpriv->fifos.tx_queue->state =
+ MCP25XXFD_CAN_TX_QUEUE_STATE_STARTED;
+ break;
+ }
+ break;
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_STOPPED:
+ switch (state) {
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_STARTED:
+ netif_wake_queue(net);
+ cpriv->fifos.tx_queue->state = state;
+ break;
+ }
+ break;
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_STARTED:
+ switch (state) {
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_RUNABLE:
+ case MCP25XXFD_CAN_TX_QUEUE_STATE_STOPPED:
+ netif_stop_queue(net);
+ cpriv->fifos.tx_queue->state = state;
+ break;
+ }
+ break;
+ default:
+ WARN(true, "Unsupported tx_queue state: %i\n",
+ cpriv->fifos.tx_queue->state);
+ break;
+ }
+}
+
+void mcp25xxfd_can_tx_queue_manage(struct mcp25xxfd_can_priv *cpriv, int state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+
+ mcp25xxfd_can_tx_queue_manage_nolock(cpriv, state);
+
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+}
+
+void mcp25xxfd_can_tx_queue_restart(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 state = MCP25XXFD_CAN_TX_QUEUE_STATE_RESTART;
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+
+ /* only move if there is nothing pending or idle */
+ mask = cpriv->fifos.tx_queue->idle |
+ cpriv->fifos.tx_queue->in_fill_fifo_transfer |
+ cpriv->fifos.tx_queue->in_trigger_fifo_transfer |
+ cpriv->fifos.tx_queue->in_can_transfer;
+ if (mask)
+ goto out;
+
+ /* move all items from transferred to idle */
+ cpriv->fifos.tx_queue->idle |= cpriv->fifos.tx_queue->transferred;
+ cpriv->fifos.tx_queue->transferred = 0;
+
+ /* and enable queue */
+ mcp25xxfd_can_tx_queue_manage_nolock(cpriv, state);
+out:
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+}
+
+static
+int mcp25xxfd_can_tx_tef_read(struct mcp25xxfd_can_priv *cpriv,
+ int start, int count)
+{
+ u32 tef_offset = start * cpriv->fifos.tef.size;
+ struct mcp25xxfd_can_obj_tef *tef =
+ (struct mcp25xxfd_can_obj_tef *)(cpriv->sram + tef_offset);
+ int last, read, ret;
+
+ /* compute how many we can read in one go */
+ last = start + count;
+ read = (last > cpriv->fifos.tef.count) ?
+ (cpriv->fifos.tef.count - start) :
+ count;
+
+ /* and read it */
+ ret = mcp25xxfd_cmd_read_regs(cpriv->priv->spi,
+ MCP25XXFD_SRAM_ADDR(tef_offset),
+ &tef->id, sizeof(*tef) * read);
+ if (ret)
+ return ret;
+
+ /* and read a second part on wrap */
+ if (read != count) {
+ /* update stats */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tef_read_splits);
+ /* compute the addresses */
+ read = count - read;
+ tef = (struct mcp25xxfd_can_obj_tef *)(cpriv->sram);
+ /* and read again */
+ ret = mcp25xxfd_cmd_read_regs(cpriv->priv->spi,
+ MCP25XXFD_SRAM_ADDR(0),
+ &tef->id,
+ sizeof(*tef) * read);
+ }
+
+ return ret;
+}
+
+static
+int mcp25xxfd_can_tx_handle_int_tefif_fifo(struct mcp25xxfd_can_priv *cpriv,
+ bool read_data)
+{
+ u32 tef_offset = cpriv->fifos.tef.index * cpriv->fifos.tef.size;
+ struct mcp25xxfd_can_obj_tef *tef =
+ (struct mcp25xxfd_can_obj_tef *)(cpriv->sram + tef_offset);
+ int fifo, ret;
+ unsigned long flags;
+
+ /* read the next TEF entry to get the transmit timestamp and fifo */
+ if (read_data) {
+ ret = mcp25xxfd_can_tx_tef_read(cpriv,
+ cpriv->fifos.tef.index, 1);
+ if (ret)
+ return ret;
+ }
+
+ /* get the fifo from tef */
+ fifo = (tef->flags & MCP25XXFD_CAN_OBJ_FLAGS_SEQ_MASK) >>
+ MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT;
+
+ /* check that the fifo is valid */
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+ if ((cpriv->fifos.tx_queue->in_can_transfer & BIT(fifo)) == 0)
+ netdev_err(cpriv->can.dev,
+ "tefif: fifo %i not pending - tef data: id: %08x flags: %08x, ts: %08x - this may be a problem with spi signal quality- try reducing spi-clock speed if this can get reproduced",
+ fifo, tef->id, tef->flags, tef->ts);
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+
+ /* update stats */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tef_reads);
+
+ /* now we can schedule the fifo for echo submission */
+ mcp25xxfd_can_queue_frame(cpriv, fifo, tef->ts, false);
+
+ /* increment the tef index with wraparround */
+ cpriv->fifos.tef.index++;
+ if (cpriv->fifos.tef.index >= cpriv->fifos.tef.count)
+ cpriv->fifos.tef.index = 0;
+
+ /* finally just increment the TEF pointer */
+ return mcp25xxfd_cmd_write_mask(cpriv->priv->spi, MCP25XXFD_CAN_TEFCON,
+ MCP25XXFD_CAN_TEFCON_UINC,
+ MCP25XXFD_CAN_TEFCON_UINC);
+}
+
+/* reading TEF entries can be made even more efficient by reading
+ * multiple TEF entries in one go.
+ * Under the assumption that we have count(TEF) >= count(TX_FIFO)
+ * we can even release TEFs early (before we read them)
+ * (and potentially restarting the transmit-queue early aswell)
+ */
+
+static int
+mcp25xxfd_can_tx_handle_int_tefif_conservative(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 tefsta;
+ int ret;
+
+ /* read the TEF status */
+ ret = mcp25xxfd_cmd_read_mask(cpriv->priv->spi, MCP25XXFD_CAN_TEFSTA,
+ &tefsta, MCP25XXFD_CAN_TEFSTA_TEFNEIF);
+ if (ret)
+ return ret;
+
+ /* read the tef in an inefficient loop */
+ while (tefsta & MCP25XXFD_CAN_TEFSTA_TEFNEIF) {
+ /* read one tef */
+ ret = mcp25xxfd_can_tx_handle_int_tefif_fifo(cpriv, true);
+ if (ret)
+ return ret;
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tef_conservative_reads);
+
+ /* read the TEF status */
+ ret = mcp25xxfd_cmd_read_mask(cpriv->priv->spi,
+ MCP25XXFD_CAN_TEFSTA, &tefsta,
+ MCP25XXFD_CAN_TEFSTA_TEFNEIF);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+mcp25xxfd_can_tx_handle_int_tefif_optimized(struct mcp25xxfd_can_priv *cpriv,
+ u32 finished)
+{
+ int i, fifo, count, ret;
+
+ /* count the number of fifos that have terminated */
+ for (i = 0, fifo = cpriv->fifos.tx.start, count = 0;
+ i < cpriv->fifos.tx.count; i++, fifo++)
+ if (finished & BIT(fifo))
+ count++;
+
+ /* read them in one go if possible
+ * we also assume that we have count(TEF) >= count(TX-FIFOS)
+ * this may require 2 reads when we wrap arround
+ * (that is unless count(TEF) == count(TX-FIFOS))
+ */
+ ret = mcp25xxfd_can_tx_tef_read(cpriv, cpriv->fifos.tef.index, count);
+ if (ret)
+ return ret;
+
+ /* update stats */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tef_optimized_reads);
+ i = min_t(int, MCP25XXFD_CAN_TEF_READ_BINS - 1, count - 1);
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tef_optimized_read_sizes[i]);
+
+ /* now iterate those */
+ for (i = 0, fifo = cpriv->fifos.tx.start; i < cpriv->fifos.tx.count;
+ i++, fifo++) {
+ if (finished & BIT(fifo)) {
+ ret = mcp25xxfd_can_tx_handle_int_tefif_fifo(cpriv,
+ false);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int mcp25xxfd_can_tx_handle_int_tefif(struct mcp25xxfd_can_priv *cpriv)
+{
+ unsigned long flags;
+ u32 finished;
+
+ if (!(cpriv->status.intf & MCP25XXFD_CAN_INT_TEFIF))
+ return 0;
+
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_tef_count);
+
+ /* compute finished fifos and clear them immediately
+ *
+ * bit in txreq == 0 means successfully sent
+ */
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+ finished = ~cpriv->status.txreq & cpriv->fifos.tx_queue->in_can_transfer;
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+
+ /* run in optimized mode if possible */
+ if (finished)
+ return mcp25xxfd_can_tx_handle_int_tefif_optimized(cpriv,
+ finished);
+ /* otherwise play it safe */
+ netdev_warn(cpriv->can.dev,
+ "Something is wrong - we got a TEF interrupt but we were not able to detect a finished fifo\n");
+ return mcp25xxfd_can_tx_handle_int_tefif_conservative(cpriv);
+}
+
+static
+void mcp25xxfd_can_tx_fill_fifo_common(struct mcp25xxfd_can_priv *cpriv,
+ struct mcp25xxfd_tx_spi_message *smsg,
+ struct mcp25xxfd_can_obj_tx *tx,
+ int dlc, u8 *data)
+{
+ int len = can_dlc2len(dlc);
+
+ /* update statistics */
+ MCP25XXFD_DEBUGFS_INCR(cpriv->fifos.tx.dlc_usage[dlc]);
+ MCP25XXFD_DEBUGFS_INCR(cpriv->fifos.info[smsg->fifo].use_count);
+
+ /* add fifo number as seq */
+ tx->flags |= smsg->fifo << MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT;
+
+ /* copy data to tx->data for future reference */
+ memcpy(tx->data, data, len);
+
+ /* transform header to controller format */
+ mcp25xxfd_cmd_convert_from_cpu(&tx->id, sizeof(*tx) / sizeof(u32));
+
+ /* copy header + data to final location - we are not aligned */
+ memcpy(smsg->fill_fifo.data.header, &tx->id, sizeof(*tx) + len);
+
+ /* transfers to sram should be a multiple of 4 and be zero padded */
+ for (; len & 3; len++)
+ *(smsg->fill_fifo.data.header + sizeof(*tx) + len) = 0;
+
+ /* convert it back to CPU format */
+ mcp25xxfd_cmd_convert_to_cpu(&tx->id, sizeof(*tx) / sizeof(u32));
+
+ /* set up size of transfer */
+ smsg->fill_fifo.xfer.len = sizeof(smsg->fill_fifo.data.cmd) +
+ sizeof(smsg->fill_fifo.data.header) + len;
+}
+
+static
+void mcp25xxfd_can_tx_fill_fifo_fd(struct mcp25xxfd_can_priv *cpriv,
+ struct canfd_frame *frame,
+ struct mcp25xxfd_tx_spi_message *smsg,
+ struct mcp25xxfd_can_obj_tx *tx)
+{
+ int dlc = can_len2dlc(frame->len);
+
+ /* update some statistics */
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tx_fd_count);
+
+ /* compute can id */
+ mcp25xxfd_can_id_to_mcp25xxfd(frame->can_id, &tx->id, &tx->flags);
+
+ /* setup flags */
+ tx->flags |= dlc << MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT;
+ tx->flags |= (frame->can_id & CAN_EFF_FLAG) ?
+ MCP25XXFD_CAN_OBJ_FLAGS_IDE : 0;
+ tx->flags |= (frame->can_id & CAN_RTR_FLAG) ?
+ MCP25XXFD_CAN_OBJ_FLAGS_RTR : 0;
+ if (frame->flags & CANFD_BRS) {
+ tx->flags |= MCP25XXFD_CAN_OBJ_FLAGS_BRS;
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tx_brs_count);
+ }
+ tx->flags |= (frame->flags & CANFD_ESI) ?
+ MCP25XXFD_CAN_OBJ_FLAGS_ESI : 0;
+ tx->flags |= MCP25XXFD_CAN_OBJ_FLAGS_FDF;
+
+ /* and do common processing */
+ mcp25xxfd_can_tx_fill_fifo_common(cpriv, smsg, tx, dlc, frame->data);
+}
+
+static
+void mcp25xxfd_can_tx_fill_fifo(struct mcp25xxfd_can_priv *cpriv,
+ struct can_frame *frame,
+ struct mcp25xxfd_tx_spi_message *smsg,
+ struct mcp25xxfd_can_obj_tx *tx)
+{
+ /* set frame to valid dlc */
+ if (frame->can_dlc > 8)
+ frame->can_dlc = 8;
+
+ /* compute can id */
+ mcp25xxfd_can_id_to_mcp25xxfd(frame->can_id, &tx->id, &tx->flags);
+
+ /* setup flags */
+ tx->flags |= frame->can_dlc << MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT;
+ tx->flags |= (frame->can_id & CAN_EFF_FLAG) ?
+ MCP25XXFD_CAN_OBJ_FLAGS_IDE : 0;
+ tx->flags |= (frame->can_id & CAN_RTR_FLAG) ?
+ MCP25XXFD_CAN_OBJ_FLAGS_RTR : 0;
+
+ /* and do common processing */
+ mcp25xxfd_can_tx_fill_fifo_common(cpriv, smsg, tx, frame->can_dlc,
+ frame->data);
+}
+
+static struct mcp25xxfd_tx_spi_message *
+mcp25xxfd_can_tx_queue_get_next_fifo(struct mcp25xxfd_can_priv *cpriv)
+{
+ u32 state = MCP25XXFD_CAN_TX_QUEUE_STATE_RUNABLE;
+ struct mcp25xxfd_tx_spi_message_queue *q = cpriv->fifos.tx_queue;
+ struct mcp25xxfd_tx_spi_message *smsg;
+ unsigned long flags;
+
+ /* we need to hold this lock to protect us against
+ * concurrent modifications of cpriv->fifos.tx_queue->idle
+ * in the interrupt thread
+ */
+ spin_lock_irqsave(&q->lock, flags);
+
+ /* get the first entry from idle */
+ smsg = mcp25xxfd_can_tx_queue_first_spi_message(q, &q->idle);
+ if (!smsg)
+ goto out_busy;
+
+ /* and move the fifo to next stage */
+ mcp25xxfd_can_tx_queue_move_spi_message(&q->idle,
+ &q->in_fill_fifo_transfer,
+ smsg->fifo);
+
+ /* if queue is empty then stop the network queue immediately */
+ if (!q->idle)
+ mcp25xxfd_can_tx_queue_manage_nolock(cpriv, state);
+out_busy:
+ spin_unlock_irqrestore(&q->lock, flags);
+
+ return smsg;
+}
+
+/* submit the can message to the can-bus */
+netdev_tx_t mcp25xxfd_can_tx_start_xmit(struct sk_buff *skb,
+ struct net_device *net)
+{
+ u32 state = MCP25XXFD_CAN_TX_QUEUE_STATE_STOPPED;
+ struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
+ struct mcp25xxfd_priv *priv = cpriv->priv;
+ struct spi_device *spi = priv->spi;
+ struct mcp25xxfd_tx_spi_message *smsg;
+ struct mcp25xxfd_can_obj_tx *tx;
+ int ret;
+
+ /* invalid skb we can ignore */
+ if (can_dropped_invalid_skb(net, skb))
+ return NETDEV_TX_OK;
+
+ /* get the fifo message structure to process now */
+ smsg = mcp25xxfd_can_tx_queue_get_next_fifo(cpriv);
+ if (!smsg)
+ goto out_busy;
+
+ /* compute the fifo in sram */
+ tx = (struct mcp25xxfd_can_obj_tx *)
+ (cpriv->sram + cpriv->fifos.info[smsg->fifo].offset);
+
+ /* fill in message from skb->data depending on can2.0 or canfd */
+ if (can_is_canfd_skb(skb))
+ mcp25xxfd_can_tx_fill_fifo_fd(cpriv,
+ (struct canfd_frame *)skb->data,
+ smsg, tx);
+ else
+ mcp25xxfd_can_tx_fill_fifo(cpriv,
+ (struct can_frame *)skb->data,
+ smsg, tx);
+
+ /* submit the two messages asyncronously
+ * the reason why we separate transfers into two spi_messages is:
+ * * because the spi framework (currently) does add a 10us delay
+ * between 2 spi_transfers in a single spi_message when
+ * change_cs is set - 2 consecutive spi messages show a shorter
+ * cs disable phase increasing bus utilization
+ * (code reduction with a fix in spi core would be aprox.50 lines)
+ * * this allows the interrupt handler to start spi messages earlier
+ * so reducing latencies a bit and to allow for better concurrency
+ * * this separation - in the future - may get used to fill fifos
+ * early and reduce the delay on "rollover"
+ */
+ ret = spi_async(spi, &smsg->fill_fifo.msg);
+ if (ret)
+ goto out_async_failed;
+
+ /* keep it for reference until the message really got transmitted */
+ can_put_echo_skb(skb, net, smsg->fifo);
+
+ ret = spi_async(spi, &smsg->trigger_fifo.msg);
+ if (ret)
+ goto out_async_failed;
+
+ return NETDEV_TX_OK;
+out_async_failed:
+ netdev_err(net, "spi_async submission of fifo %i failed - %i\n",
+ smsg->fifo, ret);
+
+out_busy:
+ /* stop the queue */
+ mcp25xxfd_can_tx_queue_manage_nolock(cpriv, state);
+
+ return NETDEV_TX_BUSY;
+}
+
+/* submit the fifo back to the network stack */
+int mcp25xxfd_can_tx_submit_frame(struct mcp25xxfd_can_priv *cpriv, int fifo)
+{
+ struct mcp25xxfd_tx_spi_message_queue *q = cpriv->fifos.tx_queue;
+ struct mcp25xxfd_can_obj_tx *tx = (struct mcp25xxfd_can_obj_tx *)
+ (cpriv->sram + cpriv->fifos.info[fifo].offset);
+ int dlc = (tx->flags & MCP25XXFD_CAN_OBJ_FLAGS_DLC_MASK) >>
+ MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT;
+ unsigned long flags;
+
+ /* update counters */
+ cpriv->can.dev->stats.tx_packets++;
+ cpriv->can.dev->stats.tx_bytes += can_dlc2len(dlc);
+ MCP25XXFD_DEBUGFS_INCR(cpriv->fifos.tx.dlc_usage[dlc]);
+ if (tx->flags & MCP25XXFD_CAN_OBJ_FLAGS_FDF)
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tx_fd_count);
+ if (tx->flags & MCP25XXFD_CAN_OBJ_FLAGS_BRS)
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, tx_brs_count);
+
+ spin_lock_irqsave(&cpriv->fifos.tx_queue->lock, flags);
+
+ /* release the echo buffer */
+ can_get_echo_skb(cpriv->can.dev, fifo);
+
+ /* move from in_can_transfer to transferred */
+ mcp25xxfd_can_tx_queue_move_spi_message(&q->in_can_transfer,
+ &q->transferred, fifo);
+
+ spin_unlock_irqrestore(&cpriv->fifos.tx_queue->lock, flags);
+
+ return 0;
+}
+
+/* interrupt handler */
+static
+int mcp25xxfd_can_tx_handle_int_txatif_fifo(struct mcp25xxfd_can_priv *cpriv,
+ int fifo)
+{
+ struct mcp25xxfd_tx_spi_message_queue *q = cpriv->fifos.tx_queue;
+ u32 val;
+ unsigned long flags;
+ int ret;
+
+ /* read fifo status */
+ ret = mcp25xxfd_cmd_read(cpriv->priv->spi,
+ MCP25XXFD_CAN_FIFOSTA(fifo), &val);
+ if (ret)
+ return ret;
+
+ /* clear the relevant interrupt flags */
+ ret = mcp25xxfd_cmd_write_mask(cpriv->priv->spi,
+ MCP25XXFD_CAN_FIFOSTA(fifo), 0,
+ MCP25XXFD_CAN_FIFOSTA_TXABT |
+ MCP25XXFD_CAN_FIFOSTA_TXLARB |
+ MCP25XXFD_CAN_FIFOSTA_TXERR |
+ MCP25XXFD_CAN_FIFOSTA_TXATIF);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&q->lock, flags);
+ /* for specific cases we probably could trigger a retransmit
+ * instead of an abort.
+ */
+
+ /* and we release it from the echo_skb buffer
+ * NOTE: this is one place where packet delivery will not
+ * be ordered, as we do not have any timing information
+ * when this occurred
+ */
+ can_get_echo_skb(cpriv->can.dev, fifo);
+
+ mcp25xxfd_can_tx_queue_move_spi_message(&q->in_can_transfer,
+ &q->transferred, fifo);
+
+ spin_unlock_irqrestore(&q->lock, flags);
+
+ /* but we need to run a bit of cleanup */
+ cpriv->status.txif &= ~BIT(fifo);
+ cpriv->can.dev->stats.tx_aborted_errors++;
+
+ /* handle all the known cases accordingly - ignoring FIFO full */
+ val &= MCP25XXFD_CAN_FIFOSTA_TXABT |
+ MCP25XXFD_CAN_FIFOSTA_TXLARB |
+ MCP25XXFD_CAN_FIFOSTA_TXERR;
+ switch (val) {
+ case MCP25XXFD_CAN_FIFOSTA_TXERR:
+ /* this indicates a possible bus error */
+ break;
+ default:
+ dev_warn_ratelimited(&cpriv->priv->spi->dev,
+ "Unknown TX-Fifo abort condition: %08x - stopping tx-queue\n",
+ val);
+ break;
+ }
+
+ return 0;
+}
+
+int mcp25xxfd_can_tx_handle_int_txatif(struct mcp25xxfd_can_priv *cpriv)
+{
+ int i, f, ret;
+
+ /* if txatif is unset, then there are no
+ * can frames that have been transmitted
+ * and need to get reingested into the network stack
+ */
+ if (!cpriv->status.txatif)
+ return 0;
+ MCP25XXFD_DEBUGFS_STATS_INCR(cpriv, int_txat_count);
+
+ /* process all the fifos with that flag set */
+ for (i = 0, f = cpriv->fifos.tx.start; i < cpriv->fifos.tx.count;
+ i++, f++) {
+ if (cpriv->status.txatif & BIT(f)) {
+ ret = mcp25xxfd_can_tx_handle_int_txatif_fifo(cpriv, f);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int mcp25xxfd_can_tx_queue_alloc(struct mcp25xxfd_can_priv *cpriv)
+{
+ struct mcp25xxfd_tx_spi_message *msg;
+ size_t size = sizeof(struct mcp25xxfd_tx_spi_message_queue) +
+ cpriv->fifos.tx.count * sizeof(*msg);
+ int i, f;
+
+ /* allocate the fifos as an array */
+ cpriv->fifos.tx_queue = kzalloc(size, GFP_KERNEL);
+ if (!cpriv->fifos.tx_queue)
+ return -ENOMEM;
+
+ /* initialize the tx_queue structure */
+ spin_lock_init(&cpriv->fifos.tx_queue->lock);
+
+ /* initialize the individual spi_message structures */
+ for (i = 0, f = cpriv->fifos.tx.start; i < cpriv->fifos.tx.count;
+ i++, f++) {
+ msg = &cpriv->fifos.tx_queue->message[i];
+ cpriv->fifos.tx_queue->fifo2message[f] = msg;
+ mcp25xxfd_can_tx_message_init(cpriv, msg, f);
+ }
+
+ return 0;
+}
+
+void mcp25xxfd_can_tx_queue_free(struct mcp25xxfd_can_priv *cpriv)
+{
+ /* eventually we may need to wait here
+ * for all transfers to have finished
+ */
+
+ kfree(cpriv->fifos.tx_queue);
+ cpriv->fifos.tx_queue = NULL;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.h
new file mode 100644
index 000000000000..1000a80b1ee0
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_tx.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CAN_TX_H
+#define __MCP25XXFD_CAN_TX_H
+
+#include <linux/spinlock.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_can_priv.h"
+
+/* structure of a spi message that is prepared and can get submitted quickly */
+struct mcp25xxfd_tx_spi_message {
+ /* the network device this is related to */
+ struct mcp25xxfd_can_priv *cpriv;
+ /* the fifo this fills */
+ u32 fifo;
+ /* the xfer to fill in the fifo data */
+ struct {
+ struct spi_message msg;
+ struct spi_transfer xfer;
+ struct {
+ u8 cmd[2];
+ u8 header[sizeof(struct mcp25xxfd_can_obj_tx)];
+ u8 data[64];
+ } data;
+ } fill_fifo;
+ /* the xfer to enable transmission on the can bus */
+ struct {
+ struct spi_message msg;
+ struct spi_transfer xfer;
+ struct {
+ u8 cmd[2];
+ u8 data;
+ } data;
+ } trigger_fifo;
+};
+
+struct mcp25xxfd_tx_spi_message_queue {
+ /* spinlock protecting the bitmaps
+ * as well as state and the skb_echo_* functions
+ */
+ spinlock_t lock;
+ /* bitmap of which fifo is in which stage */
+ u32 idle;
+ u32 in_fill_fifo_transfer;
+ u32 in_trigger_fifo_transfer;
+ u32 in_can_transfer;
+ u32 transferred;
+
+ /* the queue state as seen per controller */
+ int state;
+#define MCP25XXFD_CAN_TX_QUEUE_STATE_STOPPED 0
+#define MCP25XXFD_CAN_TX_QUEUE_STATE_STARTED 1
+#define MCP25XXFD_CAN_TX_QUEUE_STATE_RUNABLE 2
+#define MCP25XXFD_CAN_TX_QUEUE_STATE_RESTART 3
+
+ /* map each fifo to a mcp25xxfd_tx_spi_message */
+ struct mcp25xxfd_tx_spi_message *fifo2message[32];
+
+ /* the individual messages */
+ struct mcp25xxfd_tx_spi_message message[];
+};
+
+int mcp25xxfd_can_tx_submit_frame(struct mcp25xxfd_can_priv *cpriv, int fifo);
+void mcp25xxfd_can_tx_queue_restart(struct mcp25xxfd_can_priv *cpriv);
+
+int mcp25xxfd_can_tx_handle_int_txatif(struct mcp25xxfd_can_priv *cpriv);
+int mcp25xxfd_can_tx_handle_int_tefif(struct mcp25xxfd_can_priv *cpriv);
+
+netdev_tx_t mcp25xxfd_can_tx_start_xmit(struct sk_buff *skb,
+ struct net_device *net);
+
+void mcp25xxfd_can_tx_queue_manage(struct mcp25xxfd_can_priv *cpriv, int state);
+
+int mcp25xxfd_can_tx_queue_alloc(struct mcp25xxfd_can_priv *cpriv);
+void mcp25xxfd_can_tx_queue_free(struct mcp25xxfd_can_priv *cpriv);
+
+#endif /* __MCP25XXFD_CAN_TX_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.c
new file mode 100644
index 000000000000..32b5888df88e
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.c
@@ -0,0 +1,498 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+/* Known hardware issues and workarounds in this driver:
+ *
+ * * There is one situation where the controller will require a full POR
+ * (total power off) to recover from a bad Clock configuration.
+ * This happens when the wrong clock is configured in the device tree
+ * (say 4MHz are configured, while 40MHz is the actual clock frequency
+ * of the HW).
+ * In such a situation the driver tries to enable the PLL, which will
+ * never synchronize and the controller becomes unresponsive to further
+ * spi requests until a full POR.
+ *
+ * Mitigation:
+ * none as of now
+ *
+ * Possible implementation of a mitigation/sanity check:
+ * during initialization:
+ * * try to identify the HW at 1MHz:
+ * on success:
+ * * controller is identified
+ * on failure:
+ * * controller is absent - fail
+ * * force controller clock to run with disabled PLL
+ * * try to identify the HW at 2MHz:
+ * on success:
+ * * controller clock is >= 4 MHz
+ * * this may be 4MHz
+ * on failure:
+ * * controller clock is < 4 MHz
+ * * try to identify the HW at 2.5MHz:
+ * on success:
+ * * controller clock is >= 5 MHz
+ * * this may not be 4MHz
+ * on failure:
+ * * controller clock is 4 MHz
+ * * enable PLL
+ * * exit successfully (or run last test for verification purposes)
+ * * try to identify the HW at <dt-clock/2> MHz:
+ * on success:
+ * * controller clock is >= <dt-clock/2> MHz
+ * (it could be higher though)
+ * on failure:
+ * * the controller is not running at the
+ * clock rate configured in the DT
+ * * if PLL is enabled warn about requirements of POR
+ * * fail
+ *
+ * Side-effects:
+ * * longer initialization time
+ *
+ * Possible issues with mitigation:
+ * * possibly miss-identification because the SPI block may work
+ * "somewhat" at frequencies > < clock / 2 + delta f>
+ * this may be especially true for the situation where we test if
+ * 2.5MHz SPI-Clock works.
+ * * also SPI HW-clock dividers may do a round down to fixed frequencies
+ * which is not properly reported and may result in false positives
+ * because a frequency lower than expected is used.
+ *
+ * This is the reason why only simple testing is enabled at the risk of
+ * the need for a POR.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_can.h"
+#include "mcp25xxfd_clock.h"
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_priv.h"
+
+/* the PLL may take some time to synchronize - use 1 second as timeout */
+#define MCP25XXFD_OSC_POLLING_JIFFIES (HZ)
+
+static u32 _mcp25xxfd_clkout_mask(struct mcp25xxfd_priv *priv)
+{
+ u32 val = 0;
+
+ if (priv->config.clock_div2)
+ val |= MCP25XXFD_OSC_SCLKDIV;
+
+ switch (priv->config.clock_odiv) {
+ case 0:
+ break;
+ case 1:
+ val |= MCP25XXFD_OSC_CLKODIV_1 << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 2:
+ val |= MCP25XXFD_OSC_CLKODIV_2 << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 4:
+ val |= MCP25XXFD_OSC_CLKODIV_4 << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 10:
+ val |= MCP25XXFD_OSC_CLKODIV_10 << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ default:
+ /* this should never happen but is error-handled
+ * by the dt-parsing
+ */
+ break;
+ }
+
+ return val;
+}
+
+static int _mcp25xxfd_waitfor_osc(struct mcp25xxfd_priv *priv,
+ u32 waitfor, u32 mask)
+{
+ unsigned long timeout;
+ int ret;
+
+ /* wait for synced pll/osc/sclk */
+ timeout = jiffies + MCP25XXFD_OSC_POLLING_JIFFIES;
+ while (time_before_eq(jiffies, timeout)) {
+ ret = mcp25xxfd_cmd_read(priv->spi, MCP25XXFD_OSC,
+ &priv->regs.osc);
+ if (ret)
+ return ret;
+ /* check for expected bits to be set/unset */
+ if ((priv->regs.osc & mask) == waitfor)
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int _mcp25xxfd_clock_configure_osc(struct mcp25xxfd_priv *priv,
+ u32 value, u32 waitfor, u32 mask)
+{
+ int ret;
+
+ /* write the osc value to the controller - waking it if necessary */
+ ret = mcp25xxfd_cmd_write(priv->spi, MCP25XXFD_OSC, value);
+ if (ret)
+ return ret;
+
+ /* wait for the clock to stabelize */
+ ret = _mcp25xxfd_waitfor_osc(priv, waitfor, mask);
+
+ /* on timeout try again setting the register */
+ if (ret == -ETIMEDOUT) {
+ /* write the clock to the controller */
+ ret = mcp25xxfd_cmd_write(priv->spi, MCP25XXFD_OSC, value);
+ if (ret)
+ return ret;
+
+ /* wait for the clock to stabelize */
+ ret = _mcp25xxfd_waitfor_osc(priv, waitfor, mask);
+ }
+
+ /* handle timeout special - report the fact */
+ if (ret == -ETIMEDOUT)
+ dev_err(&priv->spi->dev,
+ "Clock did not switch within the timeout period\n");
+
+ return ret;
+}
+
+static int _mcp25xxfd_clock_start(struct mcp25xxfd_priv *priv)
+{
+ u32 value = _mcp25xxfd_clkout_mask(priv);
+ u32 waitfor = MCP25XXFD_OSC_OSCRDY;
+ u32 mask = waitfor | MCP25XXFD_OSC_OSCDIS | MCP25XXFD_OSC_PLLRDY |
+ MCP25XXFD_OSC_PLLEN;
+
+ /* enable PLL as well - set expectations */
+ if (priv->config.clock_pll) {
+ value |= MCP25XXFD_OSC_PLLEN;
+ waitfor |= MCP25XXFD_OSC_PLLRDY | MCP25XXFD_OSC_PLLEN;
+ }
+
+ /* set the oscilator now */
+ return _mcp25xxfd_clock_configure_osc(priv, value, waitfor, mask);
+}
+
+static int _mcp25xxfd_clock_stop(struct mcp25xxfd_priv *priv)
+{
+ u32 value = _mcp25xxfd_clkout_mask(priv);
+ u32 waitfor = 0;
+ u32 mask = MCP25XXFD_OSC_OSCDIS | MCP25XXFD_OSC_PLLRDY |
+ MCP25XXFD_OSC_PLLEN;
+ int ret;
+
+ ret = _mcp25xxfd_clock_configure_osc(priv, value, waitfor, mask);
+ if (ret)
+ return ret;
+
+ /* finally switch the controller mode to sleep
+ * by this time the controller should be in config mode already
+ * this way we wake to config mode again
+ */
+ return mcp25xxfd_can_sleep_mode(priv);
+}
+
+int mcp25xxfd_clock_start(struct mcp25xxfd_priv *priv, int requestor_mask)
+{
+ int ret = 0;
+
+ /* without a clock there is nothing we can do... */
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ mutex_lock(&priv->clk_user_lock);
+
+ /* if clock is already started, then skip */
+ if (priv->clk_user_mask & requestor_mask)
+ goto out;
+
+ /* enable the clock on the host side*/
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ goto out;
+
+ /* enable the clock on the controller side */
+ ret = _mcp25xxfd_clock_start(priv);
+ if (ret)
+ goto out;
+
+ /* mark the clock for the specific component as started */
+ priv->clk_user_mask |= requestor_mask;
+
+ /* and now we use the normal spi speed */
+ priv->spi_use_speed_hz = priv->spi_normal_speed_hz;
+
+out:
+ mutex_unlock(&priv->clk_user_lock);
+
+ return ret;
+}
+
+int mcp25xxfd_clock_stop(struct mcp25xxfd_priv *priv, int requestor_mask)
+{
+ int ret;
+
+ /* keep the clock on if explicitely configured */
+ if (priv->config.clock_allways_on)
+ return 0;
+
+ /* without a clock there is nothing we can do... */
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ mutex_lock(&priv->clk_user_lock);
+
+ /* if the mask is empty then skip, as the clock is stopped */
+ if (!priv->clk_user_mask)
+ goto out;
+
+ /* clear the clock mask */
+ priv->clk_user_mask &= ~requestor_mask;
+
+ /* if the mask is not empty then skip, as the clock is needed */
+ if (priv->clk_user_mask)
+ goto out;
+
+ /* and now we use the setup spi speed */
+ priv->spi_use_speed_hz = priv->spi_setup_speed_hz;
+
+ /* stop the clock on the controller */
+ ret = _mcp25xxfd_clock_stop(priv);
+
+ /* and we stop the clock on the host*/
+ if (!IS_ERR(priv->clk))
+ clk_disable_unprepare(priv->clk);
+out:
+ mutex_unlock(&priv->clk_user_lock);
+
+ return 0;
+}
+
+static int _mcp25xxfd_clock_probe(struct mcp25xxfd_priv *priv)
+{
+ int ret;
+
+ /* Wait for oscillator startup timer after power up */
+ mdelay(MCP25XXFD_OST_DELAY_MS);
+
+ /* send a "blind" reset, hoping we are in Config mode */
+ mcp25xxfd_cmd_reset(priv->spi);
+
+ /* Wait for oscillator startup again */
+ mdelay(MCP25XXFD_OST_DELAY_MS);
+
+ /* check clock register that the clock is ready or disabled */
+ ret = mcp25xxfd_cmd_read_regs(priv->spi, MCP25XXFD_OSC |
+ MCP25XXFD_ADDRESS_WITH_CRC,
+ &priv->regs.osc, 4);
+ if (ret == -EILSEQ)
+ dev_err(&priv->spi->dev,
+ "CRC read of clock register resulted in a bad CRC mismatch - hw not found\n");
+
+ if (ret)
+ return ret;
+
+ /* there can only be one... */
+ switch (priv->regs.osc &
+ (MCP25XXFD_OSC_OSCRDY | MCP25XXFD_OSC_OSCDIS)) {
+ case MCP25XXFD_OSC_OSCRDY: /* either the clock is ready */
+ break;
+ case MCP25XXFD_OSC_OSCDIS: /* or the clock is disabled */
+ break;
+ default:
+ /* otherwise there is no valid device (or in strange state)
+ *
+ * if PLL is enabled but not ready, then there may be
+ * something "fishy"
+ * this happened during driver development
+ * (enabling pll, when when on wrong clock), so best warn
+ * about such a possibility
+ */
+ if ((priv->regs.osc &
+ (MCP25XXFD_OSC_PLLEN | MCP25XXFD_OSC_PLLRDY))
+ == MCP25XXFD_OSC_PLLEN)
+ dev_err(&priv->spi->dev,
+ "mcp25xxfd may be in a strange state - a power disconnect may be required\n");
+
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int mcp25xxfd_clock_probe(struct mcp25xxfd_priv *priv)
+{
+ int ret;
+
+ /* this will also enable the MCP25XXFD_CLK_USER_CAN clock */
+ ret = _mcp25xxfd_clock_probe(priv);
+
+ /* on error retry a second time */
+ if (ret == -ENODEV) {
+ ret = _mcp25xxfd_clock_probe(priv);
+ if (!ret)
+ dev_info(&priv->spi->dev,
+ "found device only during retry\n");
+ }
+ if (ret) {
+ if (ret == -ENODEV)
+ dev_err(&priv->spi->dev,
+ "Cannot initialize MCP%x. Wrong wiring? (oscilator register reads as %08x)\n",
+ priv->model, priv->regs.osc);
+ }
+
+ return ret;
+}
+
+void mcp25xxfd_clock_release(struct mcp25xxfd_priv *priv)
+{
+ if (!IS_ERR_OR_NULL(priv->clk))
+ clk_disable_unprepare(priv->clk);
+}
+
+#ifdef CONFIG_OF_DYNAMIC
+static int mcp25xxfd_clock_of_parse(struct mcp25xxfd_priv *priv)
+{
+ struct spi_device *spi = priv->spi;
+ const struct device_node *np = spi->dev.of_node;
+ u32 val;
+ int ret;
+
+ priv->config.clock_div2 =
+ of_property_read_bool(np, "microchip,clock-div2");
+
+ priv->config.clock_allways_on =
+ of_property_read_bool(np, "microchip,clock-allways-on");
+
+ priv->config.clock_odiv = 10;
+ ret = of_property_read_u32_index(np, "microchip,clock-out-div",
+ 0, &val);
+ if (!ret) {
+ switch (val) {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 10:
+ priv->config.clock_odiv = val;
+ break;
+ default:
+ dev_err(&spi->dev,
+ "Invalid value in device tree for microchip,clock_out_div: %u - valid values: 0, 1, 2, 4, 10\n",
+ val);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+#else
+static int mcp25xxfd_clock_of_parse(struct mcp25xxfd_priv *priv)
+{
+ return 0;
+}
+#endif
+
+int mcp25xxfd_clock_init(struct mcp25xxfd_priv *priv)
+{
+ struct spi_device *spi = priv->spi;
+ struct clk *clk;
+ int ret, freq;
+
+ mutex_init(&priv->clk_user_lock);
+
+ priv->config.clock_div2 = false;
+ priv->config.clock_allways_on = false;
+ priv->config.clock_odiv = 10;
+
+ ret = mcp25xxfd_clock_of_parse(priv);
+ if (ret)
+ return ret;
+
+ /* get clock */
+ clk = devm_clk_get(&spi->dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ freq = clk_get_rate(clk);
+ if (freq < MCP25XXFD_MIN_CLOCK_FREQUENCY ||
+ freq > MCP25XXFD_MAX_CLOCK_FREQUENCY) {
+ dev_err(&spi->dev,
+ "Clock frequency %i is not in range [%i:%i]\n",
+ freq,
+ MCP25XXFD_MIN_CLOCK_FREQUENCY,
+ MCP25XXFD_MAX_CLOCK_FREQUENCY);
+ return -ERANGE;
+ }
+
+ /* enable the clock and mark as enabled */
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+ priv->clk = clk;
+
+ /* if we have a clock that is <= 4MHz, enable the pll */
+ priv->config.clock_pll =
+ (freq <= MCP25XXFD_AUTO_PLL_MAX_CLOCK_FREQUENCY);
+
+ /* decide on the effective clock rate */
+ priv->clock_freq = freq;
+ if (priv->config.clock_pll)
+ priv->clock_freq *= MCP25XXFD_PLL_MULTIPLIER;
+ if (priv->config.clock_div2)
+ priv->clock_freq /= MCP25XXFD_SCLK_DIVIDER;
+
+ /* calculate the clock frequencies to use
+ *
+ * setup clock speed is at most 1/4 the input clock speed
+ * the reason for the factor of 4 is that there is
+ * a clock divider in the controller that MAY be enabled in some
+ * circumstances so we may find a controller with that enabled
+ * during probe phase
+ */
+ priv->spi_setup_speed_hz = freq / 4;
+
+ /* normal operation clock speeds */
+ priv->spi_normal_speed_hz = priv->clock_freq / 2;
+ if (priv->config.clock_div2) {
+ priv->spi_setup_speed_hz /= MCP25XXFD_SCLK_DIVIDER;
+ priv->spi_normal_speed_hz /= MCP25XXFD_SCLK_DIVIDER;
+ }
+
+ /* set limit on speed */
+ if (spi->max_speed_hz) {
+ priv->spi_setup_speed_hz = min_t(int,
+ priv->spi_setup_speed_hz,
+ spi->max_speed_hz);
+ priv->spi_normal_speed_hz = min_t(int,
+ priv->spi_normal_speed_hz,
+ spi->max_speed_hz);
+ }
+
+ /* use setup speed by default
+ * - this is switched when clock is enabled/disabled
+ */
+ priv->spi_use_speed_hz = priv->spi_setup_speed_hz;
+
+ return 0;
+}
+
+void mcp25xxfd_clock_fake_sleep(struct mcp25xxfd_priv *priv)
+{
+ priv->regs.osc &= ~(MCP25XXFD_OSC_OSCRDY |
+ MCP25XXFD_OSC_PLLRDY |
+ MCP25XXFD_OSC_SCLKRDY);
+ priv->regs.osc |= MCP25XXFD_OSC_OSCDIS;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.h
new file mode 100644
index 000000000000..049e95cfa9ad
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_clock.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CLOCK_H
+#define __MCP25XXFD_CLOCK_H
+
+#include "mcp25xxfd_priv.h"
+
+#define MCP25XXFD_CLK_USER_CAN BIT(0)
+#define MCP25XXFD_CLK_USER_GPIO0 BIT(1)
+#define MCP25XXFD_CLK_USER_GPIO1 BIT(2)
+#define MCP25XXFD_CLK_USER_CLKOUT BIT(3)
+
+/* shared (internal) clock control */
+int mcp25xxfd_clock_init(struct mcp25xxfd_priv *priv);
+int mcp25xxfd_clock_probe(struct mcp25xxfd_priv *priv);
+void mcp25xxfd_clock_release(struct mcp25xxfd_priv *priv);
+
+int mcp25xxfd_clock_stop(struct mcp25xxfd_priv *priv, int requestor_mask);
+int mcp25xxfd_clock_start(struct mcp25xxfd_priv *priv, int requestor_mask);
+
+void mcp25xxfd_clock_fake_sleep(struct mcp25xxfd_priv *priv);
+
+#endif /* __MCP25XXFD_CLOCK_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.c
new file mode 100644
index 000000000000..81a4ff49ebc6
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_crc.h"
+#include "mcp25xxfd_priv.h"
+
+/* module parameter */
+static bool use_spi_crc;
+module_param(use_spi_crc, bool, 0664);
+MODULE_PARM_DESC(use_spi_crc, "Use SPI CRC instruction\n");
+
+/* SPI helper */
+
+/* wrapper arround spi_sync, that sets speed_hz */
+static int mcp25xxfd_cmd_sync_transfer(struct spi_device *spi,
+ struct spi_transfer *xfer,
+ unsigned int xfers)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int i;
+
+ for (i = 0; i < xfers; i++)
+ xfer[i].speed_hz = priv->spi_use_speed_hz;
+
+ return spi_sync_transfer(spi, xfer, xfers);
+}
+
+/* simple spi_write wrapper with speed_hz
+ * WARINING: tx_buf needs to be on heap!
+ */
+static int mcp25xxfd_cmd_sync_write(struct spi_device *spi,
+ const void *tx_buf,
+ unsigned len)
+{
+ struct spi_transfer xfer = {
+ .tx_buf = tx_buf,
+ .len = len,
+ };
+
+ return mcp25xxfd_cmd_sync_transfer(spi, &xfer, 1);
+}
+
+/* alloc buffer */
+static int mcp25xxfd_cmd_alloc_buf(struct spi_device *spi,
+ size_t len,
+ u8 **tx, u8 **rx)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* allocate from heap in case the size is to big
+ * or the preallocated buffer is already used (i.e locked)
+ */
+ if (len > sizeof(priv->spi_tx) ||
+ !mutex_trylock(&priv->spi_rxtx_lock)) {
+ /* allocate tx+rx in one allocation if rx is requested */
+ *tx = kzalloc(rx ? 2 * len : len, GFP_KERNEL);
+ if (!*tx)
+ return -ENOMEM;
+ if (rx)
+ *rx = *tx + len;
+ } else {
+ /* use the preallocated buffers instead */
+ *tx = priv->spi_tx;
+ memset(priv->spi_tx, 0, sizeof(priv->spi_tx));
+ if (rx) {
+ *rx = priv->spi_rx;
+ memset(priv->spi_rx, 0, sizeof(priv->spi_rx));
+ }
+ }
+
+ return 0;
+}
+
+static void mcp25xxfd_cmd_release_buf(struct spi_device *spi, u8 *tx, u8 *rx)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ if (tx == priv->spi_tx)
+ mutex_unlock(&priv->spi_rxtx_lock);
+ else
+ kfree(tx);
+}
+
+/* an optimization of spi_write_then_read that merges the transfers
+ * this also makes sure that the data is ALWAYS on heap
+ */
+static int mcp25xxfd_cmd_write_then_read(struct spi_device *spi,
+ const void *tx_buf,
+ unsigned int tx_len,
+ void *rx_buf,
+ unsigned int rx_len,
+ void *crc_buf)
+{
+ int crc_len = crc_buf ? 2 : 0;
+ struct spi_transfer xfer[2];
+ u8 *spi_tx, *spi_rx;
+ int xfers;
+ int ret;
+
+ /* get pointer to buffers */
+ ret = mcp25xxfd_cmd_alloc_buf(spi, tx_len + rx_len + crc_len,
+ &spi_tx, &spi_rx);
+ if (ret)
+ return ret;
+
+ /* clear the xfers */
+ memset(xfer, 0, sizeof(xfer));
+
+ /* special handling for half-duplex */
+ if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) {
+ xfers = 2;
+ xfer[0].tx_buf = spi_tx;
+ xfer[0].len = tx_len;
+ /* the offset for rx_buf needs to get aligned */
+ xfer[1].rx_buf = spi_rx + tx_len;
+ xfer[1].len = rx_len + crc_len;
+ } else {
+ xfers = 1;
+ xfer[0].len = tx_len + rx_len + crc_len;
+ xfer[0].tx_buf = spi_tx;
+ xfer[0].rx_buf = spi_rx;
+ }
+
+ /* copy data - especially to avoid buffers from stack */
+ memcpy(spi_tx, tx_buf, tx_len);
+
+ /* do the transfer */
+ ret = mcp25xxfd_cmd_sync_transfer(spi, xfer, xfers);
+ if (ret)
+ goto out;
+
+ /* copy result back */
+ memcpy(rx_buf, xfer[0].rx_buf + tx_len, rx_len);
+ if (crc_buf)
+ memcpy(crc_buf, xfer[0].rx_buf + tx_len + rx_len, crc_len);
+
+out:
+ mcp25xxfd_cmd_release_buf(spi, spi_tx, spi_rx);
+
+ return ret;
+}
+
+static int mcp25xxfd_cmd_write_then_write(struct spi_device *spi,
+ const void *tx_buf,
+ unsigned int tx_len,
+ const void *tx2_buf,
+ unsigned int tx2_len)
+{
+ struct spi_transfer xfer;
+ u8 *spi_tx;
+ int ret;
+
+ /* get pointer to buffers */
+ ret = mcp25xxfd_cmd_alloc_buf(spi, tx_len + tx2_len, &spi_tx, NULL);
+ if (ret)
+ return ret;
+
+ /* setup xfer */
+ memset(&xfer, 0, sizeof(xfer));
+ xfer.len = tx_len + tx2_len;
+ xfer.tx_buf = spi_tx;
+
+ /* copy data to correct location in buffer */
+ memcpy(spi_tx, tx_buf, tx_len);
+ memcpy(spi_tx + tx_len, tx2_buf, tx2_len);
+
+ /* run the transfer */
+ ret = mcp25xxfd_cmd_sync_transfer(spi, &xfer, 1);
+
+ mcp25xxfd_cmd_release_buf(spi, spi_tx, NULL);
+
+ return ret;
+}
+
+/* mcp25xxfd spi command/protocol helper */
+
+/* read multiple bytes, transform some registers */
+int mcp25xxfd_cmd_readn(struct spi_device *spi, u32 reg,
+ void *data, int n)
+{
+ u8 cmd[2];
+
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_READ, reg, cmd);
+
+ return mcp25xxfd_cmd_write_then_read(spi, cmd, ARRAY_SIZE(cmd), data, n, NULL);
+}
+
+static u16 _mcp25xxfd_cmd_compute_crc(u8 *cmd, u8 *data, int n)
+{
+ u16 crc = 0xffff;
+
+ crc = mcp25xxfd_crc(crc, cmd, 3);
+ crc = mcp25xxfd_crc(crc, data, n);
+
+ return crc;
+}
+
+static int _mcp25xxfd_cmd_readn_crc(struct spi_device *spi, u32 reg,
+ void *data, int n)
+{
+ u8 cmd[3], crcd[2];
+ u16 crcc, crcr;
+ int ret;
+
+ /* prepare command */
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_READ_CRC, reg, cmd);
+ /* count depends on word (=RAM) or byte access (Registers) */
+ if (reg < MCP25XXFD_SRAM_ADDR(0) ||
+ reg >= MCP25XXFD_SRAM_ADDR(MCP25XXFD_SRAM_SIZE))
+ cmd[2] = n;
+ else
+ cmd[2] = n / 4;
+
+ /* now read for real */
+ ret = mcp25xxfd_cmd_write_then_read(spi, &cmd, 3, data, n, crcd);
+ if (ret)
+ return ret;
+
+ /* the received crc */
+ crcr = (crcd[0] << 8) + crcd[1];
+
+ /* compute the crc */
+ crcc = _mcp25xxfd_cmd_compute_crc(cmd, data, n);
+
+ /* if it matches, then return */
+ if (crcc == crcr)
+ return 0;
+
+ /* here possibly handle crc variants with a single bit7 flips */
+
+ /* return with error and rate limited */
+ dev_err_ratelimited(&spi->dev,
+ "CRC read error: computed: %04x received: %04x - data: %*ph %*ph%s\n",
+ crcc, crcr, 3, cmd, min_t(int, 64, n), data,
+ (n > 64) ? "..." : "");
+ return -EILSEQ;
+}
+
+static int mcp25xxfd_cmd_readn_crc(struct spi_device *spi, u32 reg,
+ void *data, int n)
+{
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+#endif
+ int ret;
+
+ for (; n > 0; n -= 254, reg += 254, data += 254) {
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ priv->stats.spi_crc_read++;
+ if (n > 254)
+ priv->stats.spi_crc_read_split++;
+#endif
+ ret = _mcp25xxfd_cmd_readn_crc(spi, reg, data, n);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* read a register, but we are only interrested in a few bytes */
+int mcp25xxfd_cmd_read_mask(struct spi_device *spi, u32 reg,
+ u32 *data, u32 mask)
+{
+ int first_byte, last_byte, len_byte;
+ int ret;
+
+ /* check that at least one bit is set */
+ if (!mask)
+ return -EINVAL;
+
+ /* calculate first and last byte used */
+ first_byte = mcp25xxfd_cmd_first_byte(mask);
+ last_byte = mcp25xxfd_cmd_last_byte(mask);
+ len_byte = last_byte - first_byte + 1;
+
+ mcp25xxfd_cmd_convert_from_cpu(data, 1);
+
+ /* do a partial read */
+ ret = mcp25xxfd_cmd_readn(spi, reg + first_byte,
+ ((void *)data + first_byte), len_byte);
+ if (ret)
+ return ret;
+
+ mcp25xxfd_cmd_convert_to_cpu(data, 1);
+
+ return 0;
+}
+
+int mcp25xxfd_cmd_writen(struct spi_device *spi, u32 reg,
+ void *data, int n)
+{
+ u8 cmd[2];
+
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_WRITE, reg, cmd);
+
+ return mcp25xxfd_cmd_write_then_write(spi, &cmd, 2, data, n);
+}
+
+/* read a register, but we are only interrested in a few bytes */
+int mcp25xxfd_cmd_write_mask(struct spi_device *spi, u32 reg,
+ u32 data, u32 mask)
+{
+ int first_byte, last_byte, len_byte;
+ u8 cmd[2];
+
+ /* check that at least one bit is set */
+ if (!mask)
+ return -EINVAL;
+
+ /* calculate first and last byte used */
+ first_byte = mcp25xxfd_cmd_first_byte(mask);
+ last_byte = mcp25xxfd_cmd_last_byte(mask);
+ len_byte = last_byte - first_byte + 1;
+
+ /* prepare buffer */
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_WRITE,
+ reg + first_byte, cmd);
+
+ mcp25xxfd_cmd_convert_from_cpu(&data, 1);
+
+ return mcp25xxfd_cmd_write_then_write(spi,
+ cmd, sizeof(cmd),
+ ((void *)&data + first_byte),
+ len_byte);
+}
+
+int mcp25xxfd_cmd_write_regs(struct spi_device *spi, u32 reg,
+ u32 *data, u32 bytes)
+{
+ int ret;
+
+ /* first transpose to controller format */
+ mcp25xxfd_cmd_convert_from_cpu(data, bytes / sizeof(bytes));
+
+ /* now write it */
+ ret = mcp25xxfd_cmd_writen(spi, reg, data, bytes);
+
+ /* and convert it back to cpu format even if it fails */
+ mcp25xxfd_cmd_convert_to_cpu(data, bytes / sizeof(bytes));
+
+ return ret;
+}
+
+int mcp25xxfd_cmd_read_regs(struct spi_device *spi, u32 reg,
+ u32 *data, u32 bytes)
+{
+ int ret;
+
+ /* read it using crc */
+ if ((use_spi_crc) || (reg & MCP25XXFD_ADDRESS_WITH_CRC))
+ ret = mcp25xxfd_cmd_readn_crc(spi,
+ reg & MCP25XXFD_ADDRESS_MASK,
+ data, bytes);
+ else
+ ret = mcp25xxfd_cmd_readn(spi, reg, data, bytes);
+
+ /* and convert it to cpu format */
+ mcp25xxfd_cmd_convert_to_cpu((u32 *)data, bytes / sizeof(bytes));
+
+ return ret;
+}
+
+int mcp25xxfd_cmd_reset(struct spi_device *spi)
+{
+ u8 *cmd;
+ int ret;
+
+ /* allocate 2 bytes on heap, as we use sync_write */
+ cmd = kzalloc(2, GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ mcp25xxfd_cmd_calc(MCP25XXFD_INSTRUCTION_RESET, 0, cmd);
+
+ /* write the reset command */
+ ret = mcp25xxfd_cmd_sync_write(spi, cmd, 2);
+
+ kfree(cmd);
+
+ return ret;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.h
new file mode 100644
index 000000000000..a60a14c4f3b7
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_cmd.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_CMD_H
+#define __MCP25XXFD_CMD_H
+
+#include <linux/byteorder/generic.h>
+#include <linux/spi/spi.h>
+
+/* SPI commands */
+#define MCP25XXFD_INSTRUCTION_RESET 0x0000
+#define MCP25XXFD_INSTRUCTION_READ 0x3000
+#define MCP25XXFD_INSTRUCTION_WRITE 0x2000
+#define MCP25XXFD_INSTRUCTION_READ_CRC 0xB000
+#define MCP25XXFD_INSTRUCTION_WRITE_CRC 0xA000
+#define MCP25XXFD_INSTRUCTION_WRITE_SAVE 0xC000
+
+#define MCP25XXFD_ADDRESS_MASK 0x0fff
+/* a bit to use CRC commands if possible */
+#define MCP25XXFD_ADDRESS_WITH_CRC BIT(31)
+
+static inline void mcp25xxfd_cmd_convert_to_cpu(u32 *data, int n)
+{
+ le32_to_cpu_array(data, n);
+}
+
+static inline void mcp25xxfd_cmd_convert_from_cpu(u32 *data, int n)
+{
+ cpu_to_le32_array(data, n);
+}
+
+static inline void mcp25xxfd_cmd_calc(u16 cmd, u16 addr, u8 *data)
+{
+ cmd |= addr & MCP25XXFD_ADDRESS_MASK;
+
+ data[0] = cmd >> 8;
+ data[1] = cmd;
+}
+
+static inline int mcp25xxfd_cmd_first_byte(u32 mask)
+{
+ return (mask & 0x0000ffff) ?
+ ((mask & 0x000000ff) ? 0 : 1) :
+ ((mask & 0x00ff0000) ? 2 : 3);
+}
+
+static inline int mcp25xxfd_cmd_last_byte(u32 mask)
+{
+ return (mask & 0xffff0000) ?
+ ((mask & 0xff000000) ? 3 : 2) :
+ ((mask & 0x0000ff00) ? 1 : 0);
+}
+
+int mcp25xxfd_cmd_readn(struct spi_device *spi, u32 reg,
+ void *data, int n);
+int mcp25xxfd_cmd_read_mask(struct spi_device *spi, u32 reg,
+ u32 *data, u32 mask);
+static inline int mcp25xxfd_cmd_read(struct spi_device *spi, u32 reg,
+ u32 *data)
+{
+ return mcp25xxfd_cmd_read_mask(spi, reg, data, -1);
+}
+
+int mcp25xxfd_cmd_read_regs(struct spi_device *spi, u32 reg,
+ u32 *data, u32 bytes);
+
+int mcp25xxfd_cmd_writen(struct spi_device *spi, u32 reg,
+ void *data, int n);
+int mcp25xxfd_cmd_write_mask(struct spi_device *spi, u32 reg,
+ u32 data, u32 mask);
+static inline int mcp25xxfd_cmd_write(struct spi_device *spi, u32 reg,
+ u32 data)
+{
+ return mcp25xxfd_cmd_write_mask(spi, reg, data, -1);
+}
+
+int mcp25xxfd_cmd_write_regs(struct spi_device *spi, u32 reg,
+ u32 *data, u32 bytes);
+
+int mcp25xxfd_cmd_reset(struct spi_device *spi);
+
+#endif /* __MCP25XXFD_CMD_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.c
new file mode 100644
index 000000000000..466f989845dd
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_crc.h"
+#include "mcp25xxfd_regs.h"
+#include "mcp25xxfd_priv.h"
+
+/* the standard crc16 in linux/crc16.h is unfortunately not
+ * computing the correct results (left shift vs. right shift)
+ * so here an implementation with a table generated by:
+ * http://lkml.iu.edu/hypermail/linux/kernel/0508.1/1085.html
+ *
+ * if someone has a better idea how to make crc16 produce the expected
+ * result, then please come forward...
+ */
+static const u16 _mcp25xxfd_crc_table[256] = {
+ 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
+ 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
+ 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
+ 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
+ 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
+ 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
+ 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
+ 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
+ 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
+ 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
+ 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
+ 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
+ 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
+ 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
+ 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
+ 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
+ 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
+ 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
+ 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
+ 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
+ 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
+ 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
+ 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
+ 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
+ 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
+ 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
+ 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
+ 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
+ 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
+ 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
+ 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
+ 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
+};
+
+static inline u16 mcp25xxfd_crc_byte(u16 crc, const u8 data)
+{
+ u8 index = (crc >> 8) ^ data;
+
+ return (crc << 8) ^ _mcp25xxfd_crc_table[index];
+}
+
+u16 mcp25xxfd_crc(u16 crc, u8 const *buffer, size_t len)
+{
+ while (len--)
+ crc = mcp25xxfd_crc_byte(crc, *buffer++);
+ return crc;
+}
+
+int mcp25xxfd_crc_enable_int(struct mcp25xxfd_priv *priv, bool enable)
+{
+ u32 mask = MCP25XXFD_CRC_CRCERRIE | MCP25XXFD_CRC_FERRIE;
+
+ priv->regs.crc &= ~mask;
+ priv->regs.crc |= enable ? mask : 0;
+
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_CRC,
+ priv->regs.crc, mask);
+}
+
+int mcp25xxfd_crc_clear_int(struct mcp25xxfd_priv *priv)
+{
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_CRC, 0,
+ MCP25XXFD_CRC_CRCERRIF |
+ MCP25XXFD_CRC_FERRIF);
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.h
new file mode 100644
index 000000000000..25db96b0b9c9
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_crc.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_CRC_H
+#define __MCP25XXFD_CRC_H
+
+#include "mcp25xxfd_priv.h"
+
+int mcp25xxfd_crc_enable_int(struct mcp25xxfd_priv *priv, bool enable);
+int mcp25xxfd_crc_clear_int(struct mcp25xxfd_priv *priv);
+
+u16 mcp25xxfd_crc(u16 crc, u8 const *buffer, size_t len);
+
+#endif /* __MCP25XXFD_CRC_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.c
new file mode 100644
index 000000000000..20969c76db46
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/seq_file.h>
+
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_debugfs.h"
+#include "mcp25xxfd_priv.h"
+
+static int mcp25xxfd_debugfs_dump_regs_range(struct seq_file *file,
+ u32 start, u32 end)
+{
+ struct spi_device *spi = file->private;
+ u32 data[32];
+ int bytes = end - start + sizeof(*data);
+ int i, l, count, ret;
+
+ for (count = bytes / sizeof(*data); count > 0; count -= 32) {
+ /* read up to 32 registers in one go */
+ l = min(count, 32);
+ ret = mcp25xxfd_cmd_read_regs(spi, start,
+ data, l * sizeof(*data));
+ if (ret)
+ return ret;
+ /* dump those read registers */
+ for (i = 0; i < l; i++, start += sizeof(*data))
+ seq_printf(file, "Reg 0x%03x = 0x%08x\n",
+ start, data[i]);
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_debugfs_dump_regs(struct seq_file *file, void *offset)
+{
+ return mcp25xxfd_debugfs_dump_regs_range(file, MCP25XXFD_OSC,
+ MCP25XXFD_DEVID);
+}
+
+static int mcp25xxfd_debugfs_dump_can_regs(struct seq_file *file,
+ void *offset)
+{
+ return mcp25xxfd_debugfs_dump_regs_range(file, MCP25XXFD_CAN_CON,
+ MCP25XXFD_CAN_TXQUA);
+}
+
+static int mcp25xxfd_debugfs_dump_can_all_regs(struct seq_file *file,
+ void *offset)
+{
+ return mcp25xxfd_debugfs_dump_regs_range(file, MCP25XXFD_CAN_CON,
+ MCP25XXFD_CAN_FLTMASK(31));
+}
+
+static void mcp25xxfd_debugfs_mod_setup(struct mcp25xxfd_priv *priv)
+{
+ struct dentry *root, *regs;
+
+ /* the base directory */
+ priv->debugfs_dir = debugfs_create_dir(priv->device_name, NULL);
+ root = priv->debugfs_dir;
+
+ /* expose some parameters related to clocks */
+ debugfs_create_u32("spi_setup_speed_hz", 0644, root,
+ &priv->spi_setup_speed_hz);
+ debugfs_create_u32("spi_normal_speed_hz", 0644, root,
+ &priv->spi_normal_speed_hz);
+ debugfs_create_u32("spi_use_speed_hz", 0644, root,
+ &priv->spi_use_speed_hz);
+ debugfs_create_u32("clk_user_mask", 0444, root, &priv->clk_user_mask);
+
+ /* some statistics */
+ debugfs_create_u64("spi_crc_read", 0444, root,
+ &priv->stats.spi_crc_read);
+ debugfs_create_u64("spi_crc_read_split", 0444, root,
+ &priv->stats.spi_crc_read_split);
+
+ /* expose the system registers */
+ priv->debugfs_regs_dir = debugfs_create_dir("regs", root);
+ regs = priv->debugfs_regs_dir;
+ debugfs_create_x32("osc", 0444, regs, &priv->regs.osc);
+ debugfs_create_x32("iocon", 0444, regs, &priv->regs.iocon);
+ debugfs_create_x32("crc", 0444, regs, &priv->regs.crc);
+ debugfs_create_x32("ecccon", 0444, regs, &priv->regs.ecccon);
+
+ /* dump the controller registers themselves */
+ debugfs_create_devm_seqfile(&priv->spi->dev, "regs_live_dump",
+ root, mcp25xxfd_debugfs_dump_regs);
+ /* and the essential can registers */
+ debugfs_create_devm_seqfile(&priv->spi->dev, "can_regs_live_dump",
+ root, mcp25xxfd_debugfs_dump_can_regs);
+ /* and the complete can registers */
+ debugfs_create_devm_seqfile(&priv->spi->dev,
+ "can_regs_all_live_dump", root,
+ mcp25xxfd_debugfs_dump_can_all_regs);
+}
+
+void mcp25xxfd_debugfs_setup(struct mcp25xxfd_priv *priv)
+{
+ mcp25xxfd_debugfs_mod_setup(priv);
+}
+
+void mcp25xxfd_debugfs_remove(struct mcp25xxfd_priv *priv)
+{
+ debugfs_remove_recursive(priv->debugfs_dir);
+ priv->debugfs_dir = NULL;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.h
new file mode 100644
index 000000000000..905f15ea7f5d
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_debugfs.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_DEBUGFS_H
+#define __MCP25XXFD_DEBUGFS_H
+
+#include "mcp25xxfd_priv.h"
+
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+
+void mcp25xxfd_debugfs_setup(struct mcp25xxfd_priv *priv);
+void mcp25xxfd_debugfs_remove(struct mcp25xxfd_priv *priv);
+
+#else
+
+static inline void mcp25xxfd_debugfs_setup(struct mcp25xxfd_priv *priv)
+{
+}
+
+static inline void mcp25xxfd_debugfs_remove(struct mcp25xxfd_priv *priv)
+{
+}
+
+#endif /* CONFIG_CAN_MCP25XXFD_DEBUG_FS */
+#endif /* __MCP25XXFD_DEBUGFS_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.c
new file mode 100644
index 000000000000..526f345d0a17
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_ecc.h"
+#include "mcp25xxfd_priv.h"
+#include "mcp25xxfd_regs.h"
+
+int mcp25xxfd_ecc_clear_int(struct mcp25xxfd_priv *priv)
+{
+ u32 val, addr;
+ int ret;
+
+ /* first report the error address */
+ ret = mcp25xxfd_cmd_read(priv->spi, MCP25XXFD_ECCSTAT, &val);
+ if (ret)
+ return ret;
+
+ /* if no flags are set then nothing to do */
+ if (!(val & (MCP25XXFD_ECCSTAT_SECIF | MCP25XXFD_ECCSTAT_DEDIF)))
+ return 0;
+
+ addr = (val & MCP25XXFD_ECCSTAT_ERRADDR_MASK) >>
+ MCP25XXFD_ECCSTAT_ERRADDR_SHIFT;
+
+ dev_err_ratelimited(&priv->spi->dev, "ECC %s bit error at %03x\n",
+ (val & MCP25XXFD_ECCSTAT_DEDIF) ?
+ "double" : "single",
+ addr);
+
+ /* and clear the error */
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_ECCSTAT, 0,
+ MCP25XXFD_ECCSTAT_SECIF |
+ MCP25XXFD_ECCSTAT_DEDIF);
+}
+
+int mcp25xxfd_ecc_enable_int(struct mcp25xxfd_priv *priv, bool enable)
+{
+ u32 mask = MCP25XXFD_ECCCON_SECIE | MCP25XXFD_ECCCON_DEDIE;
+
+ priv->regs.ecccon &= ~mask;
+ priv->regs.ecccon |= MCP25XXFD_ECCCON_ECCEN | (enable ? mask : 0);
+
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_ECCCON,
+ priv->regs.ecccon,
+ MCP25XXFD_ECCCON_ECCEN | mask);
+}
+
+int mcp25xxfd_ecc_enable(struct mcp25xxfd_priv *priv)
+{
+ u8 buffer[256];
+ int i, ret;
+
+ /* set up RAM ECC - enable interrupts sets it as well */
+ ret = mcp25xxfd_ecc_enable_int(priv, false);
+ if (ret)
+ return ret;
+
+ /* and clear SRAM so that no reads fails from now on */
+ memset(buffer, 0, sizeof(buffer));
+ for (i = 0; i < MCP25XXFD_SRAM_SIZE; i += sizeof(buffer)) {
+ ret = mcp25xxfd_cmd_writen(priv->spi, MCP25XXFD_SRAM_ADDR(i),
+ buffer, sizeof(buffer));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.h
new file mode 100644
index 000000000000..117f58c65a46
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_ecc.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_ECC_H
+#define __MCP25XXFD_ECC_H
+
+#include "mcp25xxfd_priv.h"
+
+int mcp25xxfd_ecc_clear_int(struct mcp25xxfd_priv *priv);
+int mcp25xxfd_ecc_enable_int(struct mcp25xxfd_priv *priv, bool enable);
+int mcp25xxfd_ecc_enable(struct mcp25xxfd_priv *priv);
+
+#endif /* __MCP25XXFD_ECC_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.c
new file mode 100644
index 000000000000..5bda9d8a6e7e
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ *
+ * Based on Microchip MCP251x CAN controller driver written by
+ * David Vrabel, Copyright 2006 Arcom Control Systems Ltd.
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "mcp25xxfd_clock.h"
+#include "mcp25xxfd_cmd.h"
+#include "mcp25xxfd_gpio.h"
+#include "mcp25xxfd_priv.h"
+
+static int mcp25xxfd_gpio_request(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ int clock_requestor = offset ?
+ MCP25XXFD_CLK_USER_GPIO1 : MCP25XXFD_CLK_USER_GPIO0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* if we have XSTANDBY enabled then gpio0 is not available either */
+ if (priv->config.gpio0_xstandby && offset == 0)
+ return -EINVAL;
+
+ mcp25xxfd_clock_start(priv, clock_requestor);
+
+ return 0;
+}
+
+static void mcp25xxfd_gpio_free(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ int clock_requestor = offset ?
+ MCP25XXFD_CLK_USER_GPIO1 : MCP25XXFD_CLK_USER_GPIO0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return;
+
+ mcp25xxfd_clock_stop(priv, clock_requestor);
+}
+
+static int mcp25xxfd_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask = (offset) ? MCP25XXFD_IOCON_GPIO1 : MCP25XXFD_IOCON_GPIO0;
+ int ret;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* read the relevant gpio Latch */
+ ret = mcp25xxfd_cmd_read_mask(priv->spi, MCP25XXFD_IOCON,
+ &priv->regs.iocon, mask);
+ if (ret)
+ return ret;
+
+ /* return the match */
+ return priv->regs.iocon & mask;
+}
+
+static void mcp25xxfd_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask = (offset) ? MCP25XXFD_IOCON_LAT1 : MCP25XXFD_IOCON_LAT0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return;
+
+ /* update in memory representation with the corresponding value */
+ if (value)
+ priv->regs.iocon |= mask;
+ else
+ priv->regs.iocon &= ~mask;
+
+ mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_IOCON,
+ priv->regs.iocon, mask);
+}
+
+static int mcp25xxfd_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask_tri = (offset) ?
+ MCP25XXFD_IOCON_TRIS1 : MCP25XXFD_IOCON_TRIS0;
+ u32 mask_stby = (offset) ?
+ 0 : MCP25XXFD_IOCON_XSTBYEN;
+ u32 mask_pm = (offset) ?
+ MCP25XXFD_IOCON_PM1 : MCP25XXFD_IOCON_PM0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* set the mask */
+ priv->regs.iocon |= mask_tri | mask_pm;
+
+ /* clear stby */
+ priv->regs.iocon &= ~mask_stby;
+
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_IOCON,
+ priv->regs.iocon,
+ mask_tri | mask_stby | mask_pm);
+}
+
+static int mcp25xxfd_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask_tri = (offset) ?
+ MCP25XXFD_IOCON_TRIS1 : MCP25XXFD_IOCON_TRIS0;
+ u32 mask_lat = (offset) ?
+ MCP25XXFD_IOCON_LAT1 : MCP25XXFD_IOCON_LAT0;
+ u32 mask_pm = (offset) ?
+ MCP25XXFD_IOCON_PM1 : MCP25XXFD_IOCON_PM0;
+ u32 mask_stby = (offset) ?
+ 0 : MCP25XXFD_IOCON_XSTBYEN;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* clear the tristate bit and also clear stby */
+ priv->regs.iocon &= ~(mask_tri | mask_stby);
+
+ /* set GPIO mode */
+ priv->regs.iocon |= mask_pm;
+
+ /* set the value */
+ if (value)
+ priv->regs.iocon |= mask_lat;
+ else
+ priv->regs.iocon &= ~mask_lat;
+
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_IOCON,
+ priv->regs.iocon,
+ mask_tri | mask_lat |
+ mask_pm | mask_stby);
+}
+
+#ifdef CONFIG_OF_DYNAMIC
+static void mcp25xxfd_gpio_read_of(struct mcp25xxfd_priv *priv)
+{
+ const struct device_node *np = priv->spi->dev.of_node;
+
+ priv->config.gpio_open_drain =
+ of_property_read_bool(np, "microchip,gpio-open-drain");
+ priv->config.gpio0_xstandby =
+ of_property_read_bool(np, "microchip,gpio0-xstandby");
+}
+#else
+static void mcp25xxfd_gpio_read_of(struct mcp25xxfd_priv *priv)
+{
+ priv->config.gpio_open_drain = false;
+ priv->config.gpio0_xstandby = false;
+}
+#endif
+
+static int mcp25xxfd_gpio_setup_regs(struct mcp25xxfd_priv *priv)
+{
+ /* handle open-drain */
+ if (priv->config.gpio_open_drain)
+ priv->regs.iocon |= MCP25XXFD_IOCON_INTOD;
+ else
+ priv->regs.iocon &= ~MCP25XXFD_IOCON_INTOD;
+
+ /* handle xstandby */
+ if (priv->config.gpio0_xstandby) {
+ priv->regs.iocon &= ~(MCP25XXFD_IOCON_TRIS0 |
+ MCP25XXFD_IOCON_GPIO0);
+ priv->regs.iocon |= MCP25XXFD_IOCON_XSTBYEN;
+ } else {
+ priv->regs.iocon &= ~(MCP25XXFD_IOCON_XSTBYEN);
+ }
+
+ /* handle sof / clko */
+ if (priv->config.clock_odiv == 0)
+ priv->regs.iocon |= MCP25XXFD_IOCON_SOF;
+ else
+ priv->regs.iocon &= ~MCP25XXFD_IOCON_SOF;
+
+ /* update the iocon register */
+ return mcp25xxfd_cmd_write_regs(priv->spi, MCP25XXFD_IOCON,
+ &priv->regs.iocon, sizeof(u32));
+}
+
+static int mcp25xxfd_gpio_setup_gpiochip(struct mcp25xxfd_priv *priv)
+{
+ struct gpio_chip *gpio = &priv->gpio;
+
+ /* gpiochip only handles GPIO0 and GPIO1 */
+ gpio->owner = THIS_MODULE;
+ gpio->parent = &priv->spi->dev;
+ gpio->label = dev_name(&priv->spi->dev);
+ gpio->direction_input = mcp25xxfd_gpio_direction_input;
+ gpio->get = mcp25xxfd_gpio_get;
+ gpio->direction_output = mcp25xxfd_gpio_direction_output;
+ gpio->set = mcp25xxfd_gpio_set;
+ gpio->request = mcp25xxfd_gpio_request;
+ gpio->free = mcp25xxfd_gpio_free;
+ gpio->base = -1;
+ gpio->ngpio = 2;
+ gpio->can_sleep = 1;
+
+ return gpiochip_add_data(gpio, priv);
+}
+
+int mcp25xxfd_gpio_setup(struct mcp25xxfd_priv *priv)
+{
+ int ret;
+
+ /* setting up defaults */
+ priv->config.gpio0_xstandby = false;
+
+ mcp25xxfd_gpio_read_of(priv);
+ ret = mcp25xxfd_gpio_setup_regs(priv);
+ if (ret)
+ return ret;
+
+ return mcp25xxfd_gpio_setup_gpiochip(priv);
+}
+
+void mcp25xxfd_gpio_remove(struct mcp25xxfd_priv *priv)
+{
+ gpiochip_remove(&priv->gpio);
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.h
new file mode 100644
index 000000000000..cd4f0aa5e032
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_gpio.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_GPIO_H
+#define __MCP25XXFD_GPIO_H
+
+#include "mcp25xxfd_priv.h"
+
+#ifdef CONFIG_GPIOLIB
+
+/* gpiolib support */
+int mcp25xxfd_gpio_setup(struct mcp25xxfd_priv *priv);
+void mcp25xxfd_gpio_remove(struct mcp25xxfd_priv *priv);
+
+#else
+
+static inline int mcp25xxfd_gpio_setup(struct mcp25xxfd_priv *priv)
+{
+ return 0;
+}
+
+static inline void mcp25xxfd_gpio_remove(struct mcp25xxfd_priv *priv)
+{
+}
+
+#endif
+
+#endif /* __MCP25XXFD_GPIO_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.c
new file mode 100644
index 000000000000..cca9c996b542
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_can_int.h"
+#include "mcp25xxfd_crc.h"
+#include "mcp25xxfd_ecc.h"
+#include "mcp25xxfd_int.h"
+#include "mcp25xxfd_priv.h"
+
+int mcp25xxfd_int_clear(struct mcp25xxfd_priv *priv)
+{
+ int ret;
+
+ ret = mcp25xxfd_ecc_clear_int(priv);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_crc_clear_int(priv);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_can_int_clear(priv);
+
+ return ret;
+}
+
+int mcp25xxfd_int_enable(struct mcp25xxfd_priv *priv, bool enable)
+{
+ /* error handling only on enable for this function */
+ int ret = 0;
+
+ /* if we enable clear interrupt flags first */
+ if (enable) {
+ ret = mcp25xxfd_int_clear(priv);
+ if (ret)
+ goto out;
+ }
+
+ ret = mcp25xxfd_crc_enable_int(priv, enable);
+ if (ret)
+ goto out;
+
+ ret = mcp25xxfd_ecc_enable(priv);
+ if (ret)
+ goto out_crc;
+
+ ret = mcp25xxfd_ecc_enable_int(priv, enable);
+ if (ret)
+ goto out_crc;
+
+ ret = mcp25xxfd_can_int_enable(priv, enable);
+ if (ret)
+ goto out_ecc;
+
+ /* if we disable interrupts clear interrupt flags last */
+ if (!enable)
+ mcp25xxfd_int_clear(priv);
+
+ return 0;
+
+out_ecc:
+ mcp25xxfd_ecc_enable_int(priv, false);
+
+out_crc:
+ mcp25xxfd_crc_enable_int(priv, false);
+out:
+ return ret;
+}
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.h
new file mode 100644
index 000000000000..4daf0182d1af
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_int.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_INT_H
+#define __MCP25XXFD_INT_H
+
+#include "mcp25xxfd_priv.h"
+
+int mcp25xxfd_int_clear(struct mcp25xxfd_priv *priv);
+int mcp25xxfd_int_enable(struct mcp25xxfd_priv *priv, bool enable);
+
+#endif /* __MCP25XXFD_INT_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_priv.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_priv.h
new file mode 100644
index 000000000000..ced89e0b9e3c
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_priv.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+#ifndef __MCP25XXFD_PRIV_H
+#define __MCP25XXFD_PRIV_H
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/gpio/driver.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include "mcp25xxfd_regs.h"
+
+/* some defines for the driver */
+#define DEVICE_NAME "mcp25xxfd"
+
+enum mcp25xxfd_model {
+ CAN_MCP2517FD = 0x2517,
+ CAN_MCP2518FD = 0x2518,
+};
+
+struct mcp25xxfd_can_priv;
+struct mcp25xxfd_priv {
+ struct spi_device *spi;
+ struct clk *clk;
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio;
+#endif
+ struct mcp25xxfd_can_priv *cpriv;
+
+ /* the actual model of the mcp25xxfd */
+ enum mcp25xxfd_model model;
+
+ /* full device name used for debugfs and interrupts */
+ char device_name[32];
+
+ /* everything clock related */
+ int clock_freq;
+ struct {
+ /* clock configuration */
+ int clock_pll;
+ int clock_div2;
+ int clock_odiv;
+ int clock_allways_on;
+ /* gpio related */
+ bool gpio_open_drain;
+ bool gpio0_xstandby;
+ } config;
+
+ /* lock for enabling/disabling the clock */
+ struct mutex clk_user_lock;
+ u32 clk_user_mask;
+ u32 clk_sleep_mask;
+
+ /* power related */
+ struct regulator *power;
+
+ /* the distinct spi_speeds to use for spi communication */
+ u32 spi_setup_speed_hz;
+ u32 spi_normal_speed_hz;
+ u32 spi_use_speed_hz;
+
+ /* spi-tx/rx buffers for efficient transfers
+ * used during setup and irq
+ */
+ struct mutex spi_rxtx_lock; /* protects use of spi_tx/rx */
+ u8 spi_tx[MCP25XXFD_SRAM_SIZE];
+ u8 spi_rx[MCP25XXFD_SRAM_SIZE];
+
+ /* configuration registers */
+ struct {
+ u32 osc;
+ u32 iocon;
+ u32 crc;
+ u32 ecccon;
+ } regs;
+
+ /* debugfs related */
+#ifdef CONFIG_CAN_MCP25XXFD_DEBUG_FS
+ struct dentry *debugfs_dir;
+ struct dentry *debugfs_regs_dir;
+ struct {
+ u64 spi_crc_read;
+ u64 spi_crc_read_split;
+ } stats;
+#endif
+};
+
+#endif /* __MCP25XXFD_PRIV_H */
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_regs.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_regs.h
new file mode 100644
index 000000000000..80a166248955
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_regs.h
@@ -0,0 +1,681 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2019 Martin Sperl <kernel@martin.sperl.org>
+ */
+
+#ifndef __MCP25XXFD_REGS_H
+#define __MCP25XXFD_REGS_H
+
+#include <linux/bitops.h>
+
+/* some constants derived from the datasheets */
+#define MCP25XXFD_OST_DELAY_MS 3
+#define MCP25XXFD_MIN_CLOCK_FREQUENCY 1000000
+#define MCP25XXFD_MAX_CLOCK_FREQUENCY 40000000
+#define MCP25XXFD_PLL_MULTIPLIER 10
+#define MCP25XXFD_AUTO_PLL_MAX_CLOCK_FREQUENCY \
+ (MCP25XXFD_MAX_CLOCK_FREQUENCY / MCP25XXFD_PLL_MULTIPLIER)
+#define MCP25XXFD_SCLK_DIVIDER 2
+
+/* GPIO, clock, ecc related register definitions of Controller itself */
+#define MCP25XXFD_SFR_BASE(x) (0xE00 + (x))
+#define MCP25XXFD_OSC MCP25XXFD_SFR_BASE(0x00)
+# define MCP25XXFD_OSC_PLLEN BIT(0)
+# define MCP25XXFD_OSC_OSCDIS BIT(2)
+# define MCP25XXFD_OSC_SCLKDIV BIT(4)
+# define MCP25XXFD_OSC_CLKODIV_BITS 2
+# define MCP25XXFD_OSC_CLKODIV_SHIFT 5
+# define MCP25XXFD_OSC_CLKODIV_MASK \
+ GENMASK(MCP25XXFD_OSC_CLKODIV_SHIFT \
+ + MCP25XXFD_OSC_CLKODIV_BITS - 1, \
+ MCP25XXFD_OSC_CLKODIV_SHIFT)
+# define MCP25XXFD_OSC_CLKODIV_10 3
+# define MCP25XXFD_OSC_CLKODIV_4 2
+# define MCP25XXFD_OSC_CLKODIV_2 1
+# define MCP25XXFD_OSC_CLKODIV_1 0
+# define MCP25XXFD_OSC_PLLRDY BIT(8)
+# define MCP25XXFD_OSC_OSCRDY BIT(10)
+# define MCP25XXFD_OSC_SCLKRDY BIT(12)
+#define MCP25XXFD_IOCON MCP25XXFD_SFR_BASE(0x04)
+# define MCP25XXFD_IOCON_TRIS0 BIT(0)
+# define MCP25XXFD_IOCON_TRIS1 BIT(1)
+# define MCP25XXFD_IOCON_XSTBYEN BIT(6)
+# define MCP25XXFD_IOCON_LAT0 BIT(8)
+# define MCP25XXFD_IOCON_LAT1 BIT(9)
+# define MCP25XXFD_IOCON_GPIO0 BIT(16)
+# define MCP25XXFD_IOCON_GPIO1 BIT(17)
+# define MCP25XXFD_IOCON_PM0 BIT(24)
+# define MCP25XXFD_IOCON_PM1 BIT(25)
+# define MCP25XXFD_IOCON_TXCANOD BIT(28)
+# define MCP25XXFD_IOCON_SOF BIT(29)
+# define MCP25XXFD_IOCON_INTOD BIT(30)
+#define MCP25XXFD_CRC MCP25XXFD_SFR_BASE(0x08)
+# define MCP25XXFD_CRC_MASK GENMASK(15, 0)
+# define MCP25XXFD_CRC_CRCERRIF BIT(16)
+# define MCP25XXFD_CRC_FERRIF BIT(17)
+# define MCP25XXFD_CRC_CRCERRIE BIT(24)
+# define MCP25XXFD_CRC_FERRIE BIT(25)
+#define MCP25XXFD_ECCCON MCP25XXFD_SFR_BASE(0x0C)
+# define MCP25XXFD_ECCCON_ECCEN BIT(0)
+# define MCP25XXFD_ECCCON_SECIE BIT(1)
+# define MCP25XXFD_ECCCON_DEDIE BIT(2)
+# define MCP25XXFD_ECCCON_PARITY_BITS 7
+# define MCP25XXFD_ECCCON_PARITY_SHIFT 8
+# define MCP25XXFD_ECCCON_PARITY_MASK \
+ GENMASK(MCP25XXFD_ECCCON_PARITY_SHIFT \
+ + MCP25XXFD_ECCCON_PARITY_BITS - 1, \
+ MCP25XXFD_ECCCON_PARITY_SHIFT)
+#define MCP25XXFD_ECCSTAT MCP25XXFD_SFR_BASE(0x10)
+# define MCP25XXFD_ECCSTAT_SECIF BIT(1)
+# define MCP25XXFD_ECCSTAT_DEDIF BIT(2)
+# define MCP25XXFD_ECCSTAT_ERRADDR_SHIFT 16
+# define MCP25XXFD_ECCSTAT_ERRADDR_MASK \
+ GENMASK(MCP25XXFD_ECCSTAT_ERRADDR_SHIFT + 11, \
+ MCP25XXFD_ECCSTAT_ERRADDR_SHIFT)
+
+#define MCP25XXFD_DEVID MCP25XXFD_SFR_BASE(0x14)
+# define MCP25XXFD_DEVID_REV_BITS 4
+# define MCP25XXFD_DEVID_REV_SHIFT 0
+# define MCP25XXFD_DEVID_REV_MASK \
+ GENMASK(MCP25XXFD_DEVID_REV_SHIFT + \
+ MCP25XXFD_DEVID_REV_BITS - 1, \
+ MCP25XXFD_DEVID_REV_SHIFT)
+# define MCP25XXFD_DEVID_ID_BITS 4
+# define MCP25XXFD_DEVID_ID_SHIFT 4
+# define MCP25XXFD_DEVID_ID_MASK \
+ GENMASK(MCP25XXFD_DEVID_ID_SHIFT + \
+ MCP25XXFD_DEVID_ID_BITS - 1, \
+ MCP25XXFD_DEVID_ID_SHIFT)
+
+/* CAN related register definitions of Controller CAN block */
+#define MCP25XXFD_CAN_SFR_BASE(x) (0x000 + (x))
+#define MCP25XXFD_CAN_CON \
+ MCP25XXFD_CAN_SFR_BASE(0x00)
+# define MCP25XXFD_CAN_CON_DNCNT_BITS 5
+# define MCP25XXFD_CAN_CON_DNCNT_SHIFT 0
+# define MCP25XXFD_CAN_CON_DNCNT_MASK \
+ GENMASK(MCP25XXFD_CAN_CON_DNCNT_SHIFT + \
+ MCP25XXFD_CAN_CON_DNCNT_BITS - 1, \
+ MCP25XXFD_CAN_CON_DNCNT_SHIFT)
+# define MCP25XXFD_CAN_CON_ISOCRCEN BIT(5)
+# define MCP25XXFD_CAN_CON_PXEDIS BIT(6)
+# define MCP25XXFD_CAN_CON_WAKFIL BIT(8)
+# define MCP25XXFD_CAN_CON_WFT_BITS 2
+# define MCP25XXFD_CAN_CON_WFT_SHIFT 9
+# define MCP25XXFD_CAN_CON_WFT_MASK \
+ GENMASK(MCP25XXFD_CAN_CON_WFT_SHIFT + \
+ MCP25XXFD_CAN_CON_WFT_BITS - 1, \
+ MCP25XXFD_CAN_CON_WFT_SHIFT)
+# define MCP25XXFD_CAN_CON_BUSY BIT(11)
+# define MCP25XXFD_CAN_CON_BRSDIS BIT(12)
+# define MCP25XXFD_CAN_CON_RTXAT BIT(16)
+# define MCP25XXFD_CAN_CON_ESIGM BIT(17)
+# define MCP25XXFD_CAN_CON_SERR2LOM BIT(18)
+# define MCP25XXFD_CAN_CON_STEF BIT(19)
+# define MCP25XXFD_CAN_CON_TXQEN BIT(20)
+# define MCP25XXFD_CAN_CON_OPMOD_BITS 3
+# define MCP25XXFD_CAN_CON_OPMOD_SHIFT 21
+# define MCP25XXFD_CAN_CON_OPMOD_MASK \
+ GENMASK(MCP25XXFD_CAN_CON_OPMOD_SHIFT + \
+ MCP25XXFD_CAN_CON_OPMOD_BITS - 1, \
+ MCP25XXFD_CAN_CON_OPMOD_SHIFT)
+# define MCP25XXFD_CAN_CON_REQOP_BITS 3
+# define MCP25XXFD_CAN_CON_REQOP_SHIFT 24
+# define MCP25XXFD_CAN_CON_REQOP_MASK \
+ GENMASK(MCP25XXFD_CAN_CON_REQOP_SHIFT + \
+ MCP25XXFD_CAN_CON_REQOP_BITS - 1, \
+ MCP25XXFD_CAN_CON_REQOP_SHIFT)
+# define MCP25XXFD_CAN_CON_MODE_MIXED 0
+# define MCP25XXFD_CAN_CON_MODE_SLEEP 1
+# define MCP25XXFD_CAN_CON_MODE_INT_LOOPBACK 2
+# define MCP25XXFD_CAN_CON_MODE_LISTENONLY 3
+# define MCP25XXFD_CAN_CON_MODE_CONFIG 4
+# define MCP25XXFD_CAN_CON_MODE_EXT_LOOPBACK 5
+# define MCP25XXFD_CAN_CON_MODE_CAN2_0 6
+# define MCP25XXFD_CAN_CON_MODE_RESTRICTED 7
+# define MCP25XXFD_CAN_CON_ABAT BIT(27)
+# define MCP25XXFD_CAN_CON_TXBWS_BITS 4
+# define MCP25XXFD_CAN_CON_TXBWS_SHIFT 28
+# define MCP25XXFD_CAN_CON_TXBWS_MASK \
+ GENMASK(MCP25XXFD_CAN_CON_TXBWS_SHIFT + \
+ MCP25XXFD_CAN_CON_TXBWS_BITS - 1, \
+ MCP25XXFD_CAN_CON_TXBWS_SHIFT)
+# define MCP25XXFD_CAN_CON_DEFAULT \
+ (MCP25XXFD_CAN_CON_ISOCRCEN | \
+ MCP25XXFD_CAN_CON_PXEDIS | \
+ MCP25XXFD_CAN_CON_WAKFIL | \
+ (3 << MCP25XXFD_CAN_CON_WFT_SHIFT) | \
+ MCP25XXFD_CAN_CON_STEF | \
+ MCP25XXFD_CAN_CON_TXQEN | \
+ (MCP25XXFD_CAN_CON_MODE_CONFIG << MCP25XXFD_CAN_CON_OPMOD_SHIFT) | \
+ (MCP25XXFD_CAN_CON_MODE_CONFIG << MCP25XXFD_CAN_CON_REQOP_SHIFT))
+# define MCP25XXFD_CAN_CON_DEFAULT_MASK \
+ (MCP25XXFD_CAN_CON_DNCNT_MASK | \
+ MCP25XXFD_CAN_CON_ISOCRCEN | \
+ MCP25XXFD_CAN_CON_PXEDIS | \
+ MCP25XXFD_CAN_CON_WAKFIL | \
+ MCP25XXFD_CAN_CON_WFT_MASK | \
+ MCP25XXFD_CAN_CON_BRSDIS | \
+ MCP25XXFD_CAN_CON_RTXAT | \
+ MCP25XXFD_CAN_CON_ESIGM | \
+ MCP25XXFD_CAN_CON_SERR2LOM | \
+ MCP25XXFD_CAN_CON_STEF | \
+ MCP25XXFD_CAN_CON_TXQEN | \
+ MCP25XXFD_CAN_CON_OPMOD_MASK | \
+ MCP25XXFD_CAN_CON_REQOP_MASK | \
+ MCP25XXFD_CAN_CON_ABAT | \
+ MCP25XXFD_CAN_CON_TXBWS_MASK)
+#define MCP25XXFD_CAN_NBTCFG MCP25XXFD_CAN_SFR_BASE(0x04)
+# define MCP25XXFD_CAN_NBTCFG_SJW_BITS 7
+# define MCP25XXFD_CAN_NBTCFG_SJW_SHIFT 0
+# define MCP25XXFD_CAN_NBTCFG_SJW_MASK \
+ GENMASK(MCP25XXFD_CAN_NBTCFG_SJW_SHIFT + \
+ MCP25XXFD_CAN_NBTCFG_SJW_BITS - 1, \
+ MCP25XXFD_CAN_NBTCFG_SJW_SHIFT)
+# define MCP25XXFD_CAN_NBTCFG_TSEG2_BITS 7
+# define MCP25XXFD_CAN_NBTCFG_TSEG2_SHIFT 8
+# define MCP25XXFD_CAN_NBTCFG_TSEG2_MASK \
+ GENMASK(MCP25XXFD_CAN_NBTCFG_TSEG2_SHIFT + \
+ MCP25XXFD_CAN_NBTCFG_TSEG2_BITS - 1, \
+ MCP25XXFD_CAN_NBTCFG_TSEG2_SHIFT)
+# define MCP25XXFD_CAN_NBTCFG_TSEG1_BITS 8
+# define MCP25XXFD_CAN_NBTCFG_TSEG1_SHIFT 16
+# define MCP25XXFD_CAN_NBTCFG_TSEG1_MASK \
+ GENMASK(MCP25XXFD_CAN_NBTCFG_TSEG1_SHIFT + \
+ MCP25XXFD_CAN_NBTCFG_TSEG1_BITS - 1, \
+ MCP25XXFD_CAN_NBTCFG_TSEG1_SHIFT)
+# define MCP25XXFD_CAN_NBTCFG_BRP_BITS 8
+# define MCP25XXFD_CAN_NBTCFG_BRP_SHIFT 24
+# define MCP25XXFD_CAN_NBTCFG_BRP_MASK \
+ GENMASK(MCP25XXFD_CAN_NBTCFG_BRP_SHIFT + \
+ MCP25XXFD_CAN_NBTCFG_BRP_BITS - 1, \
+ MCP25XXFD_CAN_NBTCFG_BRP_SHIFT)
+#define MCP25XXFD_CAN_DBTCFG MCP25XXFD_CAN_SFR_BASE(0x08)
+# define MCP25XXFD_CAN_DBTCFG_SJW_BITS 4
+# define MCP25XXFD_CAN_DBTCFG_SJW_SHIFT 0
+# define MCP25XXFD_CAN_DBTCFG_SJW_MASK \
+ GENMASK(MCP25XXFD_CAN_DBTCFG_SJW_SHIFT + \
+ MCP25XXFD_CAN_DBTCFG_SJW_BITS - 1, \
+ MCP25XXFD_CAN_DBTCFG_SJW_SHIFT)
+# define MCP25XXFD_CAN_DBTCFG_TSEG2_BITS 4
+# define MCP25XXFD_CAN_DBTCFG_TSEG2_SHIFT 8
+# define MCP25XXFD_CAN_DBTCFG_TSEG2_MASK \
+ GENMASK(MCP25XXFD_CAN_DBTCFG_TSEG2_SHIFT + \
+ MCP25XXFD_CAN_DBTCFG_TSEG2_BITS - 1, \
+ MCP25XXFD_CAN_DBTCFG_TSEG2_SHIFT)
+# define MCP25XXFD_CAN_DBTCFG_TSEG1_BITS 5
+# define MCP25XXFD_CAN_DBTCFG_TSEG1_SHIFT 16
+# define MCP25XXFD_CAN_DBTCFG_TSEG1_MASK \
+ GENMASK(MCP25XXFD_CAN_DBTCFG_TSEG1_SHIFT + \
+ MCP25XXFD_CAN_DBTCFG_TSEG1_BITS - 1, \
+ MCP25XXFD_CAN_DBTCFG_TSEG1_SHIFT)
+# define MCP25XXFD_CAN_DBTCFG_BRP_BITS 8
+# define MCP25XXFD_CAN_DBTCFG_BRP_SHIFT 24
+# define MCP25XXFD_CAN_DBTCFG_BRP_MASK \
+ GENMASK(MCP25XXFD_CAN_DBTCFG_BRP_SHIFT + \
+ MCP25XXFD_CAN_DBTCFG_BRP_BITS - 1, \
+ MCP25XXFD_CAN_DBTCFG_BRP_SHIFT)
+#define MCP25XXFD_CAN_TDC MCP25XXFD_CAN_SFR_BASE(0x0C)
+# define MCP25XXFD_CAN_TDC_TDCV_BITS 6
+# define MCP25XXFD_CAN_TDC_TDCV_SHIFT 0
+# define MCP25XXFD_CAN_TDC_TDCV_MASK \
+ GENMASK(MCP25XXFD_CAN_TDC_TDCV_SHIFT + \
+ MCP25XXFD_CAN_TDC_TDCV_BITS - 1, \
+ MCP25XXFD_CAN_TDC_TDCV_SHIFT)
+# define MCP25XXFD_CAN_TDC_TDCO_BITS 7
+# define MCP25XXFD_CAN_TDC_TDCO_SHIFT 8
+# define MCP25XXFD_CAN_TDC_TDCO_MASK \
+ GENMASK(MCP25XXFD_CAN_TDC_TDCO_SHIFT + \
+ MCP25XXFD_CAN_TDC_TDCO_BITS - 1, \
+ MCP25XXFD_CAN_TDC_TDCO_SHIFT)
+# define MCP25XXFD_CAN_TDC_TDCMOD_BITS 2
+# define MCP25XXFD_CAN_TDC_TDCMOD_SHIFT 16
+# define MCP25XXFD_CAN_TDC_TDCMOD_MASK \
+ GENMASK(MCP25XXFD_CAN_TDC_TDCMOD_SHIFT + \
+ MCP25XXFD_CAN_TDC_TDCMOD_BITS - 1, \
+ MCP25XXFD_CAN_TDC_TDCMOD_SHIFT)
+# define MCP25XXFD_CAN_TDC_TDCMOD_DISABLED 0
+# define MCP25XXFD_CAN_TDC_TDCMOD_MANUAL 1
+# define MCP25XXFD_CAN_TDC_TDCMOD_AUTO 2
+# define MCP25XXFD_CAN_TDC_SID11EN BIT(24)
+# define MCP25XXFD_CAN_TDC_EDGFLTEN BIT(25)
+#define MCP25XXFD_CAN_TBC MCP25XXFD_CAN_SFR_BASE(0x10)
+#define MCP25XXFD_CAN_TSCON MCP25XXFD_CAN_SFR_BASE(0x14)
+# define MCP25XXFD_CAN_TSCON_TBCPRE_BITS 10
+# define MCP25XXFD_CAN_TSCON_TBCPRE_SHIFT 0
+# define MCP25XXFD_CAN_TSCON_TBCPRE_MASK \
+ GENMASK(MCP25XXFD_CAN_TSCON_TBCPRE_SHIFT + \
+ MCP25XXFD_CAN_TSCON_TBCPRE_BITS - 1, \
+ MCP25XXFD_CAN_TSCON_TBCPRE_SHIFT)
+# define MCP25XXFD_CAN_TSCON_TBCEN BIT(16)
+# define MCP25XXFD_CAN_TSCON_TSEOF BIT(17)
+# define MCP25XXFD_CAN_TSCON_TSRES BIT(18)
+#define MCP25XXFD_CAN_VEC MCP25XXFD_CAN_SFR_BASE(0x18)
+# define MCP25XXFD_CAN_VEC_ICODE_BITS 7
+# define MCP25XXFD_CAN_VEC_ICODE_SHIFT 0
+# define MCP25XXFD_CAN_VEC_ICODE_MASK \
+ GENMASK(MCP25XXFD_CAN_VEC_ICODE_SHIFT + \
+ MCP25XXFD_CAN_VEC_ICODE_BITS - 1, \
+ MCP25XXFD_CAN_VEC_ICODE_SHIFT)
+# define MCP25XXFD_CAN_VEC_FILHIT_BITS 5
+# define MCP25XXFD_CAN_VEC_FILHIT_SHIFT 8
+# define MCP25XXFD_CAN_VEC_FILHIT_MASK \
+ GENMASK(MCP25XXFD_CAN_VEC_FILHIT_SHIFT + \
+ MCP25XXFD_CAN_VEC_FILHIT_BITS - 1, \
+ MCP25XXFD_CAN_VEC_FILHIT_SHIFT)
+# define MCP25XXFD_CAN_VEC_TXCODE_BITS 7
+# define MCP25XXFD_CAN_VEC_TXCODE_SHIFT 16
+# define MCP25XXFD_CAN_VEC_TXCODE_MASK \
+ GENMASK(MCP25XXFD_CAN_VEC_TXCODE_SHIFT + \
+ MCP25XXFD_CAN_VEC_TXCODE_BITS - 1, \
+ MCP25XXFD_CAN_VEC_TXCODE_SHIFT)
+# define MCP25XXFD_CAN_VEC_RXCODE_BITS 7
+# define MCP25XXFD_CAN_VEC_RXCODE_SHIFT 24
+# define MCP25XXFD_CAN_VEC_RXCODE_MASK \
+ GENMASK(MCP25XXFD_CAN_VEC_RXCODE_SHIFT + \
+ MCP25XXFD_CAN_VEC_RXCODE_BITS - 1, \
+ MCP25XXFD_CAN_VEC_RXCODE_SHIFT)
+#define MCP25XXFD_CAN_INT MCP25XXFD_CAN_SFR_BASE(0x1C)
+# define MCP25XXFD_CAN_INT_IF_SHIFT 0
+# define MCP25XXFD_CAN_INT_TXIF BIT(0)
+# define MCP25XXFD_CAN_INT_RXIF BIT(1)
+# define MCP25XXFD_CAN_INT_TBCIF BIT(2)
+# define MCP25XXFD_CAN_INT_MODIF BIT(3)
+# define MCP25XXFD_CAN_INT_TEFIF BIT(4)
+# define MCP25XXFD_CAN_INT_ECCIF BIT(8)
+# define MCP25XXFD_CAN_INT_SPICRCIF BIT(9)
+# define MCP25XXFD_CAN_INT_TXATIF BIT(10)
+# define MCP25XXFD_CAN_INT_RXOVIF BIT(11)
+# define MCP25XXFD_CAN_INT_SERRIF BIT(12)
+# define MCP25XXFD_CAN_INT_CERRIF BIT(13)
+# define MCP25XXFD_CAN_INT_WAKIF BIT(14)
+# define MCP25XXFD_CAN_INT_IVMIF BIT(15)
+# define MCP25XXFD_CAN_INT_IF_MASK \
+ (MCP25XXFD_CAN_INT_TXIF | \
+ MCP25XXFD_CAN_INT_RXIF | \
+ MCP25XXFD_CAN_INT_TBCIF | \
+ MCP25XXFD_CAN_INT_MODIF | \
+ MCP25XXFD_CAN_INT_TEFIF | \
+ MCP25XXFD_CAN_INT_ECCIF | \
+ MCP25XXFD_CAN_INT_SPICRCIF | \
+ MCP25XXFD_CAN_INT_TXATIF | \
+ MCP25XXFD_CAN_INT_RXOVIF | \
+ MCP25XXFD_CAN_INT_CERRIF | \
+ MCP25XXFD_CAN_INT_SERRIF | \
+ MCP25XXFD_CAN_INT_WAKIF | \
+ MCP25XXFD_CAN_INT_IVMIF)
+# define MCP25XXFD_CAN_INT_IF_CLEAR_MASK \
+ (MCP25XXFD_CAN_INT_TBCIF | \
+ MCP25XXFD_CAN_INT_MODIF | \
+ MCP25XXFD_CAN_INT_CERRIF | \
+ MCP25XXFD_CAN_INT_SERRIF | \
+ MCP25XXFD_CAN_INT_WAKIF | \
+ MCP25XXFD_CAN_INT_IVMIF)
+# define MCP25XXFD_CAN_INT_IE_SHIFT 16
+# define MCP25XXFD_CAN_INT_TXIE \
+ (MCP25XXFD_CAN_INT_TXIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_RXIE \
+ (MCP25XXFD_CAN_INT_RXIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_TBCIE \
+ (MCP25XXFD_CAN_INT_TBCIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_MODIE \
+ (MCP25XXFD_CAN_INT_MODIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_TEFIE \
+ (MCP25XXFD_CAN_INT_TEFIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_ECCIE \
+ (MCP25XXFD_CAN_INT_ECCIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_SPICRCIE \
+ (MCP25XXFD_CAN_INT_SPICRCIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_TXATIE \
+ (MCP25XXFD_CAN_INT_TXATIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_RXOVIE \
+ (MCP25XXFD_CAN_INT_RXOVIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_CERRIE \
+ (MCP25XXFD_CAN_INT_CERRIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_SERRIE \
+ (MCP25XXFD_CAN_INT_SERRIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_WAKIE \
+ (MCP25XXFD_CAN_INT_WAKIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_IVMIE \
+ (MCP25XXFD_CAN_INT_IVMIF << MCP25XXFD_CAN_INT_IE_SHIFT)
+# define MCP25XXFD_CAN_INT_IE_MASK \
+ (MCP25XXFD_CAN_INT_TXIE | \
+ MCP25XXFD_CAN_INT_RXIE | \
+ MCP25XXFD_CAN_INT_TBCIE | \
+ MCP25XXFD_CAN_INT_MODIE | \
+ MCP25XXFD_CAN_INT_TEFIE | \
+ MCP25XXFD_CAN_INT_ECCIE | \
+ MCP25XXFD_CAN_INT_SPICRCIE | \
+ MCP25XXFD_CAN_INT_TXATIE | \
+ MCP25XXFD_CAN_INT_RXOVIE | \
+ MCP25XXFD_CAN_INT_CERRIE | \
+ MCP25XXFD_CAN_INT_SERRIE | \
+ MCP25XXFD_CAN_INT_WAKIE | \
+ MCP25XXFD_CAN_INT_IVMIE)
+#define MCP25XXFD_CAN_RXIF MCP25XXFD_CAN_SFR_BASE(0x20)
+#define MCP25XXFD_CAN_TXIF MCP25XXFD_CAN_SFR_BASE(0x24)
+#define MCP25XXFD_CAN_RXOVIF MCP25XXFD_CAN_SFR_BASE(0x28)
+#define MCP25XXFD_CAN_TXATIF MCP25XXFD_CAN_SFR_BASE(0x2C)
+#define MCP25XXFD_CAN_TXREQ MCP25XXFD_CAN_SFR_BASE(0x30)
+#define MCP25XXFD_CAN_TREC MCP25XXFD_CAN_SFR_BASE(0x34)
+# define MCP25XXFD_CAN_TREC_REC_BITS 8
+# define MCP25XXFD_CAN_TREC_REC_SHIFT 0
+# define MCP25XXFD_CAN_TREC_REC_MASK \
+ GENMASK(MCP25XXFD_CAN_TREC_REC_SHIFT + \
+ MCP25XXFD_CAN_TREC_REC_BITS - 1, \
+ MCP25XXFD_CAN_TREC_REC_SHIFT)
+# define MCP25XXFD_CAN_TREC_TEC_BITS 8
+# define MCP25XXFD_CAN_TREC_TEC_SHIFT 8
+# define MCP25XXFD_CAN_TREC_TEC_MASK \
+ GENMASK(MCP25XXFD_CAN_TREC_TEC_SHIFT + \
+ MCP25XXFD_CAN_TREC_TEC_BITS - 1, \
+ MCP25XXFD_CAN_TREC_TEC_SHIFT)
+# define MCP25XXFD_CAN_TREC_EWARN BIT(16)
+# define MCP25XXFD_CAN_TREC_RXWARN BIT(17)
+# define MCP25XXFD_CAN_TREC_TXWARN BIT(18)
+# define MCP25XXFD_CAN_TREC_RXBP BIT(19)
+# define MCP25XXFD_CAN_TREC_TXBP BIT(20)
+# define MCP25XXFD_CAN_TREC_TXBO BIT(21)
+#define MCP25XXFD_CAN_BDIAG0 MCP25XXFD_CAN_SFR_BASE(0x38)
+# define MCP25XXFD_CAN_BDIAG0_NRERRCNT_BITS 8
+# define MCP25XXFD_CAN_BDIAG0_NRERRCNT_SHIFT 0
+# define MCP25XXFD_CAN_BDIAG0_NRERRCNT_MASK \
+ GENMASK(MCP25XXFD_CAN_BDIAG0_NRERRCNT_SHIFT + \
+ MCP25XXFD_CAN_BDIAG0_NRERRCNT_BITS - 1, \
+ MCP25XXFD_CAN_BDIAG0_NRERRCNT_SHIFT)
+# define MCP25XXFD_CAN_BDIAG0_NTERRCNT_BITS 8
+# define MCP25XXFD_CAN_BDIAG0_NTERRCNT_SHIFT 8
+# define MCP25XXFD_CAN_BDIAG0_NTERRCNT_MASK \
+ GENMASK(MCP25XXFD_CAN_BDIAG0_NTERRCNT_SHIFT + \
+ MCP25XXFD_CAN_BDIAG0_NTERRCNT_BITS - 1, \
+ MCP25XXFD_CAN_BDIAG0_NTERRCNT_SHIFT)
+# define MCP25XXFD_CAN_BDIAG0_DRERRCNT_BITS 8
+# define MCP25XXFD_CAN_BDIAG0_DRERRCNT_SHIFT 16
+# define MCP25XXFD_CAN_BDIAG0_DRERRCNT_MASK \
+ GENMASK(MCP25XXFD_CAN_BDIAG0_DRERRCNT_SHIFT + \
+ MCP25XXFD_CAN_BDIAG0_DRERRCNT_BITS - 1, \
+ MCP25XXFD_CAN_BDIAG0_DRERRCNT_SHIFT)
+# define MCP25XXFD_CAN_BDIAG0_DTERRCNT_BITS 8
+# define MCP25XXFD_CAN_BDIAG0_DTERRCNT_SHIFT 24
+# define MCP25XXFD_CAN_BDIAG0_DTERRCNT_MASK \
+ GENMASK(MCP25XXFD_CAN_BDIAG0_DTERRCNT_SHIFT + \
+ MCP25XXFD_CAN_BDIAG0_DTERRCNT_BITS - 1, \
+ MCP25XXFD_CAN_BDIAG0_DTERRCNT_SHIFT)
+#define MCP25XXFD_CAN_BDIAG1 MCP25XXFD_CAN_SFR_BASE(0x3C)
+# define MCP25XXFD_CAN_BDIAG1_EFMSGCNT_BITS 16
+# define MCP25XXFD_CAN_BDIAG1_EFMSGCNT_SHIFT 0
+# define MCP25XXFD_CAN_BDIAG1_EFMSGCNT_MASK \
+ GENMASK(MCP25XXFD_CAN_BDIAG1_EFMSGCNT_SHIFT + \
+ MCP25XXFD_CAN_BDIAG1_EFMSGCNT_BITS - 1, \
+ MCP25XXFD_CAN_BDIAG1_EFMSGCNT_SHIFT)
+# define MCP25XXFD_CAN_BDIAG1_NBIT0ERR BIT(16)
+# define MCP25XXFD_CAN_BDIAG1_NBIT1ERR BIT(17)
+# define MCP25XXFD_CAN_BDIAG1_NACKERR BIT(18)
+# define MCP25XXFD_CAN_BDIAG1_NFORMERR BIT(19)
+# define MCP25XXFD_CAN_BDIAG1_NSTUFERR BIT(20)
+# define MCP25XXFD_CAN_BDIAG1_NCRCERR BIT(21)
+# define MCP25XXFD_CAN_BDIAG1_TXBOERR BIT(23)
+# define MCP25XXFD_CAN_BDIAG1_DBIT0ERR BIT(24)
+# define MCP25XXFD_CAN_BDIAG1_DBIT1ERR BIT(25)
+# define MCP25XXFD_CAN_BDIAG1_DFORMERR BIT(27)
+# define MCP25XXFD_CAN_BDIAG1_DSTUFERR BIT(28)
+# define MCP25XXFD_CAN_BDIAG1_DCRCERR BIT(29)
+# define MCP25XXFD_CAN_BDIAG1_ESI BIT(30)
+# define MCP25XXFD_CAN_BDIAG1_DLCMM BIT(31)
+#define MCP25XXFD_CAN_TEFCON MCP25XXFD_CAN_SFR_BASE(0x40)
+# define MCP25XXFD_CAN_TEFCON_TEFNEIE BIT(0)
+# define MCP25XXFD_CAN_TEFCON_TEFHIE BIT(1)
+# define MCP25XXFD_CAN_TEFCON_TEFFIE BIT(2)
+# define MCP25XXFD_CAN_TEFCON_TEFOVIE BIT(3)
+# define MCP25XXFD_CAN_TEFCON_TEFTSEN BIT(5)
+# define MCP25XXFD_CAN_TEFCON_UINC BIT(8)
+# define MCP25XXFD_CAN_TEFCON_FRESET BIT(10)
+# define MCP25XXFD_CAN_TEFCON_FSIZE_BITS 5
+# define MCP25XXFD_CAN_TEFCON_FSIZE_SHIFT 24
+# define MCP25XXFD_CAN_TEFCON_FSIZE_MASK \
+ GENMASK(MCP25XXFD_CAN_TEFCON_FSIZE_SHIFT + \
+ MCP25XXFD_CAN_TEFCON_FSIZE_BITS - 1, \
+ MCP25XXFD_CAN_TEFCON_FSIZE_SHIFT)
+#define MCP25XXFD_CAN_TEFSTA MCP25XXFD_CAN_SFR_BASE(0x44)
+# define MCP25XXFD_CAN_TEFSTA_TEFNEIF BIT(0)
+# define MCP25XXFD_CAN_TEFSTA_TEFHIF BIT(1)
+# define MCP25XXFD_CAN_TEFSTA_TEFFIF BIT(2)
+# define MCP25XXFD_CAN_TEFSTA_TEFOVIF BIT(3)
+#define MCP25XXFD_CAN_TEFUA MCP25XXFD_CAN_SFR_BASE(0x48)
+#define MCP25XXFD_CAN_RESERVED MCP25XXFD_CAN_SFR_BASE(0x4C)
+#define MCP25XXFD_CAN_TXQCON MCP25XXFD_CAN_SFR_BASE(0x50)
+# define MCP25XXFD_CAN_TXQCON_TXQNIE BIT(0)
+# define MCP25XXFD_CAN_TXQCON_TXQEIE BIT(2)
+# define MCP25XXFD_CAN_TXQCON_TXATIE BIT(4)
+# define MCP25XXFD_CAN_TXQCON_TXEN BIT(7)
+# define MCP25XXFD_CAN_TXQCON_UINC BIT(8)
+# define MCP25XXFD_CAN_TXQCON_TXREQ BIT(9)
+# define MCP25XXFD_CAN_TXQCON_FRESET BIT(10)
+# define MCP25XXFD_CAN_TXQCON_TXPRI_BITS 5
+# define MCP25XXFD_CAN_TXQCON_TXPRI_SHIFT 16
+# define MCP25XXFD_CAN_TXQCON_TXPRI_MASK \
+ GENMASK(MCP25XXFD_CAN_TXQCON_TXPRI_SHIFT + \
+ MCP25XXFD_CAN_TXQCON_TXPRI_BITS - 1, \
+ MCP25XXFD_CAN_TXQCON_TXPRI_SHIFT)
+# define MCP25XXFD_CAN_TXQCON_TXAT_BITS 2
+# define MCP25XXFD_CAN_TXQCON_TXAT_SHIFT 21
+# define MCP25XXFD_CAN_TXQCON_TXAT_MASK \
+ GENMASK(MCP25XXFD_CAN_TXQCON_TXAT_SHIFT + \
+ #MCP25XXFD_CAN_TXQCON_TXAT_BITS - 1, \
+ MCP25XXFD_CAN_TXQCON_TXAT_SHIFT)
+# define MCP25XXFD_CAN_TXQCON_FSIZE_BITS 5
+# define MCP25XXFD_CAN_TXQCON_FSIZE_SHIFT 24
+# define MCP25XXFD_CAN_TXQCON_FSIZE_MASK \
+ GENMASK(MCP25XXFD_CAN_TXQCON_FSIZE_SHIFT + \
+ MCP25XXFD_CAN_TXQCON_FSIZE_BITS - 1, \
+ MCP25XXFD_CAN_TXQCON_FSIZE_SHIFT)
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_BITS 3
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_SHIFT 29
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_MASK \
+ GENMASK(MCP25XXFD_CAN_TXQCON_PLSIZE_SHIFT + \
+ MCP25XXFD_CAN_TXQCON_PLSIZE_BITS - 1, \
+ MCP25XXFD_CAN_TXQCON_PLSIZE_SHIFT)
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_8 0
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_12 1
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_16 2
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_20 3
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_24 4
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_32 5
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_48 6
+# define MCP25XXFD_CAN_TXQCON_PLSIZE_64 7
+
+#define MCP25XXFD_CAN_TXQSTA MCP25XXFD_CAN_SFR_BASE(0x54)
+# define MCP25XXFD_CAN_TXQSTA_TXQNIF BIT(0)
+# define MCP25XXFD_CAN_TXQSTA_TXQEIF BIT(2)
+# define MCP25XXFD_CAN_TXQSTA_TXATIF BIT(4)
+# define MCP25XXFD_CAN_TXQSTA_TXERR BIT(5)
+# define MCP25XXFD_CAN_TXQSTA_TXLARB BIT(6)
+# define MCP25XXFD_CAN_TXQSTA_TXABT BIT(7)
+# define MCP25XXFD_CAN_TXQSTA_TXQCI_BITS 5
+# define MCP25XXFD_CAN_TXQSTA_TXQCI_SHIFT 8
+# define MCP25XXFD_CAN_TXQSTA_TXQCI_MASK \
+ GENMASK(MCP25XXFD_CAN_TXQSTA_TXQCI_SHIFT + \
+ MCP25XXFD_CAN_TXQSTA_TXQCI_BITS - 1, \
+ MCP25XXFD_CAN_TXQSTA_TXQCI_SHIFT)
+
+#define MCP25XXFD_CAN_TXQUA MCP25XXFD_CAN_SFR_BASE(0x58)
+#define MCP25XXFD_CAN_FIFOCON(x) \
+ MCP25XXFD_CAN_SFR_BASE(0x5C + 12 * ((x) - 1))
+#define MCP25XXFD_CAN_FIFOCON_TFNRFNIE BIT(0)
+#define MCP25XXFD_CAN_FIFOCON_TFHRFHIE BIT(1)
+#define MCP25XXFD_CAN_FIFOCON_TFERFFIE BIT(2)
+#define MCP25XXFD_CAN_FIFOCON_RXOVIE BIT(3)
+#define MCP25XXFD_CAN_FIFOCON_TXATIE BIT(4)
+#define MCP25XXFD_CAN_FIFOCON_RXTSEN BIT(5)
+#define MCP25XXFD_CAN_FIFOCON_RTREN BIT(6)
+#define MCP25XXFD_CAN_FIFOCON_TXEN BIT(7)
+#define MCP25XXFD_CAN_FIFOCON_UINC BIT(8)
+#define MCP25XXFD_CAN_FIFOCON_TXREQ BIT(9)
+#define MCP25XXFD_CAN_FIFOCON_FRESET BIT(10)
+# define MCP25XXFD_CAN_FIFOCON_TXPRI_BITS 5
+# define MCP25XXFD_CAN_FIFOCON_TXPRI_SHIFT 16
+# define MCP25XXFD_CAN_FIFOCON_TXPRI_MASK \
+ GENMASK(MCP25XXFD_CAN_FIFOCON_TXPRI_SHIFT + \
+ MCP25XXFD_CAN_FIFOCON_TXPRI_BITS - 1, \
+ MCP25XXFD_CAN_FIFOCON_TXPRI_SHIFT)
+# define MCP25XXFD_CAN_FIFOCON_TXAT_BITS 2
+# define MCP25XXFD_CAN_FIFOCON_TXAT_SHIFT 21
+# define MCP25XXFD_CAN_FIFOCON_TXAT_MASK \
+ GENMASK(MCP25XXFD_CAN_FIFOCON_TXAT_SHIFT + \
+ MCP25XXFD_CAN_FIFOCON_TXAT_BITS - 1, \
+ MCP25XXFD_CAN_FIFOCON_TXAT_SHIFT)
+# define MCP25XXFD_CAN_FIFOCON_TXAT_ONE_SHOT 0
+# define MCP25XXFD_CAN_FIFOCON_TXAT_THREE_SHOT 1
+# define MCP25XXFD_CAN_FIFOCON_TXAT_UNLIMITED 2
+# define MCP25XXFD_CAN_FIFOCON_FSIZE_BITS 5
+# define MCP25XXFD_CAN_FIFOCON_FSIZE_SHIFT 24
+# define MCP25XXFD_CAN_FIFOCON_FSIZE_MASK \
+ GENMASK(MCP25XXFD_CAN_FIFOCON_FSIZE_SHIFT + \
+ MCP25XXFD_CAN_FIFOCON_FSIZE_BITS - 1, \
+ MCP25XXFD_CAN_FIFOCON_FSIZE_SHIFT)
+# define MCP25XXFD_CAN_FIFOCON_PLSIZE_BITS 3
+# define MCP25XXFD_CAN_FIFOCON_PLSIZE_SHIFT 29
+# define MCP25XXFD_CAN_FIFOCON_PLSIZE_MASK \
+ GENMASK(MCP25XXFD_CAN_FIFOCON_PLSIZE_SHIFT + \
+ MCP25XXFD_CAN_FIFOCON_PLSIZE_BITS - 1, \
+ MCP25XXFD_CAN_FIFOCON_PLSIZE_SHIFT)
+#define MCP25XXFD_CAN_FIFOSTA(x) \
+ MCP25XXFD_CAN_SFR_BASE(0x60 + 12 * ((x) - 1))
+# define MCP25XXFD_CAN_FIFOSTA_TFNRFNIF BIT(0)
+# define MCP25XXFD_CAN_FIFOSTA_TFHRFHIF BIT(1)
+# define MCP25XXFD_CAN_FIFOSTA_TFERFFIF BIT(2)
+# define MCP25XXFD_CAN_FIFOSTA_RXOVIF BIT(3)
+# define MCP25XXFD_CAN_FIFOSTA_TXATIF BIT(4)
+# define MCP25XXFD_CAN_FIFOSTA_TXERR BIT(5)
+# define MCP25XXFD_CAN_FIFOSTA_TXLARB BIT(6)
+# define MCP25XXFD_CAN_FIFOSTA_TXABT BIT(7)
+# define MCP25XXFD_CAN_FIFOSTA_FIFOCI_BITS 5
+# define MCP25XXFD_CAN_FIFOSTA_FIFOCI_SHIFT 8
+# define MCP25XXFD_CAN_FIFOSTA_FIFOCI_MASK \
+ GENMASK(MCP25XXFD_CAN_FIFOSTA_FIFOCI_SHIFT + \
+ MCP25XXFD_CAN_FIFOSTA_FIFOCI_BITS - 1, \
+ MCP25XXFD_CAN_FIFOSTA_FIFOCI_SHIFT)
+#define MCP25XXFD_CAN_FIFOUA(x) \
+ MCP25XXFD_CAN_SFR_BASE(0x64 + 12 * ((x) - 1))
+#define MCP25XXFD_CAN_FLTCON(x) \
+ MCP25XXFD_CAN_SFR_BASE(0x1D0 + (x))
+# define MCP25XXFD_CAN_FLTCON_SHIFT(x) (((x) & 3) * 8)
+# define MCP25XXFD_CAN_FLTCON_BITS(x) MCP25XXFD_CAN_FLTCON_BITS_
+# define MCP25XXFD_CAN_FLTCON_BITS_ 5
+ /* avoid macro reuse warning, so do not use GENMASK as above */
+# define MCP25XXFD_CAN_FLTCON_MASK(x) \
+ (GENMASK(MCP25XXFD_CAN_FLTCON_BITS_ - 1, 0) << \
+ MCP25XXFD_CAN_FLTCON_SHIFT(x))
+# define MCP25XXFD_CAN_FLTCON_FLTEN(x) \
+ BIT(7 + MCP25XXFD_CAN_FLTCON_SHIFT(x))
+#define MCP25XXFD_CAN_FLTOBJ(x) \
+ MCP25XXFD_CAN_SFR_BASE(0x1F0 + 8 * (x))
+# define MCP25XXFD_CAN_FLTOBJ_SID_BITS 11
+# define MCP25XXFD_CAN_FLTOBJ_SID_SHIFT 0
+# define MCP25XXFD_CAN_FLTOBJ_SID_MASK \
+ GENMASK(MCP25XXFD_CAN_FLTOBJ_SID_SHIFT + \
+ MCP25XXFD_CAN_FLTOBJ_SID_BITS - 1, \
+ MCP25XXFD_CAN_FLTOBJ_SID_SHIFT)
+# define MCP25XXFD_CAN_FLTOBJ_EID_BITS 18
+# define MCP25XXFD_CAN_FLTOBJ_EID_SHIFT 11
+# define MCP25XXFD_CAN_FLTOBJ_EID_MASK \
+ GENMASK(MCP25XXFD_CAN_FLTOBJ_EID_SHIFT + \
+ MCP25XXFD_CAN_FLTOBJ_EID_BITS - 1, \
+ MCP25XXFD_CAN_FLTOBJ_EID_SHIFT)
+# define MCP25XXFD_CAN_FLTOBJ_SID11 BIT(29)
+# define MCP25XXFD_CAN_FLTOBJ_EXIDE BIT(30)
+#define MCP25XXFD_CAN_FLTMASK(x) \
+ MCP25XXFD_CAN_SFR_BASE(0x1F4 + 8 * (x))
+# define MCP25XXFD_CAN_MASK_MSID_BITS 11
+# define MCP25XXFD_CAN_MASK_MSID_SHIFT 0
+# define MCP25XXFD_CAN_MASK_MSID_MASK \
+ GENMASK(MCP25XXFD_CAN_MASK_MSID_SHIFT + \
+ MCP25XXFD_CAN_MASK_MSID_BITS - 1, \
+ MCP25XXFD_CAN_MASK_MSID_SHIFT)
+# define MCP25XXFD_CAN_MASK_MEID_BITS 18
+# define MCP25XXFD_CAN_MASK_MEID_SHIFT 11
+# define MCP25XXFD_CAN_MASK_MEID_MASK \
+ GENMASK(MCP25XXFD_CAN_MASK_MEID_SHIFT + \
+ MCP25XXFD_CAN_MASK_MEID_BITS - 1, \
+ MCP25XXFD_CAN_MASK_MEID_SHIFT)
+# define MCP25XXFD_CAN_MASK_MSID11 BIT(29)
+# define MCP25XXFD_CAN_MASK_MIDE BIT(30)
+
+/* the FIFO Objects in SRAM */
+#define MCP25XXFD_SRAM_SIZE 2048
+#define MCP25XXFD_SRAM_ADDR(x) (0x400 + (x))
+
+/* memory structure in sram for tx fifos */
+struct mcp25xxfd_can_obj_tx {
+ u32 id;
+ u32 flags;
+ u8 data[];
+};
+
+/* memory structure in sram for rx fifos */
+struct mcp25xxfd_can_obj_rx {
+ u32 id;
+ u32 flags;
+ u32 ts;
+ u8 data[];
+};
+
+/* memory structure in sram for tef fifos */
+struct mcp25xxfd_can_obj_tef {
+ u32 id;
+ u32 flags;
+ u32 ts;
+};
+
+#define MCP25XXFD_CAN_OBJ_ID_SID_BITS 11
+#define MCP25XXFD_CAN_OBJ_ID_SID_SHIFT 0
+#define MCP25XXFD_CAN_OBJ_ID_SID_MASK \
+ GENMASK(MCP25XXFD_CAN_OBJ_ID_SID_SHIFT + \
+ MCP25XXFD_CAN_OBJ_ID_SID_BITS - 1, \
+ MCP25XXFD_CAN_OBJ_ID_SID_SHIFT)
+#define MCP25XXFD_CAN_OBJ_ID_EID_BITS 18
+#define MCP25XXFD_CAN_OBJ_ID_EID_SHIFT 11
+#define MCP25XXFD_CAN_OBJ_ID_EID_MASK \
+ GENMASK(MCP25XXFD_CAN_OBJ_ID_EID_SHIFT + \
+ MCP25XXFD_CAN_OBJ_ID_EID_BITS - 1, \
+ MCP25XXFD_CAN_OBJ_ID_EID_SHIFT)
+#define MCP25XXFD_CAN_OBJ_ID_SID_BIT11 BIT(29)
+
+#define MCP25XXFD_CAN_OBJ_FLAGS_DLC_BITS 4
+#define MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT 0
+#define MCP25XXFD_CAN_OBJ_FLAGS_DLC_MASK \
+ GENMASK(MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT + \
+ MCP25XXFD_CAN_OBJ_FLAGS_DLC_BITS - 1, \
+ MCP25XXFD_CAN_OBJ_FLAGS_DLC_SHIFT)
+#define MCP25XXFD_CAN_OBJ_FLAGS_IDE BIT(4)
+#define MCP25XXFD_CAN_OBJ_FLAGS_RTR BIT(5)
+#define MCP25XXFD_CAN_OBJ_FLAGS_BRS BIT(6)
+#define MCP25XXFD_CAN_OBJ_FLAGS_FDF BIT(7)
+#define MCP25XXFD_CAN_OBJ_FLAGS_ESI BIT(8)
+#define MCP25XXFD_CAN_OBJ_FLAGS_SEQ_BITS 7
+#define MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT 9
+#define MCP25XXFD_CAN_OBJ_FLAGS_SEQ_MASK \
+ GENMASK(MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT + \
+ MCP25XXFD_CAN_OBJ_FLAGS_SEQ_BITS - 1, \
+ MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT)
+/* the mcp2518 has an extended number of SEQ bits */
+#define MCP25XXFD_CAN_OBJ_FLAGS_SEQX_BITS 23
+#define MCP25XXFD_CAN_OBJ_FLAGS_SEQX_MASK \
+ GENMASK(MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT + \
+ MCP25XXFD_CAN_OBJ_FLAGS_SEQX_BITS - 1, \
+ MCP25XXFD_CAN_OBJ_FLAGS_SEQ_SHIFT)
+#define MCP25XXFD_CAN_OBJ_FLAGS_FILHIT_BITS 5
+#define MCP25XXFD_CAN_OBJ_FLAGS_FILHIT_SHIFT 11
+#define MCP25XXFD_CAN_OBJ_FLAGS_FILHIT_MASK \
+ GENMASK(MCP25XXFD_CAN_FLAGS_FILHIT_SHIFT + \
+ MCP25XXFD_CAN_FLAGS_FILHIT_BITS - 1, \
+ MCP25XXFD_CAN_FLAGS_FILHIT_SHIFT)
+
+/* custom status error */
+#define MCP25XXFD_CAN_ERR_DATA7_MCP25XXFD_SERR_RX BIT(0)
+#define MCP25XXFD_CAN_ERR_DATA7_MCP25XXFD_SERR_TX BIT(1)
+#define MCP25XXFD_CAN_ERR_DATA7_MCP25XXFD_ECC BIT(2)
+
+#endif /* __MCP25XXFD_REGS_H */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 454c3a5d43bb..9020604a3d68 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -4062,6 +4062,8 @@ static int __maybe_unused fec_suspend(struct device *dev)
if (fep->wol_flag & FEC_WOL_FLAG_ENABLE)
fep->wol_flag |= FEC_WOL_FLAG_SLEEP_ON;
phy_stop(ndev->phydev);
+ if (fep->reg_phy)
+ disable_irq(ndev->phydev->irq);
napi_disable(&fep->napi);
netif_tx_lock_bh(ndev);
netif_device_detach(ndev);
@@ -4097,6 +4099,8 @@ static int __maybe_unused fec_suspend(struct device *dev)
if (fep->clk_enet_out || fep->reg_phy)
fep->link = 0;
+ pm_runtime_force_suspend(ndev->dev.parent);
+
return 0;
}
@@ -4107,6 +4111,8 @@ static int __maybe_unused fec_resume(struct device *dev)
int ret;
int val;
+ pm_runtime_force_resume(ndev->dev.parent);
+
if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) {
ret = regulator_enable(fep->reg_phy);
if (ret)
@@ -4133,6 +4139,8 @@ static int __maybe_unused fec_resume(struct device *dev)
fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
} else {
pinctrl_pm_select_default_state(&fep->pdev->dev);
+ if (fep->reg_phy)
+ enable_irq(ndev->phydev->irq);
}
fec_restart(ndev);
netif_tx_lock_bh(ndev);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 663c68ed6ef9..2ba914d9d68d 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -705,6 +705,70 @@ static int ksz9131_of_load_skew_values(struct phy_device *phydev,
return phy_write_mmd(phydev, 2, reg, newval);
}
+#define KSZ9131RN_MMD_COMMON_CTRL_REG 2
+#define KSZ9131RN_RXC_DLL_CTRL 76
+#define KSZ9131RN_TXC_DLL_CTRL 77
+#define KSZ9131RN_DLL_CTRL_BYPASS BIT_MASK(12)
+#define KSZ9131RN_DLL_ENABLE_DELAY 0
+#define KSZ9131RN_DLL_DISABLE_DELAY BIT(12)
+
+static int ksz9131_config_rgmii_delay(struct phy_device *phydev)
+{
+ u16 rxcdll_val, txcdll_val;
+ int new, ret;
+
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ break;
+ default:
+ return 0;
+ }
+
+ ret = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_RXC_DLL_CTRL);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~KSZ9131RN_DLL_CTRL_BYPASS) | rxcdll_val;
+
+ if (new != ret) {
+ ret = phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_RXC_DLL_CTRL, new);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_TXC_DLL_CTRL);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~KSZ9131RN_DLL_CTRL_BYPASS) | txcdll_val;
+
+ if (new != ret) {
+ ret = phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_TXC_DLL_CTRL, new);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int ksz9131_config_init(struct phy_device *phydev)
{
const struct device *dev = &phydev->mdio.dev;
@@ -731,6 +795,12 @@ static int ksz9131_config_init(struct phy_device *phydev)
if (!of_node)
return 0;
+ if (phy_interface_is_rgmii(phydev)) {
+ ret = ksz9131_config_rgmii_delay(phydev);
+ if (ret < 0)
+ return ret;
+ }
+
ret = ksz9131_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_CLK_PAD_SKEW, 5,
clk_skews, 2);
@@ -1040,8 +1110,6 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
}, {
.phy_id = PHY_ID_KSZ8041RNLI,
.phy_id_mask = MICREL_PHY_ID_MASK,
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 9e6dc289ec3e..4d9ac4ae29b1 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -2674,11 +2674,8 @@ mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct mwifiex_bg_scan_cfg *bgscan_cfg;
struct ieee_types_header *ie;
- if (!request || (!request->n_ssids && !request->n_match_sets)) {
- wiphy_err(wiphy, "%s : Invalid Sched_scan parameters",
- __func__);
+ if (!request || (!request->n_ssids && !request->n_match_sets))
return -EINVAL;
- }
wiphy_info(wiphy, "sched_scan start : n_ssids=%d n_match_sets=%d ",
request->n_ssids, request->n_match_sets);
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a296eaf52a5b..6000ddf99fa3 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -440,6 +440,7 @@ int of_irq_count(struct device_node *dev)
return nr;
}
+EXPORT_SYMBOL_GPL(of_irq_count);
/**
* of_irq_to_resource_table - Fill in resource table with node's IRQ info
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index c655d9de144e..f37b805fd730 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -100,9 +100,10 @@ struct imx6_pcie_drvdata {
struct imx6_pcie {
struct dw_pcie *pci;
- int clkreq_gpio;
- int dis_gpio;
- int reset_gpio;
+ struct gpio_desc *clkreq_gpiod;
+ struct gpio_desc *dis_gpiod;
+ struct gpio_desc *power_on_gpiod;
+ struct gpio_desc *reset_gpiod;
bool gpio_active_high;
struct clk *pcie_bus;
struct clk *pcie_phy;
@@ -111,6 +112,7 @@ struct imx6_pcie {
struct clk *pciex2_per;
struct clk *pcie_inbound_axi;
struct clk *pcie;
+ struct clk *pcie_ext;
struct clk *pcie_aux;
struct clk *phy_per;
struct clk *misc_per;
@@ -878,7 +880,7 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
PHY_PLL_LOCK_WAIT_TIMEOUT))
dev_err(dev, "PCIe PLL lock timeout\n");
}
-static void imx8_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
+static int imx8_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
{
u32 val, retries = 0, tmp = 0, orig = 0;
struct dw_pcie *pci = imx6_pcie->pci;
@@ -946,10 +948,13 @@ static void imx8_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
break;
}
- if (retries >= PHY_PLL_LOCK_WAIT_MAX_RETRIES)
+ if (retries >= PHY_PLL_LOCK_WAIT_MAX_RETRIES) {
dev_err(dev, "PCIe PLL lock timeout\n");
- else
- dev_info(dev, "PCIe PLL locked after %d us.\n", retries * 10);
+ return -ENODEV;
+ }
+
+ dev_info(dev, "PCIe PLL locked after %d us.\n", retries * 10);
+ return 0;
}
static void imx6_pcie_clk_enable(struct imx6_pcie *imx6_pcie)
@@ -1133,6 +1138,9 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
break;
}
+ if (imx6_pcie->dis_gpiod)
+ gpiod_set_value_cansleep(imx6_pcie->dis_gpiod, 1);
+
if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
int ret = regulator_disable(imx6_pcie->vpcie);
@@ -1142,7 +1150,7 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
}
}
-static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
+static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
{
struct dw_pcie *pci = imx6_pcie->pci;
struct device *dev = pci->dev;
@@ -1154,10 +1162,26 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
if (ret) {
dev_err(dev, "failed to enable vpcie regulator: %d\n",
ret);
- return;
+ return ret;
}
}
+ if (imx6_pcie->power_on_gpiod)
+ gpiod_set_value_cansleep(imx6_pcie->power_on_gpiod, 1);
+
+ if (imx6_pcie->clkreq_gpiod)
+ gpiod_set_value_cansleep(imx6_pcie->clkreq_gpiod, 1);
+
+ mdelay(2);
+ if (imx6_pcie->dis_gpiod)
+ gpiod_set_value_cansleep(imx6_pcie->dis_gpiod, 0);
+
+ ret = clk_prepare_enable(imx6_pcie->pcie_ext);
+ if (ret) {
+ dev_err(dev, "unable to enable pcie_ext clock\n");
+ return ret;
+ }
+
switch (imx6_pcie->drvdata->variant) {
case IMX8QXP:
case IMX8QM:
@@ -1170,12 +1194,13 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
}
/* Some boards don't have PCIe reset GPIO. */
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- gpio_set_value_cansleep(imx6_pcie->reset_gpio,
- imx6_pcie->gpio_active_high);
- msleep(100);
- gpio_set_value_cansleep(imx6_pcie->reset_gpio,
+ if (imx6_pcie->reset_gpiod) {
+ gpiod_set_value_cansleep(imx6_pcie->reset_gpiod,
!imx6_pcie->gpio_active_high);
+ msleep(100);
+ gpiod_set_value_cansleep(imx6_pcie->reset_gpiod,
+ imx6_pcie->gpio_active_high);
+ msleep(20);
}
switch (imx6_pcie->drvdata->variant) {
@@ -1206,13 +1231,15 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
dev_err(dev, "ERROR PM_REQ_CORE_RST is still set.\n");
/* wait for phy pll lock firstly. */
- imx8_pcie_wait_for_phy_pll_lock(imx6_pcie);
+ if(imx8_pcie_wait_for_phy_pll_lock(imx6_pcie) != 0)
+ goto err_pll;
break;
case IMX8MQ:
case IMX8MM:
reset_control_deassert(imx6_pcie->pciephy_reset);
- imx8_pcie_wait_for_phy_pll_lock(imx6_pcie);
+ if(imx8_pcie_wait_for_phy_pll_lock(imx6_pcie) != 0)
+ goto err_pll;
/*
* Set the over ride low and enabled
* make sure that REF_CLK is turned on.
@@ -1289,7 +1316,8 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
reset_control_deassert(imx6_pcie->pciephy_reset);
udelay(10);
- imx8_pcie_wait_for_phy_pll_lock(imx6_pcie);
+ if(imx8_pcie_wait_for_phy_pll_lock(imx6_pcie) != 0)
+ goto err_pll;
break;
case IMX7D:
reset_control_deassert(imx6_pcie->pciephy_reset);
@@ -1329,7 +1357,25 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
break;
}
- return;
+ return 0;
+
+err_pll:
+ if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie))
+ ret = regulator_disable(imx6_pcie->vpcie);
+
+ clk_disable_unprepare(imx6_pcie->pcie_ext);
+
+ switch (imx6_pcie->drvdata->variant) {
+ case IMX8QXP:
+ case IMX8QM:
+ case IMX8MP:
+ break;
+ default:
+ imx6_pcie_clk_disable(imx6_pcie);
+ break;
+ }
+
+ return -ENODEV;
}
static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
@@ -1837,8 +1883,6 @@ err_reset_phy:
imx6_pcie_clk_disable(imx6_pcie);
if (imx6_pcie->vpcie != NULL)
regulator_disable(imx6_pcie->vpcie);
- if (imx6_pcie->epdev_on != NULL)
- regulator_disable(imx6_pcie->epdev_on);
}
return ret;
@@ -1865,12 +1909,16 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
- if (gpio_is_valid(imx6_pcie->dis_gpio))
- gpio_set_value_cansleep(imx6_pcie->dis_gpio, 1);
+ if (imx6_pcie->power_on_gpiod)
+ gpiod_set_value_cansleep(imx6_pcie->power_on_gpiod, 1);
imx6_pcie_assert_core_reset(imx6_pcie);
imx6_pcie_init_phy(imx6_pcie);
- imx6_pcie_deassert_core_reset(imx6_pcie);
+ if(imx6_pcie_deassert_core_reset(imx6_pcie) == -ENODEV) {
+ if (imx6_pcie->power_on_gpiod)
+ gpiod_set_value_cansleep(imx6_pcie->power_on_gpiod, 0);
+ return -ENODEV;
+ }
imx6_setup_phy_mpll(imx6_pcie);
if (!(IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
&& (imx6_pcie->hard_wired == 0))) {
@@ -2351,7 +2399,8 @@ static int imx6_pcie_resume_noirq(struct device *dev)
} else {
imx6_pcie_assert_core_reset(imx6_pcie);
imx6_pcie_init_phy(imx6_pcie);
- imx6_pcie_deassert_core_reset(imx6_pcie);
+ if(imx6_pcie_deassert_core_reset(imx6_pcie) == -ENODEV)
+ return -ENODEV;
dw_pcie_setup_rc(pp);
pci_imx_set_msi_en(pp);
@@ -2413,28 +2462,31 @@ static int imx6_pcie_probe(struct platform_device *pdev)
}
}
- imx6_pcie->phy = devm_phy_get(dev, "pcie-phy");
- if (IS_ERR(imx6_pcie->phy)) {
- if (PTR_ERR(imx6_pcie->phy) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- dev_info(dev, "couldn't get pcie-phy\n");
- imx6_pcie->phy = NULL;
- }
+ /* pcie-phy uses in iMX8MP variant only */
+ if (imx6_pcie->drvdata->variant == IMX8MP) {
+ imx6_pcie->phy = devm_phy_get(dev, "pcie-phy");
+ if (IS_ERR(imx6_pcie->phy)) {
+ if (PTR_ERR(imx6_pcie->phy) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_info(dev, "couldn't get pcie-phy\n");
+ imx6_pcie->phy = NULL;
+ }
- /* Find the HSIO MIX if one is defined, only imx8mp uses it */
- np = of_parse_phandle(node, "fsl,imx8mp-hsio-mix", 0);
- if (np) {
- struct resource res;
+ /* Find the HSIO MIX if one is defined, only imx8mp uses it */
+ np = of_parse_phandle(node, "fsl,imx8mp-hsio-mix", 0);
+ if (np) {
+ struct resource res;
- ret = of_address_to_resource(np, 0, &res);
- if (ret) {
- dev_err(dev, "Unable to find HSIO MIX res\n");
- return ret;
- }
- imx6_pcie->hsmix_base = devm_ioremap_resource(dev, &res);
- if (IS_ERR(imx6_pcie->hsmix_base)) {
- dev_err(dev, "Unable to map HSIO MIX res\n");
- return PTR_ERR(imx6_pcie->hsmix_base);
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret) {
+ dev_err(dev, "Unable to find HSIO MIX res\n");
+ return ret;
+ }
+ imx6_pcie->hsmix_base = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(imx6_pcie->hsmix_base)) {
+ dev_err(dev, "Unable to map HSIO MIX res\n");
+ return PTR_ERR(imx6_pcie->hsmix_base);
+ }
}
}
@@ -2467,46 +2519,49 @@ static int imx6_pcie_probe(struct platform_device *pdev)
}
/* Fetch GPIOs */
- imx6_pcie->clkreq_gpio = of_get_named_gpio(node, "clkreq-gpio", 0);
- if (gpio_is_valid(imx6_pcie->clkreq_gpio)) {
- devm_gpio_request_one(&pdev->dev, imx6_pcie->clkreq_gpio,
- GPIOF_OUT_INIT_LOW, "PCIe CLKREQ");
- } else if (imx6_pcie->clkreq_gpio == -EPROBE_DEFER) {
- return imx6_pcie->clkreq_gpio;
+ imx6_pcie->clkreq_gpiod = devm_gpiod_get_optional(dev, "clkreq",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx6_pcie->clkreq_gpiod)) {
+ ret = PTR_ERR(imx6_pcie->clkreq_gpiod);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "unable to get clkreq gpio\n");
+ return ret;
}
- imx6_pcie->dis_gpio = of_get_named_gpio(node, "disable-gpio", 0);
- if (gpio_is_valid(imx6_pcie->dis_gpio)) {
- ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->dis_gpio,
- GPIOF_OUT_INIT_LOW, "PCIe DIS");
- if (ret) {
+ imx6_pcie->dis_gpiod = devm_gpiod_get_optional(dev, "disable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx6_pcie->dis_gpiod)) {
+ ret = PTR_ERR(imx6_pcie->dis_gpiod);
+ if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "unable to get disable gpio\n");
+ return ret;
+ }
+
+ imx6_pcie->power_on_gpiod = devm_gpiod_get_optional(dev, "power-on",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx6_pcie->power_on_gpiod)) {
+ ret = PTR_ERR(imx6_pcie->power_on_gpiod);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "unable to get power-on gpio\n");
return ret;
}
- } else if (imx6_pcie->dis_gpio == -EPROBE_DEFER) {
- return imx6_pcie->dis_gpio;
- }
imx6_pcie->epdev_on = devm_regulator_get(&pdev->dev,
"epdev_on");
if (IS_ERR(imx6_pcie->epdev_on))
return -EPROBE_DEFER;
- imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
imx6_pcie->gpio_active_high = of_property_read_bool(node,
"reset-gpio-active-high");
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio,
- imx6_pcie->gpio_active_high ?
- GPIOF_OUT_INIT_HIGH :
- GPIOF_OUT_INIT_LOW,
- "PCIe reset");
- if (ret) {
+ imx6_pcie->reset_gpiod = devm_gpiod_get_optional(dev, "reset",
+ imx6_pcie->gpio_active_high ?
+ GPIOD_OUT_LOW :
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(imx6_pcie->reset_gpiod)) {
+ ret = PTR_ERR(imx6_pcie->reset_gpiod);
+ if (ret != -EPROBE_DEFER)
dev_err(dev, "unable to get reset gpio\n");
- return ret;
- }
- } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
- return imx6_pcie->reset_gpio;
+ return ret;
}
/* Fetch clocks */
@@ -2528,6 +2583,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(imx6_pcie->pcie);
}
+ imx6_pcie->pcie_ext = devm_clk_get_optional(&pdev->dev, "pcie_ext");
+ if (IS_ERR(imx6_pcie->pcie_ext)) {
+ dev_err(&pdev->dev,
+ "pcie_ext clock source missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie_ext);
+ }
+
switch (imx6_pcie->drvdata->variant) {
case IMX6SX:
imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
@@ -2941,7 +3003,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)
} else {
dev_err(dev, "unable to add pcie port.\n");
}
- goto err_ret;
+ goto err_reg;
}
pci_imx_set_msi_en(&imx6_pcie->pci->pp);
@@ -2987,6 +3049,8 @@ static int imx6_pcie_probe(struct platform_device *pdev)
return 0;
+err_reg:
+ regulator_disable(imx6_pcie->epdev_on);
err_ret:
imx6_pcie_detach_pd(dev);
return ret;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 654f8a1e7d61..be8d987dd77d 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2505,6 +2505,21 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
quirk_unhide_mch_dev6);
+#ifdef CONFIG_PCI_FORCE_GEN1
+/*
+ * The Apalis evaluation board needs to set the link speed to 2.5 GT/s (GEN1).
+ * The default link speed setting is 5 GT/s (GEN2). 0x98 is the Link Control 2
+ * PCIe Capability Register of the PEX8605 PCIe switch. The switch supports
+ * link speed auto negotiation, but falsely sets the link speed to 5 GT/s.
+ */
+static void quirk_apalis_plx_gen1(struct pci_dev *dev)
+{
+ pci_write_config_dword(dev, 0x98, 0x1);
+ mdelay(50);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8605, quirk_apalis_plx_gen1);
+#endif /* CONFIG_PCI_FORCE_GEN1 */
+
#ifdef CONFIG_PCI_MSI
/*
* Some chipsets do not support MSI. We cannot easily rely on setting
@@ -3245,6 +3260,15 @@ static void fixup_ti816x_class(struct pci_dev *dev)
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
PCI_CLASS_NOT_DEFINED, 8, fixup_ti816x_class);
+/* TW6869 Frame grabber has same problem as ti816x */
+static void fixup_tw6869_class(struct pci_dev* dev)
+{
+ dev_info(&dev->dev, "Setting PCI class for tw6869 PCIe device\n");
+ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869,
+ PCI_CLASS_NOT_DEFINED, 0, fixup_tw6869_class);
+
/*
* Some PCIe devices do not work reliably with the claimed maximum
* payload size supported.
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index 6a4bbb506551..2725d30aa9c7 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -24,6 +24,7 @@ static struct gpio_desc *reset_gpio;
static u32 timeout = DEFAULT_TIMEOUT_MS;
static u32 active_delay = 100;
static u32 inactive_delay = 100;
+static void *prev_pm_power_off = NULL;
static void gpio_poweroff_do_poweroff(void)
{
@@ -49,14 +50,28 @@ static void gpio_poweroff_do_poweroff(void)
static int gpio_poweroff_probe(struct platform_device *pdev)
{
bool input = false;
+ bool force = false;
enum gpiod_flags flags;
- /* If a pm_power_off function has already been added, leave it alone */
+
+ force = of_property_read_bool(pdev->dev.of_node, "force-mode");
+
+ /*
+ * If a pm_power_off function has already been added, leave it alone,
+ * if force-mode is not enabled.
+ */
if (pm_power_off != NULL) {
- dev_err(&pdev->dev,
- "%s: pm_power_off function already registered",
- __func__);
- return -EBUSY;
+ if (force) {
+ dev_warn(&pdev->dev,
+ "%s: pm_power_off function replaced",
+ __func__);
+ prev_pm_power_off = pm_power_off;
+ } else {
+ dev_err(&pdev->dev,
+ "%s: pm_power_off function already registered",
+ __func__);
+ return -EBUSY;
+ }
}
input = device_property_read_bool(&pdev->dev, "input");
@@ -81,7 +96,7 @@ static int gpio_poweroff_probe(struct platform_device *pdev)
static int gpio_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == &gpio_poweroff_do_poweroff)
- pm_power_off = NULL;
+ pm_power_off = prev_pm_power_off;
return 0;
}
diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c
index bdab46a5c461..ef54edf00337 100644
--- a/drivers/regulator/bd718x7-regulator.c
+++ b/drivers/regulator/bd718x7-regulator.c
@@ -646,6 +646,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.linear_range_selectors = bd718xx_ldo1_volt_range_sel,
.enable_reg = BD718XX_REG_LDO1_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -668,6 +669,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.n_voltages = ARRAY_SIZE(ldo_2_volts),
.enable_reg = BD718XX_REG_LDO2_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -691,6 +693,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.vsel_mask = BD718XX_LDO3_MASK,
.enable_reg = BD718XX_REG_LDO3_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -714,6 +717,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.vsel_mask = BD718XX_LDO4_MASK,
.enable_reg = BD718XX_REG_LDO4_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -740,6 +744,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.linear_range_selectors = bd71847_ldo5_volt_range_sel,
.enable_reg = BD718XX_REG_LDO5_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -765,6 +770,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.vsel_mask = BD718XX_LDO6_MASK,
.enable_reg = BD718XX_REG_LDO6_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -987,6 +993,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.linear_range_selectors = bd718xx_ldo1_volt_range_sel,
.enable_reg = BD718XX_REG_LDO1_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -1009,6 +1016,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.n_voltages = ARRAY_SIZE(ldo_2_volts),
.enable_reg = BD718XX_REG_LDO2_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -1032,6 +1040,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.vsel_mask = BD718XX_LDO3_MASK,
.enable_reg = BD718XX_REG_LDO3_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -1055,6 +1064,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.vsel_mask = BD718XX_LDO4_MASK,
.enable_reg = BD718XX_REG_LDO4_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -1080,6 +1090,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.vsel_mask = BD71837_LDO5_MASK,
.enable_reg = BD718XX_REG_LDO5_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -1107,6 +1118,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.vsel_mask = BD718XX_LDO6_MASK,
.enable_reg = BD718XX_REG_LDO6_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
@@ -1132,6 +1144,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.vsel_mask = BD71837_LDO7_MASK,
.enable_reg = BD71837_REG_LDO7_VOLT,
.enable_mask = BD718XX_LDO_EN,
+ .enable_time = 1000,
.owner = THIS_MODULE,
},
.init = {
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index 6b9ce8f34e0e..442faa078e3a 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -594,6 +594,12 @@ static int pca9450_buck123_dvs_init(struct pca9450_pmic *pmic)
}
}
}
+ /* clear the preset enable bit as we use PCA9450_BUCKxOUT_DVSy regs */
+ ret = pca9450_clear_bits(pca9450, PCA9450_BUCK123_DVS, \
+ BUCK123_PRESET_EN);
+ if (ret < 0)
+ return ret;
+
return 0;
}
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index 0398b57692e9..566366186a99 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -960,6 +960,91 @@ err_ret:
}
#endif
+static void pfuze100_regulator_shutdown(struct i2c_client *client)
+{
+ struct pfuze_chip *pfuze_chip;
+ int ret;
+
+ if (!of_machine_is_compatible("toradex,colibri_imx6dl") &&
+ !of_machine_is_compatible("toradex,apalis_imx6q"))
+ return;
+
+ /* Configure all regulators to off on PMIC standby. For Colibri iMX6
+ * we use the PMIC_STBY_REQ after shutdown, as the PMIC_ON_REQ signal
+ * together with VCC_BATT supplied from a battery leads to a
+ * nonbooting system.
+ * After the system has been shutdown with PMIC_ON_REQ it will never
+ * restart either by RESET or power cycle.
+ */
+ pfuze_chip = i2c_get_clientdata(client);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_SW1ABVOL + PFUZE100_MODE_OFFSET,
+ 0x0f, 4);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_SW1CVOL + PFUZE100_MODE_OFFSET,
+ 0x0f, 4);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_SW3AVOL + PFUZE100_MODE_OFFSET,
+ 0x0f, 4);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_SW3BVOL + PFUZE100_MODE_OFFSET,
+ 0x0f, 4);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_SWBSTCON1,
+ 0x60, 0);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_VGEN1VOL,
+ 0x20, 0x20);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_VGEN2VOL,
+ 0x20, 0x20);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_VGEN3VOL,
+ 0x20, 0x20);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_VGEN4VOL,
+ 0x20, 0x20);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_VGEN5VOL,
+ 0x20, 0x20);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret);
+
+ ret = regmap_update_bits(pfuze_chip->regmap,
+ PFUZE100_VGEN6VOL,
+ 0x20, 0x20);
+ if (ret < 0)
+ dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret);
+}
+
static const struct dev_pm_ops pfuze_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pfuze_suspend, pfuze_resume)
};
@@ -973,6 +1058,7 @@ static struct i2c_driver pfuze_driver = {
},
.probe = pfuze100_regulator_probe,
.remove = pfuze100_regulator_remove,
+ .shutdown = pfuze100_regulator_shutdown,
};
module_i2c_driver(pfuze_driver);
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 5cd69052e79e..451a7e82f916 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -55,6 +55,14 @@ config RPMSG_VIRTIO
select RPMSG
select VIRTIO
+config RPMSG_VIRTIO_CHAR
+ bool "Enable Virtio RPMSG char device driver support"
+ default y
+ depends on RPMSG_VIRTIO
+ depends on RPMSG_CHAR
+ help
+ Say y here to enable to use RPMSG char device interface.
+
config HAVE_IMX_RPMSG
bool "IMX RPMSG driver on the AMP SOCs"
default y
diff --git a/drivers/rpmsg/imx_rpmsg_tty.c b/drivers/rpmsg/imx_rpmsg_tty.c
index 008c998b610e..96d39616f34f 100644
--- a/drivers/rpmsg/imx_rpmsg_tty.c
+++ b/drivers/rpmsg/imx_rpmsg_tty.c
@@ -30,9 +30,16 @@ struct rpmsgtty_port {
static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len,
void *priv, u32 src)
{
- int space;
- unsigned char *cbuf;
+ int copied;
struct rpmsgtty_port *cport = dev_get_drvdata(&rpdev->dev);
+ struct tty_struct *tty = dev_get_drvdata(&rpdev->dev);
+
+ /* no one left to give data to, so sleep */
+ if (tty == NULL) {
+ dev_dbg(&rpdev->dev, "waiting for readers, discard len %d\n",
+ len);
+ return -ENOTTY;
+ }
/* flush the recv-ed none-zero data to tty node */
if (len == 0)
@@ -40,18 +47,14 @@ static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len,
dev_dbg(&rpdev->dev, "msg(<- src 0x%x) len %d\n", src, len);
- print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1,
- data, len, true);
+ print_hex_dump_debug(__func__, DUMP_PREFIX_NONE, 16, 1,
+ data, len, true);
spin_lock_bh(&cport->rx_lock);
- space = tty_prepare_flip_string(&cport->port, &cbuf, len);
- if (space <= 0) {
- dev_err(&rpdev->dev, "No memory for tty_prepare_flip_string\n");
- spin_unlock_bh(&cport->rx_lock);
- return -ENOMEM;
- }
+ copied = tty_insert_flip_string(&cport->port, data, len);
+ if (copied != len)
+ dev_err_ratelimited(&rpdev->dev, "RX copy to tty layer failed\n");
- memcpy(cbuf, data, len);
tty_flip_buffer_push(&cport->port);
spin_unlock_bh(&cport->rx_lock);
@@ -153,6 +156,9 @@ static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
rpmsgtty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
rpmsgtty_driver->init_termios = tty_std_termios;
+ /* set default to no chracter echoing of the tty driver */
+ rpmsgtty_driver->init_termios.c_lflag = rpmsgtty_driver->init_termios.c_lflag & ~ECHO;
+
tty_set_operations(rpmsgtty_driver, &imxrpmsgtty_ops);
tty_port_init(&cport->port);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 376ebbf880d6..2c4c51ec04fe 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -67,6 +67,9 @@ struct virtproc_info {
wait_queue_head_t sendq;
atomic_t sleepers;
struct rpmsg_endpoint *ns_ept;
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct list_head rsvcs;
+#endif
};
/* The feature bitmap for virtio rpmsg */
@@ -133,6 +136,35 @@ struct virtio_rpmsg_channel {
#define to_virtio_rpmsg_channel(_rpdev) \
container_of(_rpdev, struct virtio_rpmsg_channel, rpdev)
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+/**
+ * struct virtio_rpmsg_rsvc - virtio RPMsg remote service
+ * @name: name of the RPMsg remote service
+ * @addr: RPMsg address of the remote service
+ * @ept: local endpoint bound to the remote service
+ * @node: list node
+ */
+struct virtio_rpmsg_rsvc {
+ char name[RPMSG_NAME_SIZE];
+ u32 addr;
+ struct rpmsg_endpoint *ept;
+ struct list_head node;
+};
+
+/**
+ * struct virtio_rpmsg_ept - virtio RPMsg endpoint
+ * @rsvc: RPMsg service
+ * @ept: RPMsg endpoint
+ *
+ */
+struct virtio_rpmsg_ept {
+ struct virtio_rpmsg_rsvc *rsvc;
+ struct rpmsg_endpoint ept;
+};
+
+#define to_virtio_rpmsg_ept(_ept) \
+ container_of(_ept, struct virtio_rpmsg_ept, ept)
+#endif
/*
* We're allocating buffers of 512 bytes each for communications. The
* number of buffers will be computed from the number of buffers supported
@@ -208,6 +240,199 @@ rpmsg_sg_init(struct scatterlist *sg, void *cpu_addr, unsigned int len)
}
}
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+/**
+ * virtio_rpmsg_find_rsvc_by_name - find the announced remote service
+ * @vrp: virtio remote proc information
+ * @name: remote service name
+ *
+ * The caller is supposed to have mutex lock before calling this function
+ *
+ * return NULL if no remote service has been found, otherwise, return
+ * the remote service pointer.
+ */
+static struct virtio_rpmsg_rsvc *
+virtio_rpmsg_find_rsvc_by_name(struct virtproc_info *vrp, char *name)
+{
+ struct virtio_rpmsg_rsvc *rsvc;
+
+ list_for_each_entry(rsvc, &vrp->rsvcs, node) {
+ if (!strncmp(rsvc->name, name, RPMSG_NAME_SIZE))
+ /* remote service has found */
+ return rsvc;
+ }
+
+ return NULL;
+}
+
+/**
+ * virtio_rpmsg_create_rsvc_by_name - create remote service
+ * @vrp: virtio remote proc information
+ * @name: remote service name
+ *
+ * The caller is supposed to have mutex lock before calling this function
+ *
+ * return NULL if remote service creation failed. otherwise, return
+ * the remote service pointer.
+ */
+static struct virtio_rpmsg_rsvc *
+virtio_rpmsg_create_rsvc_by_name(struct virtproc_info *vrp, char *name)
+{
+ struct virtio_rpmsg_rsvc *rsvc;
+
+ rsvc = virtio_rpmsg_find_rsvc_by_name(vrp, name);
+ if (rsvc)
+ return rsvc;
+ rsvc = kzalloc(sizeof(*rsvc), GFP_KERNEL);
+ if (!rsvc)
+ return NULL;
+ strncpy(rsvc->name, name, RPMSG_NAME_SIZE);
+ list_add_tail(&rsvc->node, &vrp->rsvcs);
+ return rsvc;
+}
+
+/**
+ * virtio_rpmsg_remove_rsvc_by_name - remove remote service
+ * @vrp: virtio remote proc information
+ * @name: remote service name
+ *
+ */
+static void
+virtio_rpmsg_remove_rsvc_by_name(struct virtproc_info *vrp, char *name)
+{
+ struct virtio_rpmsg_rsvc *rsvc;
+ struct rpmsg_endpoint *ept;
+ struct virtio_rpmsg_ept *vept;
+
+ mutex_lock(&vrp->endpoints_lock);
+ list_for_each_entry(rsvc, &vrp->rsvcs, node) {
+ if (!strncmp(rsvc->name, name, RPMSG_NAME_SIZE)) {
+ /* remote service has found, no need to
+ * create
+ */
+ ept = rsvc->ept;
+ if (ept) {
+ vept = to_virtio_rpmsg_ept(ept);
+ vept->rsvc = NULL;
+ }
+ list_del(&rsvc->node);
+ kfree(rsvc);
+ break;
+ }
+ }
+ mutex_unlock(&vrp->endpoints_lock);
+}
+
+/**
+ * virtio_rpmsg_create_rsvc - create remote service with channel information
+ * @vrp: virtio remote proc information
+ * @chinfo: channel information
+ *
+ * return remote service pointer if it is successfully created; otherwise,
+ * return NULL.
+ */
+static struct virtio_rpmsg_rsvc *
+virtio_rpmsg_create_rsvc(struct virtproc_info *vrp,
+ struct rpmsg_channel_info *chinfo)
+{
+ struct virtio_rpmsg_rsvc *rsvc;
+
+ mutex_lock(&vrp->endpoints_lock);
+ rsvc = virtio_rpmsg_create_rsvc_by_name(vrp, chinfo->name);
+ if (rsvc) {
+ struct virtio_device *vdev = vrp->vdev;
+
+ rsvc->addr = chinfo->dst;
+ dev_info(&vdev->dev, "Remote has announced service %s, %d.\n",
+ chinfo->name, rsvc->addr);
+ }
+ mutex_unlock(&vrp->endpoints_lock);
+ return rsvc;
+}
+
+/**
+ * virtio_rpmsg_announce_ept_create - announce endpoint has been created
+ * @ept: RPMsg endpoint
+ *
+ * return 0 if succeeded, otherwise, return error code.
+ */
+static int virtio_rpmsg_announce_ept_create(struct rpmsg_endpoint *ept)
+{
+ struct virtio_rpmsg_ept *vept = to_virtio_rpmsg_ept(ept);
+ struct virtio_rpmsg_rsvc *rsvc = vept->rsvc;
+ struct rpmsg_device *rpdev = ept->rpdev;
+ struct virtio_rpmsg_channel *vch;
+ struct virtproc_info *vrp;
+ struct device *dev;
+ int err = 0;
+
+ if (!rpdev)
+ /* If the endpoint is not connected to a RPMsg device,
+ * no need to send the announcement.
+ */
+ return 0;
+ vch = to_virtio_rpmsg_channel(rpdev);
+ vrp = vch->vrp;
+ dev = &ept->rpdev->dev;
+ /* need to tell remote processor's name service about this channel ? */
+ if (virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
+ struct rpmsg_ns_msg nsm;
+
+ strncpy(nsm.name, rsvc->name, RPMSG_NAME_SIZE);
+ nsm.addr = ept->addr;
+ nsm.flags = RPMSG_NS_CREATE;
+
+ err = rpmsg_sendto(ept, &nsm, sizeof(nsm),
+ RPMSG_NS_ADDR);
+ if (err)
+ dev_err(dev, "failed to announce service %d\n", err);
+ }
+
+ return err;
+}
+
+/**
+ * virtio_rpmsg_announce_ept_destroy - announce endpoint has been destroyed
+ * @ept: RPMsg endpoint
+ *
+ * return 0 if succeeded, otherwise, return error code.
+ */
+static int virtio_rpmsg_announce_ept_destroy(struct rpmsg_endpoint *ept)
+{
+ struct virtio_rpmsg_ept *vept = to_virtio_rpmsg_ept(ept);
+ struct virtio_rpmsg_rsvc *rsvc = vept->rsvc;
+ struct rpmsg_device *rpdev = ept->rpdev;
+ struct virtio_rpmsg_channel *vch;
+ struct virtproc_info *vrp;
+ struct device *dev;
+ int err = 0;
+
+ if (!rpdev)
+ /* If the endpoint is not connected to a RPMsg device,
+ * no need to send the announcement.
+ */
+ return 0;
+ vch = to_virtio_rpmsg_channel(rpdev);
+ vrp = vch->vrp;
+ dev = &ept->rpdev->dev;
+ /* tell remote processor's name service we're removing this channel */
+ if (virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
+ struct rpmsg_ns_msg nsm;
+
+ strncpy(nsm.name, rsvc->name, RPMSG_NAME_SIZE);
+ nsm.addr = ept->addr;
+ nsm.flags = RPMSG_NS_DESTROY;
+
+ err = rpmsg_sendto(ept, &nsm, sizeof(nsm),
+ RPMSG_NS_ADDR);
+ if (err)
+ dev_err(dev, "failed to announce service %d\n", err);
+ }
+
+ return err;
+}
+#endif
+
/**
* __ept_release() - deallocate an rpmsg endpoint
* @kref: the ept's reference count
@@ -221,27 +446,53 @@ static void __ept_release(struct kref *kref)
{
struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint,
refcount);
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct virtio_rpmsg_ept *vept = to_virtio_rpmsg_ept(ept);
+ struct virtio_rpmsg_channel *vch;
+ struct virtproc_info *vrp;
+
+ if (ept->rpdev) {
+ vch = to_virtio_rpmsg_channel(ept->rpdev);
+ vrp = vch->vrp;
+ (void)virtio_rpmsg_announce_ept_destroy(ept);
+ mutex_lock(&vrp->endpoints_lock);
+ vept->rsvc->ept = NULL;
+ mutex_unlock(&vrp->endpoints_lock);
+ }
+ kfree(vept);
+#else
/*
* At this point no one holds a reference to ept anymore,
* so we can directly free it
*/
kfree(ept);
+#endif
}
/* for more info, see below documentation of rpmsg_create_ept() */
static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
struct rpmsg_device *rpdev,
rpmsg_rx_cb_t cb,
- void *priv, u32 addr)
+ void *priv,
+ struct rpmsg_channel_info *ch)
{
int id_min, id_max, id;
struct rpmsg_endpoint *ept;
+ u32 addr = ch->src;
struct device *dev = rpdev ? &rpdev->dev : &vrp->vdev->dev;
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct virtio_rpmsg_ept *vept;
+ struct virtio_rpmsg_rsvc *rsvc;
+ vept = kzalloc(sizeof(*vept), GFP_KERNEL);
+ if (!vept)
+ return NULL;
+ ept = &vept->ept;
+#else
ept = kzalloc(sizeof(*ept), GFP_KERNEL);
if (!ept)
return NULL;
-
+#endif
kref_init(&ept->refcount);
mutex_init(&ept->cb_lock);
@@ -251,7 +502,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
ept->ops = &virtio_endpoint_ops;
/* do we need to allocate a local address ? */
- if (addr == RPMSG_ADDR_ANY) {
+ if (ch->src == RPMSG_ADDR_ANY) {
id_min = RPMSG_RESERVED_ADDRESSES;
id_max = 0;
} else {
@@ -268,7 +519,18 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
goto free_ept;
}
ept->addr = id;
-
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ if (ept->addr != RPMSG_NS_ADDR) {
+ rsvc = virtio_rpmsg_create_rsvc_by_name(vrp, ch->name);
+ if (!rsvc)
+ goto free_ept;
+ vept->rsvc = rsvc;
+ rsvc->ept = ept;
+ dev_info(&vrp->vdev->dev, "RPMsg ept created, %s:%d,%d.\n",
+ ch->name, ept->addr, rsvc->addr);
+ (void)virtio_rpmsg_announce_ept_create(ept);
+ }
+#endif
mutex_unlock(&vrp->endpoints_lock);
return ept;
@@ -285,8 +547,7 @@ static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev
struct rpmsg_channel_info chinfo)
{
struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
-
- return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, chinfo.src);
+ return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, &chinfo);
}
/**
@@ -384,6 +645,7 @@ static void virtio_rpmsg_release_device(struct device *dev)
kfree(vch);
}
+#ifndef CONFIG_RPMSG_VIRTIO_CHAR
/*
* create an rpmsg channel using its name and address info.
* this function will be used to create both static and dynamic
@@ -436,6 +698,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
return rpdev;
}
+#endif
/* super simple buffer "allocator" that is just enough for now */
static void *get_a_tx_buf(struct virtproc_info *vrp)
@@ -677,7 +940,16 @@ static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
{
struct rpmsg_device *rpdev = ept->rpdev;
- u32 src = ept->addr, dst = rpdev->dst;
+ u32 src = ept->addr;
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct virtio_rpmsg_ept *vept = to_virtio_rpmsg_ept(ept);
+ u32 dst = vept->rsvc->addr;
+
+ if (dst == RPMSG_ADDR_ANY)
+ return -EPIPE;
+#else
+ u32 dst = rpdev->dst;
+#endif
return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
}
@@ -816,12 +1088,13 @@ static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
void *priv, u32 src)
{
struct rpmsg_ns_msg *msg = data;
- struct rpmsg_device *newch;
struct rpmsg_channel_info chinfo;
struct virtproc_info *vrp = priv;
struct device *dev = &vrp->vdev->dev;
+#ifndef CONFIG_RPMSG_VIRTIO_CHAR
+ struct rpmsg_device *newch;
int ret;
-
+#endif
#if defined(CONFIG_DYNAMIC_DEBUG)
dynamic_hex_dump("NS announcement: ", DUMP_PREFIX_NONE, 16, 1,
data, len, true);
@@ -855,13 +1128,25 @@ static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
chinfo.dst = msg->addr;
if (msg->flags & RPMSG_NS_DESTROY) {
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ virtio_rpmsg_remove_rsvc_by_name(vrp, chinfo.name);
+#else
ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
if (ret)
dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
+#endif
} else {
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct virtio_rpmsg_rsvc *rsvc;
+
+ rsvc = virtio_rpmsg_create_rsvc(vrp, &chinfo);
+ if (!rsvc)
+ dev_err(dev, "virtio_rpmsg_create_rsvc failed\n");
+#else
newch = rpmsg_create_channel(vrp, &chinfo);
if (!newch)
dev_err(dev, "rpmsg_create_channel failed\n");
+#endif
}
return 0;
@@ -877,6 +1162,10 @@ static int rpmsg_probe(struct virtio_device *vdev)
int err = 0, i;
size_t total_buf_space;
bool notify;
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct virtio_rpmsg_channel *vch;
+ struct rpmsg_device *rp_char_dev;
+#endif
vrp = kzalloc(sizeof(*vrp), GFP_KERNEL);
if (!vrp)
@@ -948,16 +1237,45 @@ static int rpmsg_probe(struct virtio_device *vdev)
/* if supported by the remote processor, enable the name service */
if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) {
+ struct rpmsg_channel_info ns_chinfo;
+
+ ns_chinfo.src = RPMSG_NS_ADDR;
+ ns_chinfo.dst = RPMSG_NS_ADDR;
+ strcpy(ns_chinfo.name, "name_service");
/* a dedicated endpoint handles the name service msgs */
vrp->ns_ept = __rpmsg_create_ept(vrp, NULL, rpmsg_ns_cb,
- vrp, RPMSG_NS_ADDR);
+ vrp, &ns_chinfo);
if (!vrp->ns_ept) {
dev_err(&vdev->dev, "failed to create the ns ept\n");
err = -ENOMEM;
goto free_coherent;
}
}
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+ if (!vch) {
+ err = -ENOMEM;
+ goto free_coherent;
+ }
+
+ /* Link the channel to our vrp */
+ vch->vrp = vrp;
+ /* Initialize remote services list */
+ INIT_LIST_HEAD(&vrp->rsvcs);
+
+ /* Assign public information to the rpmsg_device */
+ rp_char_dev = &vch->rpdev;
+ rp_char_dev->ops = &virtio_rpmsg_ops;
+ rp_char_dev->dev.parent = &vrp->vdev->dev;
+ rp_char_dev->dev.release = virtio_rpmsg_release_device;
+ err = rpmsg_chrdev_register_device(rp_char_dev);
+ if (err) {
+ kfree(vch);
+ goto free_coherent;
+ }
+ dev_info(&vdev->dev, "Registered as RPMsg char device.\n");
+#endif
/*
* Prepare to kick but don't notify yet - we can't do this before
* device is ready.
@@ -1001,6 +1319,9 @@ static void rpmsg_remove(struct virtio_device *vdev)
struct virtproc_info *vrp = vdev->priv;
size_t total_buf_space = vrp->num_bufs * vrp->buf_size;
int ret;
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ struct virtio_rpmsg_rsvc *rsvc, *tmp;
+#endif
vdev->config->reset(vdev);
@@ -1013,6 +1334,12 @@ static void rpmsg_remove(struct virtio_device *vdev)
idr_destroy(&vrp->endpoints);
+#ifdef CONFIG_RPMSG_VIRTIO_CHAR
+ list_for_each_entry_safe(rsvc, tmp, &vrp->rsvcs, node) {
+ list_del(&rsvc->node);
+ kfree(rsvc);
+ }
+#endif
vdev->config->del_vqs(vrp->vdev);
dma_free_coherent(vdev->dev.parent, total_buf_space,
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 1f7e8aefc1eb..69994ae577b7 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -121,6 +121,9 @@ enum ds_type {
#define RX8130_REG_FLAG_AF BIT(3)
#define RX8130_REG_CONTROL0 0x1e
#define RX8130_REG_CONTROL0_AIE BIT(3)
+#define RX8130_REG_CONTROL1 0x1f
+#define RX8130_REG_CONTROL1_INIEN BIT(4)
+#define RX8130_REG_CONTROL1_CHGEN BIT(5)
#define MCP794XX_REG_CONTROL 0x07
# define MCP794XX_BIT_ALM0_EN 0x10
@@ -180,6 +183,15 @@ struct chip_desc {
u16 trickle_charger_reg;
u8 (*do_trickle_setup)(struct ds1307 *, u32,
bool);
+ /* Does the RTC require trickle-resistor-ohms to select the value of
+ * the resistor between Vcc and Vbackup?
+ */
+ bool requires_trickle_resistor;
+ /* Some RTC's batteries and supercaps were charged by default, others
+ * allow charging but were not configured previously to do so.
+ * Remember this behavior to stay backwards compatible.
+ */
+ bool charge_default;
};
static const struct chip_desc chips[last_ds_type];
@@ -490,6 +502,8 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
DS1307_TRICKLE_CHARGER_NO_DIODE;
+ setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
+
switch (ohms) {
case 250:
setup |= DS1307_TRICKLE_CHARGER_250_OHM;
@@ -508,6 +522,16 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
return setup;
}
+static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
+{
+ /* make sure that the backup battery is enabled */
+ u8 setup = RX8130_REG_CONTROL1_INIEN;
+ if (diode)
+ setup |= RX8130_REG_CONTROL1_CHGEN;
+
+ return setup;
+}
+
static irqreturn_t rx8130_irq(int irq, void *dev_id)
{
struct ds1307 *ds1307 = dev_id;
@@ -896,6 +920,8 @@ static const struct chip_desc chips[last_ds_type] = {
.bbsqi_bit = DS1339_BIT_BBSQI,
.trickle_charger_reg = 0x10,
.do_trickle_setup = &do_trickle_setup_ds1339,
+ .requires_trickle_resistor = true,
+ .charge_default = true,
},
[ds_1340] = {
.century_reg = DS1307_REG_HOUR,
@@ -903,6 +929,8 @@ static const struct chip_desc chips[last_ds_type] = {
.century_bit = DS1340_BIT_CENTURY,
.do_trickle_setup = &do_trickle_setup_ds1339,
.trickle_charger_reg = 0x08,
+ .requires_trickle_resistor = true,
+ .charge_default = true,
},
[ds_1341] = {
.century_reg = DS1307_REG_MONTH,
@@ -926,6 +954,8 @@ static const struct chip_desc chips[last_ds_type] = {
.offset = 0x10,
.irq_handler = rx8130_irq,
.rtc_ops = &rx8130_rtc_ops,
+ .trickle_charger_reg = RX8130_REG_CONTROL1,
+ .do_trickle_setup = &do_trickle_setup_rx8130,
},
[m41t0] = {
.rtc_ops = &m41txx_rtc_ops,
@@ -1210,18 +1240,37 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
static u8 ds1307_trickle_init(struct ds1307 *ds1307,
const struct chip_desc *chip)
{
- u32 ohms;
- bool diode = true;
+ u32 ohms, chargeable;
+ bool diode = chip->charge_default;
if (!chip->do_trickle_setup)
return 0;
if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms",
- &ohms))
+ &ohms) && chip->requires_trickle_resistor)
return 0;
- if (device_property_read_bool(ds1307->dev, "trickle-diode-disable"))
+ /* aux-voltage-chargeable takes precedence over the deprecated
+ * trickle-diode-disable
+ */
+ if (!device_property_read_u32(ds1307->dev, "aux-voltage-chargeable",
+ &chargeable)) {
+ switch (chargeable) {
+ case 0:
+ diode = false;
+ break;
+ case 1:
+ diode = true;
+ break;
+ default:
+ dev_warn(ds1307->dev,
+ "unsupported aux-voltage-chargeable value\n");
+ break;
+ }
+ } else if (device_property_read_bool(ds1307->dev,
+ "trickle-diode-disable")) {
diode = false;
+ }
return chip->do_trickle_setup(ds1307, ohms, diode);
}
@@ -1627,7 +1676,6 @@ static int ds1307_probe(struct i2c_client *client,
trickle_charger_setup = pdata->trickle_charger_setup;
if (trickle_charger_setup && chip->trickle_charger_reg) {
- trickle_charger_setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
dev_dbg(ds1307->dev,
"writing trickle charger info 0x%x to 0x%x\n",
trickle_charger_setup, chip->trickle_charger_reg);
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 39870bc38e40..f608f89f45cd 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -888,12 +888,6 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
controller->bus_num = pdev->id;
controller->slave_abort = fsl_lpspi_slave_abort;
- ret = devm_spi_register_controller(&pdev->dev, controller);
- if (ret < 0) {
- dev_err(&pdev->dev, "spi_register_controller error.\n");
- goto out_controller_put;
- }
-
if (!fsl_lpspi->is_slave) {
controller->cs_gpios = devm_kzalloc(&controller->dev,
sizeof(int) * controller->num_chipselect, GFP_KERNEL);
@@ -901,6 +895,11 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
for (i = 0; i < controller->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
+ if (cs_gpio == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto out_controller_put;
+ }
+
if (!gpio_is_valid(cs_gpio) && lpspi_platform_info)
cs_gpio = lpspi_platform_info->chipselect[i];
@@ -971,13 +970,30 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
if (ret == -EPROBE_DEFER)
- goto out_controller_put;
-
+ goto err_disable_runtime_pm;
if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
+ else
+ /* disable LPSPI module IRQ when enable DMA mode successfully,
+ * to prevent the unexpected LPSPI module IRQ events*/
+ disable_irq(irq);
+
+ ret = devm_spi_register_controller(&pdev->dev, controller);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "spi_register_controller error.\n");
+ goto err_disable_runtime_pm;
+ }
+
+ pm_runtime_mark_last_busy(fsl_lpspi->dev);
+ pm_runtime_put_autosuspend(fsl_lpspi->dev);
return 0;
+err_disable_runtime_pm:
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+ pm_runtime_put_sync(fsl_lpspi->dev);
+ pm_runtime_disable(fsl_lpspi->dev);
+
out_controller_put:
spi_controller_put(controller);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index be503a0e6ef7..2f75db2e75f6 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -278,14 +278,14 @@ static int spidev_message(struct spidev_data *spidev,
#ifdef VERBOSE
dev_dbg(&spidev->spi->dev,
" xfer len %u %s%s%s%dbits %u usec %u usec %uHz\n",
- u_tmp->len,
- u_tmp->rx_buf ? "rx " : "",
- u_tmp->tx_buf ? "tx " : "",
- u_tmp->cs_change ? "cs " : "",
- u_tmp->bits_per_word ? : spidev->spi->bits_per_word,
- u_tmp->delay_usecs,
- u_tmp->word_delay_usecs,
- u_tmp->speed_hz ? : spidev->spi->max_speed_hz);
+ k_tmp->len,
+ k_tmp->rx_buf ? "rx " : "",
+ k_tmp->tx_buf ? "tx " : "",
+ k_tmp->cs_change ? "cs " : "",
+ k_tmp->bits_per_word ? : spidev->spi->bits_per_word,
+ k_tmp->delay_usecs,
+ k_tmp->word_delay_usecs,
+ k_tmp->speed_hz ? : spidev->spi->max_speed_hz);
#endif
spi_message_add_tail(k_tmp, &msg);
}
@@ -457,10 +457,11 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
spi->max_speed_hz = tmp;
retval = spi_setup(spi);
- if (retval >= 0)
+ if (retval == 0) {
spidev->speed_hz = tmp;
- else
- dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
+ dev_dbg(&spi->dev, "%d Hz (max)\n",
+ spidev->speed_hz);
+ }
spi->max_speed_hz = save;
}
break;
@@ -678,6 +679,7 @@ static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "lwn,bk4" },
{ .compatible = "dh,dhcom-board" },
{ .compatible = "menlo,m53cpld" },
+ { .compatible = "toradex,evalspi" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 200f5e78518d..2f648ef41cc2 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -584,10 +584,10 @@ static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0)
}
/*
- * Set the critical trip point at 5 °C under max
+ * Set the critical trip point at max
* Set the passive trip point at 10 °C under max (changeable via sysfs)
*/
- data->temp_critical = data->temp_max - (1000 * 5);
+ data->temp_critical = data->temp_max;
data->temp_passive = data->temp_max - (1000 * 10);
}
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index d1f8840e871d..b822e54f2d13 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -207,6 +207,7 @@
#define UARTMODIR_IREN 0x00020000
#define UARTMODIR_RTSWATER_S 0x8
+#define UARTMODIR_RTSWATER_M 0x0000ff00
#define UARTMODIR_TXCTSSRC 0x00000020
#define UARTMODIR_TXCTSC 0x00000010
#define UARTMODIR_RXRTSE 0x00000008
@@ -1424,6 +1425,48 @@ static void lpuart_dma_rx_free(struct uart_port *port)
sport->dma_rx_cookie = -EINVAL;
}
+static void __maybe_unused lpuart_setup_rs485(struct lpuart_port *sport)
+{
+ /* Todo implement for 8-bit registers */
+}
+
+static void lpuart32_setup_rs485(struct lpuart_port *sport)
+{
+ struct serial_rs485 *rs485 = &sport->port.rs485;
+ unsigned long val, ctrl, ctrl_saved;
+
+ val = lpuart32_read(&sport->port, UARTMODIR) &
+ ~(UARTMODIR_TXRTSPOL | UARTMODIR_TXRTSE);
+
+ /* Make sure transmitter is disabled */
+ ctrl = lpuart32_read(&sport->port, UARTCTRL);
+ ctrl_saved = ctrl;
+ ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE |
+ UARTCTRL_RIE | UARTCTRL_RE);
+ lpuart32_write(&sport->port, ctrl, UARTCTRL);
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ /* Enable auto RS-485 RTS mode */
+ val |= UARTMODIR_TXRTSE;
+
+ /*
+ * The hardware defaults to RTS logic HIGH while transfer.
+ * Switch polarity in case RTS shall be logic HIGH
+ * after transfer.
+ * Note: UART is assumed to be active high.
+ */
+ if (rs485->flags & SER_RS485_RTS_ON_SEND)
+ val &= ~UARTMODIR_TXRTSPOL;
+ else if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
+ val |= UARTMODIR_TXRTSPOL;
+ }
+
+ lpuart32_write(&sport->port, val, UARTMODIR);
+
+ /* Restore cr2 */
+ lpuart32_write(&sport->port, ctrl_saved, UARTCTRL);
+}
+
static int lpuart_config_rs485(struct uart_port *port,
struct serial_rs485 *rs485)
{
@@ -1475,6 +1518,41 @@ static int lpuart_config_rs485(struct uart_port *port,
return 0;
}
+static int lpuart32_config_rs485(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+
+ /* clear unsupported configurations */
+ rs485->delay_rts_before_send = 0;
+ rs485->delay_rts_after_send = 0;
+ rs485->flags &= ~SER_RS485_RX_DURING_TX;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ /*
+ * RTS needs to be logic HIGH either during transer _or_ after
+ * transfer, other variants are not supported by the hardware.
+ */
+
+ if (!(rs485->flags & (SER_RS485_RTS_ON_SEND |
+ SER_RS485_RTS_AFTER_SEND)))
+ rs485->flags |= SER_RS485_RTS_ON_SEND;
+
+ if (rs485->flags & SER_RS485_RTS_ON_SEND &&
+ rs485->flags & SER_RS485_RTS_AFTER_SEND)
+ rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
+ }
+
+ /* Store the new configuration */
+ sport->port.rs485 = *rs485;
+
+ /* config_rs485 gets called in irqsave context so do not lock again */
+ lpuart32_setup_rs485(sport);
+
+ return 0;
+}
+
static unsigned int lpuart_get_mctrl(struct uart_port *port)
{
unsigned int temp = 0;
@@ -1650,8 +1728,10 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
/* set RTS watermark */
if (!uart_console(&sport->port)) {
- val = lpuart32_read(&sport->port, UARTMODIR);
- val = (sport->rxfifo_size >> 1) << UARTMODIR_RTSWATER_S;
+ val = lpuart32_read(&sport->port, UARTMODIR) &
+ ~UARTMODIR_RTSWATER_M;
+ val |= ((sport->rxfifo_size >> 1) << UARTMODIR_RTSWATER_S) &
+ UARTMODIR_RTSWATER_M;
lpuart32_write(&sport->port, val, UARTMODIR);
}
@@ -1791,6 +1871,7 @@ static void lpuart32_hw_setup(struct lpuart_port *sport)
lpuart_rx_dma_startup(sport);
lpuart_tx_dma_startup(sport);
+ lpuart32_setup_rs485(sport);
lpuart32_setup_watermark_enable(sport);
lpuart32_configure(sport);
@@ -2170,6 +2251,13 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
ctrl |= UARTCTRL_M;
}
+ /*
+ * When auto RS-485 RTS mode is enabled,
+ * hardware flow control need to be disabled.
+ */
+ if (sport->port.rs485.flags & SER_RS485_ENABLED)
+ termios->c_cflag &= ~CRTSCTS;
+
if (termios->c_cflag & CRTSCTS) {
modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE;
} else {
@@ -2713,6 +2801,7 @@ static int lpuart_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct lpuart_port *sport;
struct resource *res;
+ unsigned long flags;
int ret;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
@@ -2744,7 +2833,10 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.ops = &lpuart_pops;
sport->port.flags = UPF_BOOT_AUTOCONF;
- sport->port.rs485_config = lpuart_config_rs485;
+ if (lpuart_is_32(sport))
+ sport->port.rs485_config = lpuart32_config_rs485;
+ else
+ sport->port.rs485_config = lpuart_config_rs485;
ret = lpuart_attach_pd(&pdev->dev);
if (ret)
@@ -2827,7 +2919,9 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.rs485.delay_rts_after_send)
dev_err(&pdev->dev, "driver doesn't support RTS delays\n");
- lpuart_config_rs485(&sport->port, &sport->port.rs485);
+ spin_lock_irqsave(&sport->port.lock, flags);
+ sport->port.rs485_config(&sport->port, &sport->port.rs485);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
if (!sport->dma_tx_chan)
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d8408e751656..91f90b0cc45e 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -2387,6 +2387,18 @@ static int imx_uart_probe(struct platform_device *pdev)
clk_disable_unprepare(sport->clk_ipg);
+ /* if DTE mode is requested, make sure DTE mode is selected
+ and then disable DCDDELT/RIDELT interrupts */
+ if (!imx_uart_is_imx1(sport) && sport->dte_mode) {
+ u32 ucr3, ufcr;
+ ufcr = imx_uart_readl(sport, UFCR);
+ ufcr |= UFCR_DCEDTE;
+ imx_uart_writel(sport, ufcr, UFCR);
+ ucr3 = imx_uart_readl(sport, UCR3);
+ ucr3 &= ~(UCR3_DCD | UCR3_RI);
+ imx_uart_writel(sport, ucr3, UCR3);
+ }
+
/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 6b3caf9dcd96..64f11388d2e9 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -175,6 +175,7 @@ struct hw_bank {
* @enabled_otg_timer_bits: bits of enabled otg timers
* @next_otg_timer: next nearest enabled timer to be expired
* @work: work for role changing
+ * @work_dr: work for role changing for non-OTG controllers
* @wq: workqueue thread
* @qh_pool: allocation pool for queue heads
* @td_pool: allocation pool for transfer descriptors
@@ -228,6 +229,7 @@ struct ci_hdrc {
enum otg_fsm_timer next_otg_timer;
struct usb_role_switch *role_switch;
struct work_struct work;
+ struct work_struct work_dr;
struct workqueue_struct *wq;
struct dma_pool *qh_pool;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index bc1e2120a8e7..9a7012fe07c1 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -587,16 +587,71 @@ static irqreturn_t ci_irq(int irq, void *data)
return ret;
}
+static void usb_roleswitch_workqueue(struct work_struct *work)
+{
+ struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work_dr);
+ struct ci_hdrc_cable *id, *vbus;
+ int ret;
+
+ pm_runtime_get_sync(ci->dev);
+
+ id = &ci->platdata->id_extcon;
+ if (!IS_ERR(id->edev)) {
+ int new_role;
+
+ ci_role_stop(ci);
+ hw_wait_phy_stable();
+
+ ret = extcon_get_state(id->edev, EXTCON_USB_HOST);
+ if (ret) {
+ new_role = CI_ROLE_HOST;
+ dev_info(ci->dev, "switching to host role\n");
+ } else {
+ new_role = CI_ROLE_GADGET;
+ dev_info(ci->dev, "switching to gadget role\n");
+ }
+ ci_role_start(ci, new_role);
+ }
+
+ vbus = &ci->platdata->vbus_extcon;
+ if (!IS_ERR(vbus->edev)) {
+ ret = extcon_get_state(vbus->edev, EXTCON_USB);
+ if (ret) {
+ usb_gadget_vbus_connect(&ci->gadget);
+ } else {
+ usb_gadget_vbus_disconnect(&ci->gadget);
+ }
+ }
+
+ pm_runtime_put_sync(ci->dev);
+
+ enable_irq(ci->irq);
+}
+
static int ci_cable_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
{
struct ci_hdrc_cable *cbl = container_of(nb, struct ci_hdrc_cable, nb);
struct ci_hdrc *ci = cbl->ci;
- cbl->connected = event;
- cbl->changed = true;
+ if (ci->platdata->flags & CI_HDRC_DUAL_ROLE_NOT_OTG) {
+ disable_irq_nosync(ci->irq);
+
+ /*
+ * This notifier might get called twice in succession,
+ * once for the ID pin and once for the VBUS pin. Make
+ * sure we only disable irq in case we successfully add
+ * work to the work queue.
+ */
+ if (!queue_work(system_power_efficient_wq, &ci->work_dr))
+ enable_irq(ci->irq);
+ } else {
+ cbl->connected = event;
+ cbl->changed = true;
+
+ ci_irq(ci->irq, ci);
+ }
- ci_irq(ci->irq, ci);
return NOTIFY_DONE;
}
@@ -767,6 +822,7 @@ static int ci_get_platdata(struct device *dev,
ext_id = extcon_get_edev_by_phandle(dev, 1);
if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
return PTR_ERR(ext_id);
+ platdata->flags |= CI_HDRC_DUAL_ROLE_NOT_OTG;
}
cable = &platdata->vbus_extcon;
@@ -1017,6 +1073,13 @@ static enum ci_role ci_get_role(struct ci_hdrc *ci)
* role switch, the defalt role is gadget, and the
* user can switch it through debugfs.
*/
+ struct ci_hdrc_cable *id = &ci->platdata->id_extcon;
+ if (!IS_ERR(id->edev)) {
+ if (extcon_get_state(id->edev, EXTCON_USB_HOST))
+ return CI_ROLE_HOST;
+ else
+ return CI_ROLE_GADGET;
+ }
return CI_ROLE_GADGET;
}
} else {
@@ -1158,7 +1221,15 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ci_get_otg_capable(ci);
+ if (ci->platdata->flags & CI_HDRC_DUAL_ROLE_NOT_OTG)
+ INIT_WORK(&ci->work_dr, usb_roleswitch_workqueue);
+
+ ret = ci_extcon_register(ci);
+ if (ret)
+ goto stop;
+
dr_mode = ci->platdata->dr_mode;
+
/* initialize role(s) before the interrupt is requested */
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
ret = ci_hdrc_host_init(ci);
@@ -1231,6 +1302,21 @@ static int ci_hdrc_probe(struct platform_device *pdev)
}
if (!ci_otg_is_fsm_mode(ci)) {
+
+ /* only update vbus status for peripheral */
+ if (dr_mode == USB_DR_MODE_PERIPHERAL) {
+ usb_gadget_vbus_connect(&ci->gadget);
+ } else if (ci->role == CI_ROLE_GADGET) {
+ struct ci_hdrc_cable *vbus = &ci->platdata->vbus_extcon;
+
+ /* Use vbus state from extcon if provided */
+ if (!IS_ERR(vbus->edev) &&
+ extcon_get_state(vbus->edev, EXTCON_USB))
+ usb_gadget_vbus_connect(&ci->gadget);
+ else
+ ci_handle_vbus_change(ci);
+ }
+
ret = ci_role_start(ci, ci->role);
if (ret) {
dev_err(dev, "can't start %s role\n",
@@ -1244,10 +1330,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ret)
goto stop;
- ret = ci_extcon_register(ci);
- if (ret)
- goto stop;
-
if (ci->supports_runtime_pm) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index 72f39a9751b5..83f7c80b760d 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -46,7 +46,9 @@ struct usb3503 {
struct regmap *regmap;
struct device *dev;
struct clk *clk;
+ u8 port_nrd;
u8 port_off_mask;
+ int gpio_bypass;
int gpio_intn;
int gpio_reset;
int gpio_connect;
@@ -61,6 +63,9 @@ static int usb3503_reset(struct usb3503 *hub, int state)
if (gpio_is_valid(hub->gpio_reset))
gpio_set_value_cansleep(hub->gpio_reset, state);
+ if (gpio_is_valid(hub->gpio_bypass))
+ gpio_set_value_cansleep(hub->gpio_bypass, state);
+
/* Wait T_HUBINIT == 4ms for hub logic to stabilize */
if (state)
usleep_range(4000, 10000);
@@ -87,8 +92,7 @@ static int usb3503_connect(struct usb3503 *hub)
/* PDS : Set the ports which are disabled in self-powered mode. */
if (hub->port_off_mask) {
- err = regmap_update_bits(hub->regmap, USB3503_PDS,
- hub->port_off_mask,
+ err = regmap_write(hub->regmap, USB3503_PDS,
hub->port_off_mask);
if (err < 0) {
dev_err(dev, "PDS failed (%d)\n", err);
@@ -105,12 +109,22 @@ static int usb3503_connect(struct usb3503 *hub)
return err;
}
+ /* NRD : Set non removable ports. */
+ if (hub->port_nrd) {
+ err = regmap_write(hub->regmap, USB3503_NRD,
+ hub->port_nrd);
+ if (err < 0) {
+ dev_err(dev, "NRD failed (%d)\n", err);
+ return err;
+ }
+ }
+
/* SP_LOCK: clear connect_n, config_n for hub connect */
err = regmap_update_bits(hub->regmap, USB3503_SP_ILOCK,
(USB3503_SPILOCK_CONNECT
| USB3503_SPILOCK_CONFIG), 0);
if (err < 0) {
- dev_err(dev, "SP_ILOCK failed (%d)\n", err);
+ dev_err(dev, "SP_ILOCK 2 failed (%d)\n", err);
return err;
}
}
@@ -166,7 +180,9 @@ static int usb3503_probe(struct usb3503 *hub)
int len;
if (pdata) {
+ hub->port_nrd = pdata->port_nrd;
hub->port_off_mask = pdata->port_off_mask;
+ hub->gpio_bypass = pdata->gpio_bypass;
hub->gpio_intn = pdata->gpio_intn;
hub->gpio_connect = pdata->gpio_connect;
hub->gpio_reset = pdata->gpio_reset;
@@ -225,17 +241,32 @@ static int usb3503_probe(struct usb3503 *hub)
int i;
for (i = 0; i < len / sizeof(u32); i++) {
u32 port = be32_to_cpu(property[i]);
+ dev_dbg(dev, "disabled-ports, port: %d\n", port);
if ((1 <= port) && (port <= 3))
hub->port_off_mask |= (1 << port);
}
}
+ property = of_get_property(np, "non-removable-devices", &len);
+ if (property && (len / sizeof(u32)) > 0) {
+ int i;
+ for (i = 0; i < len / sizeof(u32); i++) {
+ u32 port = be32_to_cpu(property[i]);
+ dev_dbg(dev, "non-removable-devices, port: %d\n", port);
+ if ((1 <= port) && (port <= 3))
+ hub->port_nrd |= (1 << port);
+ }
+ }
+
hub->gpio_intn = of_get_named_gpio(np, "intn-gpios", 0);
if (hub->gpio_intn == -EPROBE_DEFER)
return -EPROBE_DEFER;
hub->gpio_connect = of_get_named_gpio(np, "connect-gpios", 0);
if (hub->gpio_connect == -EPROBE_DEFER)
return -EPROBE_DEFER;
+ hub->gpio_bypass = of_get_named_gpio(np, "bypass-gpios", 0);
+ if (hub->gpio_bypass == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0);
if (hub->gpio_reset == -EPROBE_DEFER)
return -EPROBE_DEFER;
@@ -270,6 +301,17 @@ static int usb3503_probe(struct usb3503 *hub)
}
}
+ if (gpio_is_valid(hub->gpio_bypass)) {
+ err = devm_gpio_request_one(dev, hub->gpio_bypass,
+ GPIOF_OUT_INIT_LOW, "usb3503 bypass");
+ if (err) {
+ dev_err(dev,
+ "unable to request GPIO %d as bypass pin (%d)\n",
+ hub->gpio_bypass, err);
+ return err;
+ }
+ }
+
if (gpio_is_valid(hub->gpio_reset)) {
err = devm_gpio_request_one(dev, hub->gpio_reset,
GPIOF_OUT_INIT_LOW, "usb3503 reset");
@@ -404,6 +446,7 @@ MODULE_DEVICE_TABLE(i2c, usb3503_id);
static const struct of_device_id usb3503_of_match[] = {
{ .compatible = "smsc,usb3503", },
{ .compatible = "smsc,usb3503a", },
+ { .compatible = "smsc,usb3803", },
{},
};
MODULE_DEVICE_TABLE(of, usb3503_of_match);
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index a53b89be5324..5c39a2644b5c 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -44,30 +44,37 @@ void usb_phy_generic_unregister(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(usb_phy_generic_unregister);
-static int nop_set_suspend(struct usb_phy *x, int suspend)
-{
- struct usb_phy_generic *nop = dev_get_drvdata(x->dev);
-
- if (!IS_ERR(nop->clk)) {
- if (suspend)
- clk_disable_unprepare(nop->clk);
- else
- clk_prepare_enable(nop->clk);
- }
-
- return 0;
-}
-
static void nop_reset(struct usb_phy_generic *nop)
{
if (!nop->gpiod_reset)
return;
+ dev_dbg(nop->dev, "reset\n");
+
gpiod_set_value_cansleep(nop->gpiod_reset, 1);
usleep_range(10000, 20000);
gpiod_set_value_cansleep(nop->gpiod_reset, 0);
}
+static int nop_set_suspend(struct usb_phy *x, int suspend)
+{
+ struct usb_phy_generic *nop = dev_get_drvdata(x->dev);
+
+ dev_dbg(x->dev, "%s\n", suspend ? "suspend" : "resume");
+
+ if (suspend) {
+ if (!IS_ERR(nop->clk))
+ clk_disable_unprepare(nop->clk);
+ } else {
+ if (!IS_ERR(nop->clk))
+ clk_prepare_enable(nop->clk);
+
+ if (nop->reset_on_resume)
+ nop_reset(nop);
+ }
+ return 0;
+}
+
/* interface to regulator framework */
static void nop_set_vbus_draw(struct usb_phy_generic *nop, unsigned mA)
{
@@ -219,6 +226,9 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
if (of_property_read_u32(node, "clock-frequency", &clk_rate))
clk_rate = 0;
+ nop->reset_on_resume =
+ of_property_read_bool(node, "reset-on-resume");
+
needs_vcc = of_property_read_bool(node, "vcc-supply");
needs_clk = of_property_read_bool(node, "clocks");
nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
@@ -229,6 +239,8 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
"vbus-detect",
GPIOD_ASIS);
err = PTR_ERR_OR_ZERO(nop->gpiod_vbus);
+ } else {
+ nop->gpiod_reset = NULL;
}
} else if (pdata) {
type = pdata->type;
diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h
index 97289627561d..9ddca95fad33 100644
--- a/drivers/usb/phy/phy-generic.h
+++ b/drivers/usb/phy/phy-generic.h
@@ -15,6 +15,7 @@ struct usb_phy_generic {
struct gpio_desc *gpiod_vbus;
struct regulator *vbus_draw;
bool vbus_draw_enabled;
+ bool reset_on_resume;
unsigned long mA;
unsigned int vbus;
};
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 40ebb5feb7d7..a9f03a0730f5 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -443,7 +443,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
* assume that another driver will enable the backlight at the
* appropriate time. Therefore, if it is disabled, keep it so.
*/
-
+#if 0
/* if the enable GPIO is disabled, do not enable the backlight */
if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
return FB_BLANK_POWERDOWN;
@@ -455,7 +455,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
/* The PWM is disabled, keep it like this */
if (!pwm_is_enabled(pb->pwm))
return FB_BLANK_POWERDOWN;
-
+#endif
return FB_BLANK_UNBLANK;
}
diff --git a/drivers/video/fbdev/mxc/Makefile b/drivers/video/fbdev/mxc/Makefile
index aaa525afcbce..2c419a038298 100644
--- a/drivers/video/fbdev/mxc/Makefile
+++ b/drivers/video/fbdev/mxc/Makefile
@@ -12,6 +12,6 @@ obj-$(CONFIG_FB_MXC_LDB) += ldb.o
obj-$(CONFIG_FB_MXS_SII902X) += mxsfb_sii902x.o mxsfb_sii902x_audio.o
obj-$(CONFIG_FB_MXC_HDMI) += mxc_hdmi.o
obj-$(CONFIG_FB_MXC_DCIC) += mxc_dcic.o
-obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_lcdif.o mxc_ipuv3_fb.o
+obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_lcdif.o mxc_vdacif.o mxc_ipuv3_fb.o
obj-$(CONFIG_FB_MXC_EINK_PANEL) += mxc_epdc_fb.o
obj-$(CONFIG_FB_MXC_EINK_V2_PANEL) += mxc_epdc_v2_fb.o
diff --git a/drivers/video/fbdev/mxc/ldb.c b/drivers/video/fbdev/mxc/ldb.c
index 1d6c9e08590c..66a8fe51a84d 100644
--- a/drivers/video/fbdev/mxc/ldb.c
+++ b/drivers/video/fbdev/mxc/ldb.c
@@ -22,6 +22,7 @@
#include <linux/regmap.h>
#include <linux/types.h>
#include <video/of_videomode.h>
+#include <video/of_display_timing.h>
#include <video/videomode.h>
#include "mxc_dispdrv.h"
@@ -77,7 +78,8 @@ struct ldb_data;
struct ldb_chan {
struct ldb_data *ldb;
struct fb_info *fbi;
- struct videomode vm;
+ unsigned long serial_clk;
+ struct display_timings *timings;
enum crtc crtc;
int chno;
bool is_used;
@@ -301,8 +303,10 @@ static int ldb_init(struct mxc_dispdrv_handle *mddh,
struct device *dev = ldb->dev;
struct fb_info *fbi = setting->fbi;
struct ldb_chan *chan;
- struct fb_videomode fb_vm;
- int chno;
+ struct fb_videomode fb_vm, native_mode;
+ int chno, i, ret;
+ struct videomode vm;
+ unsigned long pixelclock;
chno = ldb->chan[ldb->primary_chno].is_used ?
!ldb->primary_chno : ldb->primary_chno;
@@ -322,10 +326,40 @@ static int ldb_init(struct mxc_dispdrv_handle *mddh,
chan->fbi = fbi;
- fb_videomode_from_videomode(&chan->vm, &fb_vm);
- fb_videomode_to_var(&fbi->var, &fb_vm);
-
setting->crtc = chan->crtc;
+
+ INIT_LIST_HEAD(&fbi->modelist);
+ for (i = 0; i < chan->timings->num_timings; i++) {
+ ret = videomode_from_timings(chan->timings, &vm, i);
+ if (ret < 0) {
+ dev_err(ldb->dev,
+ "failed to get video mode from timings\n");
+ return ret;
+ }
+
+ ret = fb_videomode_from_videomode(&vm, &fb_vm);
+ if (ret < 0) {
+ dev_err(ldb->dev,
+ "failed to get fb video mode from video mode\n");
+ return ret;
+ }
+
+ if (i == chan->timings->native_mode)
+ fb_videomode_from_videomode(&vm, &native_mode);
+
+ fb_add_videomode(&fb_vm, &fbi->modelist);
+ fb_videomode_to_var(&fbi->var, &fb_vm);
+ }
+
+ fb_find_mode(&fbi->var, fbi, setting->dft_mode_str, &fb_vm,
+ chan->timings->num_timings, &native_mode,
+ setting->default_bpp);
+
+ /* Calculate the LVDS clock */
+ fb_var_to_videomode(&fb_vm, &fbi->var);
+
+ pixelclock = fb_vm.pixclock ? (1000000000UL/(fb_vm.pixclock)) * 1000: 0;
+ chan->serial_clk = ldb->spl_mode ? pixelclock * 7 / 2 : pixelclock * 7;
return 0;
}
@@ -399,7 +433,6 @@ static int ldb_setup(struct mxc_dispdrv_handle *mddh,
struct clk *other_ldb_di_sel = NULL;
struct bus_mux bus_mux;
int ret = 0, id = 0, chno, other_chno;
- unsigned long serial_clk;
u32 mux_val;
ret = find_ldb_chno(ldb, fbi, &chno);
@@ -453,9 +486,7 @@ static int ldb_setup(struct mxc_dispdrv_handle *mddh,
clk_set_parent(ldb->div_sel_clk[chno], ldb_di_parent);
ldb_di_sel = clk_get_parent(ldb_di_parent);
ldb_di_sel_parent = clk_get_parent(ldb_di_sel);
- serial_clk = ldb->spl_mode ? chan.vm.pixelclock * 7 / 2 :
- chan.vm.pixelclock * 7;
- clk_set_rate(ldb_di_sel_parent, serial_clk);
+ clk_set_rate(ldb_di_sel_parent, chan.serial_clk);
/*
* split mode or dual mode:
@@ -834,9 +865,11 @@ static int ldb_probe(struct platform_device *pdev)
return -EINVAL;
}
- ret = of_get_videomode(child, &chan->vm, 0);
- if (ret)
- return -EINVAL;
+ chan->timings = of_get_display_timings(child);
+ if (!chan->timings) {
+ dev_err(ldb->dev, "failed to get display timings\n");
+ ret = -ENOENT;
+ }
sprintf(clkname, "ldb_di%d", i);
ldb->ldb_di_clk[i] = devm_clk_get(dev, clkname);
diff --git a/drivers/video/fbdev/mxc/mxc_hdmi.c b/drivers/video/fbdev/mxc/mxc_hdmi.c
index 262d4b730094..26a6421be879 100644
--- a/drivers/video/fbdev/mxc/mxc_hdmi.c
+++ b/drivers/video/fbdev/mxc/mxc_hdmi.c
@@ -73,6 +73,18 @@
#define YCBCR422_8BITS 3
#define XVYCC444 4
+static bool only_cea;
+module_param(only_cea, bool, 0644);
+MODULE_PARM_DESC(only_cea, "Allow only CEA modes");
+
+#if 0
+/* rely solely on the HPD pin for hot plug detection */
+#undef HDMI_DVI_STAT
+#define HDMI_DVI_STAT 2
+
+#undef HDMI_DVI_IH_STAT
+#define HDMI_DVI_IH_STAT 1
+#endif
/*
* We follow a flowchart which is in the "Synopsys DesignWare Courses
* HDMI Transmitter Controller User Guide, 1.30a", section 3.1
@@ -163,11 +175,11 @@ struct mxc_hdmi {
bool dft_mode_set;
char *dft_mode_str;
int default_bpp;
- u8 latest_intr_stat;
bool irq_enabled;
spinlock_t irq_lock;
bool phy_enabled;
struct fb_videomode default_mode;
+ struct fb_videomode previous_mode;
struct fb_videomode previous_non_vga_mode;
bool requesting_vga_for_initialization;
@@ -946,6 +958,9 @@ static u8 hdmi_edid_i2c_read(struct mxc_hdmi *hdmi,
return data;
}
+static int keepalive=1;
+module_param(keepalive, int, 0644);
+MODULE_PARM_DESC(keepalive, "Keep HDMI alive (don't detect disconnect)");
/* "Power-down enable (active low)"
* That mean that power up == 1! */
@@ -1268,9 +1283,6 @@ static void mxc_hdmi_phy_init(struct mxc_hdmi *hdmi)
|| (hdmi->blank != FB_BLANK_UNBLANK))
return;
- if (!hdmi->hdmi_data.video_mode.mDVI)
- hdmi_enable_overflow_interrupts();
-
/*check csc whether needed activated in HDMI mode */
cscon = (isColorSpaceConversion(hdmi) &&
!hdmi->hdmi_data.video_mode.mDVI);
@@ -1287,6 +1299,8 @@ static void mxc_hdmi_phy_init(struct mxc_hdmi *hdmi)
}
hdmi->phy_enabled = true;
+ if (!hdmi->hdmi_data.video_mode.mDVI)
+ hdmi_enable_overflow_interrupts();
}
static void hdmi_config_AVI(struct mxc_hdmi *hdmi)
@@ -1808,7 +1822,7 @@ static void mxc_hdmi_edid_rebuild_modelist(struct mxc_hdmi *hdmi)
mode = &hdmi->fbi->monspecs.modedb[i];
if (!(mode->vmode & FB_VMODE_INTERLACED) &&
- (mxc_edid_mode_to_vic(mode) != 0)) {
+ (!only_cea || mxc_edid_mode_to_vic(mode))) {
dev_dbg(&hdmi->pdev->dev, "Added mode %d:", i);
dev_dbg(&hdmi->pdev->dev,
@@ -1956,8 +1970,9 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
mxc_hdmi_edid_rebuild_modelist(hdmi);
break;
- /* Nothing to do if EDID same */
+ /* Rebuild even if they're the same in case only_cea changed */
case HDMI_EDID_SAME:
+ mxc_hdmi_edid_rebuild_modelist(hdmi);
break;
case HDMI_EDID_FAIL:
@@ -2010,74 +2025,70 @@ static void hotplug_worker(struct work_struct *work)
struct delayed_work *delay_work = to_delayed_work(work);
struct mxc_hdmi *hdmi =
container_of(delay_work, struct mxc_hdmi, hotplug_work);
- u32 phy_int_stat, phy_int_pol, phy_int_mask;
- u8 val;
+ u32 hdmi_phy_stat0, hdmi_phy_pol0, hdmi_phy_mask0;
unsigned long flags;
char event_string[32];
+ int isalive = 0;
char *envp[] = { event_string, NULL };
- phy_int_stat = hdmi->latest_intr_stat;
- phy_int_pol = hdmi_readb(HDMI_PHY_POL0);
- dev_dbg(&hdmi->pdev->dev, "phy_int_stat=0x%x, phy_int_pol=0x%x\n",
- phy_int_stat, phy_int_pol);
+ hdmi_phy_stat0 = hdmi_readb(HDMI_PHY_STAT0);
+ hdmi_phy_pol0 = hdmi_readb(HDMI_PHY_POL0);
+
+ dev_dbg(&hdmi->pdev->dev, "hdmi_phy_stat0=0x%x, hdmi_phy_pol0=0x%x\n",
+ hdmi_phy_stat0, hdmi_phy_pol0);
+
+ /* Make HPD intr active low to capture unplug event or
+ * active high to capture plugin event */
+ hdmi_writeb((HDMI_DVI_STAT & ~hdmi_phy_stat0), HDMI_PHY_POL0);
/* check cable status */
- if (phy_int_stat & HDMI_IH_PHY_STAT0_HPD) {
- /* cable connection changes */
- if (phy_int_pol & HDMI_PHY_HPD) {
- /* Plugin event */
- dev_dbg(&hdmi->pdev->dev, "EVENT=plugin\n");
- mxc_hdmi_cable_connected(hdmi);
-
- /* Make HPD intr active low to capture unplug event */
- val = hdmi_readb(HDMI_PHY_POL0);
- val &= ~HDMI_PHY_HPD;
- hdmi_writeb(val, HDMI_PHY_POL0);
-
- hdmi_set_cable_state(1);
-
- sprintf(event_string, "EVENT=plugin");
- kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
-#ifdef CONFIG_MXC_HDMI_CEC
- mxc_hdmi_cec_handle(0x80);
-#endif
- } else if (!(phy_int_pol & HDMI_PHY_HPD)) {
- /* Plugout event */
- dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n");
- hdmi_set_cable_state(0);
- mxc_hdmi_abort_stream();
- mxc_hdmi_cable_disconnected(hdmi);
+ if (hdmi_phy_stat0 & HDMI_DVI_STAT) {
+ /* Plugin event */
+ dev_dbg(&hdmi->pdev->dev, "EVENT=plugin\n");
+ mxc_hdmi_cable_connected(hdmi);
- /* Make HPD intr active high to capture plugin event */
- val = hdmi_readb(HDMI_PHY_POL0);
- val |= HDMI_PHY_HPD;
- hdmi_writeb(val, HDMI_PHY_POL0);
+ hdmi_set_cable_state(1);
- sprintf(event_string, "EVENT=plugout");
- kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+ sprintf(event_string, "EVENT=plugin");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
#ifdef CONFIG_MXC_HDMI_CEC
- mxc_hdmi_cec_handle(0x100);
+ mxc_hdmi_cec_handle(0x80);
+#endif
+ if (keepalive)
+ hdmi_writeb(HDMI_DVI_STAT, HDMI_PHY_POL0);
+ isalive=1;
+ } else if (!keepalive) {
+ /* Plugout event */
+ dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n");
+ hdmi_set_cable_state(0);
+ mxc_hdmi_abort_stream();
+ mxc_hdmi_cable_disconnected(hdmi);
+
+ sprintf(event_string, "EVENT=plugout");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+#ifdef CONFIG_MXC_HDMI_CEC
+ mxc_hdmi_cec_handle(0x100);
#endif
- } else
- dev_dbg(&hdmi->pdev->dev, "EVENT=none?\n");
}
/* Lock here to ensure full powerdown sequence
* completed before next interrupt processed */
spin_lock_irqsave(&hdmi->irq_lock, flags);
- /* Re-enable HPD interrupts */
- phy_int_mask = hdmi_readb(HDMI_PHY_MASK0);
- phy_int_mask &= ~HDMI_PHY_HPD;
- hdmi_writeb(phy_int_mask, HDMI_PHY_MASK0);
+ if (!(keepalive && isalive)) {
+ /* Re-enable HPD interrupts */
+ hdmi_phy_mask0 = hdmi_readb(HDMI_PHY_MASK0);
+ hdmi_phy_mask0 &= ~HDMI_DVI_STAT;
+ hdmi_writeb(hdmi_phy_mask0, HDMI_PHY_MASK0);
- /* Unmute interrupts */
- hdmi_writeb(~HDMI_IH_MUTE_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ /* Unmute interrupts */
+ hdmi_writeb(~HDMI_DVI_IH_STAT, HDMI_IH_MUTE_PHY_STAT0);
- if (hdmi_readb(HDMI_IH_FC_STAT2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK)
- mxc_hdmi_clear_overflow(hdmi);
+ if (hdmi_readb(HDMI_IH_FC_STAT2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK)
+ mxc_hdmi_clear_overflow(hdmi);
+ }
spin_unlock_irqrestore(&hdmi->irq_lock, flags);
}
@@ -2100,7 +2111,7 @@ static void hdcp_hdp_worker(struct work_struct *work)
static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
{
struct mxc_hdmi *hdmi = data;
- u8 val, intr_stat;
+ u8 val;
unsigned long flags;
spin_lock_irqsave(&hdmi->irq_lock, flags);
@@ -2122,25 +2133,22 @@ static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
* HDMI registers.
*/
/* Capture status - used in hotplug_worker ISR */
- intr_stat = hdmi_readb(HDMI_IH_PHY_STAT0);
-
- if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
+ if (hdmi_readb(HDMI_IH_PHY_STAT0) & HDMI_DVI_IH_STAT) {
dev_dbg(&hdmi->pdev->dev, "Hotplug interrupt received\n");
- hdmi->latest_intr_stat = intr_stat;
/* Mute interrupts until handled */
val = hdmi_readb(HDMI_IH_MUTE_PHY_STAT0);
- val |= HDMI_IH_MUTE_PHY_STAT0_HPD;
+ val |= HDMI_DVI_IH_STAT;
hdmi_writeb(val, HDMI_IH_MUTE_PHY_STAT0);
val = hdmi_readb(HDMI_PHY_MASK0);
- val |= HDMI_PHY_HPD;
+ val |= HDMI_DVI_STAT;
hdmi_writeb(val, HDMI_PHY_MASK0);
/* Clear Hotplug interrupts */
- hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(HDMI_DVI_IH_STAT, HDMI_IH_PHY_STAT0);
schedule_delayed_work(&(hdmi->hotplug_work), msecs_to_jiffies(20));
}
@@ -2172,6 +2180,9 @@ static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event)
dev_dbg(&hdmi->pdev->dev, "%s - video mode changed\n", __func__);
+ /* Save mode as 'previous_mode' so that we can know if mode changed. */
+ memcpy(&hdmi->previous_mode, &m, sizeof(struct fb_videomode));
+
hdmi->vic = 0;
if (!hdmi->requesting_vga_for_initialization) {
/* Save mode if this isn't the result of requesting
@@ -2293,13 +2304,13 @@ static void mxc_hdmi_fb_registered(struct mxc_hdmi *hdmi)
HDMI_PHY_I2CM_CTLINT_ADDR);
/* enable cable hot plug irq */
- hdmi_writeb((u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
+ hdmi_writeb((u8)~HDMI_DVI_STAT, HDMI_PHY_MASK0);
/* Clear Hotplug interrupts */
- hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(HDMI_DVI_IH_STAT, HDMI_IH_PHY_STAT0);
/* Unmute interrupts */
- hdmi_writeb(~HDMI_IH_MUTE_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(~HDMI_DVI_IH_STAT, HDMI_IH_MUTE_PHY_STAT0);
hdmi->fb_reg = true;
@@ -2312,6 +2323,7 @@ static int mxc_hdmi_fb_event(struct notifier_block *nb,
{
struct fb_event *event = v;
struct mxc_hdmi *hdmi = container_of(nb, struct mxc_hdmi, nb);
+ struct fb_videomode *mode;
if (strcmp(event->info->fix.id, hdmi->fbi->fix.id))
return 0;
@@ -2332,7 +2344,10 @@ static int mxc_hdmi_fb_event(struct notifier_block *nb,
case FB_EVENT_MODE_CHANGE:
dev_dbg(&hdmi->pdev->dev, "event=FB_EVENT_MODE_CHANGE\n");
- if (hdmi->fb_reg)
+ mode = (struct fb_videomode *)event->data;
+ if ((hdmi->fb_reg) &&
+ (mode != NULL) &&
+ !fb_mode_is_equal(&hdmi->previous_mode, mode))
mxc_hdmi_setup(hdmi, val);
break;
@@ -2631,10 +2646,10 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp,
/* Configure registers related to HDMI interrupt
* generation before registering IRQ. */
- hdmi_writeb(HDMI_PHY_HPD, HDMI_PHY_POL0);
+ hdmi_writeb(HDMI_DVI_STAT, HDMI_PHY_POL0);
/* Clear Hotplug interrupts */
- hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(HDMI_DVI_IH_STAT, HDMI_IH_PHY_STAT0);
hdmi->nb.notifier_call = mxc_hdmi_fb_event;
ret = fb_register_client(&hdmi->nb);
diff --git a/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c b/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c
index 5c32176bfe6f..d928a621207e 100644
--- a/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c
+++ b/drivers/video/fbdev/mxc/mxc_ipuv3_fb.c
@@ -1321,6 +1321,15 @@ static int mxcfb_set_par(struct fb_info *fbi)
dev_dbg(fbi->device, "pixclock = %ul Hz\n",
(u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
+ dev_info(fbi->device,"%dx%d h_sync,r,l: %d,%d,%d v_sync,l,u: %d,%d,%d pixclock=%u Hz\n",
+ fbi->var.xres, fbi->var.yres,
+ fbi->var.hsync_len,
+ fbi->var.right_margin,
+ fbi->var.left_margin,
+ fbi->var.vsync_len,
+ fbi->var.lower_margin,
+ fbi->var.upper_margin,
+ (u32)(PICOS2KHZ(fbi->var.pixclock) * 1000UL));
if (ipu_init_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di,
(PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
@@ -3055,6 +3064,10 @@ static int mxcfb_option_setup(struct platform_device *pdev, struct fb_info *fbi)
name[5] += pdev->id;
if (fb_get_options(name, &options)) {
+ if (options && !strncmp(options, "off", 3)) {
+ dev_info(&pdev->dev, "%s is turned off!\n", name);
+ return -ENODEV;
+ }
dev_err(&pdev->dev, "Can't get fb option for %s!\n", name);
return -ENODEV;
}
@@ -3133,8 +3146,7 @@ static int mxcfb_option_setup(struct platform_device *pdev, struct fb_info *fbi)
fb_mode_str = opt;
}
- if (fb_mode_str)
- pdata->mode_str = fb_mode_str;
+ pdata->mode_str = fb_mode_str;
return 0;
}
@@ -3348,8 +3360,10 @@ static void mxcfb_unsetup_overlay(struct fb_info *fbi_bg)
}
static bool ipu_usage[2][2];
-static int ipu_test_set_usage(int ipu, int di)
+static int ipu_test_set_usage(unsigned ipu, unsigned di)
{
+ if ((ipu >= 2) || (di >= 2))
+ return -EINVAL;
if (ipu_usage[ipu][di])
return -EBUSY;
else
@@ -3359,6 +3373,8 @@ static int ipu_test_set_usage(int ipu, int di)
static void ipu_clear_usage(int ipu, int di)
{
+ if ((ipu >= 2) || (di >= 2))
+ return;
ipu_usage[ipu][di] = false;
}
@@ -3530,7 +3546,7 @@ static int mxcfb_probe(struct platform_device *pdev)
mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
mxcfbi->ipu_ch = MEM_BG_SYNC;
/* Unblank the primary fb only by default */
- if (pdev->id == 0)
+ if (1) //(pdev->id == 0)
mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_UNBLANK;
else
mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
@@ -3571,7 +3587,7 @@ static int mxcfb_probe(struct platform_device *pdev)
mxcfbi->ipu_ch_nf_irq = IPU_IRQ_DC_SYNC_NFACK;
mxcfbi->ipu_alp_ch_irq = -1;
mxcfbi->ipu_ch = MEM_DC_SYNC;
- mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
+ mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_UNBLANK;
ret = mxcfb_register(fbi);
if (ret < 0)
diff --git a/drivers/video/fbdev/mxc/mxc_lcdif.c b/drivers/video/fbdev/mxc/mxc_lcdif.c
index 59d429c82017..1636bae7b8d0 100644
--- a/drivers/video/fbdev/mxc/mxc_lcdif.c
+++ b/drivers/video/fbdev/mxc/mxc_lcdif.c
@@ -37,6 +37,42 @@ struct mxc_lcdif_data {
static struct fb_videomode lcdif_modedb[] = {
{
+ /* 1024x600 @ 59 Hz , pixel clk @ 45 MHz */ /* 22222 ps*/
+ "FusionF10A", 59, 1024, 600, 22222,
+ .left_margin = 104,
+ .right_margin = 43,
+ .hsync_len = 5,
+ .upper_margin = 24,
+ .lower_margin = 20,
+ .vsync_len = 5,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,},
+ {
+ /* 800x480 @ 60 Hz , pixel clk @ 33.26MHz */
+ "FusionF07A", 60, 800, 480, 30066,
+ .left_margin = 88,
+ .right_margin = 40,
+ .hsync_len = 128,
+ .upper_margin = 33,
+ .lower_margin = 10,
+ .vsync_len = 2,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,},
+ {
+ /* 800x480 @ 60 Hz , pixel clk @ 33.26MHz */
+ "EDT-WVGA", 60, 800, 480, 30066,
+ .left_margin = 88,
+ .right_margin = 40,
+ .hsync_len = 128,
+ .upper_margin = 33,
+ .lower_margin = 10,
+ .vsync_len = 2,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,},
+ {
/* 800x480 @ 57 Hz , pixel clk @ 27MHz */
"CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
FB_SYNC_CLK_LAT_FALL,
@@ -48,6 +84,30 @@ static struct fb_videomode lcdif_modedb[] = {
FB_SYNC_CLK_LAT_FALL,
FB_VMODE_NONINTERLACED,
0,},
+ {
+ /* 640x480 @ 60 Hz , pixel clk @ 25.175MHz */
+ "EDT-VGA", 60, 640, 480, 39721,
+ .left_margin = 114,
+ .right_margin = 16,
+ .hsync_len = 30,
+ .upper_margin = 32,
+ .lower_margin = 10,
+ .vsync_len = 3,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,},
+ {
+ /* 480x272 @ 60 Hz , pixel clk @ 9MHz */
+ "EDT-480x272", 60, 480, 272, 111111,
+ .left_margin = 2,
+ .right_margin = 2,
+ .hsync_len = 41,
+ .upper_margin = 2,
+ .lower_margin = 2,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,},
};
static int lcdif_modedb_sz = ARRAY_SIZE(lcdif_modedb);
diff --git a/drivers/video/fbdev/mxc/mxc_vdacif.c b/drivers/video/fbdev/mxc/mxc_vdacif.c
new file mode 100644
index 000000000000..873c02a4ef51
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_vdacif.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014-2016 Toradex AG. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * copy of mxc_lcdif.c
+ * adds a second parallel output which drives a Video DAC
+ * available on the second IPU, first DI on a
+ * Apalis iMX6 module
+ */
+
+#include <linux/init.h>
+#include <linux/ipu.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mxcfb.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
+#include "mxc_dispdrv.h"
+
+struct mxc_vdac_platform_data {
+ u32 default_ifmt;
+ u32 ipu_id;
+ u32 disp_id;
+};
+
+struct mxc_vdacif_data {
+ struct platform_device *pdev;
+ struct mxc_dispdrv_handle *disp_vdacif;
+};
+
+#define DISPDRV_LCD "vdac"
+
+static struct fb_videomode vdacif_modedb[] = {
+ /* 0 640x350-85 VESA */
+ { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED,
+ FB_MODE_IS_VESA},
+ /* 1 640x400-85 VESA */
+ { NULL, 85, 640, 400, 31746, 96, 32, 41, 01, 64, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED,
+ FB_MODE_IS_VESA },
+ /* 2 720x400-85 VESA */
+ { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED,
+ FB_MODE_IS_VESA },
+ /* 3 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 4 640x480-72 VESA */
+ { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
+ FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 5 640x480-75 VESA */
+ { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+ FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 6 640x480-85 VESA */
+ { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+ FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 7 800x600-56 VESA */
+ { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 8 800x600-60 VESA */
+ { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 9 800x600-72 VESA */
+ { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 10 800x600-75 VESA */
+ { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 11 800x600-85 VESA */
+ { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 12 1024x768i-43 VESA */
+ { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
+ /* 13 1024x768-60 VESA */
+ { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+ FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 14 1024x768-70 VESA */
+ { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+ FB_SYNC_OE_LOW_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 15 1024x768-75 VESA */
+ { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 16 1024x768-85 VESA */
+ { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 17 1152x864-75 VESA */
+ { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 18 1280x960-60 VESA */
+ { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 19 1280x960-85 VESA */
+ { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 20 1280x1024-60 VESA */
+ { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 21 1280x1024-75 VESA */
+ { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 22 1280x1024-85 VESA */
+ { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 23 1600x1200-60 VESA */
+ { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 24 1600x1200-65 VESA */
+ { NULL, 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 25 1600x1200-70 VESA */
+ { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 26 1600x1200-75 VESA */
+ { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 27 1600x1200-85 VESA */
+ { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 28 1792x1344-60 VESA */
+ { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 29 1792x1344-75 VESA */
+ { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 30 1856x1392-60 VESA */
+ { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 31 1856x1392-75 VESA */
+ { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 32 1920x1440-60 VESA */
+ { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 33 1920x1440-75 VESA */
+ { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
+ { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED },
+ /* #16: 1920x1080p@60Hz 16:9 */
+ { NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+};
+static int vdacif_modedb_sz = ARRAY_SIZE(vdacif_modedb);
+
+static int vdacif_init(struct mxc_dispdrv_handle *disp,
+ struct mxc_dispdrv_setting *setting)
+{
+ int ret, i;
+ struct mxc_vdacif_data *vdacif = mxc_dispdrv_getdata(disp);
+ struct device *dev = &vdacif->pdev->dev;
+ struct mxc_vdac_platform_data *plat_data = dev->platform_data;
+ struct fb_videomode *modedb = vdacif_modedb;
+ int modedb_sz = vdacif_modedb_sz;
+
+ /* use platform defined ipu/di */
+ ret = ipu_di_to_crtc(dev, plat_data->ipu_id,
+ plat_data->disp_id, &setting->crtc);
+ if (ret < 0)
+ return ret;
+
+ ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
+ modedb, modedb_sz, NULL, setting->default_bpp);
+ if (!ret) {
+ fb_videomode_to_var(&setting->fbi->var, &modedb[0]);
+ setting->if_fmt = plat_data->default_ifmt;
+ }
+ /* Peter's VDAC requires OE to be low active */
+ setting->fbi->var.sync |= FB_SYNC_OE_LOW_ACT;
+
+ INIT_LIST_HEAD(&setting->fbi->modelist);
+ for (i = 0; i < modedb_sz; i++) {
+ struct fb_videomode m;
+ fb_var_to_videomode(&m, &setting->fbi->var);
+ if (fb_mode_is_equal(&m, &modedb[i])) {
+ fb_add_videomode(&modedb[i],
+ &setting->fbi->modelist);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void vdacif_deinit(struct mxc_dispdrv_handle *disp)
+{
+ /*TODO*/
+}
+
+static struct mxc_dispdrv_driver vdacif_drv = {
+ .name = DISPDRV_LCD,
+ .init = vdacif_init,
+ .deinit = vdacif_deinit,
+};
+
+static int vdac_get_of_property(struct platform_device *pdev,
+ struct mxc_vdac_platform_data *plat_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+ u32 ipu_id, disp_id;
+ const char *default_ifmt;
+
+ err = of_property_read_string(np, "default_ifmt", &default_ifmt);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property default_ifmt fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "ipu_id", &ipu_id);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
+ return err;
+ }
+ err = of_property_read_u32(np, "disp_id", &disp_id);
+ if (err) {
+ dev_dbg(&pdev->dev, "get of property disp_id fail\n");
+ return err;
+ }
+
+ if ( (ipu_id == 0) || (disp_id == 1) ) {
+ dev_err(&pdev->dev, "wrong ipu_id %x or disp_id %x, expected 1, 0\n", ipu_id, disp_id);
+ }
+ plat_data->ipu_id = ipu_id;
+ plat_data->disp_id = disp_id;
+ if (!strncmp(default_ifmt, "RGB565", 6))
+ plat_data->default_ifmt = IPU_PIX_FMT_RGB565;
+ else {
+ dev_err(&pdev->dev, "err default_ifmt!\n");
+ return -ENOENT;
+ }
+
+ return err;
+}
+
+static int mxc_vdacif_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct pinctrl *pinctrl;
+ struct mxc_vdacif_data *vdacif;
+ struct mxc_vdac_platform_data *plat_data;
+
+ dev_dbg(&pdev->dev, "%s enter\n", __func__);
+ vdacif = devm_kzalloc(&pdev->dev, sizeof(struct mxc_vdacif_data),
+ GFP_KERNEL);
+ if (!vdacif)
+ return -ENOMEM;
+ plat_data = devm_kzalloc(&pdev->dev,
+ sizeof(struct mxc_vdac_platform_data),
+ GFP_KERNEL);
+ if (!plat_data)
+ return -ENOMEM;
+ pdev->dev.platform_data = plat_data;
+
+ ret = vdac_get_of_property(pdev, plat_data);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "get vdac of property fail\n");
+ return ret;
+ }
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "can't get/select pinctrl\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ vdacif->pdev = pdev;
+ vdacif->disp_vdacif = mxc_dispdrv_register(&vdacif_drv);
+ mxc_dispdrv_setdata(vdacif->disp_vdacif, vdacif);
+
+ dev_set_drvdata(&pdev->dev, vdacif);
+ dev_dbg(&pdev->dev, "%s exit\n", __func__);
+
+ return ret;
+}
+
+static int mxc_vdacif_remove(struct platform_device *pdev)
+{
+ struct mxc_vdacif_data *vdacif = dev_get_drvdata(&pdev->dev);
+
+ mxc_dispdrv_puthandle(vdacif->disp_vdacif);
+ mxc_dispdrv_unregister(vdacif->disp_vdacif);
+ kfree(vdacif);
+ return 0;
+}
+
+static const struct of_device_id imx_vdac_dt_ids[] = {
+ { .compatible = "fsl,vdac"},
+ { /* sentinel */ }
+};
+static struct platform_driver mxc_vdacif_driver = {
+ .driver = {
+ .name = "mxc_vdacif",
+ .of_match_table = imx_vdac_dt_ids,
+ },
+ .probe = mxc_vdacif_probe,
+ .remove = mxc_vdacif_remove,
+};
+
+static int __init mxc_vdacif_init(void)
+{
+ return platform_driver_register(&mxc_vdacif_driver);
+}
+
+static void __exit mxc_vdacif_exit(void)
+{
+ platform_driver_unregister(&mxc_vdacif_driver);
+}
+
+module_init(mxc_vdacif_init);
+module_exit(mxc_vdacif_exit);
+
+MODULE_AUTHOR("Toradex AG");
+MODULE_DESCRIPTION("i.MX ipuv3 VDAC extern port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index b826c17702ed..29b851dfafec 100644
--- a/drivers/video/fbdev/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
@@ -268,6 +268,7 @@ struct mxsfb_info {
#ifdef CONFIG_FB_MXC_OVERLAY
struct mxsfb_layer overlay;
#endif
+ char *fb_mode_str;
};
#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
@@ -477,7 +478,7 @@ static const struct fb_bitfield def_rgb444[] = {
.length = 0,
}
};
-#endif
+#endif /* CONFIG_FB_MXC_OVERLAY */
static const struct fb_bitfield def_rgb666[] = {
[RED] = {
@@ -685,7 +686,6 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
"dispdrv:%s\n", host->dispdrv->drv->name);
return;
}
- host->sync = fb_info->var.sync;
}
if (host->reg_lcd) {
@@ -1302,6 +1302,41 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
return 0;
}
+/*
+ * Parse user specified options (`video=')
+ * e.g.:
+ * video=mxsfb:800x480M-16@60,pixclockpol=1,outputen=1
+ */
+static int mxsfb_option_setup(struct mxsfb_info *host, struct fb_info *fb_info)
+{
+ char *options, *opt;
+ struct platform_device *pdev = host->pdev;
+
+ if (fb_get_options(DRIVER_NAME, &options)) {
+ dev_err(&pdev->dev, "Can't get fb option for %s!\n", DRIVER_NAME);
+ return -ENODEV;
+ }
+
+ if (!options || !*options)
+ return 0;
+
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt) {
+ continue;
+ } else if (!strncmp(opt, "pixclockpol=", 12)) {
+ if(simple_strtoul(opt + 12, NULL, 0))
+ host->sync |= FB_SYNC_CLK_LAT_FALL;
+ } else if (!strncmp(opt, "outputen=", 9)) {
+ if(simple_strtoul(opt + 9, NULL, 0))
+ host->sync |= FB_SYNC_OE_LOW_ACT;
+ } else {
+ host->fb_mode_str = opt;
+ }
+ }
+
+ return 0;
+}
+
static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
{
struct fb_info *fb_info = host->fb_info;
@@ -1309,12 +1344,14 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
struct device *dev = &host->pdev->dev;
struct device_node *np = host->pdev->dev.of_node;
struct device_node *display_np;
- struct device_node *timings_np;
struct display_timings *timings = NULL;
const char *disp_dev, *disp_videomode;
+ struct videomode vm;
+ struct fb_videomode fb_vm;
+ struct fb_videomode native_mode;
u32 width;
int i;
- int ret = 0;
+ int ret = 0, retval = 0;
host->id = of_alias_get_id(np, "lcdif");
@@ -1377,34 +1414,67 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
goto put_display_node;
}
- timings_np = of_find_node_by_name(display_np,
- "display-timings");
- if (!timings_np) {
- dev_err(dev, "failed to find display-timings node\n");
- ret = -ENOENT;
- goto put_display_node;
- }
-
- for (i = 0; i < of_get_child_count(timings_np); i++) {
- struct videomode vm;
- struct fb_videomode fb_vm;
+ INIT_LIST_HEAD(&fb_info->modelist);
+ for (i = 0; i < timings->num_timings; i++) {
ret = videomode_from_timings(timings, &vm, i);
if (ret < 0)
- goto put_timings_node;
+ goto put_display_node;
+
ret = fb_videomode_from_videomode(&vm, &fb_vm);
if (ret < 0)
- goto put_timings_node;
+ goto put_display_node;
if (!(vm.flags & DISPLAY_FLAGS_DE_HIGH))
fb_vm.sync |= FB_SYNC_OE_LOW_ACT;
- if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+
+ /*
+ * The PIXDATA flags of the display_flags enum are controller
+ * centric, e.g. NEGEDGE means drive data on negative edge.
+ * However, the drivers flag is display centric: Sample the
+ * data on negative (falling) edge. Therefore, check for the
+ * POSEDGE flag:
+ * drive on positive edge => sample on negative edge
+ */
+ if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
fb_vm.sync |= FB_SYNC_CLK_LAT_FALL;
+
+ if (i == timings->native_mode) {
+ native_mode = fb_vm;
+ fb_videomode_to_var(&fb_info->var, &fb_vm);
+ }
+
fb_add_videomode(&fb_vm, &fb_info->modelist);
}
-put_timings_node:
- of_node_put(timings_np);
+ retval = fb_find_mode(&fb_info->var, fb_info, host->fb_mode_str, &fb_vm,
+ timings->num_timings, &native_mode,
+ fb_info->var.bits_per_pixel);
+ if (retval != 1)
+ /* save the sync value getting from dtb */
+ host->sync = fb_info->var.sync;
+
+ switch (retval) {
+ case 0:
+ dev_err(dev, "fb_find_mode can't find a "
+ "suitable timing\n");
+ break;
+ case 1:
+ dev_info(dev, "Using timings from kernel parameters\n");
+ break;
+ case 2:
+ dev_info(dev, "Using timings from kernel parameters "
+ "and ignoring refresh rate\n");
+ break;
+ case 3:
+ dev_info(dev, "Using timings from devicetree\n");
+ break;
+ case 4:
+ dev_warn(dev, "Falling back to any valid timing\n");
+ default:
+ break;
+ }
+
put_display_node:
if (timings)
kfree(timings);
@@ -1417,7 +1487,6 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
int ret;
struct fb_info *fb_info = host->fb_info;
struct fb_var_screeninfo *var = &fb_info->var;
- struct fb_modelist *modelist;
fb_info->fbops = &mxsfb_ops;
fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
@@ -1427,6 +1496,10 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
fb_info->fix.accel = FB_ACCEL_NONE;
+ ret = mxsfb_option_setup(host, fb_info);
+ if (ret)
+ return ret;
+
ret = mxsfb_init_fbinfo_dt(host);
if (ret)
return ret;
@@ -1436,15 +1509,6 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
else
sprintf(fb_info->fix.id, "mxs-lcdif%d", host->id);
- if (!list_empty(&fb_info->modelist)) {
- /* first video mode in the modelist as default video mode */
- modelist = list_first_entry(&fb_info->modelist,
- struct fb_modelist, list);
- fb_videomode_to_var(var, &modelist->mode);
- }
- /* save the sync value getting from dtb */
- host->sync = fb_info->var.sync;
-
var->nonstd = 0;
var->activate = FB_ACTIVATE_NOW;
var->accel_flags = 0;
@@ -2177,11 +2241,14 @@ static void mxsfb_overlay_suspend(struct mxsfb_info *fbi)
clk_disable_pix(fbi);
}
}
-#endif
+#endif /* CONFIG_PM_SLEEP */
-#else
+#else /* CONFIG_FB_MXC_OVERLAY */
static void mxsfb_overlay_init(struct mxsfb_info *fbi) {}
static void mxsfb_overlay_exit(struct mxsfb_info *fbi) {}
+#endif /* CONFIG_FB_MXC_OVERLAY */
+
+#if !(defined(CONFIG_FB_MXC_OVERLAY) && defined(CONFIG_PM_SLEEP))
static void mxsfb_overlay_resume(struct mxsfb_info *fbi) {}
static void mxsfb_overlay_suspend(struct mxsfb_info *fbi) {}
#endif
@@ -2291,8 +2358,6 @@ static int mxsfb_probe(struct platform_device *pdev)
goto fb_release;
}
- INIT_LIST_HEAD(&fb_info->modelist);
-
pm_runtime_enable(&host->pdev->dev);
ret = mxsfb_init_fbinfo(host);
@@ -2438,7 +2503,7 @@ static int mxsfb_runtime_resume(struct device *dev)
return 0;
}
-#endif
+#endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP
static int mxsfb_suspend(struct device *pdev)
@@ -2455,6 +2520,7 @@ static int mxsfb_suspend(struct device *pdev)
host->restore_blank = saved_blank;
console_unlock();
+ pm_runtime_force_suspend(&host->pdev->dev);
pinctrl_pm_select_sleep_state(pdev);
return 0;
@@ -2466,6 +2532,7 @@ static int mxsfb_resume(struct device *pdev)
struct fb_info *fb_info = host->fb_info;
pinctrl_pm_select_default_state(pdev);
+ pm_runtime_force_resume(&host->pdev->dev);
console_lock();
mxsfb_overlay_resume(host);
@@ -2475,7 +2542,7 @@ static int mxsfb_resume(struct device *pdev)
return 0;
}
-#endif
+#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops mxsfb_pm_ops = {
SET_RUNTIME_PM_OPS(mxsfb_runtime_suspend, mxsfb_runtime_resume, NULL)
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 6d6f8c08792d..d8e3a0c7c653 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -68,4 +68,8 @@ config LOGO_SUPERH_CLUT224
depends on SUPERH
default y
+config LOGO_CUSTOM_CLUT224
+ bool "Custom 224-color Linux logo"
+ default n
+
endif # LOGO
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index 16f60c1e1766..4aba1b9e3106 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_LOGO_SUPERH_CLUT224) += logo_superh_clut224.o
obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o
+obj-$(CONFIG_LOGO_CUSTOM_CLUT224) += logo_custom_clut224.o
+
# How to generate logo's
pnmtologo := scripts/pnmtologo
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index 141f15a9a459..ec3f00502a96 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -100,6 +100,10 @@ const struct linux_logo * __ref fb_find_logo(int depth)
/* SuperH Linux logo */
logo = &logo_superh_clut224;
#endif
+#ifdef CONFIG_LOGO_CUSTOM_CLUT224
+ /* Custom Linux logo */
+ logo = &logo_custom_clut224;
+#endif
}
return logo;
}
diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c
index e0e62149a6f4..a84a29f72bd5 100644
--- a/drivers/watchdog/imx_sc_wdt.c
+++ b/drivers/watchdog/imx_sc_wdt.c
@@ -69,7 +69,12 @@ static int imx_sc_wdt_start(struct watchdog_device *wdog)
arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_WDOG_ACT,
SC_TIMER_WDOG_ACTION_PARTITION,
0, 0, 0, 0, 0, &res);
- return res.a0 ? -EACCES : 0;
+ if (res.a0)
+ return -EACCES;
+
+ dev_dbg(wdog->parent, "Watchdog started\n");
+
+ return 0;
}
static int imx_sc_wdt_stop(struct watchdog_device *wdog)
@@ -79,6 +84,8 @@ static int imx_sc_wdt_stop(struct watchdog_device *wdog)
arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_STOP_WDOG,
0, 0, 0, 0, 0, 0, &res);
+ dev_dbg(wdog->parent, "Watchdog stopped\n");
+
return res.a0 ? -EACCES : 0;
}
@@ -91,6 +98,8 @@ static int imx_sc_wdt_set_timeout(struct watchdog_device *wdog,
arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_TIMEOUT_WDOG,
timeout * 1000, 0, 0, 0, 0, 0, &res);
+ dev_dbg(wdog->parent, "Set timeout to %d seconds\n", timeout);
+
return res.a0 ? -EACCES : 0;
}
@@ -112,6 +121,8 @@ static int imx_sc_wdt_set_pretimeout(struct watchdog_device *wdog,
wdog->pretimeout = pretimeout;
+ dev_dbg(wdog->parent, "Set pretimeout to %d seconds\n", pretimeout);
+
return 0;
}
diff --git a/include/drm/bridge/cdns-mhdp-common.h b/include/drm/bridge/cdns-mhdp-common.h
index 381a5eb5da0b..a6efc7dc7e72 100755
--- a/include/drm/bridge/cdns-mhdp-common.h
+++ b/include/drm/bridge/cdns-mhdp-common.h
@@ -713,7 +713,7 @@ struct cdns_mhdp_device {
} hdmi;
};
const struct cdns_plat_data *plat_data;
-
+ struct i2c_adapter *ddc; /* optional regular DDC I2C bus */
};
u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset);
diff --git a/include/linux/input/fusion_F0710A.h b/include/linux/input/fusion_F0710A.h
new file mode 100644
index 000000000000..7d152cbdd06e
--- /dev/null
+++ b/include/linux/input/fusion_F0710A.h
@@ -0,0 +1,20 @@
+/* linux/input/fusion_F0710A.h
+ *
+ * Platform data for Fusion F0710A driver
+ *
+ * Copyright (c) 2013 Toradex AG (stefan.agner@toradex.ch)
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#ifndef __LINUX_I2C_FUSION_F0710A_H
+#define __LINUX_I2C_FUSION_F0710A_H
+
+/* Board specific touch screen initial values */
+struct fusion_f0710a_init_data {
+ int (*pinmux_fusion_pins)(void);
+ int gpio_int;
+ int gpio_reset;
+};
+
+#endif /* __LINUX_I2C_FUSION_F0710A_H */
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
index d4d5b93efe84..57814768be44 100644
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -45,6 +45,7 @@ extern const struct linux_logo logo_superh_mono;
extern const struct linux_logo logo_superh_vga16;
extern const struct linux_logo logo_superh_clut224;
extern const struct linux_logo logo_spe_clut224;
+extern const struct linux_logo logo_custom_clut224;
extern const struct linux_logo *fb_find_logo(int depth);
#ifdef CONFIG_FB_LOGO_EXTRA
diff --git a/include/linux/mfd/pca9450.h b/include/linux/mfd/pca9450.h
index b689c2dd3b94..809eeef7c98d 100644
--- a/include/linux/mfd/pca9450.h
+++ b/include/linux/mfd/pca9450.h
@@ -92,6 +92,9 @@ enum {
PCA9450_MAX_REGISTER = 0x2F,
};
+/* PCA9450_BUCK123_DVS */
+#define BUCK123_PRESET_EN 0x80
+
/* PCA9450 BUCK ENMODE bits */
#define BUCK_ENMODE_OFF 0x00
#define BUCK_ENMODE_ONREQ 0x01
@@ -230,6 +233,7 @@ enum {
struct pca9450_board {
struct regulator_init_data *init_data[PCA9450_REGULATOR_CNT];
int gpio_intr;
+ int i2c_lt_en;
int irq_base;
};
diff --git a/include/linux/pinctrl/devinfo.h b/include/linux/pinctrl/devinfo.h
index a48ff69acddd..98df234834bd 100644
--- a/include/linux/pinctrl/devinfo.h
+++ b/include/linux/pinctrl/devinfo.h
@@ -14,11 +14,11 @@
#ifndef PINCTRL_DEVINFO_H
#define PINCTRL_DEVINFO_H
-#ifdef CONFIG_PINCTRL
-
/* The device core acts as a consumer toward pinctrl */
#include <linux/pinctrl/consumer.h>
+#ifdef CONFIG_PINCTRL
+
/**
* struct dev_pin_info - pin state container for devices
* @p: pinctrl handle for the containing device
diff --git a/include/linux/platform_data/usb3503.h b/include/linux/platform_data/usb3503.h
index e049d51c1353..435e9edb1bc4 100644
--- a/include/linux/platform_data/usb3503.h
+++ b/include/linux/platform_data/usb3503.h
@@ -16,7 +16,9 @@ enum usb3503_mode {
struct usb3503_platform_data {
enum usb3503_mode initial_mode;
+ u8 port_nrd;
u8 port_off_mask;
+ int gpio_bypass;
int gpio_intn;
int gpio_connect;
int gpio_reset;
diff --git a/include/linux/sync.h b/include/linux/sync.h
new file mode 100644
index 000000000000..4f1993871467
--- /dev/null
+++ b/include/linux/sync.h
@@ -0,0 +1,390 @@
+/*
+ * include/linux/sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SYNC_H
+#define _LINUX_SYNC_H
+
+#include <linux/types.h>
+#ifdef __KERNEL__
+
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+struct sync_timeline;
+struct sync_pt;
+struct sync_fence;
+
+/**
+ * struct sync_timeline_ops - sync object implementation ops
+ * @driver_name: name of the implentation
+ * @dup: duplicate a sync_pt
+ * @has_signaled: returns:
+ * 1 if pt has signaled
+ * 0 if pt has not signaled
+ * <0 on error
+ * @compare: returns:
+ * 1 if b will signal before a
+ * 0 if a and b will signal at the same time
+ * -1 if a will signabl before b
+ * @free_pt: called before sync_pt is freed
+ * @release_obj: called before sync_timeline is freed
+ * @print_obj: print aditional debug information about sync_timeline.
+ * should not print a newline
+ * @print_pt: print aditional debug information about sync_pt.
+ * should not print a newline
+ * @fill_driver_data: write implmentation specific driver data to data.
+ * should return an error if there is not enough room
+ * as specified by size. This information is returned
+ * to userspace by SYNC_IOC_FENCE_INFO.
+ */
+struct sync_timeline_ops {
+ const char *driver_name;
+
+ /* required */
+ struct sync_pt *(*dup)(struct sync_pt *pt);
+
+ /* required */
+ int (*has_signaled)(struct sync_pt *pt);
+
+ /* required */
+ int (*compare)(struct sync_pt *a, struct sync_pt *b);
+
+ /* optional */
+ void (*free_pt)(struct sync_pt *sync_pt);
+
+ /* optional */
+ void (*release_obj)(struct sync_timeline *sync_timeline);
+
+ /* optional */
+ void (*print_obj)(struct seq_file *s,
+ struct sync_timeline *sync_timeline);
+
+ /* optional */
+ void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt);
+
+ /* optional */
+ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
+};
+
+/**
+ * struct sync_timeline - sync object
+ * @ops: ops that define the implementaiton of the sync_timeline
+ * @name: name of the sync_timeline. Useful for debugging
+ * @destoryed: set when sync_timeline is destroyed
+ * @child_list_head: list of children sync_pts for this sync_timeline
+ * @child_list_lock: lock protecting @child_list_head, destroyed, and
+ * sync_pt.status
+ * @active_list_head: list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list: membership in global sync_timeline_list
+ */
+struct sync_timeline {
+ const struct sync_timeline_ops *ops;
+ char name[32];
+
+ /* protected by child_list_lock */
+ bool destroyed;
+
+ struct list_head child_list_head;
+ spinlock_t child_list_lock;
+
+ struct list_head active_list_head;
+ spinlock_t active_list_lock;
+
+ struct list_head sync_timeline_list;
+};
+
+/**
+ * struct sync_pt - sync point
+ * @parent: sync_timeline to which this sync_pt belongs
+ * @child_list: membership in sync_timeline.child_list_head
+ * @active_list: membership in sync_timeline.active_list_head
+ * @fence: sync_fence to which the sync_pt belongs
+ * @pt_list: membership in sync_fence.pt_list_head
+ * @status: 1: signaled, 0:active, <0: error
+ * @timestamp: time which sync_pt status transitioned from active to
+ * singaled or error.
+ */
+struct sync_pt {
+ struct sync_timeline *parent;
+ struct list_head child_list;
+
+ struct list_head active_list;
+
+ struct sync_fence *fence;
+ struct list_head pt_list;
+
+ /* protected by parent->active_list_lock */
+ int status;
+
+ ktime_t timestamp;
+};
+
+/**
+ * struct sync_fence - sync fence
+ * @file: file representing this fence
+ * @name: name of sync_fence. Useful for debugging
+ * @pt_list_head: list of sync_pts in ths fence. immutable once fence
+ * is created
+ * @waiter_list_head: list of asynchronous waiters on this fence
+ * @waiter_list_lock: lock protecting @waiter_list_head and @status
+ * @status: 1: signaled, 0:active, <0: error
+ *
+ * @wq: wait queue for fence signaling
+ * @sync_fence_list: membership in global fence list
+ */
+struct sync_fence {
+ struct file *file;
+ char name[32];
+
+ /* this list is immutable once the fence is created */
+ struct list_head pt_list_head;
+
+ struct list_head waiter_list_head;
+ spinlock_t waiter_list_lock; /* also protects status */
+ int status;
+
+ wait_queue_head_t wq;
+
+ struct list_head sync_fence_list;
+};
+
+/**
+ * struct sync_fence_waiter - metadata for asynchronous waiter on a fence
+ * @waiter_list: membership in sync_fence.waiter_list_head
+ * @callback: function pointer to call when fence signals
+ * @callback_data: pointer to pass to @callback
+ */
+struct sync_fence_waiter {
+ struct list_head waiter_list;
+
+ void (*callback)(struct sync_fence *fence, void *data);
+ void *callback_data;
+};
+
+/*
+ * API for sync_timeline implementers
+ */
+
+/**
+ * sync_timeline_create() - creates a sync object
+ * @ops: specifies the implemention ops for the object
+ * @size: size to allocate for this obj
+ * @name: sync_timeline name
+ *
+ * Creates a new sync_timeline which will use the implemetation specified by
+ * @ops. @size bytes will be allocated allowing for implemntation specific
+ * data to be kept after the generic sync_timeline stuct.
+ */
+struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name);
+
+/**
+ * sync_timeline_destory() - destorys a sync object
+ * @obj: sync_timeline to destroy
+ *
+ * A sync implemntation should call this when the @obj is going away
+ * (i.e. module unload.) @obj won't actually be freed until all its childern
+ * sync_pts are freed.
+ */
+void sync_timeline_destroy(struct sync_timeline *obj);
+
+/**
+ * sync_timeline_signal() - signal a status change on a sync_timeline
+ * @obj: sync_timeline to signal
+ *
+ * A sync implemntation should call this any time one of it's sync_pts
+ * has signaled or has an error condition.
+ */
+void sync_timeline_signal(struct sync_timeline *obj);
+
+/**
+ * sync_pt_create() - creates a sync pt
+ * @parent: sync_pt's parent sync_timeline
+ * @size: size to allocate for this pt
+ *
+ * Creates a new sync_pt as a chiled of @parent. @size bytes will be
+ * allocated allowing for implemntation specific data to be kept after
+ * the generic sync_timeline struct.
+ */
+struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size);
+
+/**
+ * sync_pt_free() - frees a sync pt
+ * @pt: sync_pt to free
+ *
+ * This should only be called on sync_pts which have been created but
+ * not added to a fence.
+ */
+void sync_pt_free(struct sync_pt *pt);
+
+/**
+ * sync_fence_create() - creates a sync fence
+ * @name: name of fence to create
+ * @pt: sync_pt to add to the fence
+ *
+ * Creates a fence containg @pt. Once this is called, the fence takes
+ * ownership of @pt.
+ */
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt);
+
+/*
+ * API for sync_fence consumers
+ */
+
+/**
+ * sync_fence_merge() - merge two fences
+ * @name: name of new fence
+ * @a: fence a
+ * @b: fence b
+ *
+ * Creates a new fence which contains copies of all the sync_pts in both
+ * @a and @b. @a and @b remain valid, independent fences.
+ */
+struct sync_fence *sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b);
+
+/**
+ * sync_fence_fdget() - get a fence from an fd
+ * @fd: fd referencing a fence
+ *
+ * Ensures @fd references a valid fence, increments the refcount of the backing
+ * file, and returns the fence.
+ */
+struct sync_fence *sync_fence_fdget(int fd);
+
+/**
+ * sync_fence_put() - puts a refernnce of a sync fence
+ * @fence: fence to put
+ *
+ * Puts a reference on @fence. If this is the last reference, the fence and
+ * all it's sync_pts will be freed
+ */
+void sync_fence_put(struct sync_fence *fence);
+
+/**
+ * sync_fence_install() - installs a fence into a file descriptor
+ * @fence: fence to instal
+ * @fd: file descriptor in which to install the fence
+ *
+ * Installs @fence into @fd. @fd's should be acquired through get_unused_fd().
+ */
+void sync_fence_install(struct sync_fence *fence, int fd);
+
+/**
+ * sync_fence_wait_async() - registers and async wait on the fence
+ * @fence: fence to wait on
+ * @callback: callback
+ * @callback_data data to pass to the callback
+ *
+ * Returns 1 if @fence has already signaled.
+ *
+ * Registers a callback to be called when @fence signals or has an error
+ */
+int sync_fence_wait_async(struct sync_fence *fence,
+ void (*callback)(struct sync_fence *, void *data),
+ void *callback_data);
+
+/**
+ * sync_fence_wait() - wait on fence
+ * @fence: fence to wait on
+ * @tiemout: timeout in ms
+ *
+ * Wait for @fence to be signaled or have an error. Waits indefintly
+ * if @timeout = 0
+ */
+int sync_fence_wait(struct sync_fence *fence, long timeout);
+
+#endif /* __KERNEL__ */
+
+/**
+ * struct sync_merge_data - data passed to merge ioctl
+ * @fd2: file descriptor of second fence
+ * @name: name of new fence
+ * @fence: returns the fd of the new fence to userspace
+ */
+struct sync_merge_data {
+ __s32 fd2; /* fd of second fence */
+ char name[32]; /* name of new fence */
+ __s32 fence; /* fd on newly created fence */
+};
+
+/**
+ * struct sync_pt_info - detailed sync_pt information
+ * @len: length of sync_pt_info including any driver_data
+ * @obj_name: name of parent sync_timeline
+ * @driver_name: name of driver implmenting the parent
+ * @status: status of the sync_pt 0:active 1:signaled <0:error
+ * @timestamp_ns: timestamp of status change in nanoseconds
+ * @driver_data: any driver dependant data
+ */
+struct sync_pt_info {
+ __u32 len;
+ char obj_name[32];
+ char driver_name[32];
+ __s32 status;
+ __u64 timestamp_ns;
+
+ __u8 driver_data[0];
+};
+
+/**
+ * struct sync_fence_info_data - data returned from fence info ioctl
+ * @len: ioctl caller writes the size of the buffer its passing in.
+ * ioctl returns length of sync_fence_data reutnred to userspace
+ * including pt_info.
+ * @name: name of fence
+ * @status: status of fence. 1: signaled 0:active <0:error
+ * @pt_info: a sync_pt_info struct for every sync_pt in the fence
+ */
+struct sync_fence_info_data {
+ __u32 len;
+ char name[32];
+ __s32 status;
+
+ __u8 pt_info[0];
+};
+
+#define SYNC_IOC_MAGIC '>'
+
+/**
+ * DOC: SYNC_IOC_WAIT - wait for a fence to signal
+ *
+ * pass timeout in milliseconds.
+ */
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __u32)
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data. Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the
+ * new fence's fd in sync_merge_data.fence
+ */
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+
+/**
+ * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len. On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To itterate over the sync_pt_infos, use the sync_pt_info.len field.
+ */
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
+ struct sync_fence_info_data)
+
+#endif /* _LINUX_SYNC_H */
diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
index 48ceea867dd6..99a39adb3ddb 100644
--- a/include/linux/sys_soc.h
+++ b/include/linux/sys_soc.h
@@ -15,6 +15,7 @@ struct soc_device_attribute {
const char *serial_number;
const char *soc_id;
const void *data;
+ const char *unique_id;
};
/**
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index b4c8416c3d1f..284d4d1695c5 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -185,6 +185,9 @@ enum {
/* module saa7191: just ident 7191 */
V4L2_IDENT_SAA7191 = 7191,
+ /* module adv7280: just ident 7280 */
+ V4L2_IDENT_ADV7280 = 7280,
+
/* module ths7303: just ident 7303 */
V4L2_IDENT_THS7303 = 7303,
diff --git a/include/video/mxc_hdmi.h b/include/video/mxc_hdmi.h
index 79eb3024f65c..bb0d33a2d460 100644
--- a/include/video/mxc_hdmi.h
+++ b/include/video/mxc_hdmi.h
@@ -573,6 +573,10 @@ enum {
HDMI_IH_MUTE_PHY_STAT0_TX_PHY_LOCK = 0x2,
HDMI_IH_MUTE_PHY_STAT0_HPD = 0x1,
+/* IH and IH_MUTE convenience macro RX_SENSE | HPD*/
+ HDMI_DVI_IH_STAT = 0x3D,
+
+
/* IH_AHBDMAAUD_STAT0 field values */
HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
@@ -871,6 +875,9 @@ enum {
HDMI_PHY_HPD = 0x02,
HDMI_PHY_TX_PHY_LOCK = 0x01,
+/* HDMI STAT convenience RX_SENSE | HPD */
+ HDMI_DVI_STAT = 0xF2,
+
/* PHY_I2CM_SLAVE_ADDR field values */
HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ee57fa20bac3..f07a2b11c3c9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -726,20 +726,17 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode)
hci_dev_lock(hdev);
conn = hci_lookup_le_connect(hdev);
+ if (!conn)
+ goto done;
if (!status) {
hci_connect_le_scan_cleanup(conn);
- goto done;
+ } else {
+ BT_ERR("HCI request failed to create LE connection: status 0x%2.2x",
+ status);
+ hci_le_conn_failed(conn, status);
}
- bt_dev_err(hdev, "request failed to create LE connection: "
- "status 0x%2.2x", status);
-
- if (!conn)
- goto done;
-
- hci_le_conn_failed(conn, status);
-
done:
hci_dev_unlock(hdev);
}
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 211007c091d5..19959fb5df4e 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config WIRELESS_EXT
- bool
+ bool "WIRELESS_EXT - wireless core extensions"
config WEXT_CORE
def_bool y
@@ -15,7 +15,7 @@ config WEXT_SPY
bool
config WEXT_PRIV
- bool
+ bool "WEXT_PRIV - Wireless Extensions priv API"
config CFG80211
tristate "cfg80211 - wireless configuration API"
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f128ffabf5e5..91779f3d0ceb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -716,7 +716,7 @@ config SND_SOC_HDAC_HDA
select SND_HDA
config SND_SOC_ICS43432
- tristate
+ tristate "InvenSense ICS43432 I2S microphone codec"
config SND_SOC_INNO_RK3036
tristate "Inno codec driver for RK3036 SoC"
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index f5b59305c957..6539c38280cd 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1514,8 +1514,34 @@ err:
return ret;
}
+static int sgtl5000_suspend(struct snd_soc_component *component)
+{
+ struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component);
+
+ clk_disable_unprepare(sgtl5000->mclk);
+
+ return 0;
+}
+
+static int sgtl5000_resume(struct snd_soc_component *component)
+{
+ int ret;
+ struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component);
+
+ ret = clk_prepare_enable(sgtl5000->mclk);
+ if (ret)
+ dev_err(component->dev, "Error enabling clock %d\n", ret);
+
+ /* Need 8 clocks before I2C accesses */
+ udelay(1);
+
+ return ret;
+}
+
static const struct snd_soc_component_driver sgtl5000_driver = {
.probe = sgtl5000_probe,
+ .suspend = sgtl5000_suspend,
+ .resume = sgtl5000_resume,
.set_bias_level = sgtl5000_set_bias_level,
.controls = sgtl5000_snd_controls,
.num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9e8c564f6e9c..b174a9381c0c 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1417,6 +1417,13 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id,
struct snd_soc_component *component = dai->component;
struct wm8904_priv *priv = snd_soc_component_get_drvdata(component);
+ /*
+ * If using sound-simple-card this is called with clk_id fixed to 0.
+ * Assume we want WM8904_CLK_MCLK for now in that case.
+ */
+ if (clk_id == 0)
+ clk_id = WM8904_CLK_MCLK;
+
switch (clk_id) {
case WM8904_CLK_MCLK:
priv->sysclk_src = clk_id;
diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c
index a6d3a7206888..adb96675ee74 100644
--- a/sound/soc/fsl/fsl_dsp.c
+++ b/sound/soc/fsl/fsl_dsp.c
@@ -70,6 +70,63 @@
#include "fsl_dsp_pool.h"
#include "fsl_dsp_xaf_api.h"
+#define DSP_DISABLE_FUSE 0x8
+#define DSP_DISABLE_MASK 0x1
+
+struct dsp_sc_msg_misc {
+ struct imx_sc_rpc_msg hdr;
+ u32 word;
+} __packed;
+
+static int dsp_sc_get_fuse(struct imx_sc_ipc *ipc, u32 word, u32 *fuse)
+{
+ struct dsp_sc_msg_misc msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_MISC;
+ hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ;
+ hdr->size = 2;
+
+ msg.word = word;
+
+ ret = imx_scu_call_rpc(ipc, &msg, true);
+ if (ret)
+ return ret;
+
+ *fuse = msg.word;
+
+ return ret;
+}
+
+static int check_dsp_is_available(void)
+{
+ uint32_t fuse = 0xffff;
+ int ret = 0;
+ struct imx_sc_ipc *ipcHandle;;
+
+ ret = imx_scu_get_handle(&ipcHandle);
+ if (ret) {
+ /* We're not running on a iMX8 or iMX8X, so there is no DSP */
+ return -EINVAL;
+ }
+
+ ret = dsp_sc_get_fuse(ipcHandle, DSP_DISABLE_FUSE, &fuse);
+ if (ret) {
+ pr_err("sc_misc_otp_fuse_read fail! %d\n", ret);
+ return -EINVAL;
+ }
+
+ pr_debug("DSP disable fuse[%i] = 0x%x\n", DSP_DISABLE_FUSE, fuse);
+ if (fuse & DSP_DISABLE_MASK) {
+ pr_info("%s: HiFi4 DSP not available on this silicon\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* ...allocate new client */
struct xf_client *xf_client_alloc(struct fsl_dsp *dsp_priv)
{
@@ -1491,7 +1548,22 @@ static struct platform_driver fsl_dsp_driver = {
.pm = &fsl_dsp_pm,
},
};
-module_platform_driver(fsl_dsp_driver);
+
+static int __init fsl_dsp_driver_init(void)
+{
+ /* do not install the driver if no DSP is found */
+ if (check_dsp_is_available())
+ return -EINVAL;
+
+ return platform_driver_register(&fsl_dsp_driver);
+}
+module_init(fsl_dsp_driver_init);
+
+static void __exit fsl_dsp_driver_exit(void)
+{
+ platform_driver_unregister(&fsl_dsp_driver);
+}
+module_exit(fsl_dsp_driver_exit);
MODULE_DESCRIPTION("Freescale DSP driver");
MODULE_ALIAS("platform:fsl-dsp");
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 49f5a8551143..93689892e97b 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -530,10 +530,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
scr = SCR_TXFIFO_AUTOSYNC | SCR_TXFIFO_CTRL_NORMAL |
SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP |
- SCR_TXFIFO_FSEL_IF8;
+ SCR_TXFIFO_FSEL_IF8 | SCR_VAL_CLEAR;
mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
- SCR_TXFIFO_FSEL_MASK;
+ SCR_TXFIFO_FSEL_MASK | SCR_VAL_MASK;
} else {
scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC;
mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|